euporie 2.8.1__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 -93
- 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 +25 -36
- 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 +8 -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.1.dist-info → euporie-2.8.5.dist-info}/METADATA +11 -15
- euporie-2.8.5.dist-info/RECORD +172 -0
- {euporie-2.8.1.dist-info → euporie-2.8.5.dist-info}/WHEEL +1 -1
- {euporie-2.8.1.dist-info → euporie-2.8.5.dist-info}/entry_points.txt +2 -2
- {euporie-2.8.1.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.1.dist-info/RECORD +0 -146
- {euporie-2.8.1.data → euporie-2.8.5.data}/data/share/applications/euporie-console.desktop +0 -0
- {euporie-2.8.1.data → euporie-2.8.5.data}/data/share/applications/euporie-notebook.desktop +0 -0
euporie/core/margins.py
CHANGED
@@ -9,13 +9,15 @@ from typing import TYPE_CHECKING, cast
|
|
9
9
|
|
10
10
|
from prompt_toolkit.data_structures import Point
|
11
11
|
from prompt_toolkit.filters import FilterOrBool, to_filter
|
12
|
+
from prompt_toolkit.layout.containers import ScrollOffsets, WindowRenderInfo
|
12
13
|
from prompt_toolkit.layout.controls import FormattedTextControl
|
13
14
|
from prompt_toolkit.layout.dimension import Dimension
|
14
15
|
from prompt_toolkit.layout.margins import Margin
|
16
|
+
from prompt_toolkit.layout.screen import WritePosition
|
15
17
|
from prompt_toolkit.mouse_events import MouseButton, MouseEventType
|
16
18
|
from prompt_toolkit.mouse_events import MouseEvent as PtkMouseEvent
|
17
19
|
|
18
|
-
from euporie.core.current import get_app
|
20
|
+
from euporie.core.app.current import get_app
|
19
21
|
from euporie.core.key_binding.bindings.mouse import MouseEvent, RelativePosition
|
20
22
|
from euporie.core.layout.containers import Window
|
21
23
|
|
@@ -27,10 +29,10 @@ if TYPE_CHECKING:
|
|
27
29
|
KeyBindingsBase,
|
28
30
|
NotImplementedOrNone,
|
29
31
|
)
|
30
|
-
from prompt_toolkit.layout.containers import Container
|
32
|
+
from prompt_toolkit.layout.containers import Container
|
31
33
|
from prompt_toolkit.layout.controls import UIContent
|
32
34
|
from prompt_toolkit.layout.mouse_handlers import MouseHandlers
|
33
|
-
from prompt_toolkit.layout.screen import Screen
|
35
|
+
from prompt_toolkit.layout.screen import Screen
|
34
36
|
|
35
37
|
from euporie.core.diagnostics import Report
|
36
38
|
|
@@ -49,9 +51,9 @@ class ClickableMargin(Margin, metaclass=ABCMeta):
|
|
49
51
|
|
50
52
|
write_position: WritePosition | None
|
51
53
|
|
52
|
-
def
|
54
|
+
def set_margin_window(self, margin_window: Window) -> None:
|
53
55
|
"""Set the write position of the menu."""
|
54
|
-
self.
|
56
|
+
self.margin_window = margin_window
|
55
57
|
|
56
58
|
|
57
59
|
class MarginContainer(Window):
|
@@ -65,6 +67,9 @@ class MarginContainer(Window):
|
|
65
67
|
self.content = FormattedTextControl(self.create_fragments)
|
66
68
|
self.always_hide_cursor = to_filter(True)
|
67
69
|
|
70
|
+
if isinstance(self.margin, ClickableMargin):
|
71
|
+
self.margin.set_margin_window(self)
|
72
|
+
|
68
73
|
def create_fragments(self) -> StyleAndTextTuples:
|
69
74
|
"""Generate text fragments to display."""
|
70
75
|
return self.margin.create_margin(
|
@@ -102,8 +107,6 @@ class MarginContainer(Window):
|
|
102
107
|
) -> None:
|
103
108
|
"""Write the actual content to the screen."""
|
104
109
|
self.write_position = write_position
|
105
|
-
if isinstance(self.margin, ClickableMargin):
|
106
|
-
self.margin.set_write_position(write_position)
|
107
110
|
|
108
111
|
margin_content: UIContent = self.content.create_content(
|
109
112
|
write_position.width + 1, write_position.height
|
@@ -112,6 +115,21 @@ class MarginContainer(Window):
|
|
112
115
|
margin_content, screen, write_position, 0, write_position.width
|
113
116
|
)
|
114
117
|
|
118
|
+
self.render_info = WindowRenderInfo(
|
119
|
+
window=self,
|
120
|
+
ui_content=margin_content,
|
121
|
+
horizontal_scroll=0,
|
122
|
+
vertical_scroll=0,
|
123
|
+
window_width=write_position.width,
|
124
|
+
window_height=write_position.height,
|
125
|
+
configured_scroll_offsets=ScrollOffsets(),
|
126
|
+
visible_line_to_row_col=visible_line_to_row_col,
|
127
|
+
rowcol_to_yx=rowcol_to_yx,
|
128
|
+
x_offset=write_position.xpos,
|
129
|
+
y_offset=write_position.ypos,
|
130
|
+
wrap_lines=False,
|
131
|
+
)
|
132
|
+
|
115
133
|
# Set mouse handlers.
|
116
134
|
def mouse_handler(mouse_event: PtkMouseEvent) -> NotImplementedOrNone:
|
117
135
|
"""Turn screen coordinates into line coordinates."""
|
@@ -164,6 +182,8 @@ class MarginContainer(Window):
|
|
164
182
|
handler=mouse_handler,
|
165
183
|
)
|
166
184
|
|
185
|
+
screen.visible_windows_to_write_positions[self] = write_position
|
186
|
+
|
167
187
|
def is_modal(self) -> bool:
|
168
188
|
"""When this container is modal."""
|
169
189
|
return False
|
@@ -214,8 +234,7 @@ class ScrollbarMargin(ClickableMargin):
|
|
214
234
|
self.thumb_top = 0.0
|
215
235
|
self.thumb_size = 0.0
|
216
236
|
|
217
|
-
self.
|
218
|
-
self.write_position: WritePosition | None = None
|
237
|
+
self.target_render_info: WindowRenderInfo | None = None
|
219
238
|
|
220
239
|
def get_width(self, get_ui_content: Callable[[], UIContent]) -> int:
|
221
240
|
"""Return the scrollbar width: always 1."""
|
@@ -226,13 +245,11 @@ class ScrollbarMargin(ClickableMargin):
|
|
226
245
|
window_render_info: WindowRenderInfo | None,
|
227
246
|
width: int,
|
228
247
|
height: int,
|
229
|
-
margin_render_info: WindowRenderInfo | None = None,
|
230
248
|
) -> StyleAndTextTuples:
|
231
249
|
"""Create the margin's formatted text."""
|
232
250
|
result: StyleAndTextTuples = []
|
233
251
|
|
234
|
-
self.
|
235
|
-
self.margin_render_info = margin_render_info
|
252
|
+
self.target_render_info = window_render_info
|
236
253
|
|
237
254
|
# If this is the first time the target is being drawn, it may not yet have a
|
238
255
|
# render_info yet. Thus, invalidate the app so we can immediately redraw the
|
@@ -400,11 +417,11 @@ class ScrollbarMargin(ClickableMargin):
|
|
400
417
|
:py:const:`None` is returned when the mouse event is handled successfully
|
401
418
|
|
402
419
|
"""
|
403
|
-
|
404
|
-
if
|
420
|
+
target_render_info = self.target_render_info
|
421
|
+
if target_render_info is None:
|
405
422
|
return NotImplemented
|
406
423
|
|
407
|
-
content_height =
|
424
|
+
content_height = target_render_info.content_height
|
408
425
|
if isinstance(mouse_event, MouseEvent):
|
409
426
|
cell_position = mouse_event.cell_position
|
410
427
|
else:
|
@@ -413,9 +430,9 @@ class ScrollbarMargin(ClickableMargin):
|
|
413
430
|
|
414
431
|
# Handle scroll events on the scrollbar
|
415
432
|
if mouse_event.event_type == MouseEventType.SCROLL_UP:
|
416
|
-
|
433
|
+
target_render_info.window._scroll_up()
|
417
434
|
elif mouse_event.event_type == MouseEventType.SCROLL_DOWN:
|
418
|
-
|
435
|
+
target_render_info.window._scroll_down()
|
419
436
|
|
420
437
|
# Mouse drag events
|
421
438
|
elif self.dragging and mouse_event.event_type == MouseEventType.MOUSE_MOVE:
|
@@ -425,8 +442,8 @@ class ScrollbarMargin(ClickableMargin):
|
|
425
442
|
+ 0.5
|
426
443
|
)
|
427
444
|
# Use the window's current vertical scroll as it may have changed since the
|
428
|
-
#
|
429
|
-
window =
|
445
|
+
# target_render_info was generated
|
446
|
+
window = target_render_info.window
|
430
447
|
delta = window.vertical_scroll - target_scroll
|
431
448
|
|
432
449
|
if isinstance(window, Window):
|
@@ -435,7 +452,7 @@ class ScrollbarMargin(ClickableMargin):
|
|
435
452
|
func()
|
436
453
|
# Hack to speed up scrolling on the :py:`ScrollingContainer`
|
437
454
|
elif hasattr(window, "scrolling"):
|
438
|
-
setattr(
|
455
|
+
setattr(target_render_info.window, "scrolling", delta) # noqa: B010
|
439
456
|
|
440
457
|
# Mouse down events
|
441
458
|
elif mouse_event.event_type == MouseEventType.MOUSE_DOWN:
|
@@ -443,20 +460,30 @@ class ScrollbarMargin(ClickableMargin):
|
|
443
460
|
arrows = self.display_arrows()
|
444
461
|
if arrows and int(row) == 0:
|
445
462
|
offset = -1
|
446
|
-
elif arrows and int(row) ==
|
463
|
+
elif arrows and int(row) == target_render_info.window_height - 1:
|
447
464
|
offset = 1
|
448
465
|
# Scroll up or down one page if clicking on the background
|
449
466
|
elif row < self.thumb_top + 1 or self.thumb_top + 1 + self.thumb_size < row:
|
450
467
|
direction = (row < (self.thumb_top + self.thumb_size // 2)) * -2 + 1
|
451
|
-
offset = direction *
|
468
|
+
offset = direction * target_render_info.window_height
|
452
469
|
# We are on the scroll button - start a drag event if this is not a
|
453
470
|
# repeated mouse event
|
454
471
|
elif not repeated:
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
472
|
+
# Restrict mouse events to the scrollbar's area. Recalculate the area
|
473
|
+
# based on the margin's window's render_info, in case this is not the
|
474
|
+
# main screen
|
475
|
+
if margin_render_info := self.margin_window.render_info:
|
476
|
+
y_min, x_min = min(margin_render_info._rowcol_to_yx.values())
|
477
|
+
y_max, x_max = max(margin_render_info._rowcol_to_yx.values())
|
478
|
+
get_app().mouse_limits = WritePosition(
|
479
|
+
xpos=x_min,
|
480
|
+
ypos=y_min,
|
481
|
+
width=x_max - x_min + 1,
|
482
|
+
height=y_max - y_min + 1,
|
483
|
+
)
|
484
|
+
self.dragging = True
|
485
|
+
self.drag_start_scroll = target_render_info.vertical_scroll
|
486
|
+
self.drag_start_offset = row - self.thumb_top
|
460
487
|
return None
|
461
488
|
# Otherwise this is a click on the centre scroll button - do nothing
|
462
489
|
else:
|
@@ -465,9 +492,9 @@ class ScrollbarMargin(ClickableMargin):
|
|
465
492
|
if mouse_event.button == MouseButton.LEFT:
|
466
493
|
func = None
|
467
494
|
if offset < 0:
|
468
|
-
func =
|
495
|
+
func = target_render_info.window._scroll_up
|
469
496
|
elif offset > 0:
|
470
|
-
func =
|
497
|
+
func = target_render_info.window._scroll_down
|
471
498
|
if func is not None:
|
472
499
|
# Scroll the window multiple times to scroll by the offset
|
473
500
|
for _ in range(abs(int(offset))):
|
@@ -517,7 +544,7 @@ class NumberedMargin(Margin):
|
|
517
544
|
def get_width(self, get_ui_content: Callable[[], UIContent]) -> int:
|
518
545
|
"""Return the width of the margin."""
|
519
546
|
line_count = get_ui_content().line_count
|
520
|
-
return len("
|
547
|
+
return len(f"{line_count}") + 2
|
521
548
|
|
522
549
|
def create_margin(
|
523
550
|
self, window_render_info: WindowRenderInfo, width: int, height: int
|
@@ -561,8 +588,10 @@ class NumberedMargin(Margin):
|
|
561
588
|
style = f"{self_style} class:line-number.current"
|
562
589
|
else:
|
563
590
|
style = self_style
|
591
|
+
if last_lineno is None and lineno == 0 and not multiline:
|
592
|
+
linestr = ">"
|
564
593
|
# Only display line number if this line is not a continuation of the previous line.
|
565
|
-
|
594
|
+
elif lineno != last_lineno:
|
566
595
|
linestr = str(lineno + 1).rjust(width - 2)
|
567
596
|
else:
|
568
597
|
linestr = " " * (width - 2)
|
euporie/core/path.py
CHANGED
@@ -13,8 +13,9 @@ from fsspec.registry import register_implementation as fs_register_implementatio
|
|
13
13
|
from upath import UPath
|
14
14
|
|
15
15
|
if TYPE_CHECKING:
|
16
|
+
from collections.abc import Mapping
|
16
17
|
from os import PathLike
|
17
|
-
from typing import Any
|
18
|
+
from typing import Any
|
18
19
|
|
19
20
|
|
20
21
|
log = logging.getLogger(__name__)
|
euporie/core/renderer.py
CHANGED
@@ -3,11 +3,13 @@
|
|
3
3
|
from __future__ import annotations
|
4
4
|
|
5
5
|
import logging
|
6
|
+
from hashlib import md5
|
6
7
|
from typing import TYPE_CHECKING
|
7
8
|
|
8
9
|
from prompt_toolkit.data_structures import Point, Size
|
9
10
|
from prompt_toolkit.filters import to_filter
|
10
11
|
from prompt_toolkit.layout.mouse_handlers import MouseHandlers
|
12
|
+
from prompt_toolkit.layout.screen import Char
|
11
13
|
from prompt_toolkit.renderer import Renderer as PtkRenderer
|
12
14
|
from prompt_toolkit.renderer import _StyleStringHasStyleCache, _StyleStringToAttrsCache
|
13
15
|
|
@@ -25,7 +27,6 @@ if TYPE_CHECKING:
|
|
25
27
|
from prompt_toolkit.output import ColorDepth, Output
|
26
28
|
from prompt_toolkit.styles import BaseStyle
|
27
29
|
|
28
|
-
|
29
30
|
__all__ = ["Renderer"]
|
30
31
|
|
31
32
|
log = logging.getLogger(__name__)
|
@@ -117,19 +118,27 @@ def _output_screen_diff(
|
|
117
118
|
write(char.char)
|
118
119
|
last_style = char.style
|
119
120
|
|
121
|
+
def hash_screen_row(row: dict[int, Char], zwe_row: dict[int, str]) -> str:
|
122
|
+
"""Generate a hash for a screen row to quickly detect changes."""
|
123
|
+
hasher = md5(usedforsecurity=False)
|
124
|
+
# Hash the character data
|
125
|
+
for idx in sorted(row.keys()):
|
126
|
+
cell = row[idx]
|
127
|
+
hasher.update(f"{idx}:{cell.char}:{cell.style}".encode())
|
128
|
+
# Hash the zero-width escapes
|
129
|
+
for idx in sorted(zwe_row.keys()):
|
130
|
+
hasher.update(f"{idx}:{zwe_row[idx]}".encode())
|
131
|
+
return hasher.hexdigest()
|
132
|
+
|
120
133
|
def get_max_column_index(row: dict[int, Char], zwe_row: dict[int, str]) -> int:
|
121
134
|
"""Return max used column index, ignoring trailing unstyled whitespace."""
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
# but we don't want that to count towards the line width
|
130
|
-
| {x - 1 for x in zwe_row}
|
131
|
-
| {0}
|
132
|
-
)
|
135
|
+
max_idx = 0
|
136
|
+
for idx, cell in row.items():
|
137
|
+
if cell.char != " " or style_string_has_style[cell.style]:
|
138
|
+
max_idx = max(max_idx, idx)
|
139
|
+
for idx in zwe_row:
|
140
|
+
max_idx = max(max_idx, idx - 1)
|
141
|
+
return max_idx
|
133
142
|
|
134
143
|
# Render for the first time: reset styling.
|
135
144
|
if not previous_screen:
|
@@ -169,6 +178,14 @@ def _output_screen_diff(
|
|
169
178
|
zwe_row = screen.zero_width_escapes[y]
|
170
179
|
previous_zwe_row = previous_screen.zero_width_escapes[y]
|
171
180
|
|
181
|
+
# Quick comparison using row hashes
|
182
|
+
new_hash = hash_screen_row(new_row, zwe_row)
|
183
|
+
prev_hash = hash_screen_row(previous_row, previous_zwe_row)
|
184
|
+
|
185
|
+
if new_hash == prev_hash:
|
186
|
+
# Rows are identical, skip to next row
|
187
|
+
continue
|
188
|
+
|
172
189
|
new_max_line_len = min(width - 1, get_max_column_index(new_row, zwe_row))
|
173
190
|
previous_max_line_len = min(
|
174
191
|
width - 1, get_max_column_index(previous_row, previous_zwe_row)
|
@@ -275,26 +292,34 @@ class Renderer(PtkRenderer):
|
|
275
292
|
)
|
276
293
|
self._extended_keys_enabled = False
|
277
294
|
self._private_sixel_colors_enabled = False
|
295
|
+
self._sgr_pixel_enabled = False
|
278
296
|
self.extend_height = to_filter(extend_height)
|
279
297
|
self.extend_width = to_filter(extend_width)
|
280
298
|
|
281
299
|
def reset(self, _scroll: bool = False, leave_alternate_screen: bool = True) -> None:
|
282
300
|
"""Reset the output."""
|
283
|
-
|
301
|
+
output = self.output
|
302
|
+
if isinstance(output, Vt100_Output):
|
284
303
|
# Disable extended keys before resetting the output
|
285
|
-
|
304
|
+
output.disable_extended_keys()
|
286
305
|
self._extended_keys_enabled = False
|
287
306
|
|
288
307
|
# Disable private sixel colors before resetting the output
|
289
|
-
|
308
|
+
output.disable_private_sixel_colors()
|
290
309
|
self._private_sixel_colors_enabled = False
|
291
310
|
|
311
|
+
# Disable sgr pixel mode
|
312
|
+
output.disable_sgr_pixel()
|
313
|
+
self._sgr_pixel_enabled = False
|
314
|
+
|
292
315
|
super().reset(_scroll, leave_alternate_screen)
|
293
316
|
|
294
317
|
def render(
|
295
318
|
self, app: Application[Any], layout: Layout, is_done: bool = False
|
296
319
|
) -> None:
|
297
320
|
"""Render the current interface to the output."""
|
321
|
+
from euporie.core.app.app import BaseApp
|
322
|
+
|
298
323
|
output = self.output
|
299
324
|
self.app = app
|
300
325
|
|
@@ -320,13 +345,29 @@ class Renderer(PtkRenderer):
|
|
320
345
|
output.enable_mouse_support()
|
321
346
|
self._mouse_support_enabled = True
|
322
347
|
|
348
|
+
if (
|
349
|
+
isinstance(output, Vt100_Output)
|
350
|
+
and isinstance(app, BaseApp)
|
351
|
+
and app.term_sgr_pixel
|
352
|
+
):
|
353
|
+
output.enable_sgr_pixel()
|
354
|
+
self._sgr_pixel_enabled = True
|
355
|
+
|
323
356
|
elif not needs_mouse_support and self._mouse_support_enabled:
|
324
357
|
output.disable_mouse_support()
|
325
358
|
self._mouse_support_enabled = False
|
326
359
|
|
360
|
+
if (
|
361
|
+
isinstance(output, Vt100_Output)
|
362
|
+
and isinstance(app, BaseApp)
|
363
|
+
and (app.term_sgr_pixel or self._sgr_pixel_enabled)
|
364
|
+
):
|
365
|
+
output.disable_sgr_pixel()
|
366
|
+
self._sgr_pixel_enabled = False
|
367
|
+
|
327
368
|
# Ensable extended keys
|
328
|
-
if not self._extended_keys_enabled and isinstance(
|
329
|
-
|
369
|
+
if not self._extended_keys_enabled and isinstance(output, Vt100_Output):
|
370
|
+
output.enable_extended_keys()
|
330
371
|
self._extended_keys_enabled = True
|
331
372
|
|
332
373
|
# Ensable private sixel graphic color registers
|
euporie/core/style.py
CHANGED
@@ -4,16 +4,19 @@ from __future__ import annotations
|
|
4
4
|
|
5
5
|
import logging
|
6
6
|
from colorsys import hls_to_rgb, rgb_to_hls
|
7
|
-
from functools import partial
|
7
|
+
from functools import cache, partial
|
8
8
|
from typing import TYPE_CHECKING
|
9
9
|
|
10
10
|
from prompt_toolkit.cache import SimpleCache
|
11
11
|
from prompt_toolkit.styles.defaults import default_ui_style
|
12
12
|
from prompt_toolkit.styles.style import Style
|
13
|
+
from pygments.styles import get_style_by_name as pyg_get_style_by_name
|
13
14
|
|
14
15
|
if TYPE_CHECKING:
|
15
16
|
from typing import Any
|
16
17
|
|
18
|
+
from pygments.style import Style as PygmentsStyle
|
19
|
+
|
17
20
|
|
18
21
|
log = logging.getLogger(__name__)
|
19
22
|
|
@@ -207,9 +210,9 @@ IPYWIDGET_STYLE = [
|
|
207
210
|
class ColorPaletteColor:
|
208
211
|
"""A representation of a color with adjustment methods."""
|
209
212
|
|
210
|
-
_cache: SimpleCache[
|
211
|
-
|
212
|
-
|
213
|
+
_cache: SimpleCache[tuple[str, float, float, float, bool], ColorPaletteColor] = (
|
214
|
+
SimpleCache()
|
215
|
+
)
|
213
216
|
|
214
217
|
def __init__(self, base: str, _base_override: str = "") -> None:
|
215
218
|
"""Create a new color.
|
@@ -440,8 +443,8 @@ def build_style(
|
|
440
443
|
# Statusbar
|
441
444
|
# "status": f"fg:{cp.fg.more(0.05)} bg:{cp.bg.less(0.15)}",
|
442
445
|
"status": f"fg:{cp.fg.more(0.05)} bg:{cp.bg.more(0.05)}",
|
443
|
-
"status-field": f"
|
444
|
-
"status-sep": f"
|
446
|
+
"status-field": f"bg:{cp.fg.more(0.1)} fg:{cp.bg.more(0.1)} reverse",
|
447
|
+
"status-sep": f"bg:{cp.bg.more(0.05)} fg:{cp.bg.more(0.1)} reverse",
|
445
448
|
# Menus & Menu bar
|
446
449
|
"menu": f"fg:{cp.fg.more(0.05)} bg:{cp.bg.more(0.05)}",
|
447
450
|
"menu bar": f"bg:{cp.bg.less(0.15)}",
|
@@ -450,11 +453,11 @@ def build_style(
|
|
450
453
|
"menu shortcut disabled": f"fg:{cp.fg.more(0.4).towards(cp.bg, 0.5)}",
|
451
454
|
"menu prefix": f"fg:{cp.fg.more(0.2)}",
|
452
455
|
"menu prefix disabled": f"fg:{cp.fg.more(0.2).towards(cp.bg, 0.5)}",
|
453
|
-
"menu selection": f"
|
454
|
-
"menu selection shortcut": f"
|
455
|
-
"menu selection prefix": f"
|
456
|
+
"menu selection": f"bg:{cp.hl.more(1)} fg:{cp.hl} reverse",
|
457
|
+
"menu selection shortcut": f"bg:{cp.hl.more(1).more(0.05)} fg:{cp.hl} reverse",
|
458
|
+
"menu selection prefix": f"bg:{cp.hl.more(1).more(0.05)} fg:{cp.hl} reverse",
|
456
459
|
"menu border": f"fg:{cp.bg.more(0.15)} bg:{cp.bg.more(0.05)}",
|
457
|
-
"menu border selection": f"bg:{cp.hl}",
|
460
|
+
"menu border selection": f"fg:{cp.bg.more(0.15)} bg:{cp.hl} noreverse",
|
458
461
|
# Tab bar
|
459
462
|
"app-tab-bar": f"bg:{cp.bg.less(0.15)}",
|
460
463
|
"app-tab-bar border": f"fg:{cp.bg.more(0.1)}",
|
@@ -466,10 +469,10 @@ def build_style(
|
|
466
469
|
# Tabs
|
467
470
|
"loading": "fg:#888888",
|
468
471
|
# Buffer
|
469
|
-
"line-number": f"
|
470
|
-
"line-number.current": f"
|
471
|
-
"line-number edge": f"
|
472
|
-
"line-number.current edge": f"
|
472
|
+
"line-number": f"bg:{cp.fg.more(0.5)} fg:{cp.bg.more(0.05)} reverse",
|
473
|
+
"line-number.current": f"bg:orange fg:{cp.bg.more(0.1)} bold",
|
474
|
+
"line-number edge": f"bg:{cp.bg.darker(0.1)}",
|
475
|
+
"line-number.current edge": f"bg:{cp.bg.darker(0.1)}",
|
473
476
|
"cursor-line": f"bg:{cp.bg.more(0.05)}",
|
474
477
|
"cursor-line search": f"bg:{cp.bg.more(0.02)}",
|
475
478
|
"cursor-line search.current": f"bg:{cp.bg.more(0.02)}",
|
@@ -479,13 +482,11 @@ def build_style(
|
|
479
482
|
"matching-bracket.other": "fg:yellow bold",
|
480
483
|
"trailing-whitespace": f"fg:{cp.fg.more(0.66)}",
|
481
484
|
"tab": f"fg:{cp.fg.more(0.66)}",
|
482
|
-
# Search
|
485
|
+
# Search results
|
483
486
|
"search": f"bg:{cp.bg.more(0.05)}",
|
484
487
|
"search.current": f"bg:{cp.bg.more(0.05)}",
|
485
488
|
"incsearch": "bg:ansibrightyellow",
|
486
489
|
"incsearch.current": "bg:ansibrightgreen",
|
487
|
-
"search-toolbar": f"fg:{cp.fg.more(0.05)} bg:{cp.bg.more(0.05)}",
|
488
|
-
"search-toolbar.title": f"fg:{cp.fg.more(0.1)} bg:{cp.bg.more(0.1)}",
|
489
490
|
# Inputs
|
490
491
|
"kernel-input": f"fg:default bg:{cp.bg.more(0.02)}",
|
491
492
|
# Cells
|
@@ -496,20 +497,22 @@ def build_style(
|
|
496
497
|
"cell border edit": f"fg:{cp.hl.adjust(hue=-0.3333, rel=False)}",
|
497
498
|
"cell input prompt": "fg:blue",
|
498
499
|
"cell output prompt": "fg:red",
|
499
|
-
"cell show outputs": "bg
|
500
|
-
"cell show inputs": "bg
|
500
|
+
"cell show outputs": f"bg:{cp.fg.more(0.5)} fg:{cp.bg.more(0.05)} reverse",
|
501
|
+
"cell show inputs": f"bg:{cp.fg.more(0.5)} fg:{cp.bg.more(0.05)} reverse",
|
502
|
+
"cell show inputs border": f"bg:{cp.bg.darker(0.1)} fg:{cp.bg.more(0.05)} reverse",
|
503
|
+
"cell show outputs border": f"bg:{cp.bg.darker(0.1)} fg:{cp.bg.more(0.05)} reverse",
|
501
504
|
# Scrollbars
|
502
505
|
"scrollbar": f"fg:{cp.bg.more(0.75)} bg:{cp.bg.more(0.15)}",
|
503
506
|
"scrollbar.background": f"fg:{cp.bg.more(0.75)} bg:{cp.bg.more(0.15)}",
|
504
|
-
"scrollbar.arrow": f"
|
507
|
+
"scrollbar.arrow": f"bg:{cp.bg.more(0.75)} fg:{cp.bg.more(0.20)} reverse",
|
505
508
|
"scrollbar.start": "",
|
506
509
|
# "scrollbar.start": f"fg:{cp.bg.more(0.75)} bg:{cp.bg.more(0.25)}",
|
507
|
-
"scrollbar.button": f"
|
508
|
-
"scrollbar.end": f"
|
510
|
+
"scrollbar.button": f"bg:{cp.bg.more(0.75)} fg:{cp.bg.more(0.75)} reverse",
|
511
|
+
"scrollbar.end": f"bg:{cp.bg.more(0.15)} fg:{cp.bg.more(0.75)} reverse",
|
509
512
|
# Overflow margin
|
510
513
|
"overflow": f"fg:{cp.fg.more(0.5)}",
|
511
514
|
# Dialogs
|
512
|
-
"dialog dialog-title": f"
|
515
|
+
"dialog dialog-title": f"bg:white fg:{cp.hl.darker(0.25)} bold reverse",
|
513
516
|
"dialog": f"fg:{cp.fg.base} bg:{cp.bg.darker(0.1)}",
|
514
517
|
"dialog text-area": f"bg:{cp.bg.lighter(0.05)}",
|
515
518
|
"dialog input text text-area": f"fg:default bg:{cp.bg.less(0.1)}",
|
@@ -517,6 +520,17 @@ def build_style(
|
|
517
520
|
"dialog border": f"fg:{cp.bg.darker(0.1).more(0.1)}",
|
518
521
|
# Horizontals rule
|
519
522
|
"hr": "fg:ansired",
|
523
|
+
# Toolbars
|
524
|
+
"toolbar": f"fg:{cp.fg.more(0.05)} bg:{cp.bg.more(0.05)}",
|
525
|
+
"toolbar.title": f"fg:{cp.fg.more(0.1)} bg:{cp.bg.more(0.1)}",
|
526
|
+
# Search bar
|
527
|
+
"search-toolbar": f"fg:{cp.fg.more(0.05)} bg:{cp.bg.more(0.05)}",
|
528
|
+
# Command bar
|
529
|
+
"toolbar menu": f"fg:{cp.fg.more(0.05)} bg:{cp.bg.more(0.05)}",
|
530
|
+
"toolbar menu completion": f"fg:{cp.fg.more(0.1)} bg:{cp.bg.more(0.1)}",
|
531
|
+
"toolbar menu completion current": f"fg:{cp.hl} bg:{cp.fg} reverse",
|
532
|
+
"toolbar menu overflow": f"fg:{cp.fg.more(0.5)}",
|
533
|
+
"toolbar menu meta": f"bg:{cp.bg.more(0.25)} bold",
|
520
534
|
# Completions menu
|
521
535
|
"menu completion-keyword": "fg:#d700af",
|
522
536
|
"menu completion-function": "fg:#005faf",
|
@@ -528,28 +542,28 @@ def build_style(
|
|
528
542
|
"menu completion-path": "fg:#aa8800",
|
529
543
|
"menu completion-dict-key": "fg:#ddbb00",
|
530
544
|
"menu selection completion-keyword": (
|
531
|
-
f"
|
545
|
+
f"bg:{ColorPaletteColor('#d700af').lighter(0.75)} fg:{cp.hl} reverse"
|
532
546
|
),
|
533
547
|
"menu selection completion-function": (
|
534
|
-
f"
|
548
|
+
f"bg:{ColorPaletteColor('#005faf').lighter(0.75)} fg:{cp.hl} reverse"
|
535
549
|
),
|
536
550
|
"menu selection completion-class": (
|
537
|
-
f"
|
551
|
+
f"bg:{ColorPaletteColor('#008700').lighter(0.75)} fg:{cp.hl} reverse"
|
538
552
|
),
|
539
553
|
"menu selection completion-statement": (
|
540
|
-
f"
|
554
|
+
f"bg:{ColorPaletteColor('#5f0000').lighter(0.75)} fg:{cp.hl} reverse"
|
541
555
|
),
|
542
556
|
"menu selection completion-instance": (
|
543
|
-
f"
|
557
|
+
f"bg:{ColorPaletteColor('#d75f00').lighter(0.75)} fg:{cp.hl} reverse"
|
544
558
|
),
|
545
559
|
"menu selection completion-module": (
|
546
|
-
f"
|
560
|
+
f"bg:{ColorPaletteColor('#d70000').lighter(0.75)} fg:{cp.hl} reverse"
|
547
561
|
),
|
548
562
|
"menu selection completion-magic": (
|
549
|
-
f"
|
563
|
+
f"bg:{ColorPaletteColor('#888888').lighter(0.75)} fg:{cp.hl} reverse"
|
550
564
|
),
|
551
565
|
"menu selection completion-path": (
|
552
|
-
f"
|
566
|
+
f"bg:{ColorPaletteColor('#aa8800').lighter(0.75)} fg:{cp.hl} reverse"
|
553
567
|
),
|
554
568
|
# Log
|
555
569
|
"log.level.nonset": "fg:grey",
|
@@ -565,7 +579,7 @@ def build_style(
|
|
565
579
|
"file-browser face": f"bg:{cp.bg.lighter(0.1)}",
|
566
580
|
"file-browser face row alt-row": f"bg:{cp.bg.lighter(0.1).more(0.01)}",
|
567
581
|
"file-browser face row hovered": f"bg:{cp.bg.more(0.2)}",
|
568
|
-
"file-browser face row selection": f"bg:{cp.hl}",
|
582
|
+
"file-browser face row selection": f"bg:{cp.fg} fg:{cp.hl} reverse",
|
569
583
|
# Shortcuts
|
570
584
|
"shortcuts.group": f"bg:{cp.bg.more(0.4)} bold underline",
|
571
585
|
# "shortcuts.row": f"bg:{cp.bg.base} nobold",
|
@@ -574,7 +588,7 @@ def build_style(
|
|
574
588
|
# Palette
|
575
589
|
"palette.item": f"fg:{cp.fg.more(0.05)} bg:{cp.bg.more(0.05)}",
|
576
590
|
"palette.item.alt": f"bg:{cp.bg.more(0.15)}",
|
577
|
-
"palette.item.selected": f"
|
591
|
+
"palette.item.selected": f"bg:{cp.hl.more(1)} fg:{cp.hl} reverse",
|
578
592
|
# Pager
|
579
593
|
"pager": f"bg:{cp.bg.more(0.05)}",
|
580
594
|
"pager.border": f"fg:{cp.bg.towards(cp.ansiblack, 0.15)} reverse",
|
@@ -594,13 +608,13 @@ def build_style(
|
|
594
608
|
"side_bar border outer": f"bg:{cp.bg}",
|
595
609
|
"side_bar buttons": f"bg:{cp.bg.less(0.15)}",
|
596
610
|
"side_bar buttons hovered": f"fg:{cp.hl}",
|
597
|
-
"side_bar buttons
|
598
|
-
"side_bar buttons
|
611
|
+
"side_bar buttons separator": f"bg:{cp.bg.less(0.15)} fg:{cp.bg.less(0.15)}",
|
612
|
+
"side_bar buttons selection": f"bg:{cp.fg} fg:{cp.hl} reverse",
|
599
613
|
"side_bar buttons separator selection before": (
|
600
|
-
f"
|
614
|
+
f"bg:{cp.bg.less(0.15)} fg:{cp.hl} reverse"
|
601
615
|
),
|
602
616
|
"side_bar buttons separator selection after": (
|
603
|
-
f"fg:{cp.hl} bg:{cp.bg.less(0.15)}"
|
617
|
+
f"fg:{cp.hl} bg:{cp.bg.less(0.15)} noreverse"
|
604
618
|
),
|
605
619
|
# Tabbed split
|
606
620
|
"tabbed-split border": f"fg:{cp.bg.more(0.2)}",
|
@@ -675,9 +689,9 @@ def build_style(
|
|
675
689
|
"text-area focused selected": "reverse",
|
676
690
|
# Buttons
|
677
691
|
"input button face": f"fg:default bg:{cp.bg.more(0.05)}",
|
678
|
-
"input button face hovered": f"fg:
|
679
|
-
"input button face selection": f"bg:{cp.bg.more(0.05)}",
|
680
|
-
"input button face focused": f"fg
|
692
|
+
"input button face hovered": f"fg:{cp.fg} bg:{cp.bg.more(0.2)}",
|
693
|
+
"input button face selection": f"bg:{cp.fg} fg:{cp.bg.more(0.05)} reverse",
|
694
|
+
"input button face focused": f"bg:{cp.fg} fg:{cp.bg.towards(cp.hl, 0.1)} reverse",
|
681
695
|
# Input widgets
|
682
696
|
"input border top": f"fg:{cp.bg.lighter(0.5)}",
|
683
697
|
"input border left": f"fg:{cp.bg.lighter(0.5)}",
|
@@ -751,3 +765,9 @@ def build_style(
|
|
751
765
|
}
|
752
766
|
|
753
767
|
return Style.from_dict(style_dict)
|
768
|
+
|
769
|
+
|
770
|
+
@cache
|
771
|
+
def get_style_by_name(name: str) -> type[PygmentsStyle]:
|
772
|
+
"""Get Pygments style, caching the result."""
|
773
|
+
return pyg_get_style_by_name(name)
|