euporie 2.8.0__py3-none-any.whl → 2.8.5__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 +267 -147
- euporie/core/__init__.py +1 -9
- euporie/core/__main__.py +31 -5
- euporie/core/_settings.py +104 -0
- euporie/core/app/__init__.py +3 -0
- euporie/core/app/_commands.py +70 -0
- euporie/core/app/_settings.py +427 -0
- euporie/core/{app.py → app/app.py} +214 -572
- 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 +182 -0
- euporie/core/bars/menu.py +258 -0
- euporie/core/{widgets → bars}/search.py +154 -57
- euporie/core/{widgets → bars}/status.py +9 -26
- euporie/core/clipboard.py +19 -80
- euporie/core/comm/base.py +8 -6
- euporie/core/comm/ipywidgets.py +21 -12
- euporie/core/comm/registry.py +2 -1
- euporie/core/commands.py +11 -5
- euporie/core/completion.py +3 -2
- euporie/core/config.py +368 -341
- euporie/core/convert/__init__.py +0 -30
- euporie/core/convert/datum.py +131 -60
- euporie/core/convert/formats/__init__.py +31 -0
- euporie/core/convert/formats/ansi.py +46 -30
- 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 +11 -8
- euporie/core/convert/utils.py +50 -23
- euporie/core/diagnostics.py +2 -2
- euporie/core/filters.py +72 -82
- euporie/core/format.py +13 -2
- euporie/core/ft/ansi.py +1 -1
- euporie/core/ft/html.py +36 -36
- euporie/core/ft/table.py +1 -3
- euporie/core/ft/utils.py +4 -1
- euporie/core/graphics.py +216 -124
- 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} +100 -139
- euporie/core/kernel/manager.py +114 -0
- euporie/core/key_binding/bindings/__init__.py +2 -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 +5 -7
- euporie/core/key_binding/bindings/mouse.py +26 -24
- euporie/core/key_binding/bindings/terminal.py +193 -0
- euporie/core/key_binding/bindings/vi.py +46 -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 -92
- euporie/core/layout/cache.py +35 -25
- euporie/core/layout/containers.py +280 -74
- euporie/core/layout/decor.py +5 -5
- euporie/core/layout/mouse.py +1 -1
- euporie/core/layout/print.py +16 -3
- euporie/core/layout/scroll.py +26 -28
- euporie/core/log.py +75 -60
- euporie/core/lsp.py +118 -24
- euporie/core/margins.py +60 -31
- euporie/core/path.py +2 -1
- euporie/core/renderer.py +58 -17
- euporie/core/style.py +60 -40
- euporie/core/suggest.py +103 -85
- euporie/core/tabs/__init__.py +34 -0
- euporie/core/tabs/_settings.py +113 -0
- euporie/core/tabs/base.py +11 -435
- euporie/core/tabs/kernel.py +420 -0
- euporie/core/tabs/notebook.py +20 -54
- euporie/core/utils.py +98 -6
- euporie/core/validation.py +1 -1
- euporie/core/widgets/_settings.py +188 -0
- euporie/core/widgets/cell.py +90 -158
- euporie/core/widgets/cell_outputs.py +26 -37
- euporie/core/widgets/decor.py +11 -41
- euporie/core/widgets/dialog.py +55 -44
- euporie/core/widgets/display.py +27 -24
- euporie/core/widgets/file_browser.py +5 -26
- euporie/core/widgets/forms.py +16 -12
- euporie/core/widgets/inputs.py +37 -81
- euporie/core/widgets/layout.py +7 -6
- euporie/core/widgets/logo.py +49 -0
- euporie/core/widgets/menu.py +13 -11
- euporie/core/widgets/pager.py +9 -11
- euporie/core/widgets/palette.py +6 -6
- euporie/hub/app.py +52 -31
- euporie/notebook/_commands.py +24 -0
- euporie/notebook/_settings.py +107 -0
- euporie/notebook/app.py +109 -210
- 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 +2 -2
- euporie/notebook/tabs/edit.py +12 -7
- euporie/notebook/tabs/json.py +3 -3
- euporie/notebook/tabs/log.py +1 -18
- euporie/notebook/tabs/notebook.py +21 -674
- 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 +8 -30
- euporie/preview/tabs/notebook.py +15 -86
- euporie/web/tabs/web.py +4 -6
- euporie/web/widgets/webview.py +5 -12
- {euporie-2.8.0.dist-info → euporie-2.8.5.dist-info}/METADATA +11 -15
- euporie-2.8.5.dist-info/RECORD +172 -0
- {euporie-2.8.0.dist-info → euporie-2.8.5.dist-info}/WHEEL +1 -1
- {euporie-2.8.0.dist-info → euporie-2.8.5.dist-info}/entry_points.txt +2 -2
- {euporie-2.8.0.dist-info → euporie-2.8.5.dist-info}/licenses/LICENSE +1 -1
- euporie/core/launch.py +0 -59
- euporie/core/terminal.py +0 -527
- euporie-2.8.0.dist-info/RECORD +0 -146
- {euporie-2.8.0.data → euporie-2.8.5.data}/data/share/applications/euporie-console.desktop +0 -0
- {euporie-2.8.0.data → euporie-2.8.5.data}/data/share/applications/euporie-notebook.desktop +0 -0
@@ -20,9 +20,8 @@ from prompt_toolkit.mouse_events import MouseButton, MouseEvent, MouseEventType
|
|
20
20
|
from prompt_toolkit.utils import Event
|
21
21
|
from upath import UPath
|
22
22
|
|
23
|
-
from euporie.core.app import get_app
|
23
|
+
from euporie.core.app.current import get_app
|
24
24
|
from euporie.core.border import InsetGrid
|
25
|
-
from euporie.core.config import add_setting
|
26
25
|
from euporie.core.layout.containers import HSplit, VSplit, Window
|
27
26
|
from euporie.core.layout.decor import FocusedStyle
|
28
27
|
from euporie.core.margins import MarginContainer, ScrollbarMargin
|
@@ -41,7 +40,7 @@ if TYPE_CHECKING:
|
|
41
40
|
from prompt_toolkit.layout.dimension import AnyDimension
|
42
41
|
from upath.core import PT
|
43
42
|
|
44
|
-
from euporie.core.
|
43
|
+
from euporie.core.bars.status import StatusBarFields
|
45
44
|
|
46
45
|
log = logging.getLogger(__name__)
|
47
46
|
|
@@ -377,9 +376,9 @@ class FileBrowserControl(UIControl):
|
|
377
376
|
self.dir = path or UPath(".")
|
378
377
|
self.hovered: int | None = None
|
379
378
|
self.selected: int | None = None
|
380
|
-
self._dir_cache: FastDictCache[
|
381
|
-
|
382
|
-
|
379
|
+
self._dir_cache: FastDictCache[tuple[Path], list[tuple[bool, Path]]] = (
|
380
|
+
FastDictCache(get_value=self.load_path, size=1)
|
381
|
+
)
|
383
382
|
self.on_select = Event(self, on_select)
|
384
383
|
self.on_chdir = Event(self, on_chdir)
|
385
384
|
self.on_open = Event(self, on_open)
|
@@ -704,23 +703,3 @@ class FileBrowser:
|
|
704
703
|
def __pt_status__(self) -> StatusBarFields:
|
705
704
|
"""Show the selected or hovered path in the statusbar."""
|
706
705
|
return self.control.__pt_status__()
|
707
|
-
|
708
|
-
# ################################### Settings ####################################
|
709
|
-
|
710
|
-
add_setting(
|
711
|
-
name="show_file_icons",
|
712
|
-
flags=["--show-file-icons"],
|
713
|
-
type_=bool,
|
714
|
-
title="File icons",
|
715
|
-
help_="Show file icons in the file manager",
|
716
|
-
default=False,
|
717
|
-
schema={
|
718
|
-
"type": "boolean",
|
719
|
-
},
|
720
|
-
description="""
|
721
|
-
Whether file icons should be shown in the file manager.
|
722
|
-
|
723
|
-
These icons exist in the unicode private use area, and may require custom
|
724
|
-
fonts such as ``awesome-terminal-fonts`` or ``nerdfonts`` to be installed.
|
725
|
-
""",
|
726
|
-
)
|
euporie/core/widgets/forms.py
CHANGED
@@ -8,7 +8,7 @@ from abc import ABCMeta, abstractmethod
|
|
8
8
|
from collections import deque
|
9
9
|
from functools import partial
|
10
10
|
from math import ceil, floor
|
11
|
-
from typing import TYPE_CHECKING,
|
11
|
+
from typing import TYPE_CHECKING, cast
|
12
12
|
from weakref import finalize
|
13
13
|
|
14
14
|
from prompt_toolkit.buffer import ValidationState
|
@@ -47,8 +47,8 @@ from prompt_toolkit.utils import Event
|
|
47
47
|
from prompt_toolkit.validation import Validator
|
48
48
|
from prompt_toolkit.widgets.base import TextArea
|
49
49
|
|
50
|
+
from euporie.core.app.current import get_app
|
50
51
|
from euporie.core.border import InsetGrid
|
51
|
-
from euporie.core.current import get_app
|
52
52
|
from euporie.core.data_structures import DiBool
|
53
53
|
from euporie.core.ft.utils import FormattedTextAlign, align
|
54
54
|
from euporie.core.margins import MarginContainer, ScrollbarMargin
|
@@ -56,7 +56,8 @@ from euporie.core.widgets.decor import Border, Shadow
|
|
56
56
|
from euporie.core.widgets.layout import Box, ConditionalSplit
|
57
57
|
|
58
58
|
if TYPE_CHECKING:
|
59
|
-
from
|
59
|
+
from collections.abc import Sequence
|
60
|
+
from typing import Any, Callable
|
60
61
|
|
61
62
|
from prompt_toolkit.buffer import Buffer, BufferAcceptHandler
|
62
63
|
from prompt_toolkit.completion.base import Completer
|
@@ -236,6 +237,7 @@ class Button:
|
|
236
237
|
|
237
238
|
def default_mouse_handler(self, mouse_event: MouseEvent) -> NotImplementedOrNone:
|
238
239
|
"""Handle mouse events."""
|
240
|
+
app = get_app()
|
239
241
|
if self.disabled():
|
240
242
|
return NotImplemented
|
241
243
|
if mouse_event.button == MouseButton.LEFT:
|
@@ -249,16 +251,15 @@ class Button:
|
|
249
251
|
):
|
250
252
|
y_min, x_min = min(render_info._rowcol_to_yx.values())
|
251
253
|
y_max, x_max = max(render_info._rowcol_to_yx.values())
|
252
|
-
|
254
|
+
app.mouse_limits = WritePosition(
|
253
255
|
xpos=x_min,
|
254
256
|
ypos=y_min,
|
255
|
-
width=x_max - x_min,
|
256
|
-
height=y_max - y_min,
|
257
|
+
width=x_max - x_min + 1,
|
258
|
+
height=y_max - y_min + 1,
|
257
259
|
)
|
258
260
|
self.on_mouse_down.fire()
|
259
261
|
|
260
262
|
if not self.has_focus():
|
261
|
-
app = get_app()
|
262
263
|
app.layout.focus(self)
|
263
264
|
# Invalidate the app - we don't do it by returning None so the
|
264
265
|
# event can bubble
|
@@ -269,7 +270,7 @@ class Button:
|
|
269
270
|
return None
|
270
271
|
|
271
272
|
elif mouse_event.event_type == MouseEventType.MOUSE_UP:
|
272
|
-
|
273
|
+
app.mouse_limits = None
|
273
274
|
if self.selected:
|
274
275
|
self.selected = False
|
275
276
|
self.on_click.fire()
|
@@ -280,11 +281,12 @@ class Button:
|
|
280
281
|
if (info := self.window.render_info) is not None and (
|
281
282
|
info._x_offset + mouse_event.position.x,
|
282
283
|
info._y_offset + mouse_event.position.y,
|
283
|
-
) !=
|
284
|
+
) != app.mouse_position:
|
285
|
+
app.mouse_limits = None
|
284
286
|
self.selected = False
|
285
287
|
return None
|
286
288
|
|
287
|
-
|
289
|
+
app.mouse_limits = None
|
288
290
|
self.selected = False
|
289
291
|
return NotImplemented
|
290
292
|
|
@@ -727,9 +729,11 @@ class Label:
|
|
727
729
|
value = self.value
|
728
730
|
data = value() if callable(value) else value
|
729
731
|
if self.html():
|
732
|
+
from prompt_toolkit.formatted_text.utils import to_plain_text
|
733
|
+
|
730
734
|
from euporie.core.ft.html import HTML
|
731
735
|
|
732
|
-
return HTML(data, collapse_root_margin=True, fill=False)
|
736
|
+
return HTML(to_plain_text(data), collapse_root_margin=True, fill=False)
|
733
737
|
return data
|
734
738
|
|
735
739
|
def __pt_container__(self) -> AnyContainer:
|
@@ -955,7 +959,7 @@ class Progress:
|
|
955
959
|
return self.container
|
956
960
|
|
957
961
|
|
958
|
-
class SizedMask(
|
962
|
+
class SizedMask(dict[int, bool]):
|
959
963
|
"""Mask with restricted number of True items."""
|
960
964
|
|
961
965
|
def __init__(self, size: int | None = None) -> None:
|
euporie/core/widgets/inputs.py
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
from __future__ import annotations
|
4
4
|
|
5
5
|
import logging
|
6
|
+
from functools import lru_cache
|
6
7
|
from typing import TYPE_CHECKING
|
7
8
|
|
8
9
|
from prompt_toolkit.auto_suggest import AutoSuggest, DynamicAutoSuggest
|
@@ -48,9 +49,8 @@ from prompt_toolkit.widgets import TextArea
|
|
48
49
|
from prompt_toolkit.widgets.toolbars import SearchToolbar
|
49
50
|
from pygments.lexers import ClassNotFound, get_lexer_by_name
|
50
51
|
|
52
|
+
from euporie.core.app.current import get_app
|
51
53
|
from euporie.core.commands import add_cmd
|
52
|
-
from euporie.core.config import add_setting
|
53
|
-
from euporie.core.current import get_app
|
54
54
|
from euporie.core.diagnostics import Report
|
55
55
|
from euporie.core.filters import buffer_is_code, scrollable
|
56
56
|
from euporie.core.key_binding.registry import (
|
@@ -70,10 +70,10 @@ from euporie.core.processors import (
|
|
70
70
|
ShowTrailingWhiteSpaceProcessor,
|
71
71
|
)
|
72
72
|
from euporie.core.suggest import ConditionalAutoSuggestAsync
|
73
|
-
from euporie.core.widgets.pager import PagerState
|
74
73
|
|
75
74
|
if TYPE_CHECKING:
|
76
|
-
from
|
75
|
+
from collections.abc import Sequence
|
76
|
+
from typing import Callable
|
77
77
|
|
78
78
|
from prompt_toolkit.buffer import BufferAcceptHandler
|
79
79
|
from prompt_toolkit.filters import Filter, FilterOrBool
|
@@ -88,15 +88,30 @@ if TYPE_CHECKING:
|
|
88
88
|
from prompt_toolkit.layout.margins import Margin
|
89
89
|
from prompt_toolkit.lexers.base import Lexer
|
90
90
|
|
91
|
+
from euporie.core.bars.status import StatusBarFields
|
91
92
|
from euporie.core.format import Formatter
|
92
93
|
from euporie.core.inspection import Inspector
|
93
|
-
from euporie.core.tabs.
|
94
|
-
from euporie.core.widgets.status import StatusBarFields
|
94
|
+
from euporie.core.tabs.kernel import KernelTab
|
95
95
|
|
96
96
|
|
97
97
|
log = logging.getLogger(__name__)
|
98
98
|
|
99
99
|
|
100
|
+
@lru_cache
|
101
|
+
def _get_lexer(highlight: bool, lexer: Lexer | None, language: str) -> Lexer:
|
102
|
+
"""Determine which lexer should be used for syntax highlighting."""
|
103
|
+
if not highlight:
|
104
|
+
return SimpleLexer()
|
105
|
+
elif lexer is not None:
|
106
|
+
return lexer
|
107
|
+
try:
|
108
|
+
pygments_lexer_class = get_lexer_by_name(language).__class__
|
109
|
+
except ClassNotFound:
|
110
|
+
return SimpleLexer()
|
111
|
+
else:
|
112
|
+
return PygmentsLexer(pygments_lexer_class, sync_from_start=False)
|
113
|
+
|
114
|
+
|
100
115
|
class KernelInput(TextArea):
|
101
116
|
"""Kernel input text areas.
|
102
117
|
|
@@ -129,7 +144,7 @@ class KernelInput(TextArea):
|
|
129
144
|
scrollbar: FilterOrBool = True,
|
130
145
|
style: str = "class:kernel-input",
|
131
146
|
search_field: SearchToolbar | None = None,
|
132
|
-
preview_search: FilterOrBool =
|
147
|
+
preview_search: FilterOrBool = False,
|
133
148
|
prompt: AnyFormattedText = "",
|
134
149
|
input_processors: list[Processor] | None = None,
|
135
150
|
name: str = "",
|
@@ -182,14 +197,6 @@ class KernelInput(TextArea):
|
|
182
197
|
self._language = language
|
183
198
|
self.lexer = lexer
|
184
199
|
|
185
|
-
def _get_lexer() -> Lexer:
|
186
|
-
try:
|
187
|
-
pygments_lexer_class = get_lexer_by_name(self.language).__class__
|
188
|
-
except ClassNotFound:
|
189
|
-
return SimpleLexer()
|
190
|
-
else:
|
191
|
-
return PygmentsLexer(pygments_lexer_class, sync_from_start=False)
|
192
|
-
|
193
200
|
self.formatters = formatters if formatters is not None else []
|
194
201
|
self._diagnostics = diagnostics or Report()
|
195
202
|
self.inspector = inspector
|
@@ -228,7 +235,8 @@ class KernelInput(TextArea):
|
|
228
235
|
|
229
236
|
# Set extra key-bindings
|
230
237
|
widgets_key_bindings = load_registered_bindings(
|
231
|
-
"euporie.core.widgets.inputs.KernelInput"
|
238
|
+
"euporie.core.widgets.inputs.KernelInput",
|
239
|
+
config=app.config,
|
232
240
|
)
|
233
241
|
if key_bindings:
|
234
242
|
widgets_key_bindings = merge_key_bindings(
|
@@ -240,7 +248,11 @@ class KernelInput(TextArea):
|
|
240
248
|
|
241
249
|
self.control = BufferControl(
|
242
250
|
buffer=self.buffer,
|
243
|
-
lexer=DynamicLexer(
|
251
|
+
lexer=DynamicLexer(
|
252
|
+
lambda: _get_lexer(
|
253
|
+
app.config.syntax_highlighting, self.lexer, self.language
|
254
|
+
)
|
255
|
+
),
|
244
256
|
input_processors=[
|
245
257
|
ConditionalProcessor(
|
246
258
|
DiagnosticProcessor(_get_diagnostics),
|
@@ -283,7 +295,7 @@ class KernelInput(TextArea):
|
|
283
295
|
diagnostics=_get_diagnostics,
|
284
296
|
show_diagnostics=to_filter(show_diagnostics),
|
285
297
|
),
|
286
|
-
app.config.
|
298
|
+
app.config.filters.line_numbers & self.buffer.multiline,
|
287
299
|
),
|
288
300
|
]
|
289
301
|
right_margins = [OverflowMargin()]
|
@@ -353,6 +365,8 @@ class KernelInput(TextArea):
|
|
353
365
|
|
354
366
|
async def inspect(self, auto: bool = False) -> None:
|
355
367
|
"""Get contextual help for the current cursor position in the current cell."""
|
368
|
+
from euporie.core.widgets.pager import PagerState
|
369
|
+
|
356
370
|
if self.inspector is None:
|
357
371
|
return
|
358
372
|
|
@@ -414,64 +428,6 @@ class KernelInput(TextArea):
|
|
414
428
|
"""Return the widget's container."""
|
415
429
|
return self.container
|
416
430
|
|
417
|
-
# ################################### Settings ####################################
|
418
|
-
|
419
|
-
add_setting(
|
420
|
-
name="line_numbers",
|
421
|
-
flags=["--line-numbers"],
|
422
|
-
type_=bool,
|
423
|
-
help_="Show or hide line numbers",
|
424
|
-
default=True,
|
425
|
-
description="""
|
426
|
-
Whether line numbers are shown by default.
|
427
|
-
""",
|
428
|
-
hooks=[lambda x: get_app().refresh()],
|
429
|
-
)
|
430
|
-
|
431
|
-
add_setting(
|
432
|
-
name="autoformat",
|
433
|
-
flags=["--autoformat"],
|
434
|
-
type_=bool,
|
435
|
-
help_="Automatically re-format code cells when run",
|
436
|
-
default=False,
|
437
|
-
description="""
|
438
|
-
Whether to automatically reformat code cells before they are run.
|
439
|
-
""",
|
440
|
-
)
|
441
|
-
|
442
|
-
add_setting(
|
443
|
-
name="autocomplete",
|
444
|
-
flags=["--autocomplete"],
|
445
|
-
type_=bool,
|
446
|
-
help_="Provide completions suggestions automatically",
|
447
|
-
default=False,
|
448
|
-
description="""
|
449
|
-
Whether to automatically suggestion completions while typing in code cells.
|
450
|
-
""",
|
451
|
-
)
|
452
|
-
|
453
|
-
add_setting(
|
454
|
-
name="autosuggest",
|
455
|
-
flags=["--autosuggest"],
|
456
|
-
type_=bool,
|
457
|
-
help_="Provide line completion suggestions",
|
458
|
-
default=True,
|
459
|
-
description="""
|
460
|
-
Whether to automatically suggestion line content while typing in code cells.
|
461
|
-
""",
|
462
|
-
)
|
463
|
-
|
464
|
-
add_setting(
|
465
|
-
name="autoinspect",
|
466
|
-
flags=["--autoinspect"],
|
467
|
-
type_=bool,
|
468
|
-
help_="Display contextual help automatically",
|
469
|
-
default=False,
|
470
|
-
description="""
|
471
|
-
Whether to automatically display contextual help when navigating through code cells.
|
472
|
-
""",
|
473
|
-
)
|
474
|
-
|
475
431
|
# ################################### Commands ####################################
|
476
432
|
|
477
433
|
@staticmethod
|
@@ -480,7 +436,7 @@ class KernelInput(TextArea):
|
|
480
436
|
)
|
481
437
|
async def _show_contextual_help() -> None:
|
482
438
|
"""Display contextual help."""
|
483
|
-
from euporie.core.tabs.
|
439
|
+
from euporie.core.tabs.kernel import KernelTab
|
484
440
|
|
485
441
|
tab = get_app().tab
|
486
442
|
if isinstance(tab, KernelTab) and (input_box := tab.current_input) is not None:
|
@@ -490,7 +446,7 @@ class KernelInput(TextArea):
|
|
490
446
|
@add_cmd(filter=buffer_is_code & buffer_has_focus)
|
491
447
|
def _history_prev() -> None:
|
492
448
|
"""Get the previous history entry."""
|
493
|
-
from euporie.core.app import get_app
|
449
|
+
from euporie.core.app.current import get_app
|
494
450
|
|
495
451
|
get_app().current_buffer.history_backward()
|
496
452
|
|
@@ -498,7 +454,7 @@ class KernelInput(TextArea):
|
|
498
454
|
@add_cmd(filter=buffer_is_code & buffer_has_focus)
|
499
455
|
def _history_next() -> None:
|
500
456
|
"""Get the next history entry."""
|
501
|
-
from euporie.core.app import get_app
|
457
|
+
from euporie.core.app.current import get_app
|
502
458
|
|
503
459
|
get_app().current_buffer.history_forward()
|
504
460
|
|
@@ -506,8 +462,8 @@ class KernelInput(TextArea):
|
|
506
462
|
@add_cmd()
|
507
463
|
def _reformat_input() -> None:
|
508
464
|
"""Format the contents of the current input field."""
|
509
|
-
from euporie.core.app import get_app
|
510
|
-
from euporie.core.tabs.
|
465
|
+
from euporie.core.app.current import get_app
|
466
|
+
from euporie.core.tabs.kernel import KernelTab
|
511
467
|
|
512
468
|
if (
|
513
469
|
(tab := get_app().tab)
|
euporie/core/widgets/layout.py
CHANGED
@@ -35,12 +35,13 @@ from euporie.core.layout.containers import HSplit, VSplit, Window
|
|
35
35
|
from euporie.core.widgets.decor import Border
|
36
36
|
|
37
37
|
if TYPE_CHECKING:
|
38
|
-
from
|
38
|
+
from collections.abc import Sequence
|
39
|
+
from typing import Any, Callable
|
39
40
|
|
40
41
|
from prompt_toolkit.filters import FilterOrBool
|
41
42
|
from prompt_toolkit.formatted_text.base import AnyFormattedText, StyleAndTextTuples
|
42
43
|
from prompt_toolkit.key_binding.key_bindings import (
|
43
|
-
|
44
|
+
KeyBindingsBase,
|
44
45
|
NotImplementedOrNone,
|
45
46
|
)
|
46
47
|
from prompt_toolkit.layout.containers import AnyContainer, Container, _Split
|
@@ -84,7 +85,7 @@ class Box:
|
|
84
85
|
style: str = "",
|
85
86
|
char: None | str | Callable[[], str] = None,
|
86
87
|
modal: bool = False,
|
87
|
-
key_bindings:
|
88
|
+
key_bindings: KeyBindingsBase | None = None,
|
88
89
|
) -> None:
|
89
90
|
"""Initialize this widget."""
|
90
91
|
if padding is None:
|
@@ -117,7 +118,7 @@ class Box:
|
|
117
118
|
height=height,
|
118
119
|
style=style,
|
119
120
|
modal=modal,
|
120
|
-
key_bindings=
|
121
|
+
key_bindings=key_bindings,
|
121
122
|
)
|
122
123
|
|
123
124
|
def __pt_container__(self) -> Container:
|
@@ -155,7 +156,7 @@ class ConditionalSplit:
|
|
155
156
|
return self._cache.get(vertical, partial(self.load_container, vertical))
|
156
157
|
|
157
158
|
def __pt_container__(self) -> AnyContainer:
|
158
|
-
"""Return a
|
159
|
+
"""Return a dynamic container."""
|
159
160
|
return DynamicContainer(self.container)
|
160
161
|
|
161
162
|
|
@@ -287,7 +288,7 @@ class TabBarControl(UIControl):
|
|
287
288
|
|
288
289
|
def is_focusable(self) -> bool:
|
289
290
|
"""Tell whether this user control is focusable."""
|
290
|
-
return
|
291
|
+
return False
|
291
292
|
|
292
293
|
def create_content(self, width: int, height: int) -> UIContent:
|
293
294
|
"""Generate the formatted text fragments which make the controls output."""
|
@@ -0,0 +1,49 @@
|
|
1
|
+
"""Defines a logo widget."""
|
2
|
+
|
3
|
+
from __future__ import annotations
|
4
|
+
|
5
|
+
from typing import TYPE_CHECKING, Callable
|
6
|
+
|
7
|
+
from prompt_toolkit.layout.containers import WindowAlign
|
8
|
+
from prompt_toolkit.layout.controls import FormattedTextControl
|
9
|
+
|
10
|
+
from euporie.core import __logo__
|
11
|
+
from euporie.core.filters import has_tabs
|
12
|
+
from euporie.core.layout.containers import Window
|
13
|
+
|
14
|
+
if TYPE_CHECKING:
|
15
|
+
from typing import Any
|
16
|
+
|
17
|
+
from prompt_toolkit.filters import FilterOrBool
|
18
|
+
from prompt_toolkit.layout.controls import UIControl
|
19
|
+
from prompt_toolkit.layout.dimension import AnyDimension
|
20
|
+
|
21
|
+
|
22
|
+
class Logo(Window):
|
23
|
+
"""A widget to display the application's logo."""
|
24
|
+
|
25
|
+
def __init__(
|
26
|
+
self,
|
27
|
+
content: UIControl | None = None,
|
28
|
+
height: AnyDimension = 1,
|
29
|
+
width: AnyDimension = 3,
|
30
|
+
style: str | Callable[[], str] = "class:menu,logo",
|
31
|
+
dont_extend_width: FilterOrBool = True,
|
32
|
+
align: WindowAlign | Callable[[], WindowAlign] = WindowAlign.CENTER,
|
33
|
+
**kwargs: Any,
|
34
|
+
) -> None:
|
35
|
+
"""Create a new window with defaults specified."""
|
36
|
+
if content is None:
|
37
|
+
content = FormattedTextControl(
|
38
|
+
[("", f" {__logo__} ")],
|
39
|
+
focusable=~has_tabs,
|
40
|
+
show_cursor=False,
|
41
|
+
)
|
42
|
+
super().__init__(
|
43
|
+
content=content,
|
44
|
+
height=height,
|
45
|
+
width=width,
|
46
|
+
style=style,
|
47
|
+
dont_extend_width=dont_extend_width,
|
48
|
+
**kwargs,
|
49
|
+
)
|
euporie/core/widgets/menu.py
CHANGED
@@ -37,14 +37,15 @@ from prompt_toolkit.layout.utils import explode_text_fragments
|
|
37
37
|
from prompt_toolkit.mouse_events import MouseEvent, MouseEventType
|
38
38
|
from prompt_toolkit.utils import get_cwidth
|
39
39
|
|
40
|
+
from euporie.core.app.current import get_app
|
41
|
+
from euporie.core.bars.status import StatusContainer
|
40
42
|
from euporie.core.border import OuterHalfGrid
|
41
|
-
from euporie.core.current import get_app
|
42
43
|
from euporie.core.layout.containers import HSplit, VSplit, Window
|
43
44
|
from euporie.core.widgets.decor import Shadow
|
44
|
-
from euporie.core.widgets.status import StatusContainer
|
45
45
|
|
46
46
|
if TYPE_CHECKING:
|
47
|
-
from
|
47
|
+
from collections.abc import Iterable, Sequence
|
48
|
+
from typing import Any, Callable
|
48
49
|
|
49
50
|
from prompt_toolkit.filters import Filter, FilterOrBool
|
50
51
|
from prompt_toolkit.formatted_text.base import (
|
@@ -57,10 +58,10 @@ if TYPE_CHECKING:
|
|
57
58
|
from prompt_toolkit.layout.containers import AnyContainer
|
58
59
|
from prompt_toolkit.layout.controls import UIControl
|
59
60
|
|
60
|
-
from euporie.core.app import BaseApp
|
61
|
+
from euporie.core.app.app import BaseApp
|
62
|
+
from euporie.core.bars.status import StatusBarFields
|
61
63
|
from euporie.core.border import GridStyle
|
62
64
|
from euporie.core.commands import Command
|
63
|
-
from euporie.core.widgets.status import StatusBarFields
|
64
65
|
|
65
66
|
|
66
67
|
log = logging.getLogger(__name__)
|
@@ -326,7 +327,6 @@ class MenuBar:
|
|
326
327
|
def _cancel(event: KeyPressEvent) -> None:
|
327
328
|
"""Leave menu."""
|
328
329
|
self.selected_menu = []
|
329
|
-
log.debug(self.last_focused)
|
330
330
|
self.refocus()
|
331
331
|
|
332
332
|
# Sub menu navigation.
|
@@ -408,8 +408,6 @@ class MenuBar:
|
|
408
408
|
"""Close the current menu."""
|
409
409
|
if self.selected_menu:
|
410
410
|
self.selected_menu = self.selected_menu[:-1]
|
411
|
-
log.debug(self.selected_menu)
|
412
|
-
log.debug(self.last_focused)
|
413
411
|
self.refocus()
|
414
412
|
|
415
413
|
# Add global CUA menu shortcut
|
@@ -516,20 +514,24 @@ class MenuBar:
|
|
516
514
|
focused = self.focused()
|
517
515
|
|
518
516
|
# This is called during the rendering. When we discover that this
|
519
|
-
# widget doesn't have the focus anymore
|
517
|
+
# widget doesn't have the focus anymore, reset the menu state.
|
520
518
|
if not focused:
|
521
519
|
self.selected_menu = []
|
522
520
|
|
523
521
|
def mouse_handler(index: int, mouse_event: MouseEvent) -> NotImplementedOrNone:
|
524
522
|
focused = self.focused()
|
525
523
|
hover = mouse_event.event_type == MouseEventType.MOUSE_MOVE
|
526
|
-
if mouse_event.event_type == MouseEventType.MOUSE_DOWN or
|
524
|
+
if mouse_event.event_type == MouseEventType.MOUSE_DOWN or (
|
525
|
+
hover and focused
|
526
|
+
):
|
527
527
|
# Toggle focus.
|
528
528
|
if not hover and focused and self.selected_menu == [index]:
|
529
529
|
self.selected_menu = []
|
530
|
-
|
530
|
+
else:
|
531
|
+
self.selected_menu = [index]
|
531
532
|
self.refocus()
|
532
533
|
return None
|
534
|
+
|
533
535
|
return NotImplemented
|
534
536
|
|
535
537
|
results: StyleAndTextTuples = []
|
euporie/core/widgets/pager.py
CHANGED
@@ -9,16 +9,12 @@ from typing import TYPE_CHECKING, NamedTuple
|
|
9
9
|
from prompt_toolkit.filters import Condition
|
10
10
|
from prompt_toolkit.layout.containers import (
|
11
11
|
ConditionalContainer,
|
12
|
-
DynamicContainer,
|
13
12
|
)
|
14
13
|
from prompt_toolkit.layout.dimension import Dimension
|
15
14
|
|
15
|
+
from euporie.core.app.current import get_app
|
16
16
|
from euporie.core.commands import add_cmd
|
17
|
-
from euporie.core.convert.datum import Datum
|
18
|
-
from euporie.core.convert.formats import BASE64_FORMATS
|
19
|
-
from euporie.core.convert.mime import MIME_FORMATS
|
20
17
|
from euporie.core.convert.registry import find_route
|
21
|
-
from euporie.core.current import get_app
|
22
18
|
from euporie.core.filters import pager_has_focus
|
23
19
|
from euporie.core.key_binding.registry import (
|
24
20
|
load_registered_bindings,
|
@@ -67,6 +63,10 @@ class PagerOutputDataElement(CellOutputDataElement):
|
|
67
63
|
metadata: Any metadata relating to the data
|
68
64
|
parent: The parent container the output-element is attached to
|
69
65
|
"""
|
66
|
+
from euporie.core.convert.datum import Datum
|
67
|
+
from euporie.core.convert.formats import BASE64_FORMATS
|
68
|
+
from euporie.core.convert.mime import MIME_FORMATS
|
69
|
+
|
70
70
|
# Get internal format
|
71
71
|
format_ = "ansi"
|
72
72
|
mime_path = PurePath(mime)
|
@@ -106,6 +106,7 @@ class PagerOutput(CellOutput):
|
|
106
106
|
Returns:
|
107
107
|
A :class:`PagerOutputDataElement` container for the currently selected mime-type.
|
108
108
|
"""
|
109
|
+
self._selected_mime = None
|
109
110
|
return PagerOutputDataElement(
|
110
111
|
mime=self.selected_mime,
|
111
112
|
data=self.data[self.selected_mime],
|
@@ -138,15 +139,12 @@ class Pager:
|
|
138
139
|
collapse=False,
|
139
140
|
style="class:pager.border",
|
140
141
|
),
|
141
|
-
Box(
|
142
|
-
DynamicContainer(lambda: self.output),
|
143
|
-
padding=0,
|
144
|
-
padding_left=1,
|
145
|
-
),
|
142
|
+
Box(self.output, padding=0, padding_left=1),
|
146
143
|
],
|
147
144
|
style="class:pager",
|
148
145
|
key_bindings=load_registered_bindings(
|
149
|
-
"euporie.core.widgets.pager.Pager"
|
146
|
+
"euporie.core.widgets.pager.Pager",
|
147
|
+
config=get_app().config,
|
150
148
|
),
|
151
149
|
height=height,
|
152
150
|
),
|
euporie/core/widgets/palette.py
CHANGED
@@ -14,15 +14,15 @@ from prompt_toolkit.layout.containers import ScrollOffsets
|
|
14
14
|
from prompt_toolkit.layout.controls import UIContent, UIControl
|
15
15
|
from prompt_toolkit.mouse_events import MouseEvent, MouseEventType
|
16
16
|
|
17
|
+
from euporie.core.app.current import get_app
|
18
|
+
from euporie.core.bars.status import StatusContainer
|
17
19
|
from euporie.core.commands import Command, add_cmd, commands
|
18
|
-
from euporie.core.current import get_app
|
19
20
|
from euporie.core.key_binding.registry import register_bindings
|
20
21
|
from euporie.core.layout.containers import HSplit, VSplit, Window
|
21
22
|
from euporie.core.layout.decor import FocusedStyle
|
22
23
|
from euporie.core.margins import MarginContainer, ScrollbarMargin
|
23
24
|
from euporie.core.widgets.dialog import Dialog
|
24
25
|
from euporie.core.widgets.forms import Text
|
25
|
-
from euporie.core.widgets.status import StatusContainer
|
26
26
|
|
27
27
|
if TYPE_CHECKING:
|
28
28
|
from prompt_toolkit.buffer import Buffer
|
@@ -31,8 +31,8 @@ if TYPE_CHECKING:
|
|
31
31
|
from prompt_toolkit.key_binding.key_processor import KeyPressEvent
|
32
32
|
from prompt_toolkit.layout.controls import GetLinePrefixCallable
|
33
33
|
|
34
|
-
from euporie.core.app import BaseApp
|
35
|
-
from euporie.core.
|
34
|
+
from euporie.core.app.app import BaseApp
|
35
|
+
from euporie.core.bars.status import StatusBarFields
|
36
36
|
|
37
37
|
log = logging.getLogger(__name__)
|
38
38
|
|
@@ -242,7 +242,7 @@ class CommandPalette(Dialog):
|
|
242
242
|
regex = re.compile(
|
243
243
|
"(?=({}))".format(".*?".join(map(re.escape, buffer.text))), re.IGNORECASE
|
244
244
|
)
|
245
|
-
for cmd in commands.values():
|
245
|
+
for cmd in set(commands.values()):
|
246
246
|
if not cmd.hidden():
|
247
247
|
matches = list(regex.finditer(cmd.title))
|
248
248
|
if matches:
|
@@ -298,7 +298,7 @@ class CommandPalette(Dialog):
|
|
298
298
|
|
299
299
|
register_bindings(
|
300
300
|
{
|
301
|
-
"euporie.core.app.BaseApp": {
|
301
|
+
"euporie.core.app.app:BaseApp": {
|
302
302
|
"show-command-palette": "c-@",
|
303
303
|
}
|
304
304
|
}
|