euporie 2.8.4__py3-none-any.whl → 2.8.6__py3-none-any.whl
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.
- euporie/console/_commands.py +143 -0
- euporie/console/_settings.py +58 -0
- euporie/console/app.py +25 -71
- euporie/console/tabs/console.py +58 -62
- euporie/core/__init__.py +1 -1
- euporie/core/__main__.py +28 -11
- euporie/core/_settings.py +109 -0
- euporie/core/app/__init__.py +3 -0
- euporie/core/app/_commands.py +95 -0
- euporie/core/app/_settings.py +457 -0
- euporie/core/{app.py → app/app.py} +212 -576
- euporie/core/app/base.py +51 -0
- euporie/core/{current.py → app/current.py} +13 -4
- euporie/core/app/cursor.py +35 -0
- euporie/core/app/dummy.py +12 -0
- euporie/core/app/launch.py +28 -0
- euporie/core/bars/__init__.py +11 -0
- euporie/core/bars/command.py +205 -0
- euporie/core/bars/menu.py +258 -0
- euporie/core/{widgets → bars}/search.py +20 -16
- euporie/core/{widgets → bars}/status.py +6 -23
- euporie/core/clipboard.py +19 -80
- euporie/core/comm/base.py +8 -6
- euporie/core/comm/ipywidgets.py +16 -7
- euporie/core/comm/registry.py +2 -1
- euporie/core/commands.py +10 -20
- euporie/core/completion.py +3 -2
- euporie/core/config.py +368 -341
- euporie/core/convert/__init__.py +0 -30
- euporie/core/convert/datum.py +116 -53
- euporie/core/convert/formats/__init__.py +31 -0
- euporie/core/convert/formats/ansi.py +9 -23
- euporie/core/convert/formats/common.py +11 -23
- euporie/core/convert/formats/html.py +45 -40
- euporie/core/convert/formats/pil.py +1 -1
- euporie/core/convert/formats/png.py +3 -5
- euporie/core/convert/formats/sixel.py +3 -3
- euporie/core/convert/registry.py +4 -6
- euporie/core/convert/utils.py +41 -4
- euporie/core/diagnostics.py +2 -2
- euporie/core/filters.py +98 -40
- euporie/core/format.py +2 -3
- euporie/core/ft/ansi.py +1 -1
- euporie/core/ft/html.py +12 -21
- euporie/core/ft/table.py +1 -3
- euporie/core/ft/utils.py +4 -1
- euporie/core/graphics.py +386 -133
- euporie/core/history.py +2 -2
- euporie/core/inspection.py +3 -2
- euporie/core/io.py +207 -28
- euporie/core/kernel/__init__.py +1 -0
- euporie/core/{kernel.py → kernel/client.py} +45 -108
- euporie/core/kernel/manager.py +114 -0
- euporie/core/key_binding/bindings/__init__.py +1 -8
- euporie/core/key_binding/bindings/basic.py +47 -7
- euporie/core/key_binding/bindings/completion.py +3 -8
- euporie/core/key_binding/bindings/micro.py +1 -6
- euporie/core/key_binding/bindings/mouse.py +2 -2
- euporie/core/key_binding/bindings/terminal.py +193 -0
- euporie/core/key_binding/key_processor.py +43 -2
- euporie/core/key_binding/registry.py +2 -0
- euporie/core/key_binding/utils.py +22 -2
- euporie/core/keys.py +7156 -93
- euporie/core/layout/cache.py +3 -3
- euporie/core/layout/containers.py +48 -4
- euporie/core/layout/decor.py +2 -2
- euporie/core/layout/mouse.py +1 -1
- euporie/core/layout/print.py +2 -1
- euporie/core/layout/scroll.py +39 -34
- euporie/core/log.py +76 -64
- euporie/core/lsp.py +118 -24
- euporie/core/margins.py +1 -1
- euporie/core/path.py +62 -13
- euporie/core/renderer.py +58 -17
- euporie/core/style.py +57 -39
- euporie/core/suggest.py +103 -85
- euporie/core/tabs/__init__.py +32 -0
- euporie/core/tabs/_settings.py +113 -0
- euporie/core/tabs/base.py +80 -470
- euporie/core/tabs/kernel.py +419 -0
- euporie/core/tabs/notebook.py +24 -101
- euporie/core/utils.py +92 -15
- euporie/core/validation.py +1 -1
- euporie/core/widgets/_settings.py +188 -0
- euporie/core/widgets/cell.py +19 -50
- euporie/core/widgets/cell_outputs.py +25 -36
- euporie/core/widgets/decor.py +11 -41
- euporie/core/widgets/dialog.py +62 -27
- euporie/core/widgets/display.py +12 -15
- euporie/core/widgets/file_browser.py +2 -23
- euporie/core/widgets/forms.py +8 -5
- euporie/core/widgets/inputs.py +13 -70
- euporie/core/widgets/layout.py +2 -1
- euporie/core/widgets/logo.py +49 -0
- euporie/core/widgets/menu.py +10 -8
- euporie/core/widgets/pager.py +6 -10
- euporie/core/widgets/palette.py +6 -6
- euporie/hub/app.py +52 -35
- euporie/notebook/_commands.py +24 -0
- euporie/notebook/_settings.py +107 -0
- euporie/notebook/app.py +49 -171
- euporie/notebook/filters.py +1 -1
- euporie/notebook/tabs/__init__.py +46 -7
- euporie/notebook/tabs/_commands.py +714 -0
- euporie/notebook/tabs/_settings.py +32 -0
- euporie/notebook/tabs/display.py +4 -4
- euporie/notebook/tabs/edit.py +11 -44
- euporie/notebook/tabs/json.py +5 -5
- euporie/notebook/tabs/log.py +1 -18
- euporie/notebook/tabs/notebook.py +11 -660
- euporie/notebook/widgets/_commands.py +11 -0
- euporie/notebook/widgets/_settings.py +19 -0
- euporie/notebook/widgets/side_bar.py +14 -34
- euporie/preview/_settings.py +104 -0
- euporie/preview/app.py +6 -31
- euporie/preview/tabs/notebook.py +6 -72
- euporie/web/__init__.py +1 -0
- euporie/web/tabs/__init__.py +14 -0
- euporie/web/tabs/web.py +11 -6
- euporie/web/widgets/__init__.py +1 -0
- euporie/web/widgets/webview.py +5 -15
- {euporie-2.8.4.dist-info → euporie-2.8.6.dist-info}/METADATA +10 -8
- euporie-2.8.6.dist-info/RECORD +175 -0
- {euporie-2.8.4.dist-info → euporie-2.8.6.dist-info}/WHEEL +1 -1
- {euporie-2.8.4.dist-info → euporie-2.8.6.dist-info}/entry_points.txt +2 -2
- {euporie-2.8.4.dist-info → euporie-2.8.6.dist-info}/licenses/LICENSE +1 -1
- euporie/core/launch.py +0 -64
- euporie/core/terminal.py +0 -522
- euporie-2.8.4.dist-info/RECORD +0 -147
- {euporie-2.8.4.data → euporie-2.8.6.data}/data/share/applications/euporie-console.desktop +0 -0
- {euporie-2.8.4.data → euporie-2.8.6.data}/data/share/applications/euporie-notebook.desktop +0 -0
euporie/core/convert/registry.py
CHANGED
@@ -8,19 +8,15 @@ from typing import TYPE_CHECKING, NamedTuple
|
|
8
8
|
from prompt_toolkit.cache import FastDictCache, SimpleCache
|
9
9
|
from prompt_toolkit.filters import to_filter
|
10
10
|
|
11
|
-
# from euporie.core.cache import cache
|
12
|
-
|
13
11
|
if TYPE_CHECKING:
|
14
|
-
from
|
12
|
+
from collections.abc import Iterable
|
13
|
+
from typing import Callable
|
15
14
|
|
16
15
|
from prompt_toolkit.filters import Filter, FilterOrBool
|
17
16
|
|
18
17
|
log = logging.getLogger(__name__)
|
19
18
|
|
20
19
|
|
21
|
-
BASE64_FORMATS = {"png", "jpeg", "pdf", "gif"}
|
22
|
-
|
23
|
-
|
24
20
|
class Converter(NamedTuple):
|
25
21
|
"""Hold a conversion function and its weight."""
|
26
22
|
|
@@ -60,6 +56,8 @@ def register(
|
|
60
56
|
|
61
57
|
def _find_route(from_: str, to: str) -> list | None:
|
62
58
|
"""Find the shortest conversion path between two formats."""
|
59
|
+
from euporie.core.convert import formats # noqa: F401
|
60
|
+
|
63
61
|
if from_ == to:
|
64
62
|
return [from_]
|
65
63
|
|
euporie/core/convert/utils.py
CHANGED
@@ -6,15 +6,49 @@ import asyncio
|
|
6
6
|
import logging
|
7
7
|
import subprocess # S404 - Security implications have been considered
|
8
8
|
import tempfile
|
9
|
+
from math import ceil
|
9
10
|
from pathlib import Path
|
10
11
|
from typing import TYPE_CHECKING
|
11
12
|
|
13
|
+
from euporie.core.app.current import get_app
|
14
|
+
|
12
15
|
if TYPE_CHECKING:
|
13
16
|
from typing import Any
|
14
17
|
|
18
|
+
from euporie.core.convert.datum import Datum
|
19
|
+
|
15
20
|
log = logging.getLogger(__name__)
|
16
21
|
|
17
22
|
|
23
|
+
async def scale_to_fit(
|
24
|
+
datum: Datum, cols: int | None, rows: int | None
|
25
|
+
) -> tuple[int, int]:
|
26
|
+
"""Calculate image size based on aspect ratio, and scale to fit."""
|
27
|
+
data = datum.data
|
28
|
+
px, py = get_app().cell_size_px
|
29
|
+
|
30
|
+
# Calculate rows based on image aspect ratio
|
31
|
+
w, h = data.size
|
32
|
+
if rows is None and cols is not None:
|
33
|
+
rows = ceil(cols / w * h)
|
34
|
+
elif cols is None and rows is not None:
|
35
|
+
cols = ceil(rows / h * w)
|
36
|
+
elif rows is None and cols is None:
|
37
|
+
cols = ceil(w / px)
|
38
|
+
rows = ceil(h / py)
|
39
|
+
assert rows is not None
|
40
|
+
assert cols is not None
|
41
|
+
|
42
|
+
# Scale to fit while maintaining aspect ratio
|
43
|
+
_width, aspect = await datum.cell_size_async()
|
44
|
+
if cols * aspect < rows:
|
45
|
+
rows = ceil(cols * aspect)
|
46
|
+
else:
|
47
|
+
cols = ceil(rows / aspect)
|
48
|
+
|
49
|
+
return cols, rows
|
50
|
+
|
51
|
+
|
18
52
|
async def call_subproc(
|
19
53
|
data: str | bytes,
|
20
54
|
cmd: list[Any],
|
@@ -43,15 +77,18 @@ async def call_subproc(
|
|
43
77
|
if use_tempfile:
|
44
78
|
# If the command cannot read from stdin, create a temporary file to pass to
|
45
79
|
# the command
|
46
|
-
|
47
|
-
|
48
|
-
tfile.close()
|
80
|
+
with tempfile.NamedTemporaryFile(delete=False, suffix=suffix) as tfile:
|
81
|
+
tfile.write(data)
|
49
82
|
cmd.append(tfile.name)
|
50
83
|
stdinput = None
|
51
84
|
else:
|
52
85
|
stdinput = data
|
53
86
|
|
54
|
-
log.
|
87
|
+
if log.level <= 0:
|
88
|
+
import shlex
|
89
|
+
|
90
|
+
log.debug("Running external command `%s`", shlex.join(cmd))
|
91
|
+
|
55
92
|
error: Exception | None = None
|
56
93
|
try:
|
57
94
|
proc = await asyncio.create_subprocess_exec(
|
euporie/core/diagnostics.py
CHANGED
@@ -4,7 +4,7 @@ from __future__ import annotations
|
|
4
4
|
|
5
5
|
import logging
|
6
6
|
from abc import ABCMeta
|
7
|
-
from typing import TYPE_CHECKING,
|
7
|
+
from typing import TYPE_CHECKING, NamedTuple
|
8
8
|
|
9
9
|
if TYPE_CHECKING:
|
10
10
|
from typing import Literal
|
@@ -23,7 +23,7 @@ class Diagnostic(NamedTuple):
|
|
23
23
|
chars: slice
|
24
24
|
|
25
25
|
|
26
|
-
class Report(
|
26
|
+
class Report(list[Diagnostic], metaclass=ABCMeta):
|
27
27
|
"""Class for storing a diagnostic report."""
|
28
28
|
|
29
29
|
@classmethod
|
euporie/core/filters.py
CHANGED
@@ -3,12 +3,12 @@
|
|
3
3
|
from __future__ import annotations
|
4
4
|
|
5
5
|
import os
|
6
|
-
from functools import
|
7
|
-
from importlib import
|
6
|
+
from functools import cache, partial, reduce
|
7
|
+
from importlib.util import find_spec
|
8
8
|
from shutil import which
|
9
9
|
from typing import TYPE_CHECKING
|
10
10
|
|
11
|
-
from prompt_toolkit.enums import EditingMode
|
11
|
+
# from prompt_toolkit.enums import EditingMode
|
12
12
|
from prompt_toolkit.filters import (
|
13
13
|
Condition,
|
14
14
|
emacs_insert_mode,
|
@@ -27,7 +27,7 @@ if TYPE_CHECKING:
|
|
27
27
|
from prompt_toolkit.layout.containers import Window
|
28
28
|
|
29
29
|
|
30
|
-
@
|
30
|
+
@cache
|
31
31
|
def command_exists(*cmds: str) -> Filter:
|
32
32
|
"""Verify a list of external commands exist on the system."""
|
33
33
|
filters = [
|
@@ -37,17 +37,13 @@ def command_exists(*cmds: str) -> Filter:
|
|
37
37
|
return reduce(lambda a, b: a & b, filters, to_filter(True))
|
38
38
|
|
39
39
|
|
40
|
-
@
|
40
|
+
@cache
|
41
41
|
def have_modules(*modules: str) -> Filter:
|
42
42
|
"""Verify a list of python modules are importable."""
|
43
43
|
|
44
44
|
def try_import(module: str) -> bool:
|
45
|
-
|
46
|
-
|
47
|
-
except ModuleNotFoundError:
|
48
|
-
return False
|
49
|
-
else:
|
50
|
-
return True
|
45
|
+
loader = find_spec(module)
|
46
|
+
return loader is not None
|
51
47
|
|
52
48
|
filters = [Condition(partial(try_import, module)) for module in modules]
|
53
49
|
return reduce(lambda a, b: a & b, filters, to_filter(True))
|
@@ -81,12 +77,20 @@ def has_suggestion() -> bool:
|
|
81
77
|
)
|
82
78
|
|
83
79
|
|
80
|
+
@Condition
|
81
|
+
def has_tabs() -> bool:
|
82
|
+
"""Filter to show if any tabs are open in an app."""
|
83
|
+
from euporie.core.app.current import get_app
|
84
|
+
|
85
|
+
return bool(get_app().tabs)
|
86
|
+
|
87
|
+
|
84
88
|
@Condition
|
85
89
|
def has_dialog() -> bool:
|
86
90
|
"""Determine if a dialog is being displayed."""
|
87
91
|
from prompt_toolkit.layout.containers import ConditionalContainer
|
88
92
|
|
89
|
-
from euporie.core.current import get_app
|
93
|
+
from euporie.core.app.current import get_app
|
90
94
|
|
91
95
|
app = get_app()
|
92
96
|
for dialog in app.dialogs.values():
|
@@ -112,18 +116,59 @@ def has_menus() -> bool:
|
|
112
116
|
has_float = has_dialog | has_menus | has_completions
|
113
117
|
|
114
118
|
|
119
|
+
@Condition
|
120
|
+
def has_toolbar() -> bool:
|
121
|
+
"""Is there an active toolbar?"""
|
122
|
+
from euporie.core.app.current import get_app
|
123
|
+
from euporie.core.bars import BAR_BUFFERS
|
124
|
+
|
125
|
+
return get_app().current_buffer.name in BAR_BUFFERS
|
126
|
+
|
127
|
+
|
115
128
|
@Condition
|
116
129
|
def tab_has_focus() -> bool:
|
117
130
|
"""Determine if there is a currently focused tab."""
|
118
|
-
from euporie.core.current import get_app
|
131
|
+
from euporie.core.app.current import get_app
|
119
132
|
|
120
133
|
return get_app().tab is not None
|
121
134
|
|
122
135
|
|
136
|
+
@Condition
|
137
|
+
def kernel_tab_has_focus() -> bool:
|
138
|
+
"""Determine if there is a focused kernel tab."""
|
139
|
+
from euporie.core.app.current import get_app
|
140
|
+
from euporie.core.tabs.kernel import KernelTab
|
141
|
+
|
142
|
+
return isinstance(get_app().tab, KernelTab)
|
143
|
+
|
144
|
+
|
145
|
+
@cache
|
146
|
+
def tab_type_has_focus(tab_class_path: str) -> Condition:
|
147
|
+
"""Determine if the focused tab is of a particular type."""
|
148
|
+
from pkgutil import resolve_name
|
149
|
+
|
150
|
+
from euporie.core.app.current import get_app
|
151
|
+
|
152
|
+
tab_class = cache(resolve_name)
|
153
|
+
|
154
|
+
return Condition(lambda: isinstance(get_app().tab, tab_class(tab_class_path)))
|
155
|
+
|
156
|
+
|
157
|
+
@Condition
|
158
|
+
def tab_can_save() -> bool:
|
159
|
+
"""Determine if the current tab can save it's contents."""
|
160
|
+
from euporie.core.app.current import get_app
|
161
|
+
from euporie.core.tabs.base import Tab
|
162
|
+
|
163
|
+
return (
|
164
|
+
tab := get_app().tab
|
165
|
+
) is not None and tab.__class__.write_file != Tab.write_file
|
166
|
+
|
167
|
+
|
123
168
|
@Condition
|
124
169
|
def pager_has_focus() -> bool:
|
125
170
|
"""Determine if there is a currently focused notebook."""
|
126
|
-
from euporie.core.current import get_app
|
171
|
+
from euporie.core.app.current import get_app
|
127
172
|
|
128
173
|
app = get_app()
|
129
174
|
pager = app.pager
|
@@ -135,7 +180,7 @@ def pager_has_focus() -> bool:
|
|
135
180
|
@Condition
|
136
181
|
def display_has_focus() -> bool:
|
137
182
|
"""Determine if there is a currently focused cell."""
|
138
|
-
from euporie.core.current import get_app
|
183
|
+
from euporie.core.app.current import get_app
|
139
184
|
from euporie.core.widgets.display import DisplayControl
|
140
185
|
|
141
186
|
return isinstance(get_app().layout.current_control, DisplayControl)
|
@@ -144,7 +189,7 @@ def display_has_focus() -> bool:
|
|
144
189
|
@Condition
|
145
190
|
def buffer_is_empty() -> bool:
|
146
191
|
"""Determine if the current buffer contains nothing."""
|
147
|
-
from euporie.core.current import get_app
|
192
|
+
from euporie.core.app.current import get_app
|
148
193
|
|
149
194
|
return not get_app().current_buffer.text
|
150
195
|
|
@@ -152,7 +197,7 @@ def buffer_is_empty() -> bool:
|
|
152
197
|
@Condition
|
153
198
|
def buffer_is_code() -> bool:
|
154
199
|
"""Determine if the current buffer contains code."""
|
155
|
-
from euporie.core.current import get_app
|
200
|
+
from euporie.core.app.current import get_app
|
156
201
|
|
157
202
|
return get_app().current_buffer.name == "code"
|
158
203
|
|
@@ -160,7 +205,7 @@ def buffer_is_code() -> bool:
|
|
160
205
|
@Condition
|
161
206
|
def buffer_is_markdown() -> bool:
|
162
207
|
"""Determine if the current buffer contains markdown."""
|
163
|
-
from euporie.core.current import get_app
|
208
|
+
from euporie.core.app.current import get_app
|
164
209
|
|
165
210
|
return get_app().current_buffer.name == "markdown"
|
166
211
|
|
@@ -168,15 +213,16 @@ def buffer_is_markdown() -> bool:
|
|
168
213
|
@Condition
|
169
214
|
def micro_mode() -> bool:
|
170
215
|
"""When the micro key-bindings are active."""
|
171
|
-
from euporie.core.
|
216
|
+
from euporie.core.app.app import ExtraEditingMode
|
217
|
+
from euporie.core.app.current import get_app
|
172
218
|
|
173
|
-
return get_app().editing_mode ==
|
219
|
+
return get_app().editing_mode == ExtraEditingMode.MICRO
|
174
220
|
|
175
221
|
|
176
222
|
@Condition
|
177
223
|
def micro_replace_mode() -> bool:
|
178
224
|
"""Determine if the editor is in overwrite mode."""
|
179
|
-
from euporie.core.current import get_app
|
225
|
+
from euporie.core.app.current import get_app
|
180
226
|
|
181
227
|
app = get_app()
|
182
228
|
return app.micro_state.input_mode == MicroInputMode.REPLACE
|
@@ -185,7 +231,7 @@ def micro_replace_mode() -> bool:
|
|
185
231
|
@Condition
|
186
232
|
def micro_insert_mode() -> bool:
|
187
233
|
"""Determine if the editor is in insert mode."""
|
188
|
-
from euporie.core.current import get_app
|
234
|
+
from euporie.core.app.current import get_app
|
189
235
|
|
190
236
|
app = get_app()
|
191
237
|
return app.micro_state.input_mode == MicroInputMode.INSERT
|
@@ -194,7 +240,7 @@ def micro_insert_mode() -> bool:
|
|
194
240
|
@Condition
|
195
241
|
def micro_recording_macro() -> bool:
|
196
242
|
"""Determine if a micro macro is being recorded."""
|
197
|
-
from euporie.core.current import get_app
|
243
|
+
from euporie.core.app.current import get_app
|
198
244
|
|
199
245
|
return get_app().micro_state.current_recording is not None
|
200
246
|
|
@@ -202,7 +248,7 @@ def micro_recording_macro() -> bool:
|
|
202
248
|
@Condition
|
203
249
|
def is_returnable() -> bool:
|
204
250
|
"""Determine if the current buffer has an accept handler."""
|
205
|
-
from euporie.core.current import get_app
|
251
|
+
from euporie.core.app.current import get_app
|
206
252
|
|
207
253
|
return get_app().current_buffer.is_returnable
|
208
254
|
|
@@ -210,7 +256,7 @@ def is_returnable() -> bool:
|
|
210
256
|
@Condition
|
211
257
|
def cursor_at_start_of_line() -> bool:
|
212
258
|
"""Determine if the cursor is at the start of a line."""
|
213
|
-
from euporie.core.current import get_app
|
259
|
+
from euporie.core.app.current import get_app
|
214
260
|
|
215
261
|
return get_app().current_buffer.document.cursor_position_col == 0
|
216
262
|
|
@@ -218,7 +264,7 @@ def cursor_at_start_of_line() -> bool:
|
|
218
264
|
@Condition
|
219
265
|
def cursor_on_first_line() -> bool:
|
220
266
|
"""Determine if the cursor is on the first line of a buffer."""
|
221
|
-
from euporie.core.current import get_app
|
267
|
+
from euporie.core.app.current import get_app
|
222
268
|
|
223
269
|
return get_app().current_buffer.document.on_first_line
|
224
270
|
|
@@ -226,11 +272,32 @@ def cursor_on_first_line() -> bool:
|
|
226
272
|
@Condition
|
227
273
|
def cursor_on_last_line() -> bool:
|
228
274
|
"""Determine if the cursor is on the last line of a buffer."""
|
229
|
-
from euporie.core.current import get_app
|
275
|
+
from euporie.core.app.current import get_app
|
230
276
|
|
231
277
|
return get_app().current_buffer.document.on_last_line
|
232
278
|
|
233
279
|
|
280
|
+
@cache
|
281
|
+
def char_after_cursor(char: str) -> Condition:
|
282
|
+
"""Generate a condition to check for a character after the cursor."""
|
283
|
+
from euporie.core.app.current import get_app
|
284
|
+
|
285
|
+
return Condition(
|
286
|
+
lambda: bool(
|
287
|
+
(post := get_app().current_buffer.document.text_after_cursor)
|
288
|
+
and post[0] == char
|
289
|
+
)
|
290
|
+
)
|
291
|
+
|
292
|
+
|
293
|
+
@Condition
|
294
|
+
def has_matching_bracket() -> bool:
|
295
|
+
"""Determine if the bracket at the cursor has a matching pair."""
|
296
|
+
from euporie.core.app.current import get_app
|
297
|
+
|
298
|
+
return bool(get_app().current_buffer.document.find_matching_bracket_position())
|
299
|
+
|
300
|
+
|
234
301
|
"""Determine if any binding style is in insert mode."""
|
235
302
|
insert_mode = (
|
236
303
|
(vi_mode & vi_insert_mode)
|
@@ -245,7 +312,7 @@ replace_mode = micro_replace_mode | vi_replace_mode
|
|
245
312
|
@Condition
|
246
313
|
def is_searching() -> bool:
|
247
314
|
"""Determine if the app is in search mode."""
|
248
|
-
from euporie.core.current import get_app
|
315
|
+
from euporie.core.app.current import get_app
|
249
316
|
|
250
317
|
app = get_app()
|
251
318
|
return (
|
@@ -265,8 +332,8 @@ def at_end_of_buffer() -> bool:
|
|
265
332
|
@Condition
|
266
333
|
def kernel_is_python() -> bool:
|
267
334
|
"""Determine if the current notebook has a python kernel."""
|
268
|
-
from euporie.core.current import get_app
|
269
|
-
from euporie.core.tabs.
|
335
|
+
from euporie.core.app.current import get_app
|
336
|
+
from euporie.core.tabs.kernel import KernelTab
|
270
337
|
|
271
338
|
kernel_tab = get_app().tab
|
272
339
|
if isinstance(kernel_tab, KernelTab):
|
@@ -277,7 +344,7 @@ def kernel_is_python() -> bool:
|
|
277
344
|
@Condition
|
278
345
|
def multiple_cells_selected() -> bool:
|
279
346
|
"""Determine if there is more than one selected cell."""
|
280
|
-
from euporie.core.current import get_app
|
347
|
+
from euporie.core.app.current import get_app
|
281
348
|
from euporie.core.tabs.notebook import BaseNotebook
|
282
349
|
|
283
350
|
nb = get_app().tab
|
@@ -286,15 +353,6 @@ def multiple_cells_selected() -> bool:
|
|
286
353
|
return False
|
287
354
|
|
288
355
|
|
289
|
-
@Condition
|
290
|
-
def kernel_tab_has_focus() -> bool:
|
291
|
-
"""Determine if there is a focused kernel tab."""
|
292
|
-
from euporie.core.current import get_app
|
293
|
-
from euporie.core.tabs.base import KernelTab
|
294
|
-
|
295
|
-
return isinstance(get_app().tab, KernelTab)
|
296
|
-
|
297
|
-
|
298
356
|
def scrollable(window: Window) -> Filter:
|
299
357
|
"""Return a filter which indicates if a window is scrollable."""
|
300
358
|
return Condition(
|
euporie/core/format.py
CHANGED
@@ -110,11 +110,10 @@ class LspFormatter(Formatter):
|
|
110
110
|
range_ = change.get("range", {})
|
111
111
|
start = range_.get("start", {})
|
112
112
|
start_line = start.get("line", 0)
|
113
|
-
start_char = start.get("
|
113
|
+
start_char = start.get("character", 0)
|
114
114
|
end = range_.get("end", {})
|
115
115
|
end_line = end.get("line", 0)
|
116
|
-
end_char = end.get("
|
117
|
-
|
116
|
+
end_char = end.get("character", 0)
|
118
117
|
segment = range_to_slice(
|
119
118
|
start_line, start_char, end_line, end_char, text
|
120
119
|
)
|
euporie/core/ft/ansi.py
CHANGED
euporie/core/ft/html.py
CHANGED
@@ -27,6 +27,7 @@ from prompt_toolkit.layout.dimension import Dimension
|
|
27
27
|
from prompt_toolkit.utils import Event
|
28
28
|
from upath import UPath
|
29
29
|
|
30
|
+
from euporie.core.app.current import get_app
|
30
31
|
from euporie.core.border import (
|
31
32
|
DiLineStyle,
|
32
33
|
DoubleLine,
|
@@ -50,7 +51,6 @@ from euporie.core.border import (
|
|
50
51
|
)
|
51
52
|
from euporie.core.convert.datum import Datum, get_loop
|
52
53
|
from euporie.core.convert.mime import get_format
|
53
|
-
from euporie.core.current import get_app
|
54
54
|
from euporie.core.data_structures import DiBool, DiInt, DiStr
|
55
55
|
from euporie.core.ft.table import Cell, Table, compute_padding
|
56
56
|
from euporie.core.ft.utils import (
|
@@ -102,8 +102,9 @@ class CssSelector(NamedTuple):
|
|
102
102
|
|
103
103
|
|
104
104
|
if TYPE_CHECKING:
|
105
|
+
from collections.abc import Generator, Iterator
|
105
106
|
from pathlib import Path
|
106
|
-
from typing import Any, Callable
|
107
|
+
from typing import Any, Callable
|
107
108
|
|
108
109
|
from fsspec.spec import AbstractFileSystem
|
109
110
|
from prompt_toolkit.filters.base import Filter
|
@@ -595,8 +596,8 @@ def css_dimension(
|
|
595
596
|
|
596
597
|
# Get cell pixel dimensions
|
597
598
|
app = get_app()
|
598
|
-
if hasattr(app, "
|
599
|
-
cell_px, cell_py = get_app().
|
599
|
+
if hasattr(app, "cell_size_px"):
|
600
|
+
cell_px, cell_py = get_app().cell_size_px
|
600
601
|
else:
|
601
602
|
cell_px, cell_py = 10, 20
|
602
603
|
|
@@ -1149,8 +1150,7 @@ class Theme(Mapping):
|
|
1149
1150
|
and parent_theme["flex_direction"].startswith("col")
|
1150
1151
|
)
|
1151
1152
|
)
|
1152
|
-
|
1153
|
-
)
|
1153
|
+
) or (parent_theme is not None and parent_theme.d_grid)
|
1154
1154
|
|
1155
1155
|
@cached_property
|
1156
1156
|
def d_inline(self) -> bool:
|
@@ -2892,7 +2892,7 @@ class Node:
|
|
2892
2892
|
s += ">"
|
2893
2893
|
if self.contents:
|
2894
2894
|
for child in self.contents:
|
2895
|
-
s += f"\n{dd} {child._outer_html(d+1, attrs=attrs)}"
|
2895
|
+
s += f"\n{dd} {child._outer_html(d + 1, attrs=attrs)}"
|
2896
2896
|
s += f"\n{dd}{dd}"
|
2897
2897
|
s += f"</{self.name}>"
|
2898
2898
|
else:
|
@@ -3263,15 +3263,6 @@ class CustomHTMLParser(HTMLParser):
|
|
3263
3263
|
Node(dom=self.dom, name="::text", text=data, parent=self.curr, attrs=[])
|
3264
3264
|
)
|
3265
3265
|
|
3266
|
-
# def handle_endtag(self, tag: str) -> None:
|
3267
|
-
# """Handle end tags: close the currently opened element."""
|
3268
|
-
# if tag == self.curr.name:
|
3269
|
-
# self.curr.closed = True
|
3270
|
-
# if self.curr.parent:
|
3271
|
-
# self.curr = self.curr.parent
|
3272
|
-
# else:
|
3273
|
-
# self.autoclose()
|
3274
|
-
|
3275
3266
|
def handle_endtag(self, tag: str) -> None:
|
3276
3267
|
"""Handle end tags: close the currently opened element."""
|
3277
3268
|
if tag != self.curr.name:
|
@@ -3285,7 +3276,6 @@ def parse_style_sheet(css_str: str, dom: HTML, condition: Filter = always) -> No
|
|
3285
3276
|
"""Collect all CSS styles from style tags."""
|
3286
3277
|
dom_css = dom.css
|
3287
3278
|
# Remove whitespace and newlines
|
3288
|
-
# css_str = css_str.strip().replace("\n", "")
|
3289
3279
|
css_str = re.sub(r"\s*\n\s*", " ", css_str)
|
3290
3280
|
# Remove comments
|
3291
3281
|
css_str = re.sub(r"\/\*[^\*]+\*\/", "", css_str)
|
@@ -4992,15 +4982,16 @@ if __name__ == "__main__":
|
|
4992
4982
|
from prompt_toolkit.shortcuts.utils import print_formatted_text
|
4993
4983
|
from prompt_toolkit.styles.style import Style
|
4994
4984
|
|
4995
|
-
from euporie.core.app import
|
4985
|
+
from euporie.core.app.dummy import DummyApp
|
4996
4986
|
from euporie.core.path import parse_path
|
4997
4987
|
from euporie.core.style import HTML_STYLE
|
4998
4988
|
|
4999
4989
|
path = parse_path(sys.argv[1])
|
5000
4990
|
|
5001
|
-
with
|
5002
|
-
input=
|
5003
|
-
|
4991
|
+
with (
|
4992
|
+
create_app_session(input=DummyApp.load_input(), output=DummyApp.load_output()),
|
4993
|
+
set_app(DummyApp()),
|
4994
|
+
):
|
5004
4995
|
print_formatted_text(
|
5005
4996
|
HTML(
|
5006
4997
|
path.read_text(),
|
euporie/core/ft/table.py
CHANGED
euporie/core/ft/utils.py
CHANGED
@@ -4,7 +4,7 @@ from __future__ import annotations
|
|
4
4
|
|
5
5
|
import re
|
6
6
|
from enum import Enum
|
7
|
-
from typing import
|
7
|
+
from typing import TYPE_CHECKING, cast
|
8
8
|
|
9
9
|
from prompt_toolkit.formatted_text.base import OneStyleAndTextTuple, StyleAndTextTuples
|
10
10
|
from prompt_toolkit.formatted_text.utils import (
|
@@ -20,6 +20,9 @@ from pygments.util import ClassNotFound
|
|
20
20
|
from euporie.core.border import GridStyle, ThinGrid
|
21
21
|
from euporie.core.data_structures import DiBool, DiInt, DiStr
|
22
22
|
|
23
|
+
if TYPE_CHECKING:
|
24
|
+
from collections.abc import Iterable
|
25
|
+
|
23
26
|
_ZERO_WIDTH_FRAGMENTS = ("[ZeroWidthEscape]", "[ReverseOverwrite]")
|
24
27
|
|
25
28
|
|