From a46c08be39e1eeb6e073d4280c33d5ba4bfa832b Mon Sep 17 00:00:00 2001 From: tonyfast Date: Tue, 24 Sep 2024 18:35:56 -0700 Subject: [PATCH] add hy lisp --- src/midgy/language/python.py | 6 ++-- src/midgy/types.py | 56 ++++++++++++++++++++++++++++++++++-- src/midgy/weave.py | 2 +- 3 files changed, 59 insertions(+), 5 deletions(-) diff --git a/src/midgy/language/python.py b/src/midgy/language/python.py index 42719e6..6d5e128 100644 --- a/src/midgy/language/python.py +++ b/src/midgy/language/python.py @@ -47,9 +47,11 @@ class Python(Markdown, type="text/x-python", language="ipython3"): html="midgy.types:HTML", markdown="midgy.types:Markdown", javascript="midgy.types:Script", - graphviz="midgy.types:DOT", - dot="midgy.types:DOT", + graphviz="midgy.types:Dot", + dot="midgy.types:Dot", md="midgy.types:Markdown", + lisp="midgy.types:Hy.eval", + hy="midgy.types:Hy.eval" ) fenced_code_blocks: list = field( default_factory=["python", "python3", "ipython3", "ipython", ""].copy diff --git a/src/midgy/types.py b/src/midgy/types.py index b81a7fa..692b2d6 100644 --- a/src/midgy/types.py +++ b/src/midgy/types.py @@ -1,4 +1,6 @@ -from functools import wraps +# all of these types should have magic counterparts +from functools import cached_property, wraps +from midgy.tangle import get_markdown_it def enforce_cls(callable): @@ -65,13 +67,23 @@ class Markdown(String): def _repr_markdown_(self): return self + def to_html(self): + from IPython import get_ipython + + shell = get_ipython() + if shell: + from midgy._magics import get_environment + + return HTML(shell.tangle.parser.parser.render(self)) + return HTML(get_markdown_it().render(self)) + class Mermaid(String): def _repr_markdown_(self): return f"""```mermaid\n{self}```""" -Md = Markdown +Md = Markdown class SVG(HTML): @@ -92,3 +104,43 @@ def _repr_svg_(self): return self.graphviz()._repr_image_svg_xml() except (ModuleNotFoundError, ImportError): pass + + +class Hy(String): + @cached_property + def shell(self): + import hy.repl + + class InteractiveHy(hy.repl.HyCompile): + + def __init__(self, *a, **kw): + from IPython import get_ipython + + shell = get_ipython() + # we'll need to scope this for non interactive versions + if shell: + main = __import__("__main__") + else: + raise TypeError("only interactive shells are supported for hy at the moment") + super().__init__(main, vars(main)) + self.hy_compiler = hy.repl.HyASTCompiler(__import__(__name__)) + + def __call__(self, src, *args, **kwargs): + import builtins + + exec, eval = super().__call__(src, *args, **kwargs) + builtins.exec(exec, vars(self.module), vars(self.module)) + return builtins.eval(eval, vars(self.module), vars(self.module)) + + @classmethod + def execute(cls, code): + return cls()(code) + + return InteractiveHy + + def _eval(self): + return self.shell.execute(self) + + @classmethod + def eval(cls, code): + return cls(code)._eval() diff --git a/src/midgy/weave.py b/src/midgy/weave.py index a339e8a..af17111 100644 --- a/src/midgy/weave.py +++ b/src/midgy/weave.py @@ -92,8 +92,8 @@ def weave( quick_doctest(self.source) data = {"text/x-python": self.out} + from IPython.display import display if weave and self.tokens[0].map[0] == int(magic): - from IPython.display import display if html: output = self.parser.parser.render(