euporie 2.3.2__py3-none-any.whl → 2.4.1__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/__main__.py +3 -1
- euporie/console/app.py +6 -4
- euporie/console/tabs/console.py +34 -9
- euporie/core/__init__.py +6 -1
- euporie/core/__main__.py +1 -1
- euporie/core/app.py +79 -109
- euporie/core/border.py +44 -14
- euporie/core/comm/base.py +5 -4
- euporie/core/comm/ipywidgets.py +11 -11
- euporie/core/comm/registry.py +12 -6
- euporie/core/commands.py +30 -23
- euporie/core/completion.py +1 -4
- euporie/core/config.py +15 -5
- euporie/core/convert/{base.py → core.py} +117 -53
- euporie/core/convert/formats/ansi.py +46 -25
- euporie/core/convert/formats/base64.py +3 -3
- euporie/core/convert/formats/common.py +38 -13
- euporie/core/convert/formats/formatted_text.py +54 -12
- euporie/core/convert/formats/html.py +5 -5
- euporie/core/convert/formats/jpeg.py +1 -1
- euporie/core/convert/formats/markdown.py +4 -4
- euporie/core/convert/formats/pdf.py +1 -1
- euporie/core/convert/formats/pil.py +5 -3
- euporie/core/convert/formats/png.py +7 -6
- euporie/core/convert/formats/rich.py +4 -3
- euporie/core/convert/formats/sixel.py +5 -5
- euporie/core/convert/utils.py +1 -1
- euporie/core/current.py +11 -5
- euporie/core/formatted_text/ansi.py +4 -8
- euporie/core/formatted_text/html.py +1630 -856
- euporie/core/formatted_text/markdown.py +177 -166
- euporie/core/formatted_text/table.py +20 -14
- euporie/core/formatted_text/utils.py +21 -10
- euporie/core/io.py +14 -14
- euporie/core/kernel.py +48 -37
- euporie/core/key_binding/bindings/micro.py +5 -1
- euporie/core/key_binding/bindings/mouse.py +2 -2
- euporie/core/keys.py +3 -0
- euporie/core/launch.py +5 -2
- euporie/core/lexers.py +13 -2
- euporie/core/log.py +135 -139
- euporie/core/margins.py +32 -14
- euporie/core/path.py +273 -0
- euporie/core/processors.py +35 -0
- euporie/core/renderer.py +21 -5
- euporie/core/style.py +34 -19
- euporie/core/tabs/base.py +101 -17
- euporie/core/tabs/notebook.py +72 -30
- euporie/core/terminal.py +56 -48
- euporie/core/utils.py +12 -16
- euporie/core/widgets/cell.py +6 -5
- euporie/core/widgets/cell_outputs.py +2 -2
- euporie/core/widgets/decor.py +74 -82
- euporie/core/widgets/dialog.py +132 -28
- euporie/core/widgets/display.py +76 -24
- euporie/core/widgets/file_browser.py +87 -31
- euporie/core/widgets/formatted_text_area.py +1 -3
- euporie/core/widgets/forms.py +79 -40
- euporie/core/widgets/inputs.py +23 -13
- euporie/core/widgets/layout.py +4 -3
- euporie/core/widgets/menu.py +368 -216
- euporie/core/widgets/page.py +99 -58
- euporie/core/widgets/pager.py +1 -1
- euporie/core/widgets/palette.py +30 -27
- euporie/core/widgets/search_bar.py +38 -25
- euporie/core/widgets/status_bar.py +103 -5
- euporie/data/desktop/euporie-console.desktop +7 -0
- euporie/data/desktop/euporie-notebook.desktop +7 -0
- euporie/hub/__main__.py +3 -1
- euporie/hub/app.py +9 -7
- euporie/notebook/__main__.py +3 -1
- euporie/notebook/app.py +7 -30
- euporie/notebook/tabs/__init__.py +7 -3
- euporie/notebook/tabs/display.py +18 -9
- euporie/notebook/tabs/edit.py +106 -23
- euporie/notebook/tabs/json.py +73 -0
- euporie/notebook/tabs/log.py +18 -8
- euporie/notebook/tabs/notebook.py +60 -41
- euporie/preview/__main__.py +3 -1
- euporie/preview/app.py +2 -1
- euporie/preview/tabs/notebook.py +23 -10
- euporie/web/tabs/web.py +149 -0
- euporie/web/widgets/webview.py +563 -0
- euporie-2.4.1.data/data/share/applications/euporie-console.desktop +7 -0
- euporie-2.4.1.data/data/share/applications/euporie-notebook.desktop +7 -0
- {euporie-2.3.2.dist-info → euporie-2.4.1.dist-info}/METADATA +6 -5
- euporie-2.4.1.dist-info/RECORD +129 -0
- {euporie-2.3.2.dist-info → euporie-2.4.1.dist-info}/WHEEL +1 -1
- euporie/core/url.py +0 -64
- euporie-2.3.2.dist-info/RECORD +0 -122
- {euporie-2.3.2.dist-info → euporie-2.4.1.dist-info}/entry_points.txt +0 -0
- {euporie-2.3.2.dist-info → euporie-2.4.1.dist-info}/licenses/LICENSE +0 -0
@@ -54,17 +54,18 @@ from euporie.notebook.filters import (
|
|
54
54
|
)
|
55
55
|
|
56
56
|
if TYPE_CHECKING:
|
57
|
+
from pathlib import Path
|
57
58
|
from typing import Any, Deque, MutableSequence, Sequence
|
58
59
|
|
59
|
-
from prompt_toolkit.formatted_text.base import
|
60
|
+
from prompt_toolkit.formatted_text.base import StyleAndTextTuples
|
60
61
|
from prompt_toolkit.key_binding.key_bindings import NotImplementedOrNone
|
61
62
|
from prompt_toolkit.layout.containers import AnyContainer
|
62
63
|
from prompt_toolkit.mouse_events import MouseEvent
|
63
|
-
from upath import UPath
|
64
64
|
|
65
65
|
from euporie.core.app import BaseApp
|
66
66
|
from euporie.core.comm.base import Comm
|
67
67
|
from euporie.core.kernel import Kernel
|
68
|
+
from euporie.core.widgets.status_bar import StatusBarFields
|
68
69
|
|
69
70
|
log = logging.getLogger(__name__)
|
70
71
|
|
@@ -75,12 +76,23 @@ class Notebook(BaseNotebook):
|
|
75
76
|
A tab which allows running and editing a notebook.
|
76
77
|
"""
|
77
78
|
|
79
|
+
name = "Notebook Editor"
|
80
|
+
weight = 3
|
81
|
+
mime_types = {"application/x-ipynb+json"}
|
82
|
+
file_extensions = {".ipynb"}
|
83
|
+
try:
|
84
|
+
from jupytext.formats import NOTEBOOK_EXTENSIONS
|
85
|
+
except ModuleNotFoundError:
|
86
|
+
pass
|
87
|
+
else:
|
88
|
+
file_extensions |= set(NOTEBOOK_EXTENSIONS)
|
89
|
+
|
78
90
|
allow_stdin = True
|
79
91
|
|
80
92
|
def __init__(
|
81
93
|
self,
|
82
94
|
app: BaseApp,
|
83
|
-
path:
|
95
|
+
path: Path | None = None,
|
84
96
|
kernel: Kernel | None = None,
|
85
97
|
comms: dict[str, Comm] | None = None,
|
86
98
|
use_kernel_history: bool = True,
|
@@ -102,9 +114,6 @@ class Notebook(BaseNotebook):
|
|
102
114
|
self.clipboard: list[Cell] = []
|
103
115
|
self.undo_buffer: Deque[tuple[int, list[Cell]]] = deque(maxlen=10)
|
104
116
|
|
105
|
-
if not kernel:
|
106
|
-
self.kernel.start(cb=self.kernel_started, wait=False)
|
107
|
-
|
108
117
|
# Tab stuff
|
109
118
|
|
110
119
|
def _statusbar_kernel_handeler(self, event: MouseEvent) -> NotImplementedOrNone:
|
@@ -115,29 +124,45 @@ class Notebook(BaseNotebook):
|
|
115
124
|
else:
|
116
125
|
return NotImplemented
|
117
126
|
|
118
|
-
def
|
119
|
-
self,
|
120
|
-
) -> tuple[Sequence[AnyFormattedText], Sequence[AnyFormattedText]]:
|
127
|
+
def __pt_status__(self) -> StatusBarFields | None:
|
121
128
|
"""Generate the formatted text for the statusbar."""
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
129
|
+
if self.loaded:
|
130
|
+
rendered = self.page.pre_rendered
|
131
|
+
return (
|
132
|
+
[
|
133
|
+
self.mode(),
|
134
|
+
f"Cell {self.page.selected_slice.start+1}",
|
135
|
+
f"Rendering… ({rendered:.0%})" if rendered < 1 else "",
|
136
|
+
"Saving…" if self.saving else "",
|
137
|
+
],
|
138
|
+
[
|
139
|
+
lambda: cast(
|
140
|
+
"StyleAndTextTuples",
|
141
|
+
[
|
142
|
+
(
|
143
|
+
"",
|
144
|
+
self.kernel_display_name,
|
145
|
+
self._statusbar_kernel_handeler,
|
146
|
+
)
|
147
|
+
],
|
148
|
+
),
|
149
|
+
KERNEL_STATUS_REPR[self.kernel.status] if self.kernel else ".",
|
150
|
+
],
|
151
|
+
)
|
152
|
+
else:
|
153
|
+
return ([], [])
|
138
154
|
|
139
155
|
# Notebook stuff
|
140
156
|
|
157
|
+
def post_init_kernel(self) -> None:
|
158
|
+
"""Start the kernel after if has been loaded."""
|
159
|
+
# Start kernel
|
160
|
+
if self.kernel._status == "stopped":
|
161
|
+
self.kernel.start(cb=self.kernel_started, wait=False)
|
162
|
+
|
163
|
+
# Load container
|
164
|
+
super().post_init_kernel()
|
165
|
+
|
141
166
|
@property
|
142
167
|
def selected_indices(self) -> list[int]:
|
143
168
|
"""Return a list of the currently selected cell indices."""
|
@@ -219,7 +244,8 @@ class Notebook(BaseNotebook):
|
|
219
244
|
width=Dimension(weight=1),
|
220
245
|
height=Dimension(min=1, weight=2),
|
221
246
|
key_bindings=load_registered_bindings(
|
222
|
-
"euporie.
|
247
|
+
"euporie.core.tabs.base.Tab",
|
248
|
+
"euporie.notebook.tabs.notebook.Notebook",
|
223
249
|
),
|
224
250
|
)
|
225
251
|
|
@@ -315,7 +341,7 @@ class Notebook(BaseNotebook):
|
|
315
341
|
|
316
342
|
def refresh_cell(self, cell: Cell) -> None:
|
317
343
|
"""Trigger the refresh of a notebook cell."""
|
318
|
-
self.page.get_child_render_info(cell.index).
|
344
|
+
self.page.get_child_render_info(cell.index).invalidate()
|
319
345
|
|
320
346
|
def add_cell_above(self) -> None:
|
321
347
|
"""Inert a cell above the current selection."""
|
@@ -568,16 +594,6 @@ class Notebook(BaseNotebook):
|
|
568
594
|
|
569
595
|
# ################################### Commands ####################################
|
570
596
|
|
571
|
-
@staticmethod
|
572
|
-
@add_cmd(
|
573
|
-
filter=notebook_has_focus,
|
574
|
-
)
|
575
|
-
def _save_notebook() -> None:
|
576
|
-
"""Save the current notebook."""
|
577
|
-
tab = get_app().tab
|
578
|
-
if isinstance(tab, Notebook):
|
579
|
-
tab.save()
|
580
|
-
|
581
597
|
@staticmethod
|
582
598
|
@add_cmd(
|
583
599
|
filter=cell_has_focus & ~buffer_has_focus,
|
@@ -930,6 +946,11 @@ class Notebook(BaseNotebook):
|
|
930
946
|
if isinstance(nb, Notebook):
|
931
947
|
for cell in nb.cells:
|
932
948
|
cell.set_cell_type("markdown", clear=True)
|
949
|
+
# Remove unallowed additional properties
|
950
|
+
json = cell.json
|
951
|
+
json.pop("execution_count", None)
|
952
|
+
json.pop("outputs", None)
|
953
|
+
cell.run_or_render()
|
933
954
|
|
934
955
|
@staticmethod
|
935
956
|
@add_cmd(
|
@@ -993,7 +1014,7 @@ class Notebook(BaseNotebook):
|
|
993
1014
|
title="Collapse cell inputs",
|
994
1015
|
)
|
995
1016
|
def _hide_cell_inputs() -> None:
|
996
|
-
"""
|
1017
|
+
"""Collapse the selected cells' inputs."""
|
997
1018
|
nb = get_app().tab
|
998
1019
|
if isinstance(nb, Notebook):
|
999
1020
|
for cell in nb.cells:
|
@@ -1028,7 +1049,7 @@ class Notebook(BaseNotebook):
|
|
1028
1049
|
title="Collapse cell outputs",
|
1029
1050
|
)
|
1030
1051
|
def _hide_cell_outputs() -> None:
|
1031
|
-
"""
|
1052
|
+
"""Collapse the selected cells' outputs."""
|
1032
1053
|
nb = get_app().tab
|
1033
1054
|
if isinstance(nb, Notebook):
|
1034
1055
|
for cell in nb.cells:
|
@@ -1187,7 +1208,6 @@ class Notebook(BaseNotebook):
|
|
1187
1208
|
register_bindings(
|
1188
1209
|
{
|
1189
1210
|
"euporie.notebook.tabs.notebook.Notebook": {
|
1190
|
-
"save-notebook": "c-s",
|
1191
1211
|
"enter-cell-edit-mode": "enter",
|
1192
1212
|
"exit-edit-mode": "escape",
|
1193
1213
|
"run-selected-cells": ["c-enter", "c-e"],
|
@@ -1234,7 +1254,6 @@ class Notebook(BaseNotebook):
|
|
1234
1254
|
"scroll-output-right": "right",
|
1235
1255
|
"toggle-expand": "w",
|
1236
1256
|
"notebook-toggle-line-numbers": "l",
|
1237
|
-
"reset-tab": "f5",
|
1238
1257
|
}
|
1239
1258
|
}
|
1240
1259
|
)
|
euporie/preview/__main__.py
CHANGED
@@ -3,9 +3,11 @@
|
|
3
3
|
|
4
4
|
def main() -> "None":
|
5
5
|
"""Call the main entrypoint to the application."""
|
6
|
+
import sys
|
7
|
+
|
6
8
|
from euporie.core import __main__
|
7
9
|
|
8
|
-
__main__.main(__name__.
|
10
|
+
__main__.main(str(sys.modules[__name__].__package__).rpartition(".")[2])
|
9
11
|
|
10
12
|
|
11
13
|
if __name__ == "__main__":
|
euporie/preview/app.py
CHANGED
@@ -20,6 +20,7 @@ from euporie.core.key_binding.registry import register_bindings
|
|
20
20
|
from euporie.preview.tabs.notebook import PreviewNotebook
|
21
21
|
|
22
22
|
if TYPE_CHECKING:
|
23
|
+
from pathlib import Path
|
23
24
|
from typing import IO, Any, TextIO
|
24
25
|
|
25
26
|
from prompt_toolkit.application.application import _AppResult
|
@@ -91,7 +92,7 @@ class PreviewApp(BaseApp):
|
|
91
92
|
# Select the first tab after files are opened
|
92
93
|
self.post_load_callables.append(partial(setattr, self, "tab_idx", 0))
|
93
94
|
|
94
|
-
def get_file_tab(self, path:
|
95
|
+
def get_file_tab(self, path: Path) -> type[Tab]:
|
95
96
|
"""Return the tab to use for a file path."""
|
96
97
|
return PreviewNotebook
|
97
98
|
|
euporie/preview/tabs/notebook.py
CHANGED
@@ -21,12 +21,12 @@ from euporie.core.widgets.cell import Cell
|
|
21
21
|
from euporie.core.widgets.page import PrintingContainer
|
22
22
|
|
23
23
|
if TYPE_CHECKING:
|
24
|
+
from pathlib import Path
|
24
25
|
from typing import Any, Callable
|
25
26
|
|
26
27
|
from prompt_toolkit.application.application import Application
|
27
28
|
from prompt_toolkit.formatted_text.base import StyleAndTextTuples
|
28
29
|
from prompt_toolkit.layout.containers import AnyContainer
|
29
|
-
from upath import UPath
|
30
30
|
|
31
31
|
from euporie.core.app import BaseApp
|
32
32
|
|
@@ -36,25 +36,28 @@ log = logging.getLogger(__name__)
|
|
36
36
|
class PreviewNotebook(BaseNotebook):
|
37
37
|
"""A notebook tab which renders cells sequentially."""
|
38
38
|
|
39
|
+
bg_init = False
|
40
|
+
|
39
41
|
def __init__(
|
40
42
|
self,
|
41
43
|
app: BaseApp,
|
42
|
-
path:
|
44
|
+
path: Path | None = None,
|
43
45
|
use_kernel_history: bool = False,
|
44
46
|
) -> None:
|
45
47
|
"""Create a new instance."""
|
46
|
-
super().__init__(app, path, use_kernel_history=use_kernel_history)
|
47
48
|
self.cell_index = 0
|
48
|
-
self.app.before_render += self.before_render
|
49
|
-
self.app.after_render += self.after_render
|
50
49
|
self.cells: FastDictCache[tuple[int], Cell] = FastDictCache(
|
51
50
|
get_value=self.get_cell
|
52
51
|
)
|
53
52
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
53
|
+
super().__init__(app, path, use_kernel_history=use_kernel_history)
|
54
|
+
|
55
|
+
self.app.before_render += self.before_render
|
56
|
+
self.app.after_render += self.after_render
|
57
|
+
|
58
|
+
def pre_init_kernel(self) -> None:
|
59
|
+
"""Filter cells before kernel is loaded."""
|
60
|
+
super().pre_init_kernel()
|
58
61
|
|
59
62
|
# Filter the cells to be shown
|
60
63
|
n_cells = len(self.json["cells"]) - 1
|
@@ -67,8 +70,17 @@ class PreviewNotebook(BaseNotebook):
|
|
67
70
|
log.debug("Showing cells %s to %s", start, stop)
|
68
71
|
self.json["cells"] = self.json["cells"][start:stop]
|
69
72
|
|
73
|
+
def post_init_kernel(self) -> None:
|
74
|
+
"""Optionally start kernel after it is loaded."""
|
75
|
+
super().post_init_kernel()
|
76
|
+
# If we are running the notebook, pause rendering util the kernel has started
|
77
|
+
if self.app.config.run:
|
78
|
+
self.app.pause_rendering()
|
79
|
+
self.kernel.start(cb=self.kernel_started, wait=True)
|
80
|
+
|
70
81
|
def print_title(self) -> None:
|
71
82
|
"""Print a notebook's filename."""
|
83
|
+
from euporie.core.border import DoubleLine
|
72
84
|
from euporie.core.formatted_text.utils import (
|
73
85
|
FormattedTextAlign,
|
74
86
|
add_border,
|
@@ -80,7 +92,8 @@ class PreviewNotebook(BaseNotebook):
|
|
80
92
|
ft: StyleAndTextTuples = [("bold", str(self.path))]
|
81
93
|
ft = wrap(ft, width - 4)
|
82
94
|
ft = align(ft, how=FormattedTextAlign.CENTER, width=width - 4)
|
83
|
-
ft = add_border(ft, width=width)
|
95
|
+
ft = add_border(ft, width=width, border_grid=DoubleLine.grid)
|
96
|
+
ft.append(("", "\n"))
|
84
97
|
self.app.print_text(ft)
|
85
98
|
|
86
99
|
def kernel_started(self, result: dict | None = None) -> None:
|
euporie/web/tabs/web.py
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
"""Defines a web-view tab."""
|
2
|
+
|
3
|
+
|
4
|
+
from __future__ import annotations
|
5
|
+
|
6
|
+
import logging
|
7
|
+
from typing import TYPE_CHECKING
|
8
|
+
|
9
|
+
from prompt_toolkit.eventloop.utils import run_in_executor_with_context
|
10
|
+
from prompt_toolkit.filters import Condition
|
11
|
+
from prompt_toolkit.layout.containers import HSplit, VSplit
|
12
|
+
from prompt_toolkit.layout.dimension import Dimension
|
13
|
+
from upath import UPath
|
14
|
+
|
15
|
+
from euporie.core.convert.core import get_mime
|
16
|
+
from euporie.core.current import get_app
|
17
|
+
from euporie.core.data_structures import DiBool
|
18
|
+
from euporie.core.margins import MarginContainer, ScrollbarMargin
|
19
|
+
from euporie.core.tabs.base import Tab
|
20
|
+
from euporie.core.widgets.decor import FocusedStyle
|
21
|
+
from euporie.core.widgets.display import DisplayWindow
|
22
|
+
from euporie.core.widgets.forms import Button, Text
|
23
|
+
from euporie.web.widgets.webview import WebViewControl
|
24
|
+
|
25
|
+
if TYPE_CHECKING:
|
26
|
+
from pathlib import Path
|
27
|
+
from typing import Any, Callable
|
28
|
+
|
29
|
+
from prompt_toolkit.layout.containers import AnyContainer
|
30
|
+
|
31
|
+
from euporie.core.app import BaseApp
|
32
|
+
from euporie.core.widgets.status_bar import StatusBarFields
|
33
|
+
|
34
|
+
log = logging.getLogger(__name__)
|
35
|
+
|
36
|
+
|
37
|
+
class WebTab(Tab):
|
38
|
+
"""Tab class for displaying files."""
|
39
|
+
|
40
|
+
name = "Web Viewer"
|
41
|
+
weight = 2
|
42
|
+
mime_types = {"text/html"}
|
43
|
+
|
44
|
+
def __init__(self, app: BaseApp, path: Path | None) -> None:
|
45
|
+
"""Call when the tab is created."""
|
46
|
+
super().__init__(app, path)
|
47
|
+
self.status: Callable[[], StatusBarFields] | None = None
|
48
|
+
|
49
|
+
def _load() -> None:
|
50
|
+
self.container = self.load_container()
|
51
|
+
|
52
|
+
run_in_executor_with_context(_load)
|
53
|
+
|
54
|
+
@property
|
55
|
+
def title(self) -> str:
|
56
|
+
"""Return the tab title."""
|
57
|
+
if webview := getattr(self, "webview", None):
|
58
|
+
if title := webview.title:
|
59
|
+
return title
|
60
|
+
if self.path is not None:
|
61
|
+
return str(self.path.name) or str(self.path)
|
62
|
+
else:
|
63
|
+
return "<Web Page>"
|
64
|
+
|
65
|
+
def load_url(self, url: str | Path, new_tab: bool = False, **kwargs: Any) -> bool:
|
66
|
+
"""Load a new URL, or the URL in the address-bar."""
|
67
|
+
log.debug("Loading %s", url)
|
68
|
+
if not url:
|
69
|
+
return False
|
70
|
+
if isinstance(url, str):
|
71
|
+
url = UPath(url)
|
72
|
+
|
73
|
+
if not new_tab and get_mime(url) == "text/html":
|
74
|
+
self.webview.load_url(url, **kwargs)
|
75
|
+
else:
|
76
|
+
get_app().open_file(url)
|
77
|
+
return True
|
78
|
+
|
79
|
+
def _url_loaded(self, webview: WebViewControl) -> None:
|
80
|
+
"""Trigger callback when the URL is loaded."""
|
81
|
+
url = webview.url
|
82
|
+
if url is not None:
|
83
|
+
self.path = UPath(url)
|
84
|
+
self.url_bar.text = str(url)
|
85
|
+
|
86
|
+
def load_container(self) -> AnyContainer:
|
87
|
+
"""Abcract method for loading the notebook's main container."""
|
88
|
+
assert self.path is not None
|
89
|
+
path = self.path
|
90
|
+
self.webview = WebViewControl(url=path, link_handler=self.load_url)
|
91
|
+
self.webview.rendered += self._url_loaded
|
92
|
+
|
93
|
+
def _status() -> StatusBarFields:
|
94
|
+
return ([self.webview.status] if self.webview is not None else [], [])
|
95
|
+
|
96
|
+
self.status = _status
|
97
|
+
|
98
|
+
button_prev = Button(
|
99
|
+
"◀",
|
100
|
+
show_borders=DiBool(top=True, right=False, bottom=True, left=True),
|
101
|
+
disabled=Condition(lambda: not self.webview.prev_stack),
|
102
|
+
on_click=lambda x: self.webview.nav_prev(),
|
103
|
+
)
|
104
|
+
button_next = Button(
|
105
|
+
"▶",
|
106
|
+
show_borders=DiBool(top=True, right=True, bottom=True, left=False),
|
107
|
+
disabled=Condition(lambda: not self.webview.next_stack),
|
108
|
+
on_click=lambda x: self.webview.nav_next(),
|
109
|
+
)
|
110
|
+
self.url_bar = Text(
|
111
|
+
text=str(path),
|
112
|
+
show_borders=DiBool(top=True, right=False, bottom=True, left=True),
|
113
|
+
accept_handler=lambda buf: self.load_url(buf.text),
|
114
|
+
)
|
115
|
+
button_go = Button(
|
116
|
+
"➜",
|
117
|
+
show_borders=DiBool(top=True, right=True, bottom=True, left=False),
|
118
|
+
on_click=lambda x: (self.load_url(self.url_bar.text) and None)
|
119
|
+
or None, # Magical typing magic
|
120
|
+
)
|
121
|
+
|
122
|
+
return HSplit(
|
123
|
+
[
|
124
|
+
VSplit(
|
125
|
+
[
|
126
|
+
FocusedStyle(button_prev),
|
127
|
+
FocusedStyle(button_next),
|
128
|
+
FocusedStyle(self.url_bar),
|
129
|
+
FocusedStyle(button_go),
|
130
|
+
],
|
131
|
+
style="class:tab.toolbar",
|
132
|
+
),
|
133
|
+
VSplit(
|
134
|
+
[
|
135
|
+
window := DisplayWindow(self.webview),
|
136
|
+
MarginContainer(ScrollbarMargin(), target=window),
|
137
|
+
]
|
138
|
+
),
|
139
|
+
],
|
140
|
+
width=Dimension(weight=1),
|
141
|
+
height=Dimension(weight=1),
|
142
|
+
)
|
143
|
+
|
144
|
+
def __pt_status__(self) -> StatusBarFields:
|
145
|
+
"""Return a list of statusbar field values shown then this tab is active."""
|
146
|
+
if callable(self.status):
|
147
|
+
return self.status()
|
148
|
+
else:
|
149
|
+
return ([], [])
|