Show More
@@ -0,0 +1,60 b'' | |||||
|
1 | ||||
|
2 | .. _shell_mimerenderer: | |||
|
3 | ||||
|
4 | ||||
|
5 | Mime Renderer Extensions | |||
|
6 | ======================== | |||
|
7 | ||||
|
8 | Like it's cousins, Jupyter Notebooks and JupyterLab, Terminal IPython can be | |||
|
9 | thought to render a number of mimetypes in the shell. This can be used to either | |||
|
10 | display inline images if your terminal emulator supports it; or open some | |||
|
11 | display results with external file viewers. | |||
|
12 | ||||
|
13 | Registering new mimetype handlers can so far only be done my extensions and | |||
|
14 | requires 4 steps: | |||
|
15 | ||||
|
16 | - Define a callable that takes 2 parameters:``data`` and ``metadata``; return | |||
|
17 | value of the callable is so far ignored. This callable is responsible for | |||
|
18 | "displaying" the given mimetype. Which can be sending the right escape | |||
|
19 | sequences and bytes to the current terminal; or open an external program. - | |||
|
20 | - Appending the right mimetype to ``ipython.display_formatter.active_types`` | |||
|
21 | for IPython to know it should not ignore those mimetypes. | |||
|
22 | - Enabling the given mimetype: ``ipython.display_formatter.formatters[mime].enabled = True`` | |||
|
23 | - Registering above callable with mimetype handler: | |||
|
24 | ``ipython.mime_renderers[mime] = handler`` | |||
|
25 | ||||
|
26 | ||||
|
27 | Here is a complete IPython extension to display images inline and convert math | |||
|
28 | to png, before displaying it inline for iterm2 on macOS :: | |||
|
29 | ||||
|
30 | ||||
|
31 | from base64 import encodebytes | |||
|
32 | from IPython.lib.latextools import latex_to_png | |||
|
33 | ||||
|
34 | ||||
|
35 | def mathcat(data, meta): | |||
|
36 | png = latex_to_png(f'$${data}$$'.replace('\displaystyle', '').replace('$$$', '$$')) | |||
|
37 | imcat(png, meta) | |||
|
38 | ||||
|
39 | IMAGE_CODE = '\033]1337;File=name=name;inline=true;:{}\a' | |||
|
40 | ||||
|
41 | def imcat(image_data, metadata): | |||
|
42 | try: | |||
|
43 | print(IMAGE_CODE.format(encodebytes(image_data).decode())) | |||
|
44 | # bug workaround | |||
|
45 | except: | |||
|
46 | print(IMAGE_CODE.format(image_data)) | |||
|
47 | ||||
|
48 | def register_mimerenderer(ipython, mime, handler): | |||
|
49 | ipython.display_formatter.active_types.append(mime) | |||
|
50 | ipython.display_formatter.formatters[mime].enabled = True | |||
|
51 | ipython.mime_renderers[mime] = handler | |||
|
52 | ||||
|
53 | def load_ipython_extension(ipython): | |||
|
54 | register_mimerenderer(ipython, 'image/png', imcat) | |||
|
55 | register_mimerenderer(ipython, 'image/jpeg', imcat) | |||
|
56 | register_mimerenderer(ipython, 'text/latex', mathcat) | |||
|
57 | ||||
|
58 | This example only work for iterm2 on macOS and skip error handling for brevity. | |||
|
59 | One could also invoke an external viewer with ``subporcess.run()`` and a | |||
|
60 | temporary file, which is left as an exercise. |
@@ -516,7 +516,7 b' class TerminalInteractiveShell(InteractiveShell):' | |||||
516 |
|
516 | |||
517 | active_eventloop = None |
|
517 | active_eventloop = None | |
518 | def enable_gui(self, gui=None): |
|
518 | def enable_gui(self, gui=None): | |
519 | if gui: |
|
519 | if gui and (gui != 'inline') : | |
520 | self.active_eventloop, self._inputhook =\ |
|
520 | self.active_eventloop, self._inputhook =\ | |
521 | get_inputhook_name_and_func(gui) |
|
521 | get_inputhook_name_and_func(gui) | |
522 | else: |
|
522 | else: |
@@ -12,7 +12,7 b' backends = [' | |||||
12 | 'tk', |
|
12 | 'tk', | |
13 | 'wx', |
|
13 | 'wx', | |
14 | 'pyglet', 'glut', |
|
14 | 'pyglet', 'glut', | |
15 |
'osx' |
|
15 | 'osx' | |
16 | ] |
|
16 | ] | |
17 |
|
17 | |||
18 | registered = {} |
|
18 | registered = {} |
@@ -29,6 +29,7 b' Extending and integrating with IPython' | |||||
29 | extensions/index |
|
29 | extensions/index | |
30 | integrating |
|
30 | integrating | |
31 | custommagics |
|
31 | custommagics | |
|
32 | shell_mimerenderer | |||
32 | inputtransforms |
|
33 | inputtransforms | |
33 | callbacks |
|
34 | callbacks | |
34 | eventloops |
|
35 | eventloops |
@@ -2,54 +2,18 b' Arbitrary Mimetypes Handing in Terminal' | |||||
2 | ======================================= |
|
2 | ======================================= | |
3 |
|
3 | |||
4 | When using IPython terminal it is now possible to register function to handle |
|
4 | When using IPython terminal it is now possible to register function to handle | |
5 | arbitrary mimetypes (``TerminalInteractiveShell.mime_renderers`` ``Dict`` |
|
5 | arbitrary mimetypes. While rendering non-text based representation was possible in | |
6 | configurable). While rendering non-text based representation was possible in |
|
|||
7 | many jupyter frontend; it was not possible in terminal IPython, as usually |
|
6 | many jupyter frontend; it was not possible in terminal IPython, as usually | |
8 | terminal are limited to displaying text. As many terminal these days provide |
|
7 | terminal are limited to displaying text. As many terminal these days provide | |
9 | escape sequences to display non-text; bringing this loved feature to IPython CLI |
|
8 | escape sequences to display non-text; bringing this loved feature to IPython CLI | |
10 | made a lot of sens. This functionality will not only allow inline images; but |
|
9 | made a lot of sens. This functionality will not only allow inline images; but | |
11 |
allow opening of external program; for example `` |
|
10 | allow opening of external program; for example ``mplayer`` to "display" sound | |
12 | files. |
|
11 | files. | |
13 |
|
12 | |||
14 | Here is a complete IPython tension to display images inline and convert math to |
|
|||
15 | png, before displaying it inline :: |
|
|||
16 |
|
||||
17 |
|
||||
18 | from base64 import encodebytes |
|
|||
19 | from IPython.lib.latextools import latex_to_png |
|
|||
20 |
|
||||
21 |
|
||||
22 | def mathcat(data, meta): |
|
|||
23 | png = latex_to_png(f'$${data}$$'.replace('\displaystyle', '').replace('$$$', '$$')) |
|
|||
24 | imcat(png, meta) |
|
|||
25 |
|
||||
26 | IMAGE_CODE = '\033]1337;File=name=name;inline=true;:{}\a' |
|
|||
27 |
|
||||
28 | def imcat(image_data, metadata): |
|
|||
29 | try: |
|
|||
30 | print(IMAGE_CODE.format(encodebytes(image_data).decode())) |
|
|||
31 | # bug workaround |
|
|||
32 | except: |
|
|||
33 | print(IMAGE_CODE.format(image_data)) |
|
|||
34 |
|
||||
35 | def register_mimerenderer(ipython, mime, handler): |
|
|||
36 | ipython.display_formatter.active_types.append(mime) |
|
|||
37 | ipython.display_formatter.formatters[mime].enabled = True |
|
|||
38 | ipython.mime_renderers[mime] = handler |
|
|||
39 |
|
||||
40 | def load_ipython_extension(ipython): |
|
|||
41 | register_mimerenderer(ipython, 'image/png', imcat) |
|
|||
42 | register_mimerenderer(ipython, 'image/jpeg', imcat) |
|
|||
43 | register_mimerenderer(ipython, 'text/latex', mathcat) |
|
|||
44 |
|
||||
45 | This example only work for iterm2 on mac os and skip error handling for brevity. |
|
|||
46 | One could also invoke an external viewer with ``subporcess.run()`` and a |
|
|||
47 | tempfile, which is left as an exercise. |
|
|||
48 |
|
||||
49 | So far only the hooks necessary for this are in place, but no default mime |
|
13 | So far only the hooks necessary for this are in place, but no default mime | |
50 | renderers added; so inline images will only be available via extensions. We will |
|
14 | renderers added; so inline images will only be available via extensions. We will | |
51 | progressively enable these features by default in the next few releases, and |
|
15 | progressively enable these features by default in the next few releases, and | |
52 | contribution is welcomed. |
|
16 | contribution is welcomed. | |
53 |
|
17 | |||
54 |
|
18 | We welcome any feedback on the API. See :ref:`shell_mimerenderer` for more | ||
55 |
|
19 | informations. |
General Comments 0
You need to be logged in to leave comments.
Login now