riched 1.6.3__tar.gz → 1.7.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-1.6.3 → riched-1.7.0}/PKG-INFO +18 -14
- {riched-1.6.3 → riched-1.7.0}/README.md +17 -13
- {riched-1.6.3 → riched-1.7.0}/pyproject.toml +1 -1
- {riched-1.6.3 → riched-1.7.0}/src/rich_editor/app.py +21 -0
- {riched-1.6.3 → riched-1.7.0}/src/rich_editor/bindings.yaml +3 -2
- {riched-1.6.3 → riched-1.7.0}/src/rich_editor/editor.py +7 -0
- {riched-1.6.3 → riched-1.7.0}/tests/test_markdown_preview.py +29 -4
- riched-1.7.0/tests/test_select_to_copy.py +128 -0
- {riched-1.6.3 → riched-1.7.0}/uv.lock +1 -1
- {riched-1.6.3 → riched-1.7.0}/.gitignore +0 -0
- {riched-1.6.3 → riched-1.7.0}/.python-version +0 -0
- {riched-1.6.3 → riched-1.7.0}/AGENTS.md +0 -0
- {riched-1.6.3 → riched-1.7.0}/docs/command-palette.svg +0 -0
- {riched-1.6.3 → riched-1.7.0}/docs/markdown-preview.svg +0 -0
- {riched-1.6.3 → riched-1.7.0}/docs/python-buffer.svg +0 -0
- {riched-1.6.3 → riched-1.7.0}/docs/search-replace.svg +0 -0
- {riched-1.6.3 → riched-1.7.0}/plans/esc-unified-sidebar-escape.md +0 -0
- {riched-1.6.3 → riched-1.7.0}/src/rich_editor/__init__.py +0 -0
- {riched-1.6.3 → riched-1.7.0}/src/rich_editor/cli.py +0 -0
- {riched-1.6.3 → riched-1.7.0}/src/rich_editor/formatting.py +0 -0
- {riched-1.6.3 → riched-1.7.0}/src/rich_editor/keybindings.py +0 -0
- {riched-1.6.3 → riched-1.7.0}/src/rich_editor/quick_open.py +0 -0
- {riched-1.6.3 → riched-1.7.0}/src/rich_editor/screens.py +0 -0
- {riched-1.6.3 → riched-1.7.0}/src/rich_editor/settings.py +0 -0
- {riched-1.6.3 → riched-1.7.0}/src/rich_editor/syntax.py +0 -0
- {riched-1.6.3 → riched-1.7.0}/tests/__init__.py +0 -0
- {riched-1.6.3 → riched-1.7.0}/tests/helpers.py +0 -0
- {riched-1.6.3 → riched-1.7.0}/tests/runner.py +0 -0
- {riched-1.6.3 → riched-1.7.0}/tests/test_cli.py +0 -0
- {riched-1.6.3 → riched-1.7.0}/tests/test_command_palette.py +0 -0
- {riched-1.6.3 → riched-1.7.0}/tests/test_create_file.py +0 -0
- {riched-1.6.3 → riched-1.7.0}/tests/test_dirty_buffers.py +0 -0
- {riched-1.6.3 → riched-1.7.0}/tests/test_editor_shortcuts.py +0 -0
- {riched-1.6.3 → riched-1.7.0}/tests/test_file_io.py +0 -0
- {riched-1.6.3 → riched-1.7.0}/tests/test_footer.py +0 -0
- {riched-1.6.3 → riched-1.7.0}/tests/test_formatting.py +0 -0
- {riched-1.6.3 → riched-1.7.0}/tests/test_quick_open.py +0 -0
- {riched-1.6.3 → riched-1.7.0}/tests/test_refresh.py +0 -0
- {riched-1.6.3 → riched-1.7.0}/tests/test_replace.py +0 -0
- {riched-1.6.3 → riched-1.7.0}/tests/test_sidebar.py +0 -0
- {riched-1.6.3 → riched-1.7.0}/tests/test_syntax.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: riched
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.7.0
|
|
4
4
|
Summary: Terminal Editor with VS Code Keybindings
|
|
5
5
|
Project-URL: Repository, https://github.com/hoishing/riched
|
|
6
6
|
Requires-Python: >=3.12
|
|
@@ -56,6 +56,7 @@ Terminal Editor with VS Code Keybindings Powered by [Rich](https://github.com/Te
|
|
|
56
56
|
- project sidebar with create, rename, quick refresh, and move-to-trash support
|
|
57
57
|
- quick file open with fuzzy search
|
|
58
58
|
- in-terminal Markdown preview with table of contents toggle
|
|
59
|
+
- mouse select-to-copy in the source editor and Markdown preview
|
|
59
60
|
- document formatting through external formatter CLIs
|
|
60
61
|
- multiple built-in theme(atom, drcula, nordic ...etc)
|
|
61
62
|
- syntax highlighting for major file formats with manual file type override
|
|
@@ -82,17 +83,17 @@ Key bindings are generated from the YAML in `src/rich_editor/bindings.yaml`.
|
|
|
82
83
|
|
|
83
84
|
App shortcuts:
|
|
84
85
|
|
|
85
|
-
| Shortcut
|
|
86
|
-
|
|
|
87
|
-
| `⌘S`
|
|
88
|
-
| `F1`
|
|
89
|
-
| `⌘B` / `⌃B`
|
|
90
|
-
| `⌘P`
|
|
91
|
-
| `⌃H`
|
|
92
|
-
| `⌃N`
|
|
93
|
-
| `⌃⇧V`
|
|
94
|
-
| `⌥⇧F`
|
|
95
|
-
| `⌘R`
|
|
86
|
+
| Shortcut | Action |
|
|
87
|
+
| ------------- | ----------------------- |
|
|
88
|
+
| `⌘S` | Save |
|
|
89
|
+
| `F1` | Command palette |
|
|
90
|
+
| `⌘B` / `⌃B` | Toggle sidebar |
|
|
91
|
+
| `⌘P` | Quick open |
|
|
92
|
+
| `⌃H` | Replace |
|
|
93
|
+
| `⌃N` | Create file |
|
|
94
|
+
| `⌘⇧V` / `⌃⇧V` | Toggle Markdown preview |
|
|
95
|
+
| `⌥⇧F` | Format document |
|
|
96
|
+
| `⌘R` | Refresh |
|
|
96
97
|
|
|
97
98
|
Editor shortcuts:
|
|
98
99
|
|
|
@@ -137,7 +138,9 @@ Riched persists the selected Textual theme in `settings.yaml` under the user con
|
|
|
137
138
|
|
|
138
139
|
## Markdown Preview
|
|
139
140
|
|
|
140
|
-
Use `⌃⇧V
|
|
141
|
+
Use `⌘⇧V` (`⌃⇧V` if Ghostty still owns `⌘⇧V`), the `Preview` button in the footer, or `F1` → `Toggle Markdown preview` to toggle an in-terminal rendered preview for Markdown files. The preview uses the current editor buffer, so unsaved edits are shown without writing them to disk.
|
|
142
|
+
|
|
143
|
+
Drag to select text in the preview to copy the rendered text to the clipboard. The same select-to-copy behavior works in the source editor.
|
|
141
144
|
|
|
142
145
|
When Markdown preview is open, the header shows a `☰` button on the right. Click it to show or hide the Markdown table of contents. The button is hidden while editing the text buffer.
|
|
143
146
|
|
|
@@ -201,7 +204,7 @@ On stock Ghostty, `⌘⌫` is delivered to terminal apps as `⌃U`, so Riched bi
|
|
|
201
204
|
|
|
202
205
|
### Ghostty hotkey conflicts
|
|
203
206
|
|
|
204
|
-
- some hotkeys are bound by Ghostty by default. eg. `⌘Z`, `⌘⇧Z`, `⌘Enter`, `⌘⇧Enter`, `⌘[`, `⌘]`, `⌘W`, `⌘Q`...etc
|
|
207
|
+
- some hotkeys are bound by Ghostty by default. eg. `⌘Z`, `⌘⇧Z`, `⌘⇧V`, `⌘Enter`, `⌘⇧Enter`, `⌘[`, `⌘]`, `⌘W`, `⌘Q`...etc
|
|
205
208
|
- Riched detects conflicted shortcuts at startup.
|
|
206
209
|
- Conflicted shortcuts are hidden from the footer until they are unbound in Ghostty config, unless the command has another available alternative.
|
|
207
210
|
- The key bindings popup marks conflicted shortcuts with `⚠️` and shows a Ghostty config reminder.
|
|
@@ -225,6 +228,7 @@ keybind = super+enter=unbind
|
|
|
225
228
|
keybind = super+shift+enter=unbind
|
|
226
229
|
keybind = super+z=unbind
|
|
227
230
|
keybind = super+shift+z=unbind
|
|
231
|
+
keybind = super+shift+v=unbind
|
|
228
232
|
```
|
|
229
233
|
|
|
230
234
|
Then reload Ghostty config with `⌘⇧,` or restart Ghostty. To inspect Ghostty's defaults before changing them:
|
|
@@ -41,6 +41,7 @@ Terminal Editor with VS Code Keybindings Powered by [Rich](https://github.com/Te
|
|
|
41
41
|
- project sidebar with create, rename, quick refresh, and move-to-trash support
|
|
42
42
|
- quick file open with fuzzy search
|
|
43
43
|
- in-terminal Markdown preview with table of contents toggle
|
|
44
|
+
- mouse select-to-copy in the source editor and Markdown preview
|
|
44
45
|
- document formatting through external formatter CLIs
|
|
45
46
|
- multiple built-in theme(atom, drcula, nordic ...etc)
|
|
46
47
|
- syntax highlighting for major file formats with manual file type override
|
|
@@ -67,17 +68,17 @@ Key bindings are generated from the YAML in `src/rich_editor/bindings.yaml`.
|
|
|
67
68
|
|
|
68
69
|
App shortcuts:
|
|
69
70
|
|
|
70
|
-
| Shortcut
|
|
71
|
-
|
|
|
72
|
-
| `⌘S`
|
|
73
|
-
| `F1`
|
|
74
|
-
| `⌘B` / `⌃B`
|
|
75
|
-
| `⌘P`
|
|
76
|
-
| `⌃H`
|
|
77
|
-
| `⌃N`
|
|
78
|
-
| `⌃⇧V`
|
|
79
|
-
| `⌥⇧F`
|
|
80
|
-
| `⌘R`
|
|
71
|
+
| Shortcut | Action |
|
|
72
|
+
| ------------- | ----------------------- |
|
|
73
|
+
| `⌘S` | Save |
|
|
74
|
+
| `F1` | Command palette |
|
|
75
|
+
| `⌘B` / `⌃B` | Toggle sidebar |
|
|
76
|
+
| `⌘P` | Quick open |
|
|
77
|
+
| `⌃H` | Replace |
|
|
78
|
+
| `⌃N` | Create file |
|
|
79
|
+
| `⌘⇧V` / `⌃⇧V` | Toggle Markdown preview |
|
|
80
|
+
| `⌥⇧F` | Format document |
|
|
81
|
+
| `⌘R` | Refresh |
|
|
81
82
|
|
|
82
83
|
Editor shortcuts:
|
|
83
84
|
|
|
@@ -122,7 +123,9 @@ Riched persists the selected Textual theme in `settings.yaml` under the user con
|
|
|
122
123
|
|
|
123
124
|
## Markdown Preview
|
|
124
125
|
|
|
125
|
-
Use `⌃⇧V
|
|
126
|
+
Use `⌘⇧V` (`⌃⇧V` if Ghostty still owns `⌘⇧V`), the `Preview` button in the footer, or `F1` → `Toggle Markdown preview` to toggle an in-terminal rendered preview for Markdown files. The preview uses the current editor buffer, so unsaved edits are shown without writing them to disk.
|
|
127
|
+
|
|
128
|
+
Drag to select text in the preview to copy the rendered text to the clipboard. The same select-to-copy behavior works in the source editor.
|
|
126
129
|
|
|
127
130
|
When Markdown preview is open, the header shows a `☰` button on the right. Click it to show or hide the Markdown table of contents. The button is hidden while editing the text buffer.
|
|
128
131
|
|
|
@@ -186,7 +189,7 @@ On stock Ghostty, `⌘⌫` is delivered to terminal apps as `⌃U`, so Riched bi
|
|
|
186
189
|
|
|
187
190
|
### Ghostty hotkey conflicts
|
|
188
191
|
|
|
189
|
-
- some hotkeys are bound by Ghostty by default. eg. `⌘Z`, `⌘⇧Z`, `⌘Enter`, `⌘⇧Enter`, `⌘[`, `⌘]`, `⌘W`, `⌘Q`...etc
|
|
192
|
+
- some hotkeys are bound by Ghostty by default. eg. `⌘Z`, `⌘⇧Z`, `⌘⇧V`, `⌘Enter`, `⌘⇧Enter`, `⌘[`, `⌘]`, `⌘W`, `⌘Q`...etc
|
|
190
193
|
- Riched detects conflicted shortcuts at startup.
|
|
191
194
|
- Conflicted shortcuts are hidden from the footer until they are unbound in Ghostty config, unless the command has another available alternative.
|
|
192
195
|
- The key bindings popup marks conflicted shortcuts with `⚠️` and shows a Ghostty config reminder.
|
|
@@ -210,6 +213,7 @@ keybind = super+enter=unbind
|
|
|
210
213
|
keybind = super+shift+enter=unbind
|
|
211
214
|
keybind = super+z=unbind
|
|
212
215
|
keybind = super+shift+z=unbind
|
|
216
|
+
keybind = super+shift+v=unbind
|
|
213
217
|
```
|
|
214
218
|
|
|
215
219
|
Then reload Ghostty config with `⌘⇧,` or restart Ghostty. To inspect Ghostty's defaults before changing them:
|
|
@@ -669,6 +669,27 @@ class RichedApp(App):
|
|
|
669
669
|
previews = list(self.query("#markdown-preview"))
|
|
670
670
|
return previews[0] if previews else None
|
|
671
671
|
|
|
672
|
+
def _copy_preview_selection(self) -> None:
|
|
673
|
+
preview = self._markdown_preview_or_none()
|
|
674
|
+
if preview is None:
|
|
675
|
+
return
|
|
676
|
+
selected = self.screen.get_selected_text()
|
|
677
|
+
if not selected:
|
|
678
|
+
return
|
|
679
|
+
in_preview = any(
|
|
680
|
+
preview in widget.ancestors_with_self for widget in self.screen.selections
|
|
681
|
+
)
|
|
682
|
+
if not in_preview:
|
|
683
|
+
return
|
|
684
|
+
self.copy_to_clipboard(selected)
|
|
685
|
+
|
|
686
|
+
def on_text_selected(self, event: events.TextSelected) -> None:
|
|
687
|
+
self._copy_preview_selection()
|
|
688
|
+
|
|
689
|
+
def on_click(self, event: events.Click) -> None:
|
|
690
|
+
if event.chain >= 2:
|
|
691
|
+
self._copy_preview_selection()
|
|
692
|
+
|
|
672
693
|
def _sidebar(self) -> DirectoryTree:
|
|
673
694
|
return self.query_one("#sidebar", DirectoryTree)
|
|
674
695
|
|
|
@@ -33,9 +33,10 @@ app:
|
|
|
33
33
|
preferred_key: ctrl+n
|
|
34
34
|
- name: toggle_markdown_preview
|
|
35
35
|
description: Toggle Markdown preview
|
|
36
|
-
key: ctrl+shift+v,shift+ctrl+v,ctrl+V,alt+shift+v,shift+alt+v,alt+shift+V,shift+alt+V,alt+v
|
|
37
|
-
preferred_key:
|
|
36
|
+
key: cmd+shift+v,shift+cmd+v,super+shift+v,shift+super+v,cmd+V,shift+cmd+V,super+V,shift+super+V,cmd+shift+V,super+shift+V,ctrl+shift+v,shift+ctrl+v,ctrl+V,alt+shift+v,shift+alt+v,alt+shift+V,shift+alt+V,alt+v
|
|
37
|
+
preferred_key: cmd+shift+v,shift+cmd+v,super+shift+v,shift+super+v
|
|
38
38
|
display_keys:
|
|
39
|
+
- cmd+shift+v
|
|
39
40
|
- ctrl+shift+v
|
|
40
41
|
- name: format_document
|
|
41
42
|
description: Format document
|
|
@@ -53,8 +53,15 @@ class _FormattingApp(Protocol):
|
|
|
53
53
|
class RichedTextArea(TextArea):
|
|
54
54
|
"""TextArea with VS Code-style line-edit shortcuts."""
|
|
55
55
|
|
|
56
|
+
ALLOW_SELECT = False
|
|
56
57
|
BINDINGS = build_static_bindings("editor")
|
|
57
58
|
|
|
59
|
+
def _end_mouse_selection(self) -> None:
|
|
60
|
+
was_selecting = self._selecting
|
|
61
|
+
super()._end_mouse_selection()
|
|
62
|
+
if was_selecting and self.selected_text:
|
|
63
|
+
self.app.copy_to_clipboard(self.selected_text)
|
|
64
|
+
|
|
58
65
|
async def _on_key(self, event: events.Key) -> None:
|
|
59
66
|
if event.key == "escape":
|
|
60
67
|
from .app import RichedApp
|
|
@@ -2,7 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from textual.widgets import DirectoryTree, Markdown, MarkdownViewer, Static
|
|
4
4
|
|
|
5
|
-
from .helpers import _editor, _file_app, _key_help_rows, _press
|
|
5
|
+
from .helpers import _directory_app, _editor, _file_app, _key_help_rows, _press
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
async def test_markdown_preview_toggles_from_primary_key() -> None:
|
|
@@ -27,8 +27,19 @@ async def test_markdown_preview_toggles_from_primary_key() -> None:
|
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
async def test_markdown_preview_opens_from_alias_keys() -> None:
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
keys = (
|
|
31
|
+
"cmd+shift+v",
|
|
32
|
+
"shift+cmd+v",
|
|
33
|
+
"super+shift+v",
|
|
34
|
+
"shift+super+v",
|
|
35
|
+
"cmd+V",
|
|
36
|
+
"super+V",
|
|
37
|
+
"ctrl+shift+v",
|
|
38
|
+
"shift+ctrl+v",
|
|
39
|
+
"ctrl+V",
|
|
40
|
+
)
|
|
41
|
+
for key in keys:
|
|
42
|
+
_, _, app = _file_app("README.md", "# Title", root_is_tmp=True, edit_mode=True)
|
|
32
43
|
async with app.run_test() as pilot:
|
|
33
44
|
await pilot.pause()
|
|
34
45
|
await _press(pilot, key)
|
|
@@ -85,6 +96,20 @@ async def test_markdown_preview_toc_button_only_shows_for_preview() -> None:
|
|
|
85
96
|
assert toc_button.styles.display == "none"
|
|
86
97
|
|
|
87
98
|
|
|
99
|
+
async def test_markdown_preview_hotkeys_warn_without_open_buffer() -> None:
|
|
100
|
+
for key in ("cmd+shift+v", "super+shift+v", "ctrl+shift+v"):
|
|
101
|
+
_, app = _directory_app()
|
|
102
|
+
notifications: list[tuple[str, str | None]] = []
|
|
103
|
+
app.notify = lambda message, **kwargs: notifications.append(
|
|
104
|
+
(str(message), kwargs.get("severity"))
|
|
105
|
+
)
|
|
106
|
+
async with app.run_test() as pilot:
|
|
107
|
+
await pilot.pause()
|
|
108
|
+
await _press(pilot, key)
|
|
109
|
+
assert not list(app.query("#markdown-preview")), key
|
|
110
|
+
assert notifications == [("No file open", "warning")], key
|
|
111
|
+
|
|
112
|
+
|
|
88
113
|
async def test_cmd_shift_v_warns_for_non_markdown_file() -> None:
|
|
89
114
|
_, _, app = _file_app("notes.txt", "# Plain text", root_is_tmp=True)
|
|
90
115
|
notifications: list[tuple[str, str | None]] = []
|
|
@@ -205,5 +230,5 @@ async def test_keys_help_warns_for_ghostty_conflicted_markdown_preview() -> None
|
|
|
205
230
|
assert ("⚠️ ⌘⇧V / ⌃⇧V", "Toggle Markdown preview") in rows
|
|
206
231
|
assert (
|
|
207
232
|
app.screen.query_one(".binding-legend", Static).content
|
|
208
|
-
== "⚠️ Unbind this shortcut in
|
|
233
|
+
== "⚠️ Unbind this shortcut in your terminal config to use it in Riched."
|
|
209
234
|
)
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from textual.widgets import MarkdownViewer, TextArea
|
|
4
|
+
from textual.widgets.markdown import MarkdownBlock
|
|
5
|
+
|
|
6
|
+
from .helpers import _editor, _file_app, _press
|
|
7
|
+
|
|
8
|
+
SENTINEL = "__clipboard_sentinel__"
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def _editor_content_offset(
|
|
12
|
+
editor: TextArea, column: int, row: int = 0
|
|
13
|
+
) -> tuple[int, int]:
|
|
14
|
+
return (
|
|
15
|
+
editor.gutter.left + editor.gutter_width + column,
|
|
16
|
+
editor.gutter.top + row,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
async def _drag(pilot, widget, start: tuple[int, int], end: tuple[int, int]) -> None:
|
|
21
|
+
await pilot.mouse_down(widget, offset=start)
|
|
22
|
+
await pilot.pause()
|
|
23
|
+
await pilot.hover(widget, offset=end)
|
|
24
|
+
await pilot.pause()
|
|
25
|
+
await pilot.mouse_up(widget, offset=end)
|
|
26
|
+
await pilot.pause()
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
async def test_editor_mouse_select_copies_source_text() -> None:
|
|
30
|
+
_, _, app = _file_app("hello.txt", "hello world")
|
|
31
|
+
async with app.run_test() as pilot:
|
|
32
|
+
await pilot.pause()
|
|
33
|
+
editor = _editor(app)
|
|
34
|
+
app.copy_to_clipboard(SENTINEL)
|
|
35
|
+
|
|
36
|
+
await _drag(
|
|
37
|
+
pilot,
|
|
38
|
+
editor,
|
|
39
|
+
_editor_content_offset(editor, 0),
|
|
40
|
+
_editor_content_offset(editor, 5),
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
assert editor.selected_text == "hello", repr(editor.selected_text)
|
|
44
|
+
assert app.clipboard == "hello", repr(app.clipboard)
|
|
45
|
+
assert "1" not in app.clipboard
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
async def test_editor_click_without_drag_does_not_copy() -> None:
|
|
49
|
+
_, _, app = _file_app("hello.txt", "hello world")
|
|
50
|
+
async with app.run_test() as pilot:
|
|
51
|
+
await pilot.pause()
|
|
52
|
+
editor = _editor(app)
|
|
53
|
+
app.copy_to_clipboard(SENTINEL)
|
|
54
|
+
offset = _editor_content_offset(editor, 0)
|
|
55
|
+
|
|
56
|
+
await pilot.mouse_down(editor, offset=offset)
|
|
57
|
+
await pilot.pause()
|
|
58
|
+
await pilot.mouse_up(editor, offset=offset)
|
|
59
|
+
await pilot.pause()
|
|
60
|
+
|
|
61
|
+
assert editor.selection.is_empty
|
|
62
|
+
assert app.clipboard == SENTINEL, repr(app.clipboard)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
async def test_editor_keyboard_selection_does_not_copy() -> None:
|
|
66
|
+
_, _, app = _file_app("hello.txt", "hello world")
|
|
67
|
+
async with app.run_test() as pilot:
|
|
68
|
+
await pilot.pause()
|
|
69
|
+
editor = _editor(app)
|
|
70
|
+
app.copy_to_clipboard(SENTINEL)
|
|
71
|
+
editor.move_cursor((0, 0))
|
|
72
|
+
await pilot.pause()
|
|
73
|
+
|
|
74
|
+
await _press(pilot, "shift+right")
|
|
75
|
+
|
|
76
|
+
assert editor.selected_text == "h", repr(editor.selected_text)
|
|
77
|
+
assert app.clipboard == SENTINEL, repr(app.clipboard)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
async def test_markdown_preview_mouse_select_copies_rendered_text() -> None:
|
|
81
|
+
_, _, app = _file_app(
|
|
82
|
+
"README.md",
|
|
83
|
+
"# Heading\n\ncopy-me-please\n",
|
|
84
|
+
root_is_tmp=True,
|
|
85
|
+
edit_mode=True,
|
|
86
|
+
)
|
|
87
|
+
async with app.run_test() as pilot:
|
|
88
|
+
await pilot.pause()
|
|
89
|
+
await _press(pilot, "cmd+shift+v")
|
|
90
|
+
preview = app.query_one("#markdown-preview", MarkdownViewer)
|
|
91
|
+
paragraph = next(
|
|
92
|
+
block
|
|
93
|
+
for block in preview.document.query(MarkdownBlock)
|
|
94
|
+
if (block.source or "").find("copy-me-please") >= 0
|
|
95
|
+
)
|
|
96
|
+
app.copy_to_clipboard(SENTINEL)
|
|
97
|
+
|
|
98
|
+
await _drag(pilot, paragraph, (0, 0), (max(1, paragraph.size.width - 1), 0))
|
|
99
|
+
|
|
100
|
+
assert "copy-me-please" in app.clipboard, repr(app.clipboard)
|
|
101
|
+
assert "# Heading" not in app.clipboard
|
|
102
|
+
assert SENTINEL not in app.clipboard
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
async def test_markdown_preview_click_without_drag_does_not_copy() -> None:
|
|
106
|
+
_, _, app = _file_app(
|
|
107
|
+
"README.md",
|
|
108
|
+
"# Heading\n\ncopy-me-please\n",
|
|
109
|
+
root_is_tmp=True,
|
|
110
|
+
edit_mode=True,
|
|
111
|
+
)
|
|
112
|
+
async with app.run_test() as pilot:
|
|
113
|
+
await pilot.pause()
|
|
114
|
+
await _press(pilot, "cmd+shift+v")
|
|
115
|
+
preview = app.query_one("#markdown-preview", MarkdownViewer)
|
|
116
|
+
paragraph = next(
|
|
117
|
+
block
|
|
118
|
+
for block in preview.document.query(MarkdownBlock)
|
|
119
|
+
if (block.source or "").find("copy-me-please") >= 0
|
|
120
|
+
)
|
|
121
|
+
app.copy_to_clipboard(SENTINEL)
|
|
122
|
+
|
|
123
|
+
await pilot.mouse_down(paragraph, offset=(0, 0))
|
|
124
|
+
await pilot.pause()
|
|
125
|
+
await pilot.mouse_up(paragraph, offset=(0, 0))
|
|
126
|
+
await pilot.pause()
|
|
127
|
+
|
|
128
|
+
assert app.clipboard == SENTINEL, repr(app.clipboard)
|
|
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
|
|
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
|