euporie 2.6.1__py3-none-any.whl → 2.7.0__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.
Files changed (67) hide show
  1. euporie/console/tabs/console.py +51 -43
  2. euporie/core/__init__.py +5 -2
  3. euporie/core/app.py +74 -57
  4. euporie/core/comm/ipywidgets.py +7 -3
  5. euporie/core/config.py +51 -27
  6. euporie/core/convert/__init__.py +2 -0
  7. euporie/core/convert/datum.py +82 -45
  8. euporie/core/convert/formats/ansi.py +1 -2
  9. euporie/core/convert/formats/common.py +7 -11
  10. euporie/core/convert/formats/ft.py +10 -7
  11. euporie/core/convert/formats/png.py +7 -6
  12. euporie/core/convert/formats/sixel.py +1 -1
  13. euporie/core/convert/formats/svg.py +28 -0
  14. euporie/core/convert/mime.py +4 -7
  15. euporie/core/data_structures.py +24 -22
  16. euporie/core/filters.py +16 -2
  17. euporie/core/format.py +30 -4
  18. euporie/core/ft/ansi.py +2 -1
  19. euporie/core/ft/html.py +155 -42
  20. euporie/core/{widgets/graphics.py → graphics.py} +225 -227
  21. euporie/core/io.py +8 -0
  22. euporie/core/key_binding/bindings/__init__.py +8 -2
  23. euporie/core/key_binding/bindings/basic.py +9 -14
  24. euporie/core/key_binding/bindings/micro.py +0 -12
  25. euporie/core/key_binding/bindings/mouse.py +107 -80
  26. euporie/core/key_binding/bindings/page_navigation.py +129 -0
  27. euporie/core/key_binding/key_processor.py +9 -1
  28. euporie/core/layout/__init__.py +1 -0
  29. euporie/core/layout/containers.py +1011 -0
  30. euporie/core/layout/decor.py +381 -0
  31. euporie/core/layout/print.py +130 -0
  32. euporie/core/layout/screen.py +75 -0
  33. euporie/core/{widgets/page.py → layout/scroll.py} +166 -111
  34. euporie/core/log.py +1 -1
  35. euporie/core/margins.py +11 -5
  36. euporie/core/path.py +43 -176
  37. euporie/core/renderer.py +31 -8
  38. euporie/core/style.py +2 -0
  39. euporie/core/tabs/base.py +2 -1
  40. euporie/core/terminal.py +19 -21
  41. euporie/core/widgets/cell.py +2 -4
  42. euporie/core/widgets/cell_outputs.py +2 -2
  43. euporie/core/widgets/decor.py +3 -359
  44. euporie/core/widgets/dialog.py +5 -5
  45. euporie/core/widgets/display.py +32 -12
  46. euporie/core/widgets/file_browser.py +3 -4
  47. euporie/core/widgets/forms.py +36 -14
  48. euporie/core/widgets/inputs.py +171 -99
  49. euporie/core/widgets/layout.py +80 -5
  50. euporie/core/widgets/menu.py +1 -3
  51. euporie/core/widgets/pager.py +3 -3
  52. euporie/core/widgets/palette.py +3 -2
  53. euporie/core/widgets/status_bar.py +2 -6
  54. euporie/core/widgets/tree.py +3 -6
  55. euporie/notebook/app.py +8 -8
  56. euporie/notebook/tabs/notebook.py +2 -2
  57. euporie/notebook/widgets/side_bar.py +1 -1
  58. euporie/preview/tabs/notebook.py +2 -2
  59. euporie/web/tabs/web.py +6 -1
  60. euporie/web/widgets/webview.py +52 -32
  61. {euporie-2.6.1.dist-info → euporie-2.7.0.dist-info}/METADATA +9 -11
  62. {euporie-2.6.1.dist-info → euporie-2.7.0.dist-info}/RECORD +67 -60
  63. {euporie-2.6.1.dist-info → euporie-2.7.0.dist-info}/WHEEL +1 -1
  64. {euporie-2.6.1.data → euporie-2.7.0.data}/data/share/applications/euporie-console.desktop +0 -0
  65. {euporie-2.6.1.data → euporie-2.7.0.data}/data/share/applications/euporie-notebook.desktop +0 -0
  66. {euporie-2.6.1.dist-info → euporie-2.7.0.dist-info}/entry_points.txt +0 -0
  67. {euporie-2.6.1.dist-info → euporie-2.7.0.dist-info}/licenses/LICENSE +0 -0
@@ -6,6 +6,10 @@ import contextlib
6
6
  import logging
7
7
  from typing import TYPE_CHECKING
8
8
 
9
+ from prompt_toolkit.auto_suggest import AutoSuggest, DynamicAutoSuggest
10
+ from prompt_toolkit.buffer import Buffer
11
+ from prompt_toolkit.completion import Completer, DynamicCompleter
12
+ from prompt_toolkit.document import Document
9
13
  from prompt_toolkit.filters import (
10
14
  Condition,
11
15
  buffer_has_focus,
@@ -13,21 +17,36 @@ from prompt_toolkit.filters import (
13
17
  has_selection,
14
18
  is_done,
15
19
  is_searching,
20
+ is_true,
16
21
  to_filter,
17
22
  )
18
23
  from prompt_toolkit.key_binding.key_bindings import merge_key_bindings
19
- from prompt_toolkit.layout.containers import ConditionalContainer
24
+ from prompt_toolkit.layout.containers import (
25
+ ConditionalContainer,
26
+ ScrollOffsets,
27
+ )
28
+ from prompt_toolkit.layout.controls import (
29
+ BufferControl,
30
+ GetLinePrefixCallable,
31
+ )
32
+ from prompt_toolkit.layout.dimension import AnyDimension
33
+ from prompt_toolkit.layout.dimension import Dimension as D
20
34
  from prompt_toolkit.layout.margins import ConditionalMargin
21
35
  from prompt_toolkit.layout.processors import ( # HighlightSearchProcessor,
36
+ BeforeInput,
22
37
  ConditionalProcessor,
23
38
  DisplayMultipleCursors,
24
39
  HighlightIncrementalSearchProcessor,
25
40
  HighlightMatchingBracketProcessor,
26
41
  HighlightSelectionProcessor,
42
+ PasswordProcessor,
43
+ Processor,
27
44
  TabsProcessor,
28
45
  )
29
46
  from prompt_toolkit.lexers import DynamicLexer, PygmentsLexer, SimpleLexer
47
+ from prompt_toolkit.validation import DynamicValidator, Validator
30
48
  from prompt_toolkit.widgets import TextArea
49
+ from prompt_toolkit.widgets.toolbars import SearchToolbar
31
50
  from pygments.lexers import ClassNotFound, get_lexer_by_name
32
51
 
33
52
  from euporie.core.commands import add_cmd
@@ -38,6 +57,7 @@ from euporie.core.key_binding.registry import (
38
57
  load_registered_bindings,
39
58
  register_bindings,
40
59
  )
60
+ from euporie.core.layout.containers import Window
41
61
  from euporie.core.margins import NumberedDiffMargin, OverflowMargin, ScrollbarMargin
42
62
  from euporie.core.processors import (
43
63
  AppendLineAutoSuggestion,
@@ -47,10 +67,14 @@ from euporie.core.suggest import ConditionalAutoSuggestAsync
47
67
  from euporie.core.widgets.pager import PagerState
48
68
 
49
69
  if TYPE_CHECKING:
50
- from typing import Any, Callable, Sequence
70
+ from typing import Callable, Sequence
51
71
 
52
- from prompt_toolkit.buffer import Buffer
53
- from prompt_toolkit.filters import FilterOrBool
72
+ from prompt_toolkit.buffer import BufferAcceptHandler
73
+ from prompt_toolkit.filters import Filter, FilterOrBool
74
+ from prompt_toolkit.formatted_text import (
75
+ AnyFormattedText,
76
+ )
77
+ from prompt_toolkit.history import History
54
78
  from prompt_toolkit.key_binding.key_bindings import KeyBindingsBase
55
79
  from prompt_toolkit.layout.containers import AnyContainer
56
80
  from prompt_toolkit.layout.layout import FocusableElement
@@ -72,46 +96,60 @@ class KernelInput(TextArea):
72
96
  def __init__(
73
97
  self,
74
98
  kernel_tab: KernelTab,
75
- *args: Any,
99
+ text: str = "",
100
+ multiline: FilterOrBool = True,
101
+ password: FilterOrBool = False,
102
+ lexer: Lexer | None = None,
103
+ auto_suggest: AutoSuggest | None = None,
104
+ completer: Completer | None = None,
105
+ complete_while_typing: FilterOrBool = True,
106
+ validator: Validator | None = None,
107
+ accept_handler: BufferAcceptHandler | None = None,
108
+ history: History | None = None,
109
+ focusable: FilterOrBool = True,
110
+ focus_on_click: FilterOrBool = True,
111
+ wrap_lines: FilterOrBool = False,
112
+ read_only: FilterOrBool = False,
113
+ width: AnyDimension = None,
114
+ height: AnyDimension = None,
115
+ dont_extend_height: FilterOrBool = False,
116
+ dont_extend_width: FilterOrBool = False,
117
+ line_numbers: bool = False,
118
+ get_line_prefix: GetLinePrefixCallable | None = None,
119
+ scrollbar: FilterOrBool = True,
120
+ style: str = "class:kernel-input",
121
+ search_field: SearchToolbar | None = None,
122
+ preview_search: FilterOrBool = True,
123
+ prompt: AnyFormattedText = "",
124
+ input_processors: list[Processor] | None = None,
125
+ name: str = "",
76
126
  left_margins: Sequence[Margin] | None = None,
77
127
  right_margins: Sequence[Margin] | None = None,
78
128
  on_text_changed: Callable[[Buffer], None] | None = None,
79
129
  on_cursor_position_changed: Callable[[Buffer], None] | None = None,
80
130
  tempfile_suffix: str | Callable[[], str] = "",
81
131
  key_bindings: KeyBindingsBase | None = None,
82
- enable_history_search: FilterOrBool | None = False,
83
- wrap_lines: FilterOrBool = False,
84
- complete_while_typing: FilterOrBool = True,
132
+ enable_history_search: FilterOrBool = False,
85
133
  autosuggest_while_typing: FilterOrBool = True,
86
- validate_while_typing: FilterOrBool | None = None,
87
- **kwargs: Any,
134
+ validate_while_typing: FilterOrBool = False,
135
+ scroll_offsets: ScrollOffsets | None = None,
88
136
  ) -> None:
89
137
  """Initiate the cell input box."""
90
138
  self.kernel_tab = kernel_tab
91
139
  app = kernel_tab.app
92
140
 
93
- kwargs.setdefault("wrap_lines", wrap_lines)
94
- kwargs.setdefault("style", "class:kernel-input")
95
- kwargs.setdefault("history", kernel_tab.history)
96
- kwargs.setdefault("search_field", app.search_bar)
97
- kwargs.setdefault("focus_on_click", True)
98
- kwargs.setdefault("preview_search", True)
99
- kwargs.setdefault(
100
- "input_processors",
101
- [
102
- ConditionalProcessor(
103
- HighlightIncrementalSearchProcessor(),
104
- filter=is_searching,
105
- ),
106
- # HighlightSearchProcessor(),
107
- HighlightSelectionProcessor(),
108
- DisplayMultipleCursors(),
109
- HighlightMatchingBracketProcessor(),
110
- TabsProcessor(char1="⇥", char2="┈"),
111
- ShowTrailingWhiteSpaceProcessor(),
112
- ],
113
- )
114
- kwargs.setdefault("completer", kernel_tab.completer)
141
+ if history is None:
142
+ history = kernel_tab.history
143
+
144
+ if search_field is None:
145
+ search_field = app.search_bar
146
+ if isinstance(search_field, SearchToolbar):
147
+ search_control = search_field.control
148
+ else:
149
+ search_control = None
150
+
151
+ if input_processors is None:
152
+ input_processors = []
115
153
 
116
154
  def _get_lexer() -> Lexer:
117
155
  try:
@@ -123,77 +161,41 @@ class KernelInput(TextArea):
123
161
  else:
124
162
  return PygmentsLexer(pygments_lexer_class, sync_from_start=False)
125
163
 
126
- kwargs.setdefault("lexer", DynamicLexer(_get_lexer))
127
- kwargs.setdefault(
128
- "auto_suggest",
129
- ConditionalAutoSuggestAsync(
130
- self.kernel_tab.suggester,
131
- filter=to_filter(autosuggest_while_typing)
132
- & Condition(lambda: app.config.autosuggest),
133
- ),
134
- )
135
- kwargs["complete_while_typing"] = Condition(
164
+ # Writeable attributes.
165
+ self.completer = completer or kernel_tab.completer
166
+ self.complete_while_typing = Condition(
136
167
  lambda: app.config.autocomplete
137
168
  ) & to_filter(complete_while_typing)
138
-
139
- super().__init__(*args, **kwargs)
140
-
141
- if validate_while_typing:
142
- self.buffer.validate_while_typing = to_filter(validate_while_typing)
143
-
144
- self.control.include_default_input_processors = False
145
- if on_text_changed:
146
- self.buffer.on_text_changed += on_text_changed
147
- if on_cursor_position_changed:
148
- self.buffer.on_cursor_position_changed += on_cursor_position_changed
149
- self.buffer.tempfile_suffix = tempfile_suffix or kernel_tab.kernel_lang_file_ext
150
-
151
- if enable_history_search is not None:
152
- self.buffer.enable_history_search = to_filter(enable_history_search)
153
-
154
- self.has_focus = has_focus(self)
155
-
156
- # Replace the autosuggest processor
157
- # Skip type checking as PT should use "("Optional[Sequence[Processor]]"
158
- # instead of "Optional[list[Processor]]"
159
- # TODO make a PR for this
160
- self.control.input_processors[0] = ConditionalProcessor( # type: ignore
161
- AppendLineAutoSuggestion(),
162
- has_focus(self.buffer) & ~is_done,
163
- )
164
-
165
- # Set style
166
- style = kwargs.get("style", "")
167
- self.window.style = lambda: (
168
- "class:text-area " + ("class:focused " if self.has_focus() else "") + style
169
- )
170
-
171
- # Add configurable line numbers
172
- self.window.left_margins = (
173
- left_margins
174
- if left_margins is not None
175
- else [
176
- ConditionalMargin(
177
- NumberedDiffMargin(),
178
- Condition(lambda: self.kernel_tab.app.config.line_numbers),
179
- )
180
- ]
169
+ self.auto_suggest = auto_suggest or ConditionalAutoSuggestAsync(
170
+ self.kernel_tab.suggester,
171
+ filter=to_filter(autosuggest_while_typing)
172
+ & Condition(lambda: app.config.autosuggest),
181
173
  )
182
-
183
- self.window.right_margins = (
184
- right_margins
185
- if right_margins is not None
186
- else [
187
- OverflowMargin(),
188
- ConditionalMargin(
189
- ScrollbarMargin(display_arrows=False),
190
- filter=scrollable(self.window),
191
- ),
192
- ]
174
+ self.read_only = read_only
175
+ self.wrap_lines = wrap_lines
176
+ self.validator = validator
177
+ self.lexer = lexer
178
+
179
+ self.buffer = Buffer(
180
+ document=Document(text, 0),
181
+ multiline=multiline,
182
+ read_only=Condition(lambda: is_true(self.read_only)),
183
+ completer=DynamicCompleter(lambda: self.completer),
184
+ complete_while_typing=Condition(
185
+ lambda: is_true(self.complete_while_typing)
186
+ ),
187
+ validator=DynamicValidator(lambda: self.validator),
188
+ auto_suggest=DynamicAutoSuggest(lambda: self.auto_suggest),
189
+ accept_handler=accept_handler,
190
+ history=history,
191
+ name=name,
192
+ validate_while_typing=validate_while_typing,
193
+ on_text_changed=on_text_changed,
194
+ on_cursor_position_changed=on_cursor_position_changed,
195
+ tempfile_suffix=tempfile_suffix or kernel_tab.kernel_lang_file_ext,
196
+ enable_history_search=to_filter(enable_history_search),
193
197
  )
194
198
 
195
- self.window.cursorline = self.has_focus
196
-
197
199
  # Set extra key-bindings
198
200
  widgets_key_bindings = load_registered_bindings(
199
201
  "euporie.core.widgets.inputs.KernelInput"
@@ -202,7 +204,77 @@ class KernelInput(TextArea):
202
204
  widgets_key_bindings = merge_key_bindings(
203
205
  [key_bindings, widgets_key_bindings]
204
206
  )
205
- self.control.key_bindings = widgets_key_bindings
207
+
208
+ self.control = BufferControl(
209
+ buffer=self.buffer,
210
+ lexer=DynamicLexer(lambda: self.lexer or _get_lexer()),
211
+ input_processors=[
212
+ ConditionalProcessor( # type: ignore
213
+ AppendLineAutoSuggestion(),
214
+ has_focus(self.buffer) & ~is_done,
215
+ ),
216
+ ConditionalProcessor(
217
+ processor=PasswordProcessor(), filter=to_filter(password)
218
+ ),
219
+ BeforeInput(prompt, style="class:text-area.prompt"),
220
+ ConditionalProcessor(
221
+ HighlightIncrementalSearchProcessor(),
222
+ filter=is_searching,
223
+ ),
224
+ # HighlightSearchProcessor(),
225
+ HighlightSelectionProcessor(),
226
+ DisplayMultipleCursors(),
227
+ ConditionalProcessor( # type: ignore
228
+ HighlightMatchingBracketProcessor(),
229
+ has_focus(self.buffer) & ~is_done,
230
+ ),
231
+ TabsProcessor(char1="⇥", char2="┈"),
232
+ ShowTrailingWhiteSpaceProcessor(),
233
+ *input_processors,
234
+ ],
235
+ search_buffer_control=search_control,
236
+ preview_search=preview_search,
237
+ focusable=focusable,
238
+ focus_on_click=focus_on_click,
239
+ include_default_input_processors=False,
240
+ key_bindings=widgets_key_bindings,
241
+ )
242
+
243
+ left_margins = [
244
+ ConditionalMargin(
245
+ NumberedDiffMargin(),
246
+ app.config.filter("line_numbers") & self.buffer.multiline,
247
+ # & Condition(lambda: len(self.buffer.text.split("\n")) > 1),
248
+ )
249
+ ]
250
+ scrollbar_margin = ConditionalMargin(
251
+ ScrollbarMargin(), filter=to_filter(scrollbar)
252
+ )
253
+ right_margins = [OverflowMargin(), scrollbar_margin]
254
+ self.window = Window(
255
+ height=lambda: height or D(min=1)
256
+ if self.buffer.multiline()
257
+ else D.exact(1),
258
+ width=width,
259
+ dont_extend_height=dont_extend_height,
260
+ dont_extend_width=dont_extend_width,
261
+ content=self.control,
262
+ wrap_lines=Condition(lambda: is_true(self.wrap_lines)),
263
+ left_margins=left_margins,
264
+ right_margins=right_margins,
265
+ get_line_prefix=get_line_prefix,
266
+ style=lambda: (
267
+ "class:text-area "
268
+ + ("class:focused " if self.has_focus() else "")
269
+ + style
270
+ ),
271
+ cursorline=has_focus(self.buffer),
272
+ scroll_offsets=scroll_offsets
273
+ or ScrollOffsets(top=1, right=1, bottom=1, left=1),
274
+ )
275
+ scrollbar_margin.filter &= scrollable(self.window)
276
+
277
+ self.has_focus: Filter = has_focus(self.buffer)
206
278
 
207
279
  def inspect(self) -> None:
208
280
  """Get contextual help for the current cursor position in the current cell."""
@@ -16,9 +16,6 @@ from prompt_toolkit.formatted_text.utils import fragment_list_width
16
16
  from prompt_toolkit.layout.containers import (
17
17
  ConditionalContainer,
18
18
  DynamicContainer,
19
- HSplit,
20
- VSplit,
21
- Window,
22
19
  to_container,
23
20
  )
24
21
  from prompt_toolkit.layout.controls import (
@@ -27,13 +24,15 @@ from prompt_toolkit.layout.controls import (
27
24
  UIContent,
28
25
  UIControl,
29
26
  )
27
+ from prompt_toolkit.layout.dimension import Dimension as D
28
+ from prompt_toolkit.layout.dimension import to_dimension
30
29
  from prompt_toolkit.mouse_events import MouseButton, MouseEventType
31
30
  from prompt_toolkit.utils import Event
32
- from prompt_toolkit.widgets import Box
33
31
 
34
32
  from euporie.core.border import OutsetGrid
35
33
  from euporie.core.data_structures import DiBool
36
34
  from euporie.core.ft.utils import truncate
35
+ from euporie.core.layout.containers import HSplit, VSplit, Window
37
36
  from euporie.core.widgets.decor import Border
38
37
 
39
38
  if TYPE_CHECKING:
@@ -41,7 +40,10 @@ if TYPE_CHECKING:
41
40
 
42
41
  from prompt_toolkit.filters import FilterOrBool
43
42
  from prompt_toolkit.formatted_text.base import AnyFormattedText, StyleAndTextTuples
44
- from prompt_toolkit.key_binding.key_bindings import NotImplementedOrNone
43
+ from prompt_toolkit.key_binding.key_bindings import (
44
+ KeyBindings,
45
+ NotImplementedOrNone,
46
+ )
45
47
  from prompt_toolkit.layout.containers import AnyContainer, Container, _Split
46
48
  from prompt_toolkit.layout.dimension import AnyDimension
47
49
  from prompt_toolkit.mouse_events import MouseEvent
@@ -51,6 +53,79 @@ if TYPE_CHECKING:
51
53
  log = logging.getLogger(__name__)
52
54
 
53
55
 
56
+ class Box:
57
+ """Add padding around a container.
58
+
59
+ This also makes sure that the parent can provide more space than required by
60
+ the child. This is very useful when wrapping a small element with a fixed
61
+ size into a ``VSplit`` or ``HSplit`` object. The ``HSplit`` and ``VSplit``
62
+ try to make sure to adapt respectively the width and height, possibly
63
+ shrinking other elements. Wrapping something in a ``Box`` makes it flexible.
64
+
65
+ Args:
66
+ body: Another container object.
67
+ padding: The margin to be used around the body. This can be
68
+ overridden by `padding_left`, padding_right`, `padding_top` and
69
+ `padding_bottom`.
70
+ style: A style string.
71
+ char: Character to be used for filling the space around the body.
72
+ (This is supposed to be a character with a terminal width of 1.)
73
+ """
74
+
75
+ def __init__(
76
+ self,
77
+ body: AnyContainer,
78
+ padding: AnyDimension = None,
79
+ padding_left: AnyDimension = None,
80
+ padding_right: AnyDimension = None,
81
+ padding_top: AnyDimension = None,
82
+ padding_bottom: AnyDimension = None,
83
+ width: AnyDimension = None,
84
+ height: AnyDimension = None,
85
+ style: str = "",
86
+ char: None | str | Callable[[], str] = None,
87
+ modal: bool = False,
88
+ key_bindings: KeyBindings | None = None,
89
+ ) -> None:
90
+ """Initialize this widget."""
91
+ if padding is None:
92
+ padding = D(preferred=0)
93
+
94
+ def get(value: AnyDimension) -> D:
95
+ if value is None:
96
+ value = padding
97
+ return to_dimension(value)
98
+
99
+ self.padding_left = get(padding_left)
100
+ self.padding_right = get(padding_right)
101
+ self.padding_top = get(padding_top)
102
+ self.padding_bottom = get(padding_bottom)
103
+ self.body = body
104
+
105
+ self.container = HSplit(
106
+ [
107
+ Window(height=self.padding_top, char=char),
108
+ VSplit(
109
+ [
110
+ Window(width=self.padding_left, char=char),
111
+ body,
112
+ Window(width=self.padding_right, char=char),
113
+ ]
114
+ ),
115
+ Window(height=self.padding_bottom, char=char),
116
+ ],
117
+ width=width,
118
+ height=height,
119
+ style=style,
120
+ modal=modal,
121
+ key_bindings=None,
122
+ )
123
+
124
+ def __pt_container__(self) -> Container:
125
+ """Return the main container for this widget."""
126
+ return self.container
127
+
128
+
54
129
  class ConditionalSplit:
55
130
  """A split container where the orientation depends on a filter."""
56
131
 
@@ -19,10 +19,7 @@ from prompt_toolkit.layout.containers import (
19
19
  ConditionalContainer,
20
20
  Container,
21
21
  Float,
22
- HSplit,
23
22
  ScrollOffsets,
24
- VSplit,
25
- Window,
26
23
  )
27
24
  from prompt_toolkit.layout.controls import FormattedTextControl, UIContent
28
25
  from prompt_toolkit.layout.dimension import Dimension
@@ -35,6 +32,7 @@ from prompt_toolkit.utils import get_cwidth
35
32
 
36
33
  from euporie.core.border import OuterHalfGrid
37
34
  from euporie.core.current import get_app
35
+ from euporie.core.layout.containers import HSplit, VSplit, Window
38
36
  from euporie.core.widgets.decor import Shadow
39
37
 
40
38
  if TYPE_CHECKING:
@@ -10,9 +10,7 @@ from prompt_toolkit.filters import Condition
10
10
  from prompt_toolkit.layout.containers import (
11
11
  ConditionalContainer,
12
12
  DynamicContainer,
13
- HSplit,
14
13
  )
15
- from prompt_toolkit.widgets import Box
16
14
 
17
15
  from euporie.core.commands import add_cmd
18
16
  from euporie.core.convert.datum import Datum
@@ -25,9 +23,11 @@ from euporie.core.key_binding.registry import (
25
23
  load_registered_bindings,
26
24
  register_bindings,
27
25
  )
26
+ from euporie.core.layout.containers import HSplit
27
+ from euporie.core.layout.decor import Line
28
28
  from euporie.core.widgets.cell_outputs import CellOutput, CellOutputDataElement
29
- from euporie.core.widgets.decor import Line
30
29
  from euporie.core.widgets.display import Display
30
+ from euporie.core.widgets.layout import Box
31
31
 
32
32
  if TYPE_CHECKING:
33
33
  from typing import Any
@@ -10,15 +10,16 @@ from typing import TYPE_CHECKING, NamedTuple
10
10
  from prompt_toolkit.data_structures import Point
11
11
  from prompt_toolkit.filters import Condition
12
12
  from prompt_toolkit.key_binding.bindings.focus import focus_next, focus_previous
13
- from prompt_toolkit.layout.containers import HSplit, ScrollOffsets, VSplit, Window
13
+ 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
17
  from euporie.core.commands import Command, add_cmd, commands
18
18
  from euporie.core.current import get_app
19
19
  from euporie.core.key_binding.registry import register_bindings
20
+ from euporie.core.layout.containers import HSplit, VSplit, Window
21
+ from euporie.core.layout.decor import FocusedStyle
20
22
  from euporie.core.margins import MarginContainer, ScrollbarMargin
21
- from euporie.core.widgets.decor import FocusedStyle
22
23
  from euporie.core.widgets.dialog import Dialog
23
24
  from euporie.core.widgets.forms import Text
24
25
  from euporie.core.widgets.status_bar import StatusContainer
@@ -10,12 +10,7 @@ from prompt_toolkit.cache import FastDictCache
10
10
  from prompt_toolkit.filters.utils import to_filter
11
11
  from prompt_toolkit.formatted_text import to_formatted_text
12
12
  from prompt_toolkit.layout import containers
13
- from prompt_toolkit.layout.containers import (
14
- ConditionalContainer,
15
- VSplit,
16
- Window,
17
- WindowAlign,
18
- )
13
+ from prompt_toolkit.layout.containers import ConditionalContainer, WindowAlign
19
14
  from prompt_toolkit.layout.containers import (
20
15
  to_container as ptk_to_container,
21
16
  )
@@ -24,6 +19,7 @@ from prompt_toolkit.layout.controls import FormattedTextControl
24
19
  from euporie.core.config import add_setting
25
20
  from euporie.core.current import get_app
26
21
  from euporie.core.filters import is_searching
22
+ from euporie.core.layout.containers import VSplit, Window
27
23
 
28
24
  if TYPE_CHECKING:
29
25
  from typing import Callable, Sequence
@@ -5,15 +5,12 @@ from __future__ import annotations
5
5
  from typing import TYPE_CHECKING, cast
6
6
 
7
7
  from prompt_toolkit.filters import Condition
8
- from prompt_toolkit.layout.containers import (
9
- ConditionalContainer,
10
- HSplit,
11
- VSplit,
12
- Window,
13
- )
8
+ from prompt_toolkit.layout.containers import ConditionalContainer
14
9
  from prompt_toolkit.layout.controls import FormattedTextControl
15
10
  from prompt_toolkit.mouse_events import MouseButton, MouseEvent, MouseEventType
16
11
 
12
+ from euporie.core.layout.containers import HSplit, VSplit, Window
13
+
17
14
  if TYPE_CHECKING:
18
15
  from typing import Any
19
16
 
euporie/notebook/app.py CHANGED
@@ -13,9 +13,6 @@ from prompt_toolkit.layout.containers import (
13
13
  ConditionalContainer,
14
14
  DynamicContainer,
15
15
  FloatContainer,
16
- HSplit,
17
- VSplit,
18
- Window,
19
16
  WindowAlign,
20
17
  )
21
18
  from prompt_toolkit.layout.controls import FormattedTextControl
@@ -28,7 +25,8 @@ from euporie.core.commands import add_cmd, get_cmd
28
25
  from euporie.core.config import add_setting
29
26
  from euporie.core.ft.utils import truncate
30
27
  from euporie.core.key_binding.registry import register_bindings
31
- from euporie.core.widgets.decor import Pattern
28
+ from euporie.core.layout.containers import HSplit, VSplit, Window
29
+ from euporie.core.layout.decor import Pattern
32
30
  from euporie.core.widgets.dialog import (
33
31
  AboutDialog,
34
32
  ConfirmDialog,
@@ -196,6 +194,7 @@ class NotebookApp(BaseApp):
196
194
  self.tab_bar_control,
197
195
  height=2,
198
196
  style="class:app-tab-bar",
197
+ dont_extend_height=True,
199
198
  ),
200
199
  filter=Condition(
201
200
  lambda: (len(self.tabs) > 1 or self.config.always_show_tab_bar)
@@ -432,7 +431,7 @@ class NotebookApp(BaseApp):
432
431
  self.config.get_item("syntax_theme").menu,
433
432
  get_cmd("toggle-background-pattern").menu,
434
433
  get_cmd("toggle-show-cell-borders").menu,
435
- get_cmd("toggle-tmux-graphics").menu,
434
+ get_cmd("toggle-multiplexer-passthrough").menu,
436
435
  separator,
437
436
  get_cmd("toggle-expand").menu,
438
437
  get_cmd("toggle-line-numbers").menu,
@@ -451,9 +450,10 @@ class NotebookApp(BaseApp):
451
450
  children=[
452
451
  get_cmd("toggle-autoformat").menu,
453
452
  separator,
454
- get_cmd("toggle-format-black").menu,
455
- get_cmd("toggle-format-isort").menu,
456
- get_cmd("toggle-format-ssort").menu,
453
+ get_cmd("toggle-formatters-ruff").menu,
454
+ get_cmd("toggle-formatters-black").menu,
455
+ get_cmd("toggle-formatters-isort").menu,
456
+ get_cmd("toggle-formatters-ssort").menu,
457
457
  ],
458
458
  ),
459
459
  get_cmd("toggle-autocomplete").menu,
@@ -39,13 +39,13 @@ from euporie.core.key_binding.registry import (
39
39
  load_registered_bindings,
40
40
  register_bindings,
41
41
  )
42
+ from euporie.core.layout.decor import Line, Pattern
43
+ from euporie.core.layout.scroll import ScrollingContainer
42
44
  from euporie.core.margins import MarginContainer, ScrollbarMargin
43
45
  from euporie.core.style import KERNEL_STATUS_REPR
44
46
  from euporie.core.tabs.base import KernelTab
45
47
  from euporie.core.tabs.notebook import BaseNotebook
46
48
  from euporie.core.widgets.cell import Cell
47
- from euporie.core.widgets.decor import Line, Pattern
48
- from euporie.core.widgets.page import ScrollingContainer
49
49
  from euporie.notebook.filters import (
50
50
  cell_has_focus,
51
51
  code_cell_selected,
@@ -19,7 +19,7 @@ from prompt_toolkit.layout.controls import FormattedTextControl
19
19
  from euporie.core.commands import add_cmd
20
20
  from euporie.core.config import add_setting
21
21
  from euporie.core.key_binding.registry import register_bindings
22
- from euporie.core.widgets.decor import Line
22
+ from euporie.core.layout.decor import Line
23
23
  from euporie.core.widgets.forms import ToggleButton, ToggleButtons
24
24
 
25
25
  if TYPE_CHECKING:
@@ -13,12 +13,12 @@ from prompt_toolkit.layout.containers import (
13
13
  Window,
14
14
  )
15
15
  from prompt_toolkit.layout.dimension import Dimension
16
- from prompt_toolkit.widgets import Box
17
16
 
18
17
  from euporie.core.config import add_setting
18
+ from euporie.core.layout.print import PrintingContainer
19
19
  from euporie.core.tabs.notebook import BaseNotebook
20
20
  from euporie.core.widgets.cell import Cell
21
- from euporie.core.widgets.page import PrintingContainer
21
+ from euporie.core.widgets.layout import Box
22
22
 
23
23
  if TYPE_CHECKING:
24
24
  from pathlib import Path