euporie 2.8.4__py3-none-any.whl → 2.8.6__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 (131) hide show
  1. euporie/console/_commands.py +143 -0
  2. euporie/console/_settings.py +58 -0
  3. euporie/console/app.py +25 -71
  4. euporie/console/tabs/console.py +58 -62
  5. euporie/core/__init__.py +1 -1
  6. euporie/core/__main__.py +28 -11
  7. euporie/core/_settings.py +109 -0
  8. euporie/core/app/__init__.py +3 -0
  9. euporie/core/app/_commands.py +95 -0
  10. euporie/core/app/_settings.py +457 -0
  11. euporie/core/{app.py → app/app.py} +212 -576
  12. euporie/core/app/base.py +51 -0
  13. euporie/core/{current.py → app/current.py} +13 -4
  14. euporie/core/app/cursor.py +35 -0
  15. euporie/core/app/dummy.py +12 -0
  16. euporie/core/app/launch.py +28 -0
  17. euporie/core/bars/__init__.py +11 -0
  18. euporie/core/bars/command.py +205 -0
  19. euporie/core/bars/menu.py +258 -0
  20. euporie/core/{widgets → bars}/search.py +20 -16
  21. euporie/core/{widgets → bars}/status.py +6 -23
  22. euporie/core/clipboard.py +19 -80
  23. euporie/core/comm/base.py +8 -6
  24. euporie/core/comm/ipywidgets.py +16 -7
  25. euporie/core/comm/registry.py +2 -1
  26. euporie/core/commands.py +10 -20
  27. euporie/core/completion.py +3 -2
  28. euporie/core/config.py +368 -341
  29. euporie/core/convert/__init__.py +0 -30
  30. euporie/core/convert/datum.py +116 -53
  31. euporie/core/convert/formats/__init__.py +31 -0
  32. euporie/core/convert/formats/ansi.py +9 -23
  33. euporie/core/convert/formats/common.py +11 -23
  34. euporie/core/convert/formats/html.py +45 -40
  35. euporie/core/convert/formats/pil.py +1 -1
  36. euporie/core/convert/formats/png.py +3 -5
  37. euporie/core/convert/formats/sixel.py +3 -3
  38. euporie/core/convert/registry.py +4 -6
  39. euporie/core/convert/utils.py +41 -4
  40. euporie/core/diagnostics.py +2 -2
  41. euporie/core/filters.py +98 -40
  42. euporie/core/format.py +2 -3
  43. euporie/core/ft/ansi.py +1 -1
  44. euporie/core/ft/html.py +12 -21
  45. euporie/core/ft/table.py +1 -3
  46. euporie/core/ft/utils.py +4 -1
  47. euporie/core/graphics.py +386 -133
  48. euporie/core/history.py +2 -2
  49. euporie/core/inspection.py +3 -2
  50. euporie/core/io.py +207 -28
  51. euporie/core/kernel/__init__.py +1 -0
  52. euporie/core/{kernel.py → kernel/client.py} +45 -108
  53. euporie/core/kernel/manager.py +114 -0
  54. euporie/core/key_binding/bindings/__init__.py +1 -8
  55. euporie/core/key_binding/bindings/basic.py +47 -7
  56. euporie/core/key_binding/bindings/completion.py +3 -8
  57. euporie/core/key_binding/bindings/micro.py +1 -6
  58. euporie/core/key_binding/bindings/mouse.py +2 -2
  59. euporie/core/key_binding/bindings/terminal.py +193 -0
  60. euporie/core/key_binding/key_processor.py +43 -2
  61. euporie/core/key_binding/registry.py +2 -0
  62. euporie/core/key_binding/utils.py +22 -2
  63. euporie/core/keys.py +7156 -93
  64. euporie/core/layout/cache.py +3 -3
  65. euporie/core/layout/containers.py +48 -4
  66. euporie/core/layout/decor.py +2 -2
  67. euporie/core/layout/mouse.py +1 -1
  68. euporie/core/layout/print.py +2 -1
  69. euporie/core/layout/scroll.py +39 -34
  70. euporie/core/log.py +76 -64
  71. euporie/core/lsp.py +118 -24
  72. euporie/core/margins.py +1 -1
  73. euporie/core/path.py +62 -13
  74. euporie/core/renderer.py +58 -17
  75. euporie/core/style.py +57 -39
  76. euporie/core/suggest.py +103 -85
  77. euporie/core/tabs/__init__.py +32 -0
  78. euporie/core/tabs/_settings.py +113 -0
  79. euporie/core/tabs/base.py +80 -470
  80. euporie/core/tabs/kernel.py +419 -0
  81. euporie/core/tabs/notebook.py +24 -101
  82. euporie/core/utils.py +92 -15
  83. euporie/core/validation.py +1 -1
  84. euporie/core/widgets/_settings.py +188 -0
  85. euporie/core/widgets/cell.py +19 -50
  86. euporie/core/widgets/cell_outputs.py +25 -36
  87. euporie/core/widgets/decor.py +11 -41
  88. euporie/core/widgets/dialog.py +62 -27
  89. euporie/core/widgets/display.py +12 -15
  90. euporie/core/widgets/file_browser.py +2 -23
  91. euporie/core/widgets/forms.py +8 -5
  92. euporie/core/widgets/inputs.py +13 -70
  93. euporie/core/widgets/layout.py +2 -1
  94. euporie/core/widgets/logo.py +49 -0
  95. euporie/core/widgets/menu.py +10 -8
  96. euporie/core/widgets/pager.py +6 -10
  97. euporie/core/widgets/palette.py +6 -6
  98. euporie/hub/app.py +52 -35
  99. euporie/notebook/_commands.py +24 -0
  100. euporie/notebook/_settings.py +107 -0
  101. euporie/notebook/app.py +49 -171
  102. euporie/notebook/filters.py +1 -1
  103. euporie/notebook/tabs/__init__.py +46 -7
  104. euporie/notebook/tabs/_commands.py +714 -0
  105. euporie/notebook/tabs/_settings.py +32 -0
  106. euporie/notebook/tabs/display.py +4 -4
  107. euporie/notebook/tabs/edit.py +11 -44
  108. euporie/notebook/tabs/json.py +5 -5
  109. euporie/notebook/tabs/log.py +1 -18
  110. euporie/notebook/tabs/notebook.py +11 -660
  111. euporie/notebook/widgets/_commands.py +11 -0
  112. euporie/notebook/widgets/_settings.py +19 -0
  113. euporie/notebook/widgets/side_bar.py +14 -34
  114. euporie/preview/_settings.py +104 -0
  115. euporie/preview/app.py +6 -31
  116. euporie/preview/tabs/notebook.py +6 -72
  117. euporie/web/__init__.py +1 -0
  118. euporie/web/tabs/__init__.py +14 -0
  119. euporie/web/tabs/web.py +11 -6
  120. euporie/web/widgets/__init__.py +1 -0
  121. euporie/web/widgets/webview.py +5 -15
  122. {euporie-2.8.4.dist-info → euporie-2.8.6.dist-info}/METADATA +10 -8
  123. euporie-2.8.6.dist-info/RECORD +175 -0
  124. {euporie-2.8.4.dist-info → euporie-2.8.6.dist-info}/WHEEL +1 -1
  125. {euporie-2.8.4.dist-info → euporie-2.8.6.dist-info}/entry_points.txt +2 -2
  126. {euporie-2.8.4.dist-info → euporie-2.8.6.dist-info}/licenses/LICENSE +1 -1
  127. euporie/core/launch.py +0 -64
  128. euporie/core/terminal.py +0 -522
  129. euporie-2.8.4.dist-info/RECORD +0 -147
  130. {euporie-2.8.4.data → euporie-2.8.6.data}/data/share/applications/euporie-console.desktop +0 -0
  131. {euporie-2.8.4.data → euporie-2.8.6.data}/data/share/applications/euporie-notebook.desktop +0 -0
euporie/notebook/app.py CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- import asyncio
6
5
  import logging
7
6
  from functools import partial
8
7
  from typing import TYPE_CHECKING, cast
@@ -12,17 +11,20 @@ from prompt_toolkit.formatted_text.base import to_formatted_text
12
11
  from prompt_toolkit.layout.containers import (
13
12
  ConditionalContainer,
14
13
  DynamicContainer,
14
+ Float,
15
15
  FloatContainer,
16
16
  WindowAlign,
17
17
  )
18
18
  from prompt_toolkit.layout.controls import FormattedTextControl
19
19
  from prompt_toolkit.layout.dimension import Dimension
20
- from upath import UPath
21
20
 
22
- from euporie.core import __logo__
23
- from euporie.core.app import BaseApp
24
- from euporie.core.commands import add_cmd, get_cmd
25
- from euporie.core.config import add_setting
21
+ from euporie.core.app.app import BaseApp
22
+ from euporie.core.bars.command import CommandBar
23
+ from euporie.core.bars.menu import ToolbarCompletionsMenu
24
+ from euporie.core.bars.search import SearchBar
25
+ from euporie.core.bars.status import StatusBar, StatusContainer
26
+ from euporie.core.commands import get_cmd
27
+ from euporie.core.filters import has_tabs
26
28
  from euporie.core.ft.utils import truncate
27
29
  from euporie.core.key_binding.registry import register_bindings
28
30
  from euporie.core.layout.containers import HSplit, VSplit, Window
@@ -41,26 +43,27 @@ from euporie.core.widgets.dialog import (
41
43
  )
42
44
  from euporie.core.widgets.file_browser import FileBrowser
43
45
  from euporie.core.widgets.layout import TabBarControl, TabBarTab
46
+ from euporie.core.widgets.logo import Logo
44
47
  from euporie.core.widgets.menu import MenuBar, MenuItem
45
48
  from euporie.core.widgets.pager import Pager
46
49
  from euporie.core.widgets.palette import CommandPalette
47
- from euporie.core.widgets.search import SearchBar
48
- from euporie.core.widgets.status import StatusBar, StatusContainer
49
50
  from euporie.notebook.enums import TabMode
50
- from euporie.notebook.tabs import Notebook
51
51
  from euporie.notebook.widgets.side_bar import SideBar
52
52
 
53
53
  if TYPE_CHECKING:
54
54
  from asyncio import AbstractEventLoop
55
- from typing import Any, Callable, Sequence
55
+ from collections.abc import Sequence
56
+ from typing import Any, Callable
56
57
 
57
58
  from prompt_toolkit.application.application import Application
58
59
  from prompt_toolkit.formatted_text import StyleAndTextTuples
59
- from prompt_toolkit.layout.containers import AnyContainer, Float
60
+ from prompt_toolkit.layout.containers import AnyContainer
60
61
 
62
+ from euporie.core.bars.status import StatusBarFields
63
+ from euporie.core.tabs import TabRegistryEntry
61
64
  from euporie.core.tabs.base import Tab
62
65
  from euporie.core.widgets.cell import Cell
63
- from euporie.core.widgets.status import StatusBarFields
66
+ from euporie.notebook.tabs.notebook import Notebook
64
67
 
65
68
  log = logging.getLogger(__name__)
66
69
 
@@ -89,30 +92,32 @@ class NotebookApp(BaseApp):
89
92
  self.on_tabs_change += self.set_tab_container
90
93
 
91
94
  # Register config hooks
92
- self.config.get_item("show_cell_borders").event += lambda x: self.refresh()
93
- self.config.get_item("tab_mode").event += self.set_tab_container
94
- self.config.get_item("background_pattern").event += self.set_tab_container
95
- self.config.get_item("background_character").event += self.set_tab_container
96
-
97
- async def _poll_terminal_colors(self) -> None:
98
- """Repeatedly query the terminal for its background and foreground colours."""
99
- while self.config.terminal_polling_interval:
100
- await asyncio.sleep(self.config.terminal_polling_interval)
101
- self.term_info.colors.send()
95
+ self.config.events.show_cell_borders += lambda x: self.refresh()
96
+ self.config.events.tab_mode += self.set_tab_container
97
+ self.config.events.background_pattern += self.set_tab_container
98
+ self.config.events.background_character += self.set_tab_container
102
99
 
103
100
  def pre_run(self, app: Application | None = None) -> None:
104
101
  """Continue loading the app."""
105
102
  super().pre_run(app)
106
- # Load style hooks and start polling terminal style
107
- if self.config.terminal_polling_interval and hasattr(
108
- self.input, "vt100_parser"
109
- ):
110
- self.create_background_task(self._poll_terminal_colors())
103
+ # Add a toolbar completion menu
104
+ self.menus["toolbar_completions"] = Float(
105
+ content=ToolbarCompletionsMenu(), ycursor=True, transparent=True
106
+ )
107
+
108
+ @property
109
+ def tab_registry(self) -> list[TabRegistryEntry]:
110
+ """Return the tab registry."""
111
+ from euporie.notebook.tabs import _TAB_REGISTRY
112
+
113
+ return _TAB_REGISTRY
111
114
 
112
115
  def format_title(self) -> StyleAndTextTuples:
113
116
  """Format the tab's title for display in the top right of the app."""
114
- if self.tab:
115
- title = truncate(to_formatted_text(self.tab.title, style="bold"), 30)
117
+ if self.tabs:
118
+ # Get tab without re-focusing it
119
+ tab = self.tabs[self._tab_idx]
120
+ title = truncate(to_formatted_text(tab.title, style="bold"), 30)
116
121
  return [("", " "), *title, ("", " ")]
117
122
  else:
118
123
  return []
@@ -190,22 +195,7 @@ class NotebookApp(BaseApp):
190
195
 
191
196
  def load_container(self) -> FloatContainer:
192
197
  """Build the main application layout."""
193
- have_tabs = Condition(lambda: bool(self.tabs))
194
-
195
- self.logo = StatusContainer(
196
- body=Window(
197
- FormattedTextControl(
198
- [("", f" {__logo__} ")],
199
- focusable=~have_tabs,
200
- show_cursor=False,
201
- style="class:menu,logo",
202
- ),
203
- height=1,
204
- width=3,
205
- dont_extend_width=True,
206
- ),
207
- status=self._statusbar_defaults,
208
- )
198
+ self.logo = StatusContainer(body=Logo(), status=self._statusbar_defaults)
209
199
 
210
200
  title_bar = ConditionalContainer(
211
201
  Window(
@@ -215,11 +205,12 @@ class NotebookApp(BaseApp):
215
205
  dont_extend_width=True,
216
206
  align=WindowAlign.RIGHT,
217
207
  ),
218
- filter=have_tabs,
208
+ filter=has_tabs,
219
209
  )
220
210
 
221
211
  self.pager = Pager()
222
212
  self.search_bar = SearchBar()
213
+ self.command_bar = CommandBar()
223
214
 
224
215
  self.dialogs["command-palette"] = CommandPalette(self)
225
216
  self.dialogs["about"] = AboutDialog(self)
@@ -241,7 +232,7 @@ class NotebookApp(BaseApp):
241
232
  title_bar,
242
233
  ]
243
234
  ),
244
- filter=self.config.filter("show_top_bar"),
235
+ filter=self.config.filters.show_top_bar,
245
236
  )
246
237
 
247
238
  titles: Sequence[str]
@@ -277,6 +268,7 @@ class NotebookApp(BaseApp):
277
268
  ],
278
269
  height=Dimension(min=1),
279
270
  ),
271
+ self.command_bar,
280
272
  self.search_bar,
281
273
  StatusBar(),
282
274
  ],
@@ -360,6 +352,8 @@ class NotebookApp(BaseApp):
360
352
  @property
361
353
  def notebook(self) -> Notebook | None:
362
354
  """Return the currently active notebook."""
355
+ from euporie.notebook.tabs.notebook import Notebook
356
+
363
357
  if isinstance(self.tab, Notebook):
364
358
  return self.tab
365
359
  return None
@@ -367,6 +361,8 @@ class NotebookApp(BaseApp):
367
361
  @property
368
362
  def cell(self) -> Cell | None:
369
363
  """Return the currently active cell."""
364
+ from euporie.notebook.tabs.notebook import Notebook
365
+
370
366
  if isinstance(self.tab, Notebook):
371
367
  return self.tab.cell
372
368
  return None
@@ -435,7 +431,7 @@ class NotebookApp(BaseApp):
435
431
  "Tab mode",
436
432
  children=[
437
433
  get_cmd(f"set-tab-mode-{choice}").menu
438
- for choice in self.config.get_item("tab_mode").choices
434
+ for choice in self.config.choices.tab_mode
439
435
  ],
440
436
  ),
441
437
  ],
@@ -457,21 +453,21 @@ class NotebookApp(BaseApp):
457
453
  ],
458
454
  description="Turn elements of euporie's interface on or off",
459
455
  ),
460
- self.config.get_item("color_scheme").menu,
456
+ self.config.menus.color_scheme,
461
457
  MenuItem(
462
458
  "Syntax highlighting",
463
459
  children=[
464
- self.config.get_item("syntax_highlighting").menu,
460
+ self.config.menus.syntax_highlighting,
465
461
  separator,
466
- *self.config.get_item("syntax_theme").menu.children,
462
+ *self.config.menus.syntax_theme.children,
467
463
  ],
468
464
  description="Configure syntax highlighting",
469
465
  ),
470
466
  get_cmd("toggle-expand").menu,
471
467
  get_cmd("toggle-line-numbers").menu,
472
- self.config.get_item("set_cursor_shape").menu,
468
+ self.config.menus.set_cursor_shape,
473
469
  separator,
474
- self.config.get_item("edit_mode").menu,
470
+ self.config.menus.edit_mode,
475
471
  separator,
476
472
  MenuItem(
477
473
  "Code tools",
@@ -504,124 +500,6 @@ class NotebookApp(BaseApp):
504
500
  ),
505
501
  ]
506
502
 
507
- # ################################### Commands ####################################
508
-
509
- @staticmethod
510
- @add_cmd()
511
- def _new_notebook() -> None:
512
- """Create a new file."""
513
- from euporie.notebook.current import get_app
514
-
515
- app = get_app()
516
- app.add_tab(tab := Notebook(app, None))
517
- tab.focus()
518
-
519
- @staticmethod
520
- @add_cmd()
521
- def _view_documentation() -> None:
522
- """Open the documentation in a web-view tab."""
523
- from euporie.core.current import get_app
524
-
525
- get_app().open_file(UPath("https://euporie.readthedocs.io/"))
526
-
527
- # ################################### Settings ####################################
528
-
529
- add_setting(
530
- name="tab_mode",
531
- flags=["--tab-mode"],
532
- type_=str,
533
- choices=[mode.value for mode in TabMode],
534
- default="stack",
535
- help_="The method used to display multiple tabs",
536
- description="""
537
- Determines how multiple tabs are displayed when more than one tab is open.
538
- * ``stack`` displays one tab at a time with a tab-bar
539
- * ``tile_horizontally`` displays tabs side-by-side
540
- * ``tile_vertically`` displays tabs one-atop-the-next
541
- """,
542
- )
543
-
544
- add_setting(
545
- name="always_show_tab_bar",
546
- flags=["--always-show-tab-bar"],
547
- type_=bool,
548
- help_="Always show the tab bar",
549
- default=False,
550
- description="""
551
- When set, the tab bar will always be shown - otherwise the tab bar is only
552
- shown when multiple tabs are open.
553
- """,
554
- )
555
-
556
- add_setting(
557
- name="background_pattern",
558
- flags=["--background-pattern", "--bg-pattern"],
559
- type_=int,
560
- choices=list(range(6)),
561
- help_="The background pattern to use",
562
- default=2,
563
- schema={
564
- "minimum": 0,
565
- "maximum": 5,
566
- },
567
- description="""
568
- The background pattern to use when the notebook is narrower than the
569
- available width. Zero mean no pattern is used.
570
- """,
571
- )
572
-
573
- add_setting(
574
- name="background_character",
575
- flags=["--background-character", "--bg-char"],
576
- type_=str,
577
- help_="Character for background pattern",
578
- default="·",
579
- schema={
580
- "maxLength": 1,
581
- },
582
- description="""
583
- The character to use when drawing the background pattern.
584
-
585
- Recommended characters include: "·", "⬤", "╳", "╱", "╲", "░", "▒", "▓", "▞", "╬"
586
- """, # ,
587
- )
588
-
589
- add_setting(
590
- name="run_after_external_edit",
591
- flags=["--run-after-external-edit"],
592
- type_=bool,
593
- help_="Run cells after editing externally",
594
- default=False,
595
- description="""
596
- Whether to execute a cell immediately after editing in `$EDITOR`.
597
- """,
598
- )
599
-
600
- add_setting(
601
- name="run",
602
- flags=["--run"],
603
- type_=bool,
604
- help_="Run the notebook files when loaded",
605
- default=False,
606
- description="""
607
- If set, notebooks will be run automatically when opened, or if previewing a
608
- file, the notebooks will be run before being output.
609
- """,
610
- )
611
-
612
- add_setting(
613
- name="show_top_bar",
614
- flags=["--show-top-bar"],
615
- type_=bool,
616
- title="top bar",
617
- help_="Show the top bar",
618
- default=True,
619
- schema={"type": "boolean"},
620
- description="""
621
- Whether the top bar should be shown at the top of the screen.
622
- """,
623
- )
624
-
625
503
  # ################################# Key Bindings ##################################
626
504
 
627
505
  register_bindings(
@@ -4,7 +4,7 @@ from __future__ import annotations
4
4
 
5
5
  from prompt_toolkit.filters import Condition
6
6
 
7
- from euporie.core.current import get_app
7
+ from euporie.core.app.current import get_app
8
8
 
9
9
 
10
10
  @Condition
@@ -1,10 +1,49 @@
1
1
  """Tab for use in euporie notebook editor."""
2
2
 
3
- from euporie.notebook.tabs.display import DisplayTab
4
- from euporie.notebook.tabs.edit import EditorTab
5
- from euporie.notebook.tabs.json import JsonTab
6
- from euporie.notebook.tabs.log import LogView
7
- from euporie.notebook.tabs.notebook import Notebook
8
- from euporie.web.tabs.web import WebTab
3
+ from euporie.core.convert.mime import MIME_FORMATS
4
+ from euporie.core.tabs import _TAB_REGISTRY, TabRegistryEntry
9
5
 
10
- __all__ = ["DisplayTab", "EditorTab", "JsonTab", "LogView", "Notebook", "WebTab"]
6
+ _TAB_REGISTRY.extend(
7
+ [
8
+ TabRegistryEntry(
9
+ path="euporie.notebook.tabs.display:DisplayTab",
10
+ name="File Viewer",
11
+ mime_types=set(MIME_FORMATS.keys()),
12
+ ),
13
+ TabRegistryEntry(
14
+ path="euporie.notebook.tabs.edit:EditorTab",
15
+ name="Text Editor",
16
+ mime_types={"text/*"},
17
+ weight=1,
18
+ ),
19
+ TabRegistryEntry(
20
+ path="euporie.notebook.tabs.json:JsonTab",
21
+ name="JSON Viewer",
22
+ mime_types={"*json"},
23
+ file_extensions={".json": None},
24
+ ),
25
+ TabRegistryEntry(
26
+ path="euporie.notebook.tabs.notebook:Notebook",
27
+ name="Notebook Editor",
28
+ mime_types={"application/x-ipynb+json"},
29
+ file_extensions={".ipynb": None},
30
+ weight=3,
31
+ ),
32
+ TabRegistryEntry(
33
+ path="euporie.web.tabs.web:WebTab",
34
+ name="Web Viewer",
35
+ mime_types={"text/html", "text/markdown"},
36
+ weight=2,
37
+ ),
38
+ ]
39
+ )
40
+
41
+ try:
42
+ from jupytext.formats import NOTEBOOK_EXTENSIONS
43
+ except ModuleNotFoundError:
44
+ pass
45
+ else:
46
+ for entry in _TAB_REGISTRY:
47
+ if entry.path == "euporie.notebook.tabs.notebook:Notebook":
48
+ entry.file_extensions.update(dict.fromkeys(NOTEBOOK_EXTENSIONS))
49
+ break