Skip to content

Commit

Permalink
✨ path.name
Browse files Browse the repository at this point in the history
  • Loading branch information
juftin committed Mar 20, 2024
1 parent 242e64d commit 0d3cdd5
Show file tree
Hide file tree
Showing 5 changed files with 165 additions and 123 deletions.
63 changes: 47 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,27 @@
# Textual Universal Directory Tree

A [Textual](https://textual.textualize.io/) plugin to make the
[DirectoryTree](https://textual.textualize.io/widgets/directory_tree/)
widget compatible with filesystems other than local.

![](docs/screenshots/test_github_screenshot.svg)
<h1 align="center">textual-universal-directorytree</h1>

<div align="center">
<a href="https://github.com/juftin/textual-universal-directorytree">
<img src="docs/screenshots/test_github_screenshot.svg" alt="textual-universal-directorytree" />
</a>
</div>

<p align="center">
<a href="https://textual.textualize.io/widgets/directory_tree/">DirectoryTree</a> widget for <a href="https://textual.textualize.io/">textual</a>, compatible with all filesystems
</p>

<p align="center">
<a href="https://github.com/juftin/textual-universal-directorytree"><img src="https://img.shields.io/pypi/v/textual-universal-directorytree?color=blue&label=%F0%9F%93%81%20textual-universal-directorytree" alt="PyPI"></a>
<a href="https://pypi.python.org/pypi/textual-universal-directorytree/"><img src="https://img.shields.io/pypi/pyversions/textual-universal-directorytree" alt="PyPI - Python Version"></a>
<a href="https://github.com/juftin/textual-universal-directorytree/blob/main/LICENSE"><img src="https://img.shields.io/github/license/juftin/textual-universal-directorytree?color=blue&label=License" alt="GitHub License"></a>
<a href="https://juftin.github.io/textual-universal-directorytree/"><img src="https://img.shields.io/static/v1?message=docs&color=526CFE&logo=Material+for+MkDocs&logoColor=FFFFFF&label=" alt="docs"></a>
<a href="https://github.com/juftin/textual-universal-directorytree/actions/workflows/tests.yaml?query=branch%3Amain"><img src="https://github.com/juftin/textual-universal-directorytree/actions/workflows/tests.yaml/badge.svg?branch=main" alt="Testing Status"></a>
<a href="https://github.com/pypa/hatch"><img src="https://img.shields.io/badge/%F0%9F%A5%9A-Hatch-4051b5.svg" alt="Hatch project"></a>
<a href="https://github.com/astral-sh/ruff"><img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json" alt="Ruff"></a>
<a href="https://github.com/pre-commit/pre-commit"><img src="https://img.shields.io/badge/pre--commit-enabled-lightgreen?logo=pre-commit" alt="pre-commit"></a>
<a href="https://github.com/semantic-release/semantic-release"><img src="https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg" alt="semantic-release"></a>
<a href="https://gitmoji.dev"><img src="https://img.shields.io/badge/gitmoji-%20😜%20😍-FFDD67.svg" alt="Gitmoji"></a>
</p>

## Installation

Expand All @@ -26,10 +43,12 @@ pip install "textual-universal-directorytree[remote]"

The below example shows how to use `textual-universal-directorytree` in a Textual app.
It uses the GitHub filesystem to display the contents of the textual GitHub repository.
It requires the `requests` library to be installed.
It requires the `requests` library to be installed (or the `remote` extra).

```python
from typing import Any, ClassVar, List
from __future__ import annotations

from typing import Any, ClassVar

from rich.syntax import Syntax
from textual import on
Expand All @@ -38,27 +57,38 @@ from textual.binding import BindingType
from textual.containers import Horizontal, VerticalScroll
from textual.widgets import DirectoryTree, Footer, Header, Static

from textual_universal_directorytree import UniversalDirectoryTree
from textual_universal_directorytree import UniversalDirectoryTree, UPath


class UniversalDirectoryTreeApp(App):
"""
The power of upath and fsspec in a Textual app
"""

BINDINGS: ClassVar[List[BindingType]] = [
TITLE = "UniversalDirectoryTree"

CSS = """
UniversalDirectoryTree {
max-width: 50%;
width: auto;
height: 100%;
dock: left;
}
"""

BINDINGS: ClassVar[list[BindingType]] = [
("q", "quit", "Quit"),
]

def __init__(self, path: str, *args: Any, **kwargs: Any):
def __init__(self, path: str | UPath, *args: Any, **kwargs: Any):
super().__init__(*args, **kwargs)
self.file_path = path
self.universal_path = UPath(path).resolve()
self.directory_tree = UniversalDirectoryTree(path=self.universal_path)
self.file_content = Static(expand=True)

def compose(self) -> ComposeResult:
yield Header()
directory_tree = UniversalDirectoryTree(path=self.file_path)
yield Horizontal(directory_tree, VerticalScroll(self.file_content))
yield Horizontal(self.directory_tree, VerticalScroll(self.file_content))
yield Footer()

@on(DirectoryTree.FileSelected)
Expand All @@ -69,12 +99,13 @@ class UniversalDirectoryTreeApp(App):
Objects returned by the FileSelected event are upath.UPath objects and
they are compatible with the familiar pathlib.Path API built into Python.
"""
self.sub_title = str(message.path)
try:
file_content = message.path.read_text()
except UnicodeDecodeError:
self.file_content.update("")
return None
lexer = Syntax.guess_lexer(path=message.path.name)
lexer = Syntax.guess_lexer(path=message.path.name, code=file_content)
code = Syntax(code=file_content, lexer=lexer)
self.file_content.update(code)
```
Expand Down
188 changes: 94 additions & 94 deletions docs/screenshots/test_github_screenshot.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 7 additions & 7 deletions requirements/requirements-docs.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#
# This file is autogenerated by hatch-pip-compile with Python 3.11
#
# [constraints] requirements.txt (SHA256: 9af71b46a759063aedcaa7dd5827200718b097dd959677acd642ee2dc7f49cd5)
# [constraints] requirements.txt (SHA256: 1ebfc36781ae1aaa100698a9c454a87469ed5695fcf63f6a2957f2729314a60a)
#
# - markdown-callouts
# - markdown-exec
Expand Down Expand Up @@ -38,7 +38,7 @@ colorama==0.4.6
# via
# griffe
# mkdocs-material
fsspec==2024.2.0
fsspec==2024.3.1
# via
# -c requirements.txt
# universal-pathlib
Expand Down Expand Up @@ -124,7 +124,7 @@ mkdocstrings==0.24.0
# mkdocstrings-python
mkdocstrings-python==1.8.0
# via hatch.envs.docs
packaging==23.2
packaging==24.0
# via
# -c requirements.txt
# mkdocs
Expand All @@ -147,7 +147,7 @@ pymdown-extensions==10.7
# markdown-exec
# mkdocs-material
# mkdocstrings
python-dateutil==2.8.2
python-dateutil==2.9.0.post0
# via
# -c requirements.txt
# ghp-import
Expand All @@ -164,19 +164,19 @@ requests==2.31.0
# via
# -c requirements.txt
# mkdocs-material
rich==13.7.0
rich==13.7.1
# via
# -c requirements.txt
# textual
six==1.16.0
# via
# -c requirements.txt
# python-dateutil
textual==0.48.2
textual==0.53.1
# via
# -c requirements.txt
# hatch.envs.docs
typing-extensions==4.9.0
typing-extensions==4.10.0
# via
# -c requirements.txt
# textual
Expand Down
6 changes: 3 additions & 3 deletions textual_universal_directorytree/alternate_paths.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ def name(self) -> str:
"""
original_name = super().name
if original_name == "":
return self.__str__()
return self.storage_options["repo"]
else:
return original_name

Expand Down Expand Up @@ -128,7 +128,7 @@ def name(self) -> str:
if self._is_top_level_bucket():
return f"{self._url.scheme}://{self._url.netloc}"
elif original_name == "":
return self.__str__()
return self.parts[-1].rstrip("/")
else:
return original_name

Expand Down Expand Up @@ -171,6 +171,6 @@ def name(self) -> str:
"""
original_name = super().name
if original_name == "":
return self.__str__()
return "/"
else:
return original_name
17 changes: 14 additions & 3 deletions textual_universal_directorytree/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,30 @@ class UniversalDirectoryTreeApp(App):
The power of upath and fsspec in a Textual app
"""

TITLE = "UniversalDirectoryTree"

CSS = """
UniversalDirectoryTree {
max-width: 50%;
width: auto;
height: 100%;
dock: left;
}
"""

BINDINGS: ClassVar[list[BindingType]] = [
("q", "quit", "Quit"),
]

def __init__(self, path: str | UPath, *args: Any, **kwargs: Any):
super().__init__(*args, **kwargs)
self.universal_path = UPath(path).resolve()
self.directory_tree = UniversalDirectoryTree(path=self.universal_path)
self.file_content = Static(expand=True)

def compose(self) -> ComposeResult:
yield Header()
directory_tree = UniversalDirectoryTree(path=self.universal_path)
yield Horizontal(directory_tree, VerticalScroll(self.file_content))
yield Horizontal(self.directory_tree, VerticalScroll(self.file_content))
yield Footer()

@on(DirectoryTree.FileSelected)
Expand All @@ -53,7 +64,7 @@ def handle_file_selected(self, message: DirectoryTree.FileSelected) -> None:
except UnicodeDecodeError:
self.file_content.update("")
return None
lexer = Syntax.guess_lexer(path=message.path.name)
lexer = Syntax.guess_lexer(path=message.path.name, code=file_content)
code = Syntax(code=file_content, lexer=lexer)
self.file_content.update(code)

Expand Down

0 comments on commit 0d3cdd5

Please sign in to comment.