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
@@ -1,176 +1,187 @@
|
|
1
1
|
"""Contain the browser CSS for formatting markdown."""
|
2
2
|
|
3
|
+
from prompt_toolkit.filters.utils import _always
|
4
|
+
|
3
5
|
from .html import CssSelector
|
4
6
|
|
5
7
|
_MARKDOWN_CSS = {
|
6
|
-
|
7
|
-
(
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
"
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
"
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
"
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
"
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
8
|
+
_always: {
|
9
|
+
(
|
10
|
+
(CssSelector(item="h1"),),
|
11
|
+
(CssSelector(item="h2"),),
|
12
|
+
(CssSelector(item="h3"),),
|
13
|
+
(CssSelector(item="h4"),),
|
14
|
+
(CssSelector(item="h5"),),
|
15
|
+
(CssSelector(item="h6"),),
|
16
|
+
): {
|
17
|
+
"text_align": "center",
|
18
|
+
},
|
19
|
+
((CssSelector(item="h1"),),): {
|
20
|
+
"font_weight": "bold",
|
21
|
+
"text_decoration": "underline",
|
22
|
+
"border_top_style": "double",
|
23
|
+
"border_right_style": "double",
|
24
|
+
"border_bottom_style": "double",
|
25
|
+
"border_left_style": "double",
|
26
|
+
"border_top_width": "0.34em",
|
27
|
+
"border_right_width": "0.34em",
|
28
|
+
"border_bottom_width": "0.34em",
|
29
|
+
"border_left_width": "0.34em",
|
30
|
+
"border_top_color": "ansiyellow",
|
31
|
+
"border_right_color": "ansiyellow",
|
32
|
+
"border_bottom_color": "ansiyellow",
|
33
|
+
"border_left_color": "ansiyellow",
|
34
|
+
"padding_bottom": "0",
|
35
|
+
},
|
36
|
+
((CssSelector(item="h2"),),): {
|
37
|
+
"font_weight": "bold",
|
38
|
+
"border_top_style": "solid",
|
39
|
+
"border_right_style": "solid",
|
40
|
+
"border_bottom_style": "solid",
|
41
|
+
"border_left_style": "solid",
|
42
|
+
"border_top_width": "0.34em",
|
43
|
+
"border_right_width": "0.34em",
|
44
|
+
"border_bottom_width": "0.34em",
|
45
|
+
"border_left_width": "0.34em",
|
46
|
+
"border_top_color": "#888888",
|
47
|
+
"border_right_color": "#888888",
|
48
|
+
"border_bottom_color": "#888888",
|
49
|
+
"border_left_color": "#888888",
|
50
|
+
"padding_bottom": "0",
|
51
|
+
},
|
52
|
+
((CssSelector(item="h3"),),): {
|
53
|
+
"font_weight": "bold",
|
54
|
+
"font_style": "italic",
|
55
|
+
"border_top_style": "solid",
|
56
|
+
"border_right_style": "solid",
|
57
|
+
"border_bottom_style": "solid",
|
58
|
+
"border_left_style": "solid",
|
59
|
+
"border_top_width": "0.1em",
|
60
|
+
"border_right_width": "0.1em",
|
61
|
+
"border_bottom_width": "0.1em",
|
62
|
+
"border_left_width": "0.1em",
|
63
|
+
"border_top_color": "#888888",
|
64
|
+
"border_right_color": "#888888",
|
65
|
+
"border_bottom_color": "#888888",
|
66
|
+
"border_left_color": "#888888",
|
67
|
+
"margin_left": "auto",
|
68
|
+
"margin_right": "auto",
|
69
|
+
"padding_top": "0",
|
70
|
+
"padding_right": "1em",
|
71
|
+
"padding_bottom": "0",
|
72
|
+
"padding_left": "1em",
|
73
|
+
},
|
74
|
+
((CssSelector(item="h4"),),): {
|
75
|
+
"text_weight": "bold",
|
76
|
+
"text_decoration": "underline",
|
77
|
+
"border_bottom_color": "#888888",
|
78
|
+
"margin_top": "1rem",
|
79
|
+
"margin_bottom": "1rem",
|
80
|
+
},
|
81
|
+
((CssSelector(item="h5"),),): {
|
82
|
+
"font_weight": "bold",
|
83
|
+
"border_bottom_color": "#888888",
|
84
|
+
"margin_top": "1rem",
|
85
|
+
"margin_bottom": "1rem",
|
86
|
+
},
|
87
|
+
((CssSelector(item="h6"),),): {
|
88
|
+
"font_style": "italic",
|
89
|
+
"border_bottom_color": "#888888",
|
90
|
+
"margin_top": "1rem",
|
91
|
+
"margin_bottom": "1rem",
|
92
|
+
},
|
84
93
|
(
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
94
|
+
(
|
95
|
+
CssSelector(item="ol"),
|
96
|
+
CssSelector(item="li"),
|
97
|
+
CssSelector(item="::marker"),
|
98
|
+
),
|
99
|
+
): {"color": "ansicyan"},
|
91
100
|
(
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
"
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
"
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
"
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
"
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
"
|
143
|
-
|
144
|
-
|
101
|
+
(
|
102
|
+
CssSelector(item="ul"),
|
103
|
+
CssSelector(item="li"),
|
104
|
+
CssSelector(item="::marker"),
|
105
|
+
),
|
106
|
+
): {"color": "ansiyellow"},
|
107
|
+
((CssSelector(item="blockquote"),),): {
|
108
|
+
"margin_top": "1em",
|
109
|
+
"margin_bottom": "1em",
|
110
|
+
"padding_left": "1em",
|
111
|
+
"border_left_width": "thick",
|
112
|
+
"border_left_style": "solid",
|
113
|
+
"border_left_color": "darkmagenta",
|
114
|
+
},
|
115
|
+
((CssSelector(item=".block"),),): {"display": "block"},
|
116
|
+
((CssSelector(item="td"),),): {
|
117
|
+
"display": "table-cell",
|
118
|
+
"border_top_style": "solid",
|
119
|
+
"border_right_style": "solid",
|
120
|
+
"border_bottom_style": "solid",
|
121
|
+
"border_left_style": "solid",
|
122
|
+
"border_top_width": "0.1em",
|
123
|
+
"border_right_width": "0.1em",
|
124
|
+
"border_bottom_width": "0.1em",
|
125
|
+
"border_left_width": "0.1em",
|
126
|
+
"padding_left": "1em",
|
127
|
+
"padding_right": "1em",
|
128
|
+
# "_pt_class": "markdown,table,border",
|
129
|
+
},
|
130
|
+
((CssSelector(item="th"),),): {
|
131
|
+
"display": "table-cell",
|
132
|
+
"border_top_style": "solid",
|
133
|
+
"border_right_style": "solid",
|
134
|
+
"border_bottom_style": "solid",
|
135
|
+
"border_left_style": "solid",
|
136
|
+
"border_top_width": "0.34em",
|
137
|
+
"border_right_width": "0.34em",
|
138
|
+
"border_bottom_width": "0.34em",
|
139
|
+
"border_left_width": "0.34em",
|
140
|
+
"padding_left": "1em",
|
141
|
+
"padding_right": "1em",
|
142
|
+
"font_weight": "bold",
|
143
|
+
# "_pt_class": "markdown,table,border",
|
144
|
+
},
|
145
|
+
((CssSelector(item="code"),),): {
|
146
|
+
"display": "inline",
|
147
|
+
"_pt_class": "markdown,code",
|
148
|
+
},
|
149
|
+
((CssSelector(item=".math"),),): {"text_transform": "latex"},
|
150
|
+
((CssSelector(item=".block"),),): {"display": "block"},
|
151
|
+
((CssSelector(item=".math.block"),),): {
|
152
|
+
"text_align": "center",
|
153
|
+
},
|
145
154
|
(
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
155
|
+
(
|
156
|
+
CssSelector(item="pre"),
|
157
|
+
CssSelector(comb=">", item="code"),
|
158
|
+
),
|
159
|
+
): {
|
160
|
+
"display": "block",
|
161
|
+
"border_top_style": "solid",
|
162
|
+
"border_top_width": "1px",
|
163
|
+
"border_right_style": "solid",
|
164
|
+
"border_right_width": "1px",
|
165
|
+
"border_bottom_style": "solid",
|
166
|
+
"border_bottom_width": "1px",
|
167
|
+
"border_left_style": "solid",
|
168
|
+
"border_left_width": "1px",
|
169
|
+
"_pt_class": "markdown,code,block",
|
170
|
+
},
|
162
171
|
(
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
"
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
172
|
+
(
|
173
|
+
CssSelector(item="pre"),
|
174
|
+
CssSelector(comb=">", item="code"),
|
175
|
+
CssSelector(item="*"),
|
176
|
+
),
|
177
|
+
): {
|
178
|
+
"pt_class": "markdown,code,block",
|
179
|
+
},
|
180
|
+
((CssSelector(item="img"),), (CssSelector(item="svg"),)): {
|
181
|
+
"display": "inline-block",
|
182
|
+
"overflow_x": "hidden",
|
183
|
+
"overflow_y": "hidden",
|
184
|
+
"vertical_align": "middle",
|
185
|
+
},
|
186
|
+
}
|
176
187
|
}
|
@@ -231,7 +231,7 @@ class DummyCell(Cell):
|
|
231
231
|
|
232
232
|
|
233
233
|
class RowCol:
|
234
|
-
"""
|
234
|
+
"""Base class for table rows and columns."""
|
235
235
|
|
236
236
|
type_: str
|
237
237
|
span_type: str
|
@@ -513,6 +513,9 @@ def compute_border_width(cell: Cell, render_count: int = 0) -> DiInt:
|
|
513
513
|
if isinstance(cell, DummyCell):
|
514
514
|
return DiInt(0, 0, 0, 0)
|
515
515
|
|
516
|
+
if isinstance(cell, SpacerCell):
|
517
|
+
cell = cell.expands
|
518
|
+
|
516
519
|
output = {"top": 1, "right": 1, "bottom": 1, "left": 1}
|
517
520
|
|
518
521
|
row = cell.row
|
@@ -668,12 +671,12 @@ def calculate_col_widths(
|
|
668
671
|
expand(width.preferred)
|
669
672
|
elif current_width > width.preferred:
|
670
673
|
contract(width.preferred)
|
671
|
-
|
674
|
+
if width.max_specified:
|
672
675
|
if current_width > width.max:
|
673
676
|
contract(width.max)
|
674
677
|
if current_width < width.max and expand_to_width:
|
675
678
|
expand(width.max)
|
676
|
-
|
679
|
+
if width.min_specified and current_width < width.min:
|
677
680
|
expand(width.min)
|
678
681
|
|
679
682
|
return col_widths
|
@@ -738,15 +741,17 @@ def compute_lines(
|
|
738
741
|
align(
|
739
742
|
wrap(
|
740
743
|
[
|
741
|
-
("", "\n" *
|
744
|
+
*([("", "\n" * padding.top)] if padding.top else []),
|
742
745
|
*compute_text(cell, render_count),
|
743
|
-
("", "\n" *
|
746
|
+
*([("", "\n" * padding.bottom)] if padding.bottom else []),
|
744
747
|
],
|
745
748
|
width=width,
|
749
|
+
placeholder="",
|
746
750
|
),
|
747
751
|
compute_align(cell, render_count),
|
748
752
|
width=width,
|
749
753
|
style=compute_style(cell, render_count),
|
754
|
+
placeholder="",
|
750
755
|
)
|
751
756
|
)
|
752
757
|
|
@@ -960,7 +965,7 @@ class Table:
|
|
960
965
|
unfilled = [
|
961
966
|
i
|
962
967
|
for i, row in self._rows.items()
|
963
|
-
if all(
|
968
|
+
if all(isinstance(cell, SpacerCell) for cell in row._cells.values())
|
964
969
|
]
|
965
970
|
|
966
971
|
index = min(
|
@@ -991,7 +996,7 @@ class Table:
|
|
991
996
|
unfilled = [
|
992
997
|
i
|
993
998
|
for i, col in self._cols.items()
|
994
|
-
if all(
|
999
|
+
if all(isinstance(cell, SpacerCell) for cell in col._cells.values())
|
995
1000
|
]
|
996
1001
|
|
997
1002
|
index = min(
|
@@ -1057,13 +1062,13 @@ class Table:
|
|
1057
1062
|
|
1058
1063
|
node_style = " ".join(
|
1059
1064
|
(
|
1060
|
-
sw_bs.top,
|
1061
|
-
sw_bs.right,
|
1062
1065
|
ne_bs.bottom,
|
1066
|
+
sw_bs.right,
|
1067
|
+
sw_bs.top,
|
1063
1068
|
ne_bs.left,
|
1064
|
-
se_bs.top,
|
1065
|
-
se_bs.left,
|
1066
1069
|
nw_bs.bottom,
|
1070
|
+
se_bs.left,
|
1071
|
+
se_bs.top,
|
1067
1072
|
nw_bs.right,
|
1068
1073
|
)
|
1069
1074
|
)
|
@@ -1111,8 +1116,8 @@ class Table:
|
|
1111
1116
|
for w, e in zip([DummyCell(), *row.cells], [*row.cells, DummyCell()]):
|
1112
1117
|
border_style = " ".join(
|
1113
1118
|
(
|
1114
|
-
compute_border_style(w, render_count).right,
|
1115
1119
|
compute_border_style(e, render_count).left,
|
1120
|
+
compute_border_style(w, render_count).right,
|
1116
1121
|
)
|
1117
1122
|
)
|
1118
1123
|
border_char = get_vertical_edge(
|
@@ -1166,7 +1171,8 @@ class Table:
|
|
1166
1171
|
continue
|
1167
1172
|
output_line.append(borders[i])
|
1168
1173
|
|
1169
|
-
|
1174
|
+
cell_style = compute_style(cell, render_count)
|
1175
|
+
padding_style = f"{cell_style} nounderline"
|
1170
1176
|
padding = compute_padding(cell, render_count)
|
1171
1177
|
padding_left, padding_right = padding.left, padding.right
|
1172
1178
|
|
@@ -1181,7 +1187,7 @@ class Table:
|
|
1181
1187
|
[
|
1182
1188
|
(padding_style, " " * (padding.left or 0)),
|
1183
1189
|
*(line or []),
|
1184
|
-
(
|
1190
|
+
(cell_style, " " * excess),
|
1185
1191
|
(padding_style, " " * (padding.right or 0)),
|
1186
1192
|
]
|
1187
1193
|
)
|
@@ -12,6 +12,7 @@ from prompt_toolkit.formatted_text.utils import (
|
|
12
12
|
split_lines,
|
13
13
|
to_plain_text,
|
14
14
|
)
|
15
|
+
from prompt_toolkit.layout.utils import explode_text_fragments
|
15
16
|
from prompt_toolkit.utils import get_cwidth
|
16
17
|
from pygments.lexers import get_lexer_by_name
|
17
18
|
from pygments.util import ClassNotFound
|
@@ -101,16 +102,16 @@ def fragment_list_to_words(
|
|
101
102
|
) -> Iterable[StyleAndTextTuples]:
|
102
103
|
"""Split formatted text into a list of word fragments which form words."""
|
103
104
|
word: StyleAndTextTuples = []
|
104
|
-
for style, string, *
|
105
|
+
for style, string, *rest in fragments:
|
105
106
|
parts = re.split(r"(?<=[\s\-])", string)
|
106
107
|
if len(parts) == 1:
|
107
|
-
word.append((style, parts[0]))
|
108
|
+
word.append(cast("OneStyleAndTextTuple", (style, parts[0], *rest)))
|
108
109
|
else:
|
109
110
|
for part in parts[:-1]:
|
110
|
-
word.append((style, part))
|
111
|
+
word.append(cast("OneStyleAndTextTuple", (style, part, *rest)))
|
111
112
|
yield word[:]
|
112
113
|
word.clear()
|
113
|
-
word.append((style, parts[-1]))
|
114
|
+
word.append(cast("OneStyleAndTextTuple", (style, parts[-1], *rest)))
|
114
115
|
if word:
|
115
116
|
yield word
|
116
117
|
|
@@ -198,7 +199,7 @@ def truncate(
|
|
198
199
|
|
199
200
|
"""
|
200
201
|
lines = split_lines(ft)
|
201
|
-
if max(fragment_list_width(line) for line in lines)
|
202
|
+
if max(fragment_list_width(line) for line in lines) <= width:
|
202
203
|
return ft
|
203
204
|
result: StyleAndTextTuples = []
|
204
205
|
phw = sum(get_cwidth(c) for c in placeholder)
|
@@ -460,22 +461,32 @@ def pad(
|
|
460
461
|
|
461
462
|
|
462
463
|
def paste(
|
463
|
-
ft_bottom: StyleAndTextTuples,
|
464
464
|
ft_top: StyleAndTextTuples,
|
465
|
+
ft_bottom: StyleAndTextTuples,
|
465
466
|
row: int = 0,
|
466
467
|
col: int = 0,
|
468
|
+
transparent: bool = False,
|
467
469
|
) -> StyleAndTextTuples:
|
468
470
|
"""Pate formatted text on top of other formatted text."""
|
469
471
|
ft: StyleAndTextTuples = []
|
470
|
-
|
471
472
|
top_lines = dict(enumerate(split_lines(ft_top), start=row))
|
472
473
|
for y, line_b in enumerate(split_lines(ft_bottom)):
|
473
474
|
if y in top_lines:
|
474
|
-
# x = 0
|
475
475
|
line_t = top_lines[y]
|
476
476
|
line_t_width = fragment_list_width(line_t)
|
477
477
|
ft += substring(line_b, 0, col)
|
478
|
-
|
478
|
+
if transparent:
|
479
|
+
chars_t = explode_text_fragments(line_t)
|
480
|
+
chars_b = explode_text_fragments(
|
481
|
+
substring(line_b, col, col + line_t_width)
|
482
|
+
)
|
483
|
+
for char_t, char_b in zip(chars_t, chars_b):
|
484
|
+
if char_t[0] == "" and char_t[1] == " ":
|
485
|
+
ft.append(char_b)
|
486
|
+
else:
|
487
|
+
ft.append(char_t)
|
488
|
+
else:
|
489
|
+
ft += line_t
|
479
490
|
ft += substring(line_b, col + line_t_width)
|
480
491
|
else:
|
481
492
|
ft += line_b
|
@@ -529,8 +540,8 @@ def concat(
|
|
529
540
|
ft_b = [*ft_b, ("", lines_below * "\n")]
|
530
541
|
|
531
542
|
ft = paste(
|
532
|
-
pad(ft_a, style=style),
|
533
543
|
ft_b,
|
544
|
+
pad(ft_a, style=style),
|
534
545
|
row=0,
|
535
546
|
col=cols_a,
|
536
547
|
)
|
euporie/core/io.py
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
"""Define custom inputs and outputs, and related methods."""
|
2
2
|
|
3
|
+
from __future__ import annotations
|
4
|
+
|
3
5
|
import logging
|
4
6
|
import re
|
5
7
|
from typing import TYPE_CHECKING
|
@@ -9,7 +11,7 @@ from prompt_toolkit.input.base import DummyInput, _dummy_context_manager
|
|
9
11
|
from prompt_toolkit.output.vt100 import Vt100_Output as PtkVt100_Output
|
10
12
|
|
11
13
|
if TYPE_CHECKING:
|
12
|
-
from typing import Any, Callable, ContextManager
|
14
|
+
from typing import Any, Callable, ContextManager
|
13
15
|
|
14
16
|
from prompt_toolkit.keys import Keys
|
15
17
|
|
@@ -30,7 +32,7 @@ _response_prefix_re = re.compile(
|
|
30
32
|
|
31
33
|
|
32
34
|
class _IsPrefixOfLongerMatchCache(vt100_parser._IsPrefixOfLongerMatchCache):
|
33
|
-
def __missing__(self, prefix:
|
35
|
+
def __missing__(self, prefix: str) -> bool:
|
34
36
|
"""Check if the response might match an OSC or APC code, or DA response."""
|
35
37
|
result = super().__missing__(prefix)
|
36
38
|
if not result:
|
@@ -47,12 +49,12 @@ vt100_parser._IS_PREFIX_OF_LONGER_MATCH_CACHE = _IsPrefixOfLongerMatchCache()
|
|
47
49
|
class Vt100Parser(vt100_parser.Vt100Parser):
|
48
50
|
"""A Vt100Parser which checks input against additional key patterns."""
|
49
51
|
|
50
|
-
def __init__(self, *args:
|
52
|
+
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
51
53
|
"""Create a new VT100 parser."""
|
52
54
|
super().__init__(*args, **kwargs)
|
53
|
-
self.queries:
|
55
|
+
self.queries: dict[Keys, re.Pattern] = {}
|
54
56
|
|
55
|
-
def _get_match(self, prefix:
|
57
|
+
def _get_match(self, prefix: str) -> None | Keys | tuple[Keys, ...]:
|
56
58
|
"""Check for additional key matches first."""
|
57
59
|
for key, pattern in self.queries.items():
|
58
60
|
if pattern.match(prefix):
|
@@ -64,9 +66,7 @@ class Vt100Parser(vt100_parser.Vt100Parser):
|
|
64
66
|
class IgnoredInput(DummyInput):
|
65
67
|
"""An input which ignores input but does not immediately close the app."""
|
66
68
|
|
67
|
-
def attach(
|
68
|
-
self, input_ready_callback: "Callable[[], None]"
|
69
|
-
) -> "ContextManager[None]":
|
69
|
+
def attach(self, input_ready_callback: Callable[[], None]) -> ContextManager[None]:
|
70
70
|
"""Do not call the callback, so the input is never closed."""
|
71
71
|
return _dummy_context_manager()
|
72
72
|
|
@@ -74,26 +74,26 @@ class IgnoredInput(DummyInput):
|
|
74
74
|
class Vt100_Output(PtkVt100_Output):
|
75
75
|
"""A Vt100 output which enables SGR pixel mouse positioning."""
|
76
76
|
|
77
|
-
def enable_mouse_support(self) ->
|
77
|
+
def enable_mouse_support(self) -> None:
|
78
78
|
"""Additionally enable SGR-pixel mouse positioning."""
|
79
79
|
super().enable_mouse_support()
|
80
80
|
self.write_raw("\x1b[?1016h")
|
81
81
|
|
82
|
-
def disable_mouse_support(self) ->
|
82
|
+
def disable_mouse_support(self) -> None:
|
83
83
|
"""Additionally disable SGR-pixel mouse positioning."""
|
84
84
|
super().disable_mouse_support()
|
85
85
|
self.write_raw("\x1b[?1016l")
|
86
86
|
|
87
|
-
def enable_extended_keys(self) ->
|
87
|
+
def enable_extended_keys(self) -> None:
|
88
88
|
"""Request extended keys."""
|
89
89
|
# xterm
|
90
90
|
self.write_raw("\x1b[>4;1m")
|
91
91
|
# kitty
|
92
|
-
self.write_raw("\x1b[
|
92
|
+
self.write_raw("\x1b[=1u")
|
93
93
|
|
94
|
-
def disable_extended_keys(self) ->
|
94
|
+
def disable_extended_keys(self) -> None:
|
95
95
|
"""Disable extended keys."""
|
96
96
|
# xterm
|
97
97
|
self.write_raw("\x1b[>4;0m")
|
98
98
|
# kitty
|
99
|
-
self.write_raw("\x1b[
|
99
|
+
self.write_raw("\x1b[=0u")
|