riched 0.2.1__tar.gz → 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {riched-0.2.1 → riched-0.3.0}/AGENTS.md +1 -1
- {riched-0.2.1 → riched-0.3.0}/PKG-INFO +14 -5
- {riched-0.2.1 → riched-0.3.0}/README.md +12 -4
- {riched-0.2.1 → riched-0.3.0}/pyproject.toml +4 -1
- {riched-0.2.1 → riched-0.3.0}/src/riched/bindings.yaml +1 -1
- riched-0.3.0/src/riched/cli.py +39 -0
- {riched-0.2.1 → riched-0.3.0}/tests/runner.py +3 -0
- riched-0.3.0/tests/test_cli.py +40 -0
- {riched-0.2.1 → riched-0.3.0}/tests/test_file_io.py +1 -2
- {riched-0.2.1 → riched-0.3.0}/tests/test_footer.py +1 -1
- {riched-0.2.1 → riched-0.3.0}/uv.lock +1 -1
- riched-0.2.1/src/riched/cli.py +0 -24
- {riched-0.2.1 → riched-0.3.0}/.gitignore +0 -0
- {riched-0.2.1 → riched-0.3.0}/.python-version +0 -0
- {riched-0.2.1 → riched-0.3.0}/src/riched/__init__.py +0 -0
- {riched-0.2.1 → riched-0.3.0}/src/riched/app.py +0 -0
- {riched-0.2.1 → riched-0.3.0}/src/riched/editor.py +0 -0
- {riched-0.2.1 → riched-0.3.0}/src/riched/keybindings.py +0 -0
- {riched-0.2.1 → riched-0.3.0}/src/riched/quick_open.py +0 -0
- {riched-0.2.1 → riched-0.3.0}/src/riched/screens.py +0 -0
- {riched-0.2.1 → riched-0.3.0}/src/riched/settings.py +0 -0
- {riched-0.2.1 → riched-0.3.0}/src/riched/syntax.py +0 -0
- {riched-0.2.1 → riched-0.3.0}/tests/__init__.py +0 -0
- {riched-0.2.1 → riched-0.3.0}/tests/helpers.py +0 -0
- {riched-0.2.1 → riched-0.3.0}/tests/test_command_palette.py +0 -0
- {riched-0.2.1 → riched-0.3.0}/tests/test_dirty_buffers.py +0 -0
- {riched-0.2.1 → riched-0.3.0}/tests/test_editor_shortcuts.py +0 -0
- {riched-0.2.1 → riched-0.3.0}/tests/test_file_tree.py +0 -0
- {riched-0.2.1 → riched-0.3.0}/tests/test_quick_open.py +0 -0
- {riched-0.2.1 → riched-0.3.0}/tests/test_syntax.py +0 -0
|
@@ -9,7 +9,7 @@ This repository is a uv-managed Python project for `riched`, a Textual TUI edito
|
|
|
9
9
|
- `uv sync`: install project dependencies from `pyproject.toml` and `uv.lock`.
|
|
10
10
|
- `uv run riched path/to/file.txt`: open or create a file in the editor.
|
|
11
11
|
- `uv run python -m tests.runner`: run the Textual Pilot end-to-end suite.
|
|
12
|
-
- `uv build`: build the source distribution and wheel in `dist/`.
|
|
12
|
+
- `rm -rf dist && uv build`: clear stale artifacts, then build the source distribution and wheel in `dist/`.
|
|
13
13
|
- `set -a; source .env; set +a; uv publish --token "$PYPI_API"`: publish built distributions for a release using the PyPI API key from `.env`.
|
|
14
14
|
- `uv add <package>`: add runtime dependencies; do not use `pip`.
|
|
15
15
|
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: riched
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: TUI editor with VSCode keybindigs
|
|
5
|
+
Project-URL: Repository, https://github.com/hoishing/riched
|
|
5
6
|
Requires-Python: >=3.12
|
|
6
7
|
Requires-Dist: pyyaml>=6.0.3
|
|
7
8
|
Requires-Dist: textual[syntax]>=8.2.4
|
|
@@ -10,7 +11,7 @@ Description-Content-Type: text/markdown
|
|
|
10
11
|
|
|
11
12
|
# Riched
|
|
12
13
|
|
|
13
|
-
> TUI editor
|
|
14
|
+
> TUI editor with VSCode keybindigs
|
|
14
15
|
|
|
15
16
|
`riched` is a TUI editor powered by the [Rich](https://github.com/Textualize/rich) package and the [Textual](https://github.com/Textualize/textual) framework, the name is a nod to Rich.
|
|
16
17
|
|
|
@@ -32,6 +33,7 @@ Description-Content-Type: text/markdown
|
|
|
32
33
|
```sh
|
|
33
34
|
uv tool install riched
|
|
34
35
|
riched .
|
|
36
|
+
riched --version
|
|
35
37
|
```
|
|
36
38
|
|
|
37
39
|
## Dev
|
|
@@ -53,7 +55,7 @@ App shortcuts:
|
|
|
53
55
|
|
|
54
56
|
| Shortcut | Action |
|
|
55
57
|
| --- | --- |
|
|
56
|
-
|
|
|
58
|
+
| `⌘S` | Save |
|
|
57
59
|
| `⌃Q` | Quit |
|
|
58
60
|
| `⌃W` | Close buffer |
|
|
59
61
|
| `F1` | Key bindings |
|
|
@@ -89,6 +91,13 @@ config directory: `~/Library/Application Support/riched/settings.yaml`
|
|
|
89
91
|
- File search prefers git-indexed files when available, follows symlinked files and directories, skips cache/build dependency folders, and caps indexing at 10,000 files.
|
|
90
92
|
- Fuzzy ranking now prioritizes exact path and filename matches such as `.zshrc`.
|
|
91
93
|
|
|
92
|
-
##
|
|
94
|
+
## Limitations
|
|
93
95
|
|
|
94
|
-
`riched`
|
|
96
|
+
- `riched` does not support multi-cursor editing because Textual `TextArea`
|
|
97
|
+
currently models one active cursor/selection.
|
|
98
|
+
- Some Command-key shortcuts can conflict with Ghostty or terminal-level
|
|
99
|
+
bindings, for example `⌘⇧P`, `⌘W`, and `⌘Q`.
|
|
100
|
+
- `riched` will not implement key bindings that require users to modify the
|
|
101
|
+
Ghostty terminal configuration, since terminal-specific configuration makes
|
|
102
|
+
shortcuts harder to document, test, and support consistently across
|
|
103
|
+
environments.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Riched
|
|
2
2
|
|
|
3
|
-
> TUI editor
|
|
3
|
+
> TUI editor with VSCode keybindigs
|
|
4
4
|
|
|
5
5
|
`riched` is a TUI editor powered by the [Rich](https://github.com/Textualize/rich) package and the [Textual](https://github.com/Textualize/textual) framework, the name is a nod to Rich.
|
|
6
6
|
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
```sh
|
|
23
23
|
uv tool install riched
|
|
24
24
|
riched .
|
|
25
|
+
riched --version
|
|
25
26
|
```
|
|
26
27
|
|
|
27
28
|
## Dev
|
|
@@ -43,7 +44,7 @@ App shortcuts:
|
|
|
43
44
|
|
|
44
45
|
| Shortcut | Action |
|
|
45
46
|
| --- | --- |
|
|
46
|
-
|
|
|
47
|
+
| `⌘S` | Save |
|
|
47
48
|
| `⌃Q` | Quit |
|
|
48
49
|
| `⌃W` | Close buffer |
|
|
49
50
|
| `F1` | Key bindings |
|
|
@@ -79,6 +80,13 @@ config directory: `~/Library/Application Support/riched/settings.yaml`
|
|
|
79
80
|
- File search prefers git-indexed files when available, follows symlinked files and directories, skips cache/build dependency folders, and caps indexing at 10,000 files.
|
|
80
81
|
- Fuzzy ranking now prioritizes exact path and filename matches such as `.zshrc`.
|
|
81
82
|
|
|
82
|
-
##
|
|
83
|
+
## Limitations
|
|
83
84
|
|
|
84
|
-
`riched`
|
|
85
|
+
- `riched` does not support multi-cursor editing because Textual `TextArea`
|
|
86
|
+
currently models one active cursor/selection.
|
|
87
|
+
- Some Command-key shortcuts can conflict with Ghostty or terminal-level
|
|
88
|
+
bindings, for example `⌘⇧P`, `⌘W`, and `⌘Q`.
|
|
89
|
+
- `riched` will not implement key bindings that require users to modify the
|
|
90
|
+
Ghostty terminal configuration, since terminal-specific configuration makes
|
|
91
|
+
shortcuts harder to document, test, and support consistently across
|
|
92
|
+
environments.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "riched"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.3.0"
|
|
4
4
|
description = "TUI editor with VSCode keybindigs"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.12"
|
|
@@ -10,6 +10,9 @@ dependencies = [
|
|
|
10
10
|
"tree-sitter-typescript>=0.23.2",
|
|
11
11
|
]
|
|
12
12
|
|
|
13
|
+
[project.urls]
|
|
14
|
+
Repository = "https://github.com/hoishing/riched"
|
|
15
|
+
|
|
13
16
|
[project.scripts]
|
|
14
17
|
riched = "riched.cli:main"
|
|
15
18
|
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
from importlib.metadata import version
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
from .app import RichedApp
|
|
8
|
+
from .keybindings import build_bindings
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def main() -> int:
|
|
12
|
+
parser = argparse.ArgumentParser(
|
|
13
|
+
prog="riched", description="A minimal Textual TUI text editor."
|
|
14
|
+
)
|
|
15
|
+
parser.add_argument(
|
|
16
|
+
"--version",
|
|
17
|
+
action="store_true",
|
|
18
|
+
help="Show the version and exit",
|
|
19
|
+
)
|
|
20
|
+
parser.add_argument("filename", nargs="?", help="File to open (created on save if missing)")
|
|
21
|
+
args = parser.parse_args()
|
|
22
|
+
|
|
23
|
+
if args.version:
|
|
24
|
+
if args.filename is not None:
|
|
25
|
+
parser.error("riched --version does not take arguments")
|
|
26
|
+
print(f"riched {version('riched')}")
|
|
27
|
+
return 0
|
|
28
|
+
|
|
29
|
+
if args.filename is None:
|
|
30
|
+
parser.error("the following arguments are required: filename")
|
|
31
|
+
|
|
32
|
+
path = Path(args.filename).expanduser()
|
|
33
|
+
root = path if path.is_dir() else Path.cwd()
|
|
34
|
+
|
|
35
|
+
class ConfiguredRichedApp(RichedApp):
|
|
36
|
+
BINDINGS = build_bindings()
|
|
37
|
+
|
|
38
|
+
ConfiguredRichedApp(path, root).run()
|
|
39
|
+
return 0
|
|
@@ -8,6 +8,7 @@ from .test_command_palette import (
|
|
|
8
8
|
test_command_palette_button_is_hidden,
|
|
9
9
|
test_command_palette_omits_maximize,
|
|
10
10
|
)
|
|
11
|
+
from .test_cli import test_version_flag_prints_current_version, test_version_flag_rejects_filename
|
|
11
12
|
from .test_dirty_buffers import (
|
|
12
13
|
test_close_buffer_clean_enters_no_buffer_state_via_ctrl_w,
|
|
13
14
|
test_close_buffer_dirty_shows_wide_modal_then_cancel,
|
|
@@ -72,6 +73,8 @@ TESTS: list[tuple[str, Callable[[], Awaitable[None]]]] = [
|
|
|
72
73
|
("open missing file", test_open_missing_file),
|
|
73
74
|
("open directory starts with no buffer", test_open_directory_starts_with_no_buffer),
|
|
74
75
|
("save writes file", test_save_writes_file),
|
|
76
|
+
("cli: version flag prints current version", test_version_flag_prints_current_version),
|
|
77
|
+
("cli: version flag rejects filename", test_version_flag_rejects_filename),
|
|
75
78
|
("command palette: button hidden", test_command_palette_button_is_hidden),
|
|
76
79
|
("command palette: omit maximize", test_command_palette_omits_maximize),
|
|
77
80
|
("quit clean exits", test_quit_clean_exits),
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import subprocess
|
|
4
|
+
import sys
|
|
5
|
+
from importlib.metadata import version
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
async def test_version_flag_prints_current_version() -> None:
|
|
9
|
+
result = subprocess.run(
|
|
10
|
+
[
|
|
11
|
+
sys.executable,
|
|
12
|
+
"-c",
|
|
13
|
+
"from riched.cli import main; raise SystemExit(main())",
|
|
14
|
+
"--version",
|
|
15
|
+
],
|
|
16
|
+
check=False,
|
|
17
|
+
capture_output=True,
|
|
18
|
+
text=True,
|
|
19
|
+
)
|
|
20
|
+
assert result.returncode == 0, result.stderr
|
|
21
|
+
assert result.stdout == f"riched {version('riched')}\n", result.stdout
|
|
22
|
+
assert result.stderr == "", result.stderr
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
async def test_version_flag_rejects_filename() -> None:
|
|
26
|
+
result = subprocess.run(
|
|
27
|
+
[
|
|
28
|
+
sys.executable,
|
|
29
|
+
"-c",
|
|
30
|
+
"from riched.cli import main; raise SystemExit(main())",
|
|
31
|
+
"--version",
|
|
32
|
+
"notes.txt",
|
|
33
|
+
],
|
|
34
|
+
check=False,
|
|
35
|
+
capture_output=True,
|
|
36
|
+
text=True,
|
|
37
|
+
)
|
|
38
|
+
assert result.returncode == 2, result.stdout
|
|
39
|
+
assert result.stdout == "", result.stdout
|
|
40
|
+
assert "riched --version does not take arguments" in result.stderr, result.stderr
|
|
@@ -58,7 +58,6 @@ async def test_save_writes_file() -> None:
|
|
|
58
58
|
await pilot.pause()
|
|
59
59
|
app.query_one("#editor", TextArea).load_text("typed content")
|
|
60
60
|
await pilot.pause()
|
|
61
|
-
await pilot.press("
|
|
61
|
+
await pilot.press("cmd+s")
|
|
62
62
|
await pilot.pause()
|
|
63
63
|
assert f.read_text() == "typed content"
|
|
64
|
-
|
|
@@ -18,7 +18,7 @@ async def test_footer_uses_macos_modifier_symbols() -> None:
|
|
|
18
18
|
for child in footer.children
|
|
19
19
|
if hasattr(child, "key_display")
|
|
20
20
|
}
|
|
21
|
-
assert labels["Save"] == "
|
|
21
|
+
assert labels["Save"] == "⌘S"
|
|
22
22
|
assert labels["Close buffer"] == "⌃W"
|
|
23
23
|
assert labels["Toggle file tree"] == "⌘B"
|
|
24
24
|
assert labels["Quick open"] == "⌘P"
|
riched-0.2.1/src/riched/cli.py
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import argparse
|
|
4
|
-
from pathlib import Path
|
|
5
|
-
|
|
6
|
-
from .app import RichedApp
|
|
7
|
-
from .keybindings import build_bindings
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
def main() -> int:
|
|
11
|
-
parser = argparse.ArgumentParser(
|
|
12
|
-
prog="riched", description="A minimal Textual TUI text editor."
|
|
13
|
-
)
|
|
14
|
-
parser.add_argument("filename", help="File to open (created on save if missing)")
|
|
15
|
-
args = parser.parse_args()
|
|
16
|
-
|
|
17
|
-
path = Path(args.filename).expanduser()
|
|
18
|
-
root = path if path.is_dir() else Path.cwd()
|
|
19
|
-
|
|
20
|
-
class ConfiguredRichedApp(RichedApp):
|
|
21
|
-
BINDINGS = build_bindings()
|
|
22
|
-
|
|
23
|
-
ConfiguredRichedApp(path, root).run()
|
|
24
|
-
return 0
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|