euporie 2.8.13__tar.gz → 2.8.14__tar.gz

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 (177) hide show
  1. {euporie-2.8.13 → euporie-2.8.14}/PKG-INFO +1 -1
  2. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/__init__.py +1 -1
  3. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/clipboard.py +16 -1
  4. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/convert/datum.py +24 -8
  5. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/convert/formats/ansi.py +25 -21
  6. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/convert/formats/base64.py +3 -1
  7. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/convert/formats/common.py +4 -4
  8. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/convert/formats/ft.py +6 -3
  9. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/convert/formats/html.py +22 -24
  10. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/convert/formats/markdown.py +4 -2
  11. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/convert/formats/pil.py +3 -1
  12. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/convert/formats/png.py +6 -4
  13. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/convert/formats/rich.py +3 -1
  14. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/convert/formats/sixel.py +3 -3
  15. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/convert/formats/svg.py +3 -1
  16. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/ft/html.py +191 -124
  17. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/ft/table.py +1 -1
  18. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/kernel/local.py +1 -1
  19. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/widgets/cell_outputs.py +39 -8
  20. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/widgets/display.py +11 -4
  21. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/widgets/menu.py +5 -5
  22. {euporie-2.8.13 → euporie-2.8.14}/.gitignore +0 -0
  23. {euporie-2.8.13 → euporie-2.8.14}/LICENSE +0 -0
  24. {euporie-2.8.13 → euporie-2.8.14}/README.rst +0 -0
  25. {euporie-2.8.13 → euporie-2.8.14}/euporie/console/__init__.py +0 -0
  26. {euporie-2.8.13 → euporie-2.8.14}/euporie/console/__main__.py +0 -0
  27. {euporie-2.8.13 → euporie-2.8.14}/euporie/console/_commands.py +0 -0
  28. {euporie-2.8.13 → euporie-2.8.14}/euporie/console/_settings.py +0 -0
  29. {euporie-2.8.13 → euporie-2.8.14}/euporie/console/app.py +0 -0
  30. {euporie-2.8.13 → euporie-2.8.14}/euporie/console/py.typed +0 -0
  31. {euporie-2.8.13 → euporie-2.8.14}/euporie/console/tabs/__init__.py +0 -0
  32. {euporie-2.8.13 → euporie-2.8.14}/euporie/console/tabs/console.py +0 -0
  33. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/__main__.py +0 -0
  34. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/_settings.py +0 -0
  35. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/app/__init__.py +0 -0
  36. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/app/_commands.py +0 -0
  37. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/app/_settings.py +0 -0
  38. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/app/app.py +0 -0
  39. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/app/base.py +0 -0
  40. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/app/current.py +0 -0
  41. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/app/cursor.py +0 -0
  42. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/app/dummy.py +0 -0
  43. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/app/launch.py +0 -0
  44. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/bars/__init__.py +0 -0
  45. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/bars/command.py +0 -0
  46. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/bars/menu.py +0 -0
  47. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/bars/search.py +0 -0
  48. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/bars/status.py +0 -0
  49. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/border.py +0 -0
  50. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/comm/__init__.py +0 -0
  51. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/comm/base.py +0 -0
  52. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/comm/ipywidgets.py +0 -0
  53. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/comm/registry.py +0 -0
  54. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/commands.py +0 -0
  55. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/completion.py +0 -0
  56. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/config.py +0 -0
  57. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/convert/__init__.py +0 -0
  58. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/convert/formats/__init__.py +0 -0
  59. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/convert/formats/jpeg.py +0 -0
  60. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/convert/formats/pdf.py +0 -0
  61. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/convert/mime.py +0 -0
  62. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/convert/registry.py +0 -0
  63. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/convert/utils.py +0 -0
  64. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/data_structures.py +0 -0
  65. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/diagnostics.py +0 -0
  66. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/filters.py +0 -0
  67. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/format.py +0 -0
  68. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/ft/__init__.py +0 -0
  69. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/ft/ansi.py +0 -0
  70. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/ft/utils.py +0 -0
  71. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/graphics.py +0 -0
  72. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/history.py +0 -0
  73. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/inspection.py +0 -0
  74. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/io.py +0 -0
  75. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/kernel/__init__.py +0 -0
  76. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/kernel/_settings.py +0 -0
  77. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/kernel/base.py +0 -0
  78. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/kernel/jupyter.py +0 -0
  79. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/kernel/jupyter_manager.py +0 -0
  80. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/key_binding/__init__.py +0 -0
  81. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/key_binding/bindings/__init__.py +0 -0
  82. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/key_binding/bindings/basic.py +0 -0
  83. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/key_binding/bindings/completion.py +0 -0
  84. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/key_binding/bindings/micro.py +0 -0
  85. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/key_binding/bindings/mouse.py +0 -0
  86. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/key_binding/bindings/page_navigation.py +0 -0
  87. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/key_binding/bindings/terminal.py +0 -0
  88. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/key_binding/bindings/vi.py +0 -0
  89. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/key_binding/key_processor.py +0 -0
  90. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/key_binding/micro_state.py +0 -0
  91. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/key_binding/registry.py +0 -0
  92. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/key_binding/utils.py +0 -0
  93. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/key_binding/vi_state.py +0 -0
  94. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/keys.py +0 -0
  95. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/layout/__init__.py +0 -0
  96. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/layout/cache.py +0 -0
  97. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/layout/containers.py +0 -0
  98. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/layout/controls.py +0 -0
  99. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/layout/decor.py +0 -0
  100. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/layout/mouse.py +0 -0
  101. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/layout/print.py +0 -0
  102. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/layout/screen.py +0 -0
  103. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/layout/scroll.py +0 -0
  104. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/lexers.py +0 -0
  105. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/log.py +0 -0
  106. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/lsp.py +0 -0
  107. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/margins.py +0 -0
  108. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/path.py +0 -0
  109. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/processors.py +0 -0
  110. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/py.typed +0 -0
  111. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/pygments.py +0 -0
  112. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/reference.py +0 -0
  113. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/renderer.py +0 -0
  114. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/style.py +0 -0
  115. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/suggest.py +0 -0
  116. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/tabs/__init__.py +0 -0
  117. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/tabs/_commands.py +0 -0
  118. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/tabs/_settings.py +0 -0
  119. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/tabs/base.py +0 -0
  120. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/tabs/kernel.py +0 -0
  121. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/tabs/notebook.py +0 -0
  122. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/utils.py +0 -0
  123. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/validation.py +0 -0
  124. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/widgets/__init__.py +0 -0
  125. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/widgets/_settings.py +0 -0
  126. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/widgets/cell.py +0 -0
  127. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/widgets/decor.py +0 -0
  128. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/widgets/dialog.py +0 -0
  129. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/widgets/file_browser.py +0 -0
  130. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/widgets/formatted_text_area.py +0 -0
  131. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/widgets/forms.py +0 -0
  132. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/widgets/inputs.py +0 -0
  133. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/widgets/layout.py +0 -0
  134. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/widgets/logo.py +0 -0
  135. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/widgets/pager.py +0 -0
  136. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/widgets/palette.py +0 -0
  137. {euporie-2.8.13 → euporie-2.8.14}/euporie/core/widgets/tree.py +0 -0
  138. {euporie-2.8.13 → euporie-2.8.14}/euporie/data/desktop/euporie-console.desktop +0 -0
  139. {euporie-2.8.13 → euporie-2.8.14}/euporie/data/desktop/euporie-notebook.desktop +0 -0
  140. {euporie-2.8.13 → euporie-2.8.14}/euporie/hub/__init__.py +0 -0
  141. {euporie-2.8.13 → euporie-2.8.14}/euporie/hub/__main__.py +0 -0
  142. {euporie-2.8.13 → euporie-2.8.14}/euporie/hub/app.py +0 -0
  143. {euporie-2.8.13 → euporie-2.8.14}/euporie/hub/py.typed +0 -0
  144. {euporie-2.8.13 → euporie-2.8.14}/euporie/notebook/__init__.py +0 -0
  145. {euporie-2.8.13 → euporie-2.8.14}/euporie/notebook/__main__.py +0 -0
  146. {euporie-2.8.13 → euporie-2.8.14}/euporie/notebook/_commands.py +0 -0
  147. {euporie-2.8.13 → euporie-2.8.14}/euporie/notebook/_settings.py +0 -0
  148. {euporie-2.8.13 → euporie-2.8.14}/euporie/notebook/app.py +0 -0
  149. {euporie-2.8.13 → euporie-2.8.14}/euporie/notebook/current.py +0 -0
  150. {euporie-2.8.13 → euporie-2.8.14}/euporie/notebook/enums.py +0 -0
  151. {euporie-2.8.13 → euporie-2.8.14}/euporie/notebook/filters.py +0 -0
  152. {euporie-2.8.13 → euporie-2.8.14}/euporie/notebook/py.typed +0 -0
  153. {euporie-2.8.13 → euporie-2.8.14}/euporie/notebook/tabs/__init__.py +0 -0
  154. {euporie-2.8.13 → euporie-2.8.14}/euporie/notebook/tabs/_commands.py +0 -0
  155. {euporie-2.8.13 → euporie-2.8.14}/euporie/notebook/tabs/_settings.py +0 -0
  156. {euporie-2.8.13 → euporie-2.8.14}/euporie/notebook/tabs/display.py +0 -0
  157. {euporie-2.8.13 → euporie-2.8.14}/euporie/notebook/tabs/edit.py +0 -0
  158. {euporie-2.8.13 → euporie-2.8.14}/euporie/notebook/tabs/json.py +0 -0
  159. {euporie-2.8.13 → euporie-2.8.14}/euporie/notebook/tabs/log.py +0 -0
  160. {euporie-2.8.13 → euporie-2.8.14}/euporie/notebook/tabs/notebook.py +0 -0
  161. {euporie-2.8.13 → euporie-2.8.14}/euporie/notebook/widgets/__init__.py +0 -0
  162. {euporie-2.8.13 → euporie-2.8.14}/euporie/notebook/widgets/_commands.py +0 -0
  163. {euporie-2.8.13 → euporie-2.8.14}/euporie/notebook/widgets/_settings.py +0 -0
  164. {euporie-2.8.13 → euporie-2.8.14}/euporie/notebook/widgets/side_bar.py +0 -0
  165. {euporie-2.8.13 → euporie-2.8.14}/euporie/preview/__init__.py +0 -0
  166. {euporie-2.8.13 → euporie-2.8.14}/euporie/preview/__main__.py +0 -0
  167. {euporie-2.8.13 → euporie-2.8.14}/euporie/preview/_settings.py +0 -0
  168. {euporie-2.8.13 → euporie-2.8.14}/euporie/preview/app.py +0 -0
  169. {euporie-2.8.13 → euporie-2.8.14}/euporie/preview/py.typed +0 -0
  170. {euporie-2.8.13 → euporie-2.8.14}/euporie/preview/tabs/__init__.py +0 -0
  171. {euporie-2.8.13 → euporie-2.8.14}/euporie/preview/tabs/notebook.py +0 -0
  172. {euporie-2.8.13 → euporie-2.8.14}/euporie/web/__init__.py +0 -0
  173. {euporie-2.8.13 → euporie-2.8.14}/euporie/web/tabs/__init__.py +0 -0
  174. {euporie-2.8.13 → euporie-2.8.14}/euporie/web/tabs/web.py +0 -0
  175. {euporie-2.8.13 → euporie-2.8.14}/euporie/web/widgets/__init__.py +0 -0
  176. {euporie-2.8.13 → euporie-2.8.14}/euporie/web/widgets/webview.py +0 -0
  177. {euporie-2.8.13 → euporie-2.8.14}/pyproject.toml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: euporie
3
- Version: 2.8.13
3
+ Version: 2.8.14
4
4
  Summary: Euporie is a suite of terminal applications for interacting with Jupyter kernels
5
5
  Project-URL: Documentation, https://euporie.readthedocs.io/en/latest
6
6
  Project-URL: Issues, https://github.com/joouha/euporie/issues
@@ -1,7 +1,7 @@
1
1
  """This package defines the euporie application and its components."""
2
2
 
3
3
  __app_name__ = "euporie"
4
- __version__ = "2.8.13"
4
+ __version__ = "2.8.14"
5
5
  __logo__ = "⚈"
6
6
  __strapline__ = "Jupyter in the terminal"
7
7
  __author__ = "Josiah Outram Halstead"
@@ -4,9 +4,12 @@ from __future__ import annotations
4
4
 
5
5
  import logging
6
6
 
7
+ import pyperclip
7
8
  from prompt_toolkit.clipboard.base import Clipboard, ClipboardData
8
9
  from prompt_toolkit.clipboard.in_memory import InMemoryClipboard
9
- from prompt_toolkit.clipboard.pyperclip import PyperclipClipboard
10
+ from prompt_toolkit.clipboard.pyperclip import (
11
+ PyperclipClipboard as PtkPyperclipClipboard,
12
+ )
10
13
  from prompt_toolkit.selection import SelectionType
11
14
 
12
15
  from euporie.core.app.current import get_app
@@ -16,6 +19,18 @@ from euporie.core.key_binding.key_processor import KeyProcessor
16
19
  log = logging.getLogger(__name__)
17
20
 
18
21
 
22
+ class PyperclipClipboard(PtkPyperclipClipboard):
23
+ """Pyperclip clipboard which suppresses pyperclip exceptions."""
24
+
25
+ def set_data(self, data: ClipboardData) -> None:
26
+ """Set the clipboard data, ignoring any clipboard errors."""
27
+ self._data = data
28
+ try:
29
+ pyperclip.copy(data.text)
30
+ except pyperclip.PyperclipException:
31
+ log.exception("Failed to set clipboard data")
32
+
33
+
19
34
  class Osc52Clipboard(Clipboard):
20
35
  """Clipboard that syncs with the system clipboard using OSC52 escape codes."""
21
36
 
@@ -137,10 +137,25 @@ class Datum(Generic[T], metaclass=_MetaDatum):
137
137
  self.align = align
138
138
  self._cell_size: tuple[int, float] | None = None
139
139
  self._conversions: dict[
140
- tuple[str, int | None, int | None, str | None, str | None, bool], T | None
140
+ tuple[
141
+ str,
142
+ int | None,
143
+ int | None,
144
+ str | None,
145
+ str | None,
146
+ tuple[tuple[str, Any], ...],
147
+ ],
148
+ T | None,
141
149
  ] = {}
142
150
  self._queue: dict[
143
- tuple[str, int | None, int | None, str | None, str | None, bool],
151
+ tuple[
152
+ str,
153
+ int | None,
154
+ int | None,
155
+ str | None,
156
+ str | None,
157
+ tuple[tuple[str, Any], ...],
158
+ ],
144
159
  asyncio.Event,
145
160
  ] = {}
146
161
  self._finalizer: finalize = finalize(self, self._cleanup_datum_sizes, self.hash)
@@ -228,8 +243,8 @@ class Datum(Generic[T], metaclass=_MetaDatum):
228
243
  rows: int | None = None,
229
244
  fg: str | None = None,
230
245
  bg: str | None = None,
231
- extend: bool = True,
232
246
  bbox: DiInt | None = None,
247
+ **kwargs: Any,
233
248
  ) -> Any:
234
249
  """Perform conversion asynchronously, caching the result."""
235
250
  if to == self.format:
@@ -241,7 +256,7 @@ class Datum(Generic[T], metaclass=_MetaDatum):
241
256
  if not bg and hasattr(app := get_app(), "color_palette"):
242
257
  bg = self.bg or app.color_palette.bg.base_hex
243
258
 
244
- if (key_conv := (to, cols, rows, fg, bg, extend)) in self._queue:
259
+ if (key_conv := (to, cols, rows, fg, bg, tuple(kwargs.items()))) in self._queue:
245
260
  await self._queue[key_conv].wait()
246
261
  if key_conv in self._conversions:
247
262
  return self._conversions[key_conv]
@@ -262,7 +277,7 @@ class Datum(Generic[T], metaclass=_MetaDatum):
262
277
  output = None
263
278
  for route in routes:
264
279
  for stage_a, stage_b in zip(route, route[1:]):
265
- key_stage = (stage_b, cols, rows, fg, bg, extend)
280
+ key_stage = (stage_b, cols, rows, fg, bg, tuple(kwargs.items()))
266
281
  if key_stage in self._conversions:
267
282
  output = self._conversions[key_stage]
268
283
  else:
@@ -277,7 +292,7 @@ class Datum(Generic[T], metaclass=_MetaDatum):
277
292
  ):
278
293
  try:
279
294
  output = await converter.func(
280
- datum, cols, rows, fg, bg, extend
295
+ datum, cols, rows, fg, bg, **kwargs
281
296
  )
282
297
  self._conversions[key_stage] = output
283
298
  except Exception:
@@ -341,10 +356,11 @@ class Datum(Generic[T], metaclass=_MetaDatum):
341
356
  rows: int | None = None,
342
357
  fg: str | None = None,
343
358
  bg: str | None = None,
344
- extend: bool = True,
359
+ bbox: DiInt | None = None,
360
+ **kwargs: Any,
345
361
  ) -> Any:
346
362
  """Convert between formats."""
347
- return self._to_sync(self.convert_async(to, cols, rows, fg, bg, extend))
363
+ return self._to_sync(self.convert_async(to, cols, rows, fg, bg, bbox, **kwargs))
348
364
 
349
365
  async def pixel_size_async(self) -> tuple[int | None, int | None]:
350
366
  """Get the dimensions of displayable data in pixels.
@@ -32,7 +32,7 @@ async def html_to_ansi_w3m(
32
32
  rows: int | None = None,
33
33
  fg: str | None = None,
34
34
  bg: str | None = None,
35
- extend: bool = True,
35
+ **kwargs: Any,
36
36
  ) -> str:
37
37
  """Convert HTML text to formatted ANSI using :command:`w3m`."""
38
38
  cmd: list[Any] = ["w3m", "-T", "text/html"]
@@ -52,7 +52,7 @@ async def html_to_ansi_elinks(
52
52
  rows: int | None = None,
53
53
  fg: str | None = None,
54
54
  bg: str | None = None,
55
- extend: bool = True,
55
+ **kwargs: Any,
56
56
  ) -> str:
57
57
  """Convert HTML text to formatted ANSI using :command:`elinks`."""
58
58
  cmd: list[Any] = [
@@ -80,7 +80,7 @@ async def html_to_ansi_lynx(
80
80
  rows: int | None = None,
81
81
  fg: str | None = None,
82
82
  bg: str | None = None,
83
- extend: bool = True,
83
+ **kwargs: Any,
84
84
  ) -> str:
85
85
  """Convert HTML text to formatted ANSI using :command:`lynx`."""
86
86
  cmd: list[Any] = ["lynx", "-dump", "-stdin"]
@@ -100,7 +100,7 @@ async def html_to_ansi_links(
100
100
  rows: int | None = None,
101
101
  fg: str | None = None,
102
102
  bg: str | None = None,
103
- extend: bool = True,
103
+ **kwargs: Any,
104
104
  ) -> str:
105
105
  """Convert HTML text to formatted ANSI using :command:`links`."""
106
106
  cmd: list[Any] = ["links", "-dump"]
@@ -120,7 +120,7 @@ async def html_to_ansi_py_htmlparser(
120
120
  rows: int | None = None,
121
121
  fg: str | None = None,
122
122
  bg: str | None = None,
123
- extend: bool = True,
123
+ **kwargs: Any,
124
124
  ) -> str:
125
125
  """Convert HTML tables to ANSI text using :py:mod:`HTMLParser`."""
126
126
  import io
@@ -177,10 +177,14 @@ async def latex_to_ansi_utftex(
177
177
  rows: int | None = None,
178
178
  fg: str | None = None,
179
179
  bg: str | None = None,
180
- extend: bool = True,
180
+ **kwargs: Any,
181
181
  ) -> str:
182
182
  """Render LaTeX maths as unicode."""
183
- return (await call_subproc(datum.data, ["utftex"])).decode()
183
+ return (
184
+ (await call_subproc(datum.data.strip().strip("$").strip(), ["utftex"]))
185
+ .decode()
186
+ .rstrip("\n")
187
+ )
184
188
 
185
189
 
186
190
  @register(
@@ -195,7 +199,7 @@ async def latex_to_ansi_py_pylatexenc(
195
199
  rows: int | None = None,
196
200
  fg: str | None = None,
197
201
  bg: str | None = None,
198
- extend: bool = True,
202
+ **kwargs: Any,
199
203
  ) -> str:
200
204
  """Convert LaTeX to ANSI using :py:mod:`pylatexenc`."""
201
205
  from pylatexenc.latex2text import LatexNodes2Text
@@ -215,7 +219,7 @@ async def latex_to_ansi_py_flatlatex(
215
219
  rows: int | None = None,
216
220
  fg: str | None = None,
217
221
  bg: str | None = None,
218
- extend: bool = True,
222
+ **kwargs: Any,
219
223
  ) -> str:
220
224
  """Convert LaTeX to ANSI using :py:mod:`flatlatex`."""
221
225
  import flatlatex
@@ -244,7 +248,7 @@ async def latex_to_ansi_py_sympy(
244
248
  rows: int | None = None,
245
249
  fg: str | None = None,
246
250
  bg: str | None = None,
247
- extend: bool = True,
251
+ **kwargs: Any,
248
252
  ) -> str:
249
253
  """Convert LaTeX to ANSI using :py:mod:`sympy`."""
250
254
  from sympy import pretty
@@ -268,7 +272,7 @@ async def pil_to_ansi_py_timg(
268
272
  rows: int | None = None,
269
273
  fg: str | None = None,
270
274
  bg: str | None = None,
271
- extend: bool = True,
275
+ **kwargs: Any,
272
276
  ) -> str:
273
277
  """Convert a PIL image to ANSI text using :py:mod:`timg`."""
274
278
  import timg
@@ -297,7 +301,7 @@ async def pil_to_ansi_py_img2unicode(
297
301
  rows: int | None = None,
298
302
  fg: str | None = None,
299
303
  bg: str | None = None,
300
- extend: bool = True,
304
+ **kwargs: Any,
301
305
  ) -> str:
302
306
  """Convert a PIL image to ANSI text using :py:mod:`img2unicode`."""
303
307
  import io
@@ -335,7 +339,7 @@ async def image_to_ansi_timg(
335
339
  rows: int | None = None,
336
340
  fg: str | None = None,
337
341
  bg: str | None = None,
338
- extend: bool = True,
342
+ **kwargs: Any,
339
343
  ) -> str:
340
344
  """Convert image data to ANSI text using :command:`timg`."""
341
345
  cmd: list[Any] = ["timg"]
@@ -356,7 +360,7 @@ async def image_to_ansi_catimg(
356
360
  rows: int | None = None,
357
361
  fg: str | None = None,
358
362
  bg: str | None = None,
359
- extend: bool = True,
363
+ **kwargs: Any,
360
364
  ) -> str:
361
365
  """Convert image data to ANSI text using :command:`catimg`."""
362
366
  cmd: list[Any] = ["catimg"]
@@ -377,7 +381,7 @@ async def image_to_ansi_icat(
377
381
  rows: int | None = None,
378
382
  fg: str | None = None,
379
383
  bg: str | None = None,
380
- extend: bool = True,
384
+ **kwargs: Any,
381
385
  ) -> str:
382
386
  """Convert image data to ANSI text using :command:`icat`."""
383
387
  cmd: list[Any] = ["icat"]
@@ -398,7 +402,7 @@ async def image_to_ansi_tiv(
398
402
  rows: int | None = None,
399
403
  fg: str | None = None,
400
404
  bg: str | None = None,
401
- extend: bool = True,
405
+ **kwargs: Any,
402
406
  ) -> str:
403
407
  """Convert image data to ANSI text using :command:`tiv`."""
404
408
  cmd: list[Any] = ["tiv"]
@@ -418,7 +422,7 @@ async def image_to_ansi_viu(
418
422
  rows: int | None = None,
419
423
  fg: str | None = None,
420
424
  bg: str | None = None,
421
- extend: bool = True,
425
+ **kwargs: Any,
422
426
  ) -> str:
423
427
  """Convert image data to ANSI text using :command:`viu`."""
424
428
  cmd: list[Any] = ["viu", "-b"]
@@ -439,7 +443,7 @@ async def image_to_ansi_jp2a(
439
443
  rows: int | None = None,
440
444
  fg: str | None = None,
441
445
  bg: str | None = None,
442
- extend: bool = True,
446
+ **kwargs: Any,
443
447
  ) -> str:
444
448
  """Convert image data to ANSI text using :command:`jp2a`."""
445
449
  cmd: list[Any] = ["jp2a", "--color"]
@@ -460,7 +464,7 @@ async def png_to_ansi_img2txt(
460
464
  rows: int | None = None,
461
465
  fg: str | None = None,
462
466
  bg: str | None = None,
463
- extend: bool = True,
467
+ **kwargs: Any,
464
468
  ) -> str:
465
469
  """Convert PNG data to ANSI text using :command:`img2txt`."""
466
470
  cmd: list[Any] = ["img2txt"]
@@ -476,7 +480,7 @@ async def png_to_ansi_py_placeholder(
476
480
  rows: int | None = None,
477
481
  fg: str | None = None,
478
482
  bg: str | None = None,
479
- extend: bool = True,
483
+ **kwargs: Any,
480
484
  ) -> str:
481
485
  """Draw placeholder ANSI text."""
482
486
  from euporie.core.border import RoundedLine
@@ -509,7 +513,7 @@ async def rich_to_ansi_py(
509
513
  rows: int | None = None,
510
514
  fg: str | None = None,
511
515
  bg: str | None = None,
512
- extend: bool = True,
516
+ **kwargs: Any,
513
517
  ) -> str:
514
518
  """Convert rich objects to formatted ANSI text."""
515
519
  import rich
@@ -8,6 +8,8 @@ from typing import TYPE_CHECKING
8
8
  from euporie.core.convert.registry import register
9
9
 
10
10
  if TYPE_CHECKING:
11
+ from typing import Any
12
+
11
13
  from euporie.core.convert.datum import Datum
12
14
 
13
15
 
@@ -21,7 +23,7 @@ async def bytes_to_base64_py(
21
23
  rows: int | None = None,
22
24
  fg: str | None = None,
23
25
  bg: str | None = None,
24
- extend: bool = True,
26
+ **kwargs: Any,
25
27
  ) -> str:
26
28
  """Convert bytes to base64 encoded data."""
27
29
  data = datum.data
@@ -23,7 +23,7 @@ async def base64_to_bytes_py(
23
23
  rows: int | None = None,
24
24
  fg: str | None = None,
25
25
  bg: str | None = None,
26
- extend: bool = True,
26
+ **kwargs: Any,
27
27
  ) -> bytes:
28
28
  """Convert base64 encoded data to bytes."""
29
29
  data = datum.data
@@ -38,7 +38,7 @@ async def imagemagick_convert(
38
38
  rows: int | None = None,
39
39
  fg: str | None = None,
40
40
  bg: str | None = None,
41
- extend: bool = True,
41
+ **kwargs: Any,
42
42
  ) -> str | bytes:
43
43
  """Convert image data to PNG bytes using ``imagemagick``."""
44
44
  cmd: list[Any] = ["magick"]
@@ -64,7 +64,7 @@ async def chafa_convert_cmd(
64
64
  rows: int | None = None,
65
65
  fg: str | None = None,
66
66
  bg: str | None = None,
67
- extend: bool = True,
67
+ **kwargs: Any,
68
68
  ) -> str | bytes:
69
69
  """Convert image data to ANSI text using :command:`chafa`."""
70
70
  cmd: list[Any] = [
@@ -93,7 +93,7 @@ async def chafa_convert_py(
93
93
  rows: int | None = None,
94
94
  fg: str | None = None,
95
95
  bg: str | None = None,
96
- extend: bool = True,
96
+ **kwargs: Any,
97
97
  ) -> str | bytes:
98
98
  """Convert image data to ANSI text using ::`chafa.py`."""
99
99
  from chafa import Canvas, CanvasConfig, PixelMode, PixelType
@@ -15,6 +15,8 @@ from euporie.core.ft.utils import strip_one_trailing_newline
15
15
  from euporie.core.lexers import detect_lexer
16
16
 
17
17
  if TYPE_CHECKING:
18
+ from typing import Any
19
+
18
20
  from prompt_toolkit.formatted_text.base import StyleAndTextTuples
19
21
 
20
22
  from euporie.core.convert.datum import Datum
@@ -22,7 +24,7 @@ if TYPE_CHECKING:
22
24
 
23
25
  log = logging.getLogger(__name__)
24
26
 
25
- _html_cache: SimpleCache[str, HTML] = SimpleCache(maxsize=20)
27
+ _html_cache: SimpleCache[tuple[str | Any, ...], HTML] = SimpleCache(maxsize=20)
26
28
 
27
29
 
28
30
  @register(
@@ -36,6 +38,7 @@ async def html_to_ft(
36
38
  fg: str | None = None,
37
39
  bg: str | None = None,
38
40
  extend: bool = True,
41
+ **kwargs: Any,
39
42
  ) -> StyleAndTextTuples:
40
43
  """Convert HTML to formatted text."""
41
44
  from euporie.core.ft.html import HTML
@@ -43,7 +46,7 @@ async def html_to_ft(
43
46
  data = datum.data
44
47
  markup = data.decode() if isinstance(data, bytes) else data
45
48
  html = _html_cache.get(
46
- datum.hash,
49
+ (datum.hash, *kwargs.items()),
47
50
  partial(
48
51
  HTML,
49
52
  markup,
@@ -75,8 +78,8 @@ async def ansi_to_ft(
75
78
  rows: int | None = None,
76
79
  fg: str | None = None,
77
80
  bg: str | None = None,
78
- extend: bool = True,
79
81
  lex: bool = False,
82
+ **kwargs: Any,
80
83
  ) -> StyleAndTextTuples:
81
84
  """Convert ANSI text to formatted text, lexing & formatting automatically."""
82
85
  data = datum.data
@@ -11,6 +11,8 @@ from euporie.core.convert.registry import register
11
11
  from euporie.core.lexers import detect_lexer
12
12
 
13
13
  if TYPE_CHECKING:
14
+ from typing import Any
15
+
14
16
  from markdown_it import MarkdownIt
15
17
 
16
18
  from euporie.core.convert.datum import Datum
@@ -24,7 +26,6 @@ def markdown_parser() -> MarkdownIt:
24
26
  from markdown_it import MarkdownIt
25
27
  from mdit_py_plugins.amsmath import amsmath_plugin
26
28
  from mdit_py_plugins.dollarmath.index import dollarmath_plugin
27
- from mdit_py_plugins.texmath.index import texmath_plugin
28
29
  from pygments import highlight
29
30
  from pygments.formatters import HtmlFormatter
30
31
 
@@ -36,30 +37,27 @@ def markdown_parser() -> MarkdownIt:
36
37
  return True
37
38
 
38
39
  return (
39
- (
40
- MarkdownParser(
41
- options_update={
42
- "highlight": lambda text, language, lang_args: highlight(
43
- text,
44
- detect_lexer(text, language=language),
45
- HtmlFormatter(
46
- nowrap=True,
47
- noclasses=True,
48
- style=(
49
- app.syntax_theme
50
- if hasattr((app := get_app()), "syntax_theme")
51
- else "default"
52
- ),
40
+ MarkdownParser(
41
+ options_update={
42
+ "highlight": lambda text, language, lang_args: highlight(
43
+ text,
44
+ detect_lexer(text, language=language),
45
+ HtmlFormatter(
46
+ nowrap=True,
47
+ noclasses=True,
48
+ style=(
49
+ app.syntax_theme
50
+ if hasattr((app := get_app()), "syntax_theme")
51
+ else "default"
53
52
  ),
54
- )
55
- }
56
- )
57
- .enable("linkify")
58
- .enable("table")
59
- .enable("strikethrough")
53
+ ),
54
+ )
55
+ }
60
56
  )
61
- .use(texmath_plugin)
62
- .use(dollarmath_plugin)
57
+ .enable("linkify")
58
+ .enable("table")
59
+ .enable("strikethrough")
60
+ .use(dollarmath_plugin, allow_space=True, double_inline=True)
63
61
  .use(amsmath_plugin)
64
62
  # .use(tasklists_plugin)
65
63
  )
@@ -72,7 +70,7 @@ async def markdown_to_html_markdown_it(
72
70
  rows: int | None = None,
73
71
  fg: str | None = None,
74
72
  bg: str | None = None,
75
- extend: bool = True,
73
+ **kwargs: Any,
76
74
  ) -> str:
77
75
  """Convert markdown to HTML using :py:mod:`markdownit_py`."""
78
76
  parser = markdown_parser()
@@ -9,6 +9,8 @@ from euporie.core.convert.registry import register
9
9
  from euporie.core.filters import have_modules
10
10
 
11
11
  if TYPE_CHECKING:
12
+ from typing import Any
13
+
12
14
  from euporie.core.convert.datum import Datum
13
15
 
14
16
  log = logging.getLogger(__name__)
@@ -27,7 +29,7 @@ async def html_to_markdown_py_html2text(
27
29
  rows: int | None = None,
28
30
  fg: str | None = None,
29
31
  bg: str | None = None,
30
- extend: bool = True,
32
+ **kwargs: Any,
31
33
  ) -> str:
32
34
  """Convert HTML to markdown tables using :py:mod:`html2text`."""
33
35
  import re
@@ -72,7 +74,7 @@ async def html_to_markdown_py_mtable(
72
74
  rows: int | None = None,
73
75
  fg: str | None = None,
74
76
  bg: str | None = None,
75
- extend: bool = True,
77
+ **kwargs: Any,
76
78
  ) -> str:
77
79
  """Convert HTML tables to markdown tables using :py:mod:`mtable`."""
78
80
  from mtable import MarkupTable
@@ -9,6 +9,8 @@ from euporie.core.convert.registry import register
9
9
  from euporie.core.filters import have_modules
10
10
 
11
11
  if TYPE_CHECKING:
12
+ from typing import Any
13
+
12
14
  from PIL.Image import Image as PilImage
13
15
 
14
16
  from euporie.core.convert.datum import Datum
@@ -44,7 +46,7 @@ async def png_to_pil_py(
44
46
  rows: int | None = None,
45
47
  fg: str | None = None,
46
48
  bg: str | None = None,
47
- extend: bool = True,
49
+ **kwargs: Any,
48
50
  ) -> PilImage:
49
51
  """Convert PNG to a pillow image using :py:mod:`PIL`."""
50
52
  import io
@@ -11,6 +11,8 @@ from euporie.core.convert.registry import register
11
11
  from euporie.core.filters import command_exists, have_modules
12
12
 
13
13
  if TYPE_CHECKING:
14
+ from typing import Any
15
+
14
16
  from euporie.core.convert.datum import Datum
15
17
 
16
18
  register(
@@ -30,8 +32,8 @@ async def latex_to_png_dvipng(
30
32
  rows: int | None = None,
31
33
  fg: str | None = None,
32
34
  bg: str | None = None,
33
- extend: bool = True,
34
35
  timeout: int = 2,
36
+ **kwargs: Any,
35
37
  ) -> bytes | None:
36
38
  """Render LaTeX as a png image using :command:`dvipng`.
37
39
 
@@ -113,7 +115,7 @@ async def latex_to_png_py_mpl(
113
115
  rows: int | None = None,
114
116
  fg: str | None = None,
115
117
  bg: str | None = None,
116
- extend: bool = True,
118
+ **kwargs: Any,
117
119
  ) -> bytes:
118
120
  """Render LaTeX as a png image using :py:module:`matplotlib`.
119
121
 
@@ -156,7 +158,7 @@ async def pil_to_png_py_pil(
156
158
  rows: int | None = None,
157
159
  fg: str | None = None,
158
160
  bg: str | None = None,
159
- extend: bool = True,
161
+ **kwargs: Any,
160
162
  ) -> bytes:
161
163
  """Convert a pillow image to sixels :py:mod:`teimpy`."""
162
164
  import io
@@ -177,7 +179,7 @@ async def svg_to_png_py_cairosvg(
177
179
  rows: int | None = None,
178
180
  fg: str | None = None,
179
181
  bg: str | None = None,
180
- extend: bool = True,
182
+ **kwargs: Any,
181
183
  ) -> str:
182
184
  """Convert SVG to PNG using :py:mod:`cairosvg`."""
183
185
  import cairosvg
@@ -8,6 +8,8 @@ from euporie.core.convert.registry import register
8
8
  from euporie.core.filters import have_modules
9
9
 
10
10
  if TYPE_CHECKING:
11
+ from typing import Any
12
+
11
13
  from rich.markdown import Markdown
12
14
 
13
15
  from euporie.core.convert.datum import Datum
@@ -24,7 +26,7 @@ async def markdown_to_rich_py(
24
26
  rows: int | None = None,
25
27
  fg: str | None = None,
26
28
  bg: str | None = None,
27
- extend: bool = True,
29
+ **kwargs: Any,
28
30
  ) -> Markdown:
29
31
  """Convert base64 encoded data to bytes."""
30
32
  from rich.markdown import Markdown
@@ -46,7 +46,7 @@ async def png_to_sixel_img2sixel(
46
46
  rows: int | None = None,
47
47
  fg: str | None = None,
48
48
  bg: str | None = None,
49
- extend: bool = True,
49
+ **kwargs: Any,
50
50
  ) -> str:
51
51
  """Convert PNG data to sixels :command:`img2sixel`."""
52
52
  cmd: list[Any] = ["img2sixel", "-I"]
@@ -76,7 +76,7 @@ async def pil_to_sixel_py_timg(
76
76
  rows: int | None = None,
77
77
  fg: str | None = None,
78
78
  bg: str | None = None,
79
- extend: bool = True,
79
+ **kwargs: Any,
80
80
  ) -> str:
81
81
  """Convert a pillow image to sixels :py:mod:`timg`."""
82
82
  import timg
@@ -95,7 +95,7 @@ async def pil_to_sixel_py_teimpy(
95
95
  rows: int | None = None,
96
96
  fg: str | None = None,
97
97
  bg: str | None = None,
98
- extend: bool = True,
98
+ **kwargs: Any,
99
99
  ) -> str:
100
100
  """Convert a pillow image to sixels :py:mod:`teimpy`."""
101
101
  import numpy as np
@@ -8,6 +8,8 @@ from euporie.core.convert.registry import register
8
8
  from euporie.core.filters import have_modules
9
9
 
10
10
  if TYPE_CHECKING:
11
+ from typing import Any
12
+
11
13
  from euporie.core.convert.datum import Datum
12
14
 
13
15
 
@@ -18,7 +20,7 @@ async def latex_to_svg_py_ziamath(
18
20
  rows: int | None = None,
19
21
  fg: str | None = None,
20
22
  bg: str | None = None,
21
- extend: bool = True,
23
+ **kwargs: Any,
22
24
  ) -> str:
23
25
  """Convert LaTeX to SVG using :py:mod:`ziamath`."""
24
26
  import ziamath as zm