diff --git a/examples/Untitled.ipynb b/examples/Untitled.ipynb
index 65a5f99..33f8810 100644
--- a/examples/Untitled.ipynb
+++ b/examples/Untitled.ipynb
@@ -2,709 +2,244 @@
"cells": [
{
"cell_type": "code",
- "execution_count": 1,
- "id": "02ab81b2-33b5-41b7-8cf3-fc4d72bbf4f6",
+ "execution_count": 15,
+ "id": "94b4116d-7d70-4c75-b5e9-62eb3b20c5ad",
"metadata": {},
"outputs": [],
"source": [
- "import dyno"
+ "from dyno.dynofile import LDynoModel as DynoModel"
]
},
{
"cell_type": "code",
- "execution_count": 35,
- "id": "c00db4e9-d9a6-43ce-ba65-6b20f865e7f2",
+ "execution_count": 16,
+ "id": "8b705a25-2cff-4c95-b2d7-a3383d2c4d1f",
"metadata": {},
"outputs": [],
"source": [
- "from dyno.report import dsge_report"
+ "model = DynoModel(\"ICAI/partial.dyno\")"
]
},
{
"cell_type": "code",
- "execution_count": 41,
- "id": "d57416c1-c112-4cda-8487-215a07db716f",
- "metadata": {},
- "outputs": [],
- "source": [
- "report = dsge_report(\"example1.mod\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "id": "f2651998-731a-4f4f-9021-d7ef28a0869c",
- "metadata": {},
- "outputs": [],
- "source": [
- "from dyno.dynofile import DynoModel"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 48,
- "id": "68fa525e-d110-458a-8f12-40e8967741cd",
- "metadata": {},
- "outputs": [],
- "source": [
- "model = DynoModel(\"example1.dyno\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 49,
- "id": "c6053ac1-004a-40ea-83d4-8afe6632131a",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "
Model
\n",
- "\n",
- "- name: anonymous
\n",
- "- symbols:\n",
- "
\n",
- " - variables:\n",
- "
\n",
- " - endogenous: r,n,k,y,i,c,w,a
\n",
- " - exogenous: epsilon
\n",
- "
\n",
- " \n",
- " - parameters: beta,delta,nss,eta,alpha,rho,khi
\n",
- "
\n",
- " \n",
- "
\n"
- ],
- "text/plain": [
- ""
- ]
- },
- "execution_count": 49,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "model"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 51,
- "id": "d8ee8a4b-4c0d-4c4a-bf46-bd4501783379",
- "metadata": {},
- "outputs": [],
- "source": [
- "dr = model.solve()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 52,
- "id": "6ca5a00f-4708-478f-91a2-fc1f5e0dd0d4",
- "metadata": {},
- "outputs": [
- {
- "ename": "",
- "evalue": "'RecursiveSolution' object has no attribute 'plot'",
- "output_type": "error",
- "traceback": [
- "\u001b[31m---------------------------------------------------------------------------\u001b[39m",
- "\u001b[31mAttributeError\u001b[39m Traceback (most recent call last)",
- "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[52]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m \u001b[43mdr\u001b[49m\u001b[43m.\u001b[49m\u001b[43mplot\u001b[49m\n",
- "\u001b[31mAttributeError\u001b[39m: 'RecursiveSolution' object has no attribute 'plot'"
- ]
- }
- ],
- "source": [
- "dr.plot"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "id": "251c07e6-8e0e-4ee0-a488-67dc62ed8b27",
- "metadata": {},
- "outputs": [
- {
- "ename": "",
- "evalue": "cannot import name 'deterministic_solve' from 'dyno.solver' (/home/pablo/Econforge/dyno.py/src/dyno/solver.py)",
- "output_type": "error",
- "traceback": [
- "\u001b[31m---------------------------------------------------------------------------\u001b[39m",
- "\u001b[31mImportError\u001b[39m Traceback (most recent call last)",
- "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[4]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m \u001b[38;5;28;01mfrom\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34;01mdyno\u001b[39;00m\u001b[34;01m.\u001b[39;00m\u001b[34;01msolver\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mimport\u001b[39;00m deterministic_solve\n",
- "\u001b[31mImportError\u001b[39m: cannot import name 'deterministic_solve' from 'dyno.solver' (/home/pablo/Econforge/dyno.py/src/dyno/solver.py)"
- ]
- }
- ],
- "source": [
- "from dyno.solver import deterministic_solve"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "fa620b07-ee4f-4152-a82e-491bc59af7b5",
- "metadata": {},
- "outputs": [],
- "source": [
- "from ipywidgets import *"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "3c96291e-e35f-410e-b9e2-d55d19a8a3a1",
- "metadata": {},
- "outputs": [],
- "source": [
- "from ipywidgets.widgets import *"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "092d0108-1156-4369-b463-0f8b19f84c38",
- "metadata": {},
- "outputs": [],
- "source": [
- "sim = deterministic_solve(model)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "7e0b8224-f314-4c73-8261-08bb7cd98df8",
- "metadata": {},
- "outputs": [],
- "source": [
- "tab_nest = widgets.Accordion([\n",
- " widgets.HTML(model._repr_html_()),\n",
- " widgets.HTML(sim._repr_html_())\n",
- "])\n",
- "tab_nest.titles = ('An accordion', 'Simulation')\n",
- "tab_nest"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "cb29370d-0c2f-46c1-9769-36d5e8ef6b51",
- "metadata": {},
- "outputs": [],
- "source": [
- "import xarray"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "64f6c01c-397f-4947-8efa-694d5e78f2b9",
- "metadata": {},
- "outputs": [],
- "source": [
- "sim.to_xarray()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "73fdb09d-adc2-4b94-b73f-3ac2aed6381d",
- "metadata": {},
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "6d83f36a-be38-4918-8caa-9061c0f18468",
- "metadata": {},
- "outputs": [],
- "source": [
- "from ipywidgets.embed import embed_minimal_html\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "e89ef6cd-171d-480e-a6ae-2e221f825fe7",
- "metadata": {},
- "outputs": [],
- "source": [
- "embed_minimal_html(\"out.html\" , [tab_nest])"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "eab1207c-27f6-4a28-9738-ff75dd70a3a0",
- "metadata": {},
- "outputs": [],
- "source": [
- "import altair as alt"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "7e396c6c-496a-4d9f-b76e-4d4c5f301431",
- "metadata": {},
- "outputs": [],
- "source": [
- "sim['t'] = sim.index"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "06de5e83-4f40-4328-843f-cc81fd1306eb",
- "metadata": {},
- "outputs": [],
- "source": [
- "import pandas\n",
- "ssim = pandas.melt(sim, id_vars=['t'])"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "c1e59c8d-1913-4d95-9e35-89ced11640e8",
- "metadata": {},
- "outputs": [],
- "source": [
- "alt.Chart(ssim).mark_line().encode(\n",
- " x = 't',\n",
- " y = 'value',\n",
- " color=alt.Y(alt.repeat(\"row\"), type='quantitative'),\n",
- ").properties(\n",
- " width=200,\n",
- " height=200\n",
- ").repeat(\n",
- " row=ssim['variable'].unique()\n",
- ")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "b56d4b0c-f923-4047-a7b1-67e65973e673",
- "metadata": {},
- "outputs": [],
- "source": [
- "ssim"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "id": "924e01c7-91c6-4eb0-9fd2-87623aea5815",
- "metadata": {},
- "outputs": [
- {
- "ename": "",
- "evalue": "name 'alt' is not defined",
- "output_type": "error",
- "traceback": [
- "\u001b[31m---------------------------------------------------------------------------\u001b[39m",
- "\u001b[31mNameError\u001b[39m Traceback (most recent call last)",
- "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[5]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m \u001b[43malt\u001b[49m.Chart(ssim).mark_line().encode(\n\u001b[32m 2\u001b[39m x=\u001b[33m'\u001b[39m\u001b[33mt\u001b[39m\u001b[33m'\u001b[39m,\n\u001b[32m 3\u001b[39m y=\u001b[33m'\u001b[39m\u001b[33mvalue\u001b[39m\u001b[33m'\u001b[39m,\n\u001b[32m 4\u001b[39m color=\u001b[33m'\u001b[39m\u001b[33mvariable\u001b[39m\u001b[33m'\u001b[39m\n\u001b[32m 5\u001b[39m ).properties(\n\u001b[32m 6\u001b[39m width=\u001b[32m180\u001b[39m,\n\u001b[32m 7\u001b[39m height=\u001b[32m180\u001b[39m\n\u001b[32m 8\u001b[39m ).facet(\n\u001b[32m 9\u001b[39m row=\u001b[33m'\u001b[39m\u001b[33mvariable\u001b[39m\u001b[33m'\u001b[39m\n\u001b[32m 10\u001b[39m )\n",
- "\u001b[31mNameError\u001b[39m: name 'alt' is not defined"
- ]
- }
- ],
- "source": [
- "alt.Chart(ssim).mark_line().encode(\n",
- " x='t',\n",
- " y='value',\n",
- " color='variable'\n",
- ").properties(\n",
- " width=180,\n",
- " height=180\n",
- ").facet(\n",
- " row='variable'\n",
- ")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 6,
- "id": "6218c7b1-d379-43c8-b583-67e14baf4497",
- "metadata": {},
- "outputs": [],
- "source": [
- "import myst_parser"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 7,
- "id": "e97e484d-73b3-4bd6-a83f-a6e0170b38da",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "\u001b[31mSignature:\u001b[39m myst_parser.setup(app)\n",
- "\u001b[31mDocstring:\u001b[39m Initialize the [Sphinx](https://github.com/sphinx-doc/sphinx) extension.\n",
- "\u001b[31mFile:\u001b[39m ~/Econforge/jupyterlab-dyno/.pixi/envs/default/lib/python3.13/site-packages/myst_parser/__init__.py\n",
- "\u001b[31mType:\u001b[39m function"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
- "source": [
- "myst_parser.setup?"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 8,
- "id": "124e32e8-cb20-4472-b73f-7b760bcd0bcc",
- "metadata": {},
- "outputs": [],
- "source": [
- "import myst_parser.docutils_"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 9,
- "id": "12e8fda1-68e2-4bb8-98be-c8bfc2dd9333",
- "metadata": {},
- "outputs": [],
- "source": [
- "import jupyterlab_myst"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 86,
- "id": "f2e93ede-56e2-48c5-aac8-e1c58d14d578",
- "metadata": {},
- "outputs": [],
- "source": [
- "\n",
- "doc = \"\"\"\n",
- "\n",
- "# Here is a title.\n",
- "\n",
- "Here's some *text*\n",
- "\n",
- "1. a list\n",
- "\n",
- "> a quote\n",
- "\n",
- "{emphasis}`content`\n",
- "\n",
- "Can I embed formulas : $a=34$ ?\n",
- "```{sidebar} my sidebar\n",
- "content\n",
- "```\n",
- ":::{tip}\n",
- "Let's give readers a helpful hint!\n",
- ":::\n",
- "\n",
- "\"\"\"\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 87,
- "id": "d39c739a-7fc4-41ff-8611-8f469d90e0ac",
- "metadata": {},
- "outputs": [],
- "source": [
- "from docutils.core import publish_string\n",
- "from myst_parser.docutils_ import Parser\n",
- "\n",
- "output = publish_string(\n",
- " source=doc,\n",
- " writer_name=\"html5\",\n",
- " settings_overrides={\n",
- " # \"myst_enable_extensions\": [\"deflist\"],\n",
- " \"embed_stylesheet\": True,\n",
- " },\n",
- " parser=Parser(),\n",
- ")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 88,
- "id": "9c5564a7-7b35-4f0d-8e0e-2afb3db7b85b",
- "metadata": {},
- "outputs": [],
- "source": [
- "html = HTML(output.decode(\"utf-8\"))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 89,
- "id": "91377fe7-1331-4b5f-a132-0a5b9f238cb5",
+ "execution_count": 17,
+ "id": "b08fd73e-74ae-43c9-9416-207feb4e6681",
"metadata": {},
"outputs": [
{
"data": {
- "application/vnd.jupyter.widget-view+json": {
- "model_id": "dea9871a261e47ba96a5ca4c6173cab9",
- "version_major": 2,
- "version_minor": 0
- },
"text/plain": [
- "HTML(value='\\n\\n\\n",
- "evalue": "write() argument must be str, not bytes",
- "output_type": "error",
- "traceback": [
- "\u001b[31m---------------------------------------------------------------------------\u001b[39m",
- "\u001b[31mTypeError\u001b[39m Traceback (most recent call last)",
- "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[63]\u001b[39m\u001b[32m, line 2\u001b[39m\n\u001b[32m 1\u001b[39m \u001b[38;5;28;01mwith\u001b[39;00m \u001b[38;5;28mopen\u001b[39m(\u001b[33m\"\u001b[39m\u001b[33mout.html\u001b[39m\u001b[33m\"\u001b[39m) \u001b[38;5;28;01mas\u001b[39;00m f:\n\u001b[32m----> \u001b[39m\u001b[32m2\u001b[39m \u001b[43mf\u001b[49m\u001b[43m.\u001b[49m\u001b[43mwrite\u001b[49m\u001b[43m(\u001b[49m\u001b[43moutput\u001b[49m\u001b[43m)\u001b[49m\n",
- "\u001b[31mTypeError\u001b[39m: write() argument must be str, not bytes"
- ]
- }
- ],
- "source": [
- "with open(\"out.html\") as f:\n",
- " f.write(output)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "9f7956b2-bd69-4761-a4c7-921b820c7024",
- "metadata": {},
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "3ff310d1-72af-4762-9589-44d001371ca0",
- "metadata": {},
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "code",
- "execution_count": 94,
- "id": "41c788bc-9939-4720-8277-361fa1dc8940",
- "metadata": {},
- "outputs": [],
- "source": [
- "from ipywidgets import Accordion, HTML\n",
- "\n",
- "acc = Accordion(children=[\n",
- " HTML(\"JI\"),\n",
- " HTML(\"JI\")\n",
- "])\n",
- "\n",
- "\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 95,
- "id": "418c5cc5-9b69-4fdd-8a7a-747f5288761e",
- "metadata": {},
- "outputs": [],
- "source": [
- "from ipywidgets.embed import embed_minimal_html\n",
- "\n",
- "embed_minimal_html('export.html', views=[acc], title='Widgets export')"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "5cd45813-a18b-461f-9a76-9cc9b47096ff",
- "metadata": {},
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "4fe195ea-c13c-4fa2-a563-fc48b861f9a5",
- "metadata": {},
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "code",
- "execution_count": 7,
- "id": "0b4742fe-8fbf-4a62-8fb0-8925f16347c6",
- "metadata": {},
- "outputs": [],
- "source": [
- "class HTML:\n",
- " def __init__(self, data):\n",
- " self.data = data\n",
- "\n",
- " def _repr_html_(self):\n",
- " return self.data\n",
- "\n",
- "doc = \"\"\"\n",
- "\n",
- "This is basic html.\n",
- "
\n",
- "\"\"\"\n",
- "\n",
- "md = \"\"\"\n",
- "# This is basic markdown\n",
- "\n",
- "\n",
- "But there aren't many nice options.\n",
- "\n",
- "$a = 4$.\n",
- "\n",
- "\n",
- "\"\"\"\n",
- "\n",
- "import mistune\n",
- "\n",
- "html = HTML(mistune.html(md))\n",
- "\n",
- "\n",
- "from markdown_it import MarkdownIt\n",
- "from mdit_py_plugins.front_matter import front_matter_plugin\n",
- "from mdit_py_plugins.footnote import footnote_plugin\n",
- "\n",
- "md = \"\"\"\n",
- "---\n",
- "title: 1\n",
- "---\n",
- "\n",
- "# Is that meant to be a title ?\n",
- "\n",
- "a | b\n",
- "- | -\n",
- "1 | 2\n",
- "\n",
- "```\n",
- "Sample text here...\n",
- "```\n",
- "::: {.note}\n",
- "\n",
- "Can I make a note here ?\n",
- "\n",
- ":::\n",
- "\n",
- "A footnote [^1]\n",
- "\n",
- "[^1]: some details\n",
- "\"\"\"\n",
- "\n",
- "#html = HTML(html_text)\n",
- "\n",
- "\n",
- "from IPython.display import display, Markdown, Latex\n",
- "\n",
- "\n",
- "html = Markdown(md)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 8,
- "id": "e93cb822-a1f4-4376-89de-3334fe23917c",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/markdown": [
- "\n",
- "---\n",
- "title: 1\n",
- "---\n",
- "\n",
- "# Is that meant to be a title ?\n",
- "\n",
- "a | b\n",
- "- | -\n",
- "1 | 2\n",
- "\n",
- "```\n",
- "Sample text here...\n",
- "```\n",
- "::: {.note}\n",
- "\n",
- "Can I make a note here ?\n",
- "\n",
- ":::\n",
- "\n",
- "A footnote [^1]\n",
- "\n",
- "[^1]: some details\n"
- ],
- "text/plain": [
- ""
- ]
- },
- "execution_count": 8,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "html"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "580482c9-9de1-4714-9883-a5a24ed24bae",
- "metadata": {},
- "source": [
- "---\n",
- "title: 1\n",
- "---\n",
- "\n",
- "# Is that meant to be a title ?\n",
- "\n",
- "a | b\n",
- "- | -\n",
- "1 | 2\n",
- "\n",
- "```\n",
- "Sample text here...\n",
- "```\n",
- "::: {.note}\n",
- "\n",
- "Can I make a note here ?\n",
- "\n",
- ":::\n",
- "\n",
- "A footnote [^1]\n",
- "\n",
- "[^1]: some details"
+ "model.jacobians"
]
},
{
"cell_type": "code",
"execution_count": null,
- "id": "b67ccab4-f7c3-4cb4-a880-ffed590a1658",
+ "id": "90823573-bc17-4155-8a6c-449f9fe00e31",
"metadata": {},
"outputs": [],
"source": []
@@ -712,7 +247,7 @@
],
"metadata": {
"kernelspec": {
- "display_name": "Python . (XPython)",
+ "display_name": "Python 3.13 (XPython)",
"language": "python",
"name": "xpython"
},
diff --git a/examples/Untitled1.ipynb b/examples/Untitled1.ipynb
deleted file mode 100644
index 567e6da..0000000
--- a/examples/Untitled1.ipynb
+++ /dev/null
@@ -1,170 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": 3,
- "id": "b00db412-890e-46a3-b73d-d70569486010",
- "metadata": {},
- "outputs": [],
- "source": [
- "txt = \"\"\"\n",
- "# This is markdown, brother.\n",
- "\n",
- "This is some text.\n",
- "\"\"\""
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 23,
- "id": "9b1c8b73-a69e-4b50-9f3e-533b4d440e8d",
- "metadata": {},
- "outputs": [],
- "source": [
- "class Report:\n",
- " \n",
- " def __init__(self, txt):\n",
- " self.txt = txt\n",
- " def _repr_markdown_(self):\n",
- " return f\"{self.txt}\"\n",
- " def _repr_html_(self):\n",
- " return f\"{self.txt}\""
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 24,
- "id": "eb985f07-5b9e-4e07-aa19-3f47e394fdaa",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "\n",
- "# This is markdown, brother.\n",
- "\n",
- "This is some text.\n",
- "
"
- ],
- "text/markdown": [
- "\n",
- "# This is markdown, brother.\n",
- "\n",
- "This is some text.\n"
- ],
- "text/plain": [
- "<__main__.Report at 0x7ba12bccfcb0>"
- ]
- },
- "execution_count": 24,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "Report(txt)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 16,
- "id": "c2d213a7-cbd7-47b0-80f2-68be72db0a62",
- "metadata": {},
- "outputs": [],
- "source": [
- "from IPython.display import Markdown"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 17,
- "id": "44d67b29-2338-4c1a-9ea8-a5a7da637636",
- "metadata": {},
- "outputs": [],
- "source": [
- "m = Markdown(txt)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 18,
- "id": "15cd5210-b7b5-477e-8eb7-017642245740",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/markdown": [
- "\n",
- "# This is markdown, brother.\n",
- "\n",
- "This is some text.\n"
- ],
- "text/plain": [
- ""
- ]
- },
- "execution_count": 18,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "m"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 20,
- "id": "d383b6cc-dafd-41bb-bf42-13d56fc2315e",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "'\\n# This is markdown, brother.\\n\\nThis is some text.\\n'"
- ]
- },
- "execution_count": 20,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "m._repr_markdown_()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "d744242b-799d-4a88-ae0c-70a5d7f19b42",
- "metadata": {},
- "outputs": [],
- "source": [
- "m._"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "id": "0705c31e-5aee-4c6e-905b-b4f13494aee6",
- "metadata": {},
- "outputs": [],
- "source": []
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python . (XPython)",
- "language": "python",
- "name": "xpython"
- },
- "language_info": {
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "version": "3.13.7"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
-}
diff --git a/examples/demo.dyno b/examples/demo.dyno
index 3bd56ea..5ec2d4d 100644
--- a/examples/demo.dyno
+++ b/examples/demo.dyno
@@ -2,9 +2,9 @@
beta <- 0.98
delta <- 0.025
nss <- 0.33
-eta <- 1.3
+eta <- 1.
rho <- 0.5
-alpha <- .33
+alpha <- .37
khi <- (1-alpha)*(1-nss)^eta/nss*(1/beta-1+delta)/(1/beta-1+delta-delta*alpha)
# equations
diff --git a/examples/example1.dyno b/examples/example1.dyno
index 6151636..64cb42d 100644
--- a/examples/example1.dyno
+++ b/examples/example1.dyno
@@ -4,7 +4,7 @@ delta <- 0.025
nss <- 0.33
eta <- 1.0
alpha <- .32
-rho <- .96
+rho <- .9
chi <- (1-alpha)*(1-nss)^eta/nss*(1/beta-1+delta)/(1/beta-1+delta-delta*alpha)
# equations
diff --git a/examples/example1.mod b/examples/example1.mod
index bc89805..85e90e3 100644
--- a/examples/example1.mod
+++ b/examples/example1.mod
@@ -35,7 +35,6 @@ beta = 0.99;
delta = 0.02509;
psi = 0;
theta = 2.95;
-
phi = 0.1;
model;
diff --git a/package.json b/package.json
index cf05365..e683430 100644
--- a/package.json
+++ b/package.json
@@ -63,8 +63,12 @@
"watch:labextension": "jupyter labextension watch ."
},
"dependencies": {
+ "@codemirror/language": "^6.0.0",
+ "@codemirror/state": "^6.2.0",
"@jupyterlab/application": "^4.4.5",
- "@jupyterlab/settingregistry": "^4.4.5"
+ "@jupyterlab/codemirror": "^4.4.5",
+ "@jupyterlab/settingregistry": "^4.4.5",
+ "@lezer/highlight": "^1.0.0"
},
"devDependencies": {
"@jupyterlab/builder": "^4.4.5",
diff --git a/pixi.toml b/pixi.toml
index 06e5c97..186ff40 100644
--- a/pixi.toml
+++ b/pixi.toml
@@ -10,11 +10,14 @@ watch = "jlpm watch & jupyter lab"
[dependencies]
jupyterlab = ">=4.0.0,<5"
jupyterlab_dyno = { path = "." }
-dyno = ">=0.1.5.dev7"
nodejs = ">=24.4.0,<24.5"
jupyterlab-myst = ">=2.4.2,<3"
tempita = ">=0.6.0,<0.7"
vega_datasets = ">=0.9.0,<0.10"
+interegular = ">=0.3.3,<0.4"
+altair = ">=5.5.0,<6"
+rich = ">=14.1.0,<15"
+comm = ">=0.2.3,<0.3"
[package]
name = "jupyterlab_dyno"
@@ -30,9 +33,10 @@ hatch-jupyter-builder = ">=0.5.0"
nodejs = ">=24.4.0,<24.5"
jupyterlab = ">=4.0.0,<5"
+
[package.run-dependencies]
+dyno = { path = "/home/pablo/Econforge/dyno.py"}
#dyno = ">=0.1.5.dev7"
-#dyno = { path = "/home/pablo/Econforge/dyno.py" }
-dyno = ">=0.1.6"
+#dyno = ">=0.1.6"
xeus-python = ">=0.17.4,<0.18"
nlohmann_json = "==3.12"
diff --git a/src/index.ts b/src/index.ts
index ccc55d4..8d34cf1 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -12,6 +12,8 @@ import { IWidgetTracker, WidgetTracker } from '@jupyterlab/apputils';
import { IRenderMimeRegistry } from '@jupyterlab/rendermime';
+import { IEditorLanguageRegistry } from '@jupyterlab/codemirror';
+
import { Token } from '@lumino/coreutils';
import { SessionContext } from '@jupyterlab/apputils';
@@ -32,6 +34,8 @@ import {
ILayoutRestorer
} from '@jupyterlab/application';
+import { dyno, mod } from './languages/dyno-language';
+
// Default settings, see schema/plugin.json for more details
let global_setting = {};
let preserveScrollPosition = true;
@@ -203,6 +207,7 @@ export class DynareWidget
const start = performance.now();
console.log(global_setting);
+
// Choose kernel code based on file type
const code = `import warnings
import json
@@ -222,6 +227,8 @@ dsge_report(txt=txt, filename=filename, **options)`;
// const prevOutputs = this._safeToJSON(this.content.model);
+ // Register comm handler after we're sure the kernel is ready (just before execution)
+ this._setupHighlightingComm();
OutputArea.execute(code, tempArea, this._sessionContext)
.then((msg: KernelMessage.IExecuteReplyMsg | undefined) => {
@@ -237,6 +244,11 @@ dsge_report(txt=txt, filename=filename, **options)`;
// }
if (nextOutputs) {
this._applyOutputsToVisibleModel(nextOutputs);
+
+ // Note: highlighting is now handled via comm, not from outputs
+ // Keep the fallback for backward compatibility
+ console.log('[DEBUG] About to call _performHighlightingBasedOnResults with outputs:', nextOutputs);
+ this._performHighlightingBasedOnResults(nextOutputs);
}
// Restore scroll position after DOM/content updates
@@ -293,6 +305,170 @@ dsge_report(txt=txt, filename=filename, **options)`;
});
}
+ /**
+ * Set up Jupyter Comm for receiving highlighting data from the kernel
+ */
+ private _setupHighlightingComm(): void {
+ try {
+ if (!this._sessionContext?.session?.kernel) {
+ console.warn('[DEBUG] No kernel available for comm setup');
+ return;
+ }
+
+ const kernel = this._sessionContext.session.kernel;
+ const commTargetName = 'jupyterlab-dyno-highlighting';
+
+ console.log('[DEBUG] Setting up comm with kernel:', kernel.id);
+ console.log('[DEBUG] Kernel status:', kernel.status);
+
+ // Check if kernel is ready
+ if (kernel.status !== 'idle' && kernel.status !== 'busy') {
+ console.warn('[DEBUG] Kernel not ready for comm setup, status:', kernel.status);
+ // Retry after a delay
+ setTimeout(() => {
+ console.log('[DEBUG] Retrying comm setup...');
+ this._setupHighlightingComm();
+ }, 1000);
+ return;
+ }
+
+ // Clean up any existing comm targets first
+ try {
+ // Note: removeCommTarget may not exist or may have different signature
+ // This is just for cleanup, so we can ignore errors
+ if (typeof (kernel as any).removeCommTarget === 'function') {
+ (kernel as any).removeCommTarget(commTargetName, () => {});
+ console.log('[DEBUG] Cleaned up existing comm target');
+ }
+ } catch (e) {
+ console.log('[DEBUG] Comm cleanup ignored (expected):', e);
+ }
+
+ // Register the comm target with defensive error handling
+ try {
+ kernel.registerCommTarget(commTargetName, (comm, msg) => {
+ try {
+ console.log('[DEBUG] ===== COMM MESSAGE RECEIVED =====');
+ console.log('[DEBUG] Comm object:', comm);
+ console.log('[DEBUG] Message:', msg);
+ console.log('[DEBUG] Message content:', msg.content);
+ console.log('[DEBUG] Message data:', msg.content.data);
+ console.log('[DEBUG] ===================================');
+
+ this._handleHighlightingData(msg.content.data);
+
+ // Set up message handler for future messages on this comm
+ comm.onMsg = (msg) => {
+ try {
+ console.log('[DEBUG] ===== SUBSEQUENT COMM MESSAGE =====');
+ console.log('[DEBUG] Received comm message:', msg.content.data);
+ console.log('[DEBUG] ====================================');
+ this._handleHighlightingData(msg.content.data);
+ } catch (handlerError) {
+ console.error('[DEBUG] Error in comm message handler:', handlerError);
+ }
+ };
+
+ // Handle comm close
+ comm.onClose = (msg) => {
+ try {
+ console.log('[DEBUG] Comm closed:', msg);
+ } catch (closeError) {
+ console.error('[DEBUG] Error in comm close handler:', closeError);
+ }
+ };
+ } catch (commError) {
+ console.error('[DEBUG] Error in comm target handler:', commError);
+ }
+ });
+
+ console.log('[DEBUG] Comm target registered successfully:', commTargetName);
+ console.log('[DEBUG] Kernel comm targets:', (kernel as any)._commTargets || 'not accessible');
+ } catch (registerError) {
+ console.error('[DEBUG] Failed to register comm target:', registerError);
+ }
+ } catch (setupError) {
+ console.error('[DEBUG] Error in _setupHighlightingComm:', setupError);
+ }
+ }
+
+ /**
+ * Handle highlighting data received from the kernel via comm
+ */
+ private _handleHighlightingData(data: any): void {
+ try {
+ console.log('[DEBUG] _handleHighlightingData called');
+
+ if (!data) {
+ console.warn('[DEBUG] No highlighting data received');
+ return;
+ }
+
+ console.log('[DEBUG] Processing highlighting data:', data);
+
+ // Extract highlighting information with safe fallbacks
+ const lines = data.lines;
+ const type = data.type || 'default';
+ const message = data.message || '';
+
+ if (!lines) {
+ console.warn('[DEBUG] No lines property in data:', data);
+ return;
+ }
+
+ if (!Array.isArray(lines)) {
+ console.warn('[DEBUG] Lines is not an array:', lines);
+ return;
+ }
+
+ if (lines.length === 0) {
+ console.log('[DEBUG] No lines to highlight');
+ return;
+ }
+
+ console.log('[DEBUG] Highlighting lines:', lines, 'with type:', type);
+
+ // Get the appropriate CSS class for the highlight type
+ const className = this._getHighlightClassName(type);
+ console.log('[DEBUG] Using CSS class:', className);
+
+ // Add a small delay to ensure editor is ready
+ setTimeout(() => {
+ try {
+ console.log('[DEBUG] Calling highlightLines...');
+ this.highlightLines(lines, className);
+
+ if (message) {
+ console.log('[DEBUG] Highlighting message:', message);
+ }
+ console.log('[DEBUG] Highlighting completed successfully');
+ } catch (highlightError) {
+ console.error('[DEBUG] Error in highlightLines:', highlightError);
+ }
+ }, 100);
+ } catch (error) {
+ console.error('[DEBUG] Error handling highlighting data:', error);
+ }
+ }
+
+ /**
+ * Get the appropriate CSS class name for a highlight type
+ */
+ private _getHighlightClassName(type: string): string {
+ switch (type.toLowerCase()) {
+ case 'error':
+ return 'jp-dyno-error-line';
+ case 'warning':
+ return 'jp-dyno-warning-line';
+ case 'success':
+ return 'jp-dyno-success-line';
+ case 'info':
+ return 'jp-dyno-highlighted-line';
+ default:
+ return 'jp-dyno-highlighted-line';
+ }
+ }
+
/**
* Safely extract nbformat outputs as JSON from a model, if available.
*/
@@ -369,8 +545,798 @@ dsge_report(txt=txt, filename=filename, **options)`;
}
}
+ /**
+ * Highlight specific lines in the associated editor
+ * @param lineNumbers Array of line numbers to highlight (1-based)
+ * @param className CSS class name for the highlight decoration
+ */
+ highlightLines(lineNumbers: number[], className: string = 'jp-dyno-highlighted-line'): void {
+ console.log(`[DEBUG] highlightLines called with lines:`, lineNumbers, `className:`, className);
+
+ if (!this._editorWidget || !this._editorWidget.content || !this._editorWidget.content.editor) {
+ console.warn('[DEBUG] Editor not available for highlighting');
+ return;
+ }
+
+ const editor = this._editorWidget.content.editor;
+
+ // Clear existing highlights first
+ this.clearHighlights();
+
+ // Store the highlighting info for later reference
+ if (!this._persistentHighlights) {
+ this._persistentHighlights = new Map();
+ }
+
+ try {
+ // For JupyterLab 4.x with CodeMirror 6, we need to use a different approach
+ // Try to get the CodeMirror editor view
+ const editorView = (editor as any).editor;
+
+ if (editorView && editorView.state && editorView.dispatch) {
+ console.log('[DEBUG] Using CodeMirror 6 style highlighting');
+
+ // Create line-level decorations using CodeMirror 6 API
+ const decorations: any[] = [];
+
+ lineNumbers.forEach(lineNum => {
+ this._persistentHighlights.set(lineNum, className);
+
+ // Convert to 0-based line number
+ const lineIndex = lineNum - 1;
+
+ if (lineIndex >= 0 && lineIndex < editorView.state.doc.lines) {
+ const line = editorView.state.doc.line(lineIndex + 1); // CodeMirror lines are 1-based
+
+ // Create a line decoration
+ const decoration = {
+ from: line.from,
+ to: line.to,
+ class: className
+ };
+
+ decorations.push(decoration);
+ console.log(`[DEBUG] Created decoration for line ${lineNum}: ${line.from}-${line.to}`);
+ }
+ });
+
+ // Store decorations for later cleanup
+ this._highlightMarks = decorations;
+
+ // Apply decorations using CSS styling approach since CodeMirror 6 decorations
+ // are complex to add dynamically. Instead, we'll add CSS classes to line elements.
+ this._applyCSSLineHighlights(lineNumbers, className);
+
+ } else {
+ console.log('[DEBUG] Fallback: Trying CSS-based highlighting');
+ this._applyCSSLineHighlights(lineNumbers, className);
+ }
+ } catch (error) {
+ console.error('[DEBUG] Error in highlightLines:', error);
+ // Fallback to CSS-based highlighting
+ this._applyCSSLineHighlights(lineNumbers, className);
+ }
+
+ console.log(`[DEBUG] Stored ${lineNumbers.length} highlights for lines: ${lineNumbers}`);
+ }
+
+ /**
+ * Apply highlighting without clearing existing highlights first
+ * Used when applying multiple highlight types from MIME data
+ * @param lineNumbers Array of line numbers to highlight (1-based)
+ * @param className CSS class name for the highlight decoration
+ */
+ private _applyHighlightingWithoutClear(lineNumbers: number[], className: string): void {
+ console.log(`[DEBUG] _applyHighlightingWithoutClear called with lines:`, lineNumbers, `className:`, className);
+
+ if (!this._editorWidget || !this._editorWidget.content || !this._editorWidget.content.editor) {
+ console.warn('[DEBUG] Editor not available for highlighting');
+ return;
+ }
+
+ const editor = this._editorWidget.content.editor;
+
+ // Store the highlighting info for later reference
+ if (!this._persistentHighlights) {
+ this._persistentHighlights = new Map();
+ }
+
+ try {
+ // For JupyterLab 4.x with CodeMirror 6, we need to use a different approach
+ // Try to get the CodeMirror editor view
+ const editorView = (editor as any).editor;
+
+ if (editorView && editorView.state && editorView.dispatch) {
+ console.log('[DEBUG] Using CodeMirror 6 style highlighting');
+
+ // Create line-level decorations using CodeMirror 6 API
+ const decorations: any[] = [];
+
+ lineNumbers.forEach(lineNum => {
+ this._persistentHighlights.set(lineNum, className);
+
+ // Convert to 0-based line number
+ const lineIndex = lineNum - 1;
+
+ if (lineIndex >= 0 && lineIndex < editorView.state.doc.lines) {
+ const line = editorView.state.doc.line(lineIndex + 1); // CodeMirror lines are 1-based
+
+ // Create a line decoration
+ const decoration = {
+ from: line.from,
+ to: line.to,
+ class: className
+ };
+
+ decorations.push(decoration);
+ console.log(`[DEBUG] Created decoration for line ${lineNum}: ${line.from}-${line.to}`);
+ }
+ });
+
+ // Store decorations for later cleanup
+ this._highlightMarks.push(...decorations);
+
+ // Apply decorations using CSS styling approach since CodeMirror 6 decorations
+ // are complex to add dynamically. Instead, we'll add CSS classes to line elements.
+ this._applyCSSLineHighlights(lineNumbers, className);
+
+ } else {
+ console.log('[DEBUG] Fallback: Trying CSS-based highlighting');
+ this._applyCSSLineHighlights(lineNumbers, className);
+ }
+ } catch (error) {
+ console.error('[DEBUG] Error in _applyHighlightingWithoutClear:', error);
+ // Fallback to CSS-based highlighting
+ this._applyCSSLineHighlights(lineNumbers, className);
+ }
+
+ console.log(`[DEBUG] Applied ${lineNumbers.length} highlights for lines: ${lineNumbers}`);
+ }
+
+ /**
+ * Apply CSS-based line highlighting as a fallback method
+ */
+ private _applyCSSLineHighlights(lineNumbers: number[], className: string): void {
+ try {
+ const editor = this._editorWidget?.content?.editor;
+ if (!editor) {
+ console.warn('[DEBUG] No editor available for CSS highlighting');
+ return;
+ }
+
+ // Get the editor's DOM element using multiple possible paths
+ let editorElement = null;
+
+ // Try different ways to get the editor element
+ if ((editor as any).host) {
+ editorElement = (editor as any).host;
+ } else if (this._editorWidget.content && (this._editorWidget.content as any).node) {
+ editorElement = (this._editorWidget.content as any).node;
+ } else if (this._editorWidget.node) {
+ editorElement = this._editorWidget.node;
+ }
+
+ if (editorElement) {
+ console.log('[DEBUG] Found editor element, looking for line elements...');
+
+ // Look for different types of line elements that might exist
+ const possibleSelectors = [
+ '.cm-line', // CodeMirror 6
+ '.CodeMirror-line', // CodeMirror 5
+ '.cm-activeLine', // CodeMirror active line
+ '[role="textbox"] > div', // Generic approach
+ '.cm-content > div' // CodeMirror 6 content
+ ];
+
+ let lineElements: NodeListOf | null = null;
+ let usedSelector = '';
+
+ for (const selector of possibleSelectors) {
+ const elements = editorElement.querySelectorAll(selector);
+ if (elements.length > 0) {
+ lineElements = elements;
+ usedSelector = selector;
+ console.log(`[DEBUG] Found ${elements.length} line elements using selector "${selector}"`);
+ break;
+ }
+ }
+
+ if (lineElements && lineElements.length > 0) {
+ console.log(`[DEBUG] Using ${lineElements.length} line elements from selector "${usedSelector}"`);
+
+ lineNumbers.forEach(lineNum => {
+ const lineIndex = lineNum - 1; // Convert to 0-based
+
+ if (lineIndex >= 0 && lineIndex < lineElements.length) {
+ const lineElement = lineElements[lineIndex];
+ if (lineElement) {
+ lineElement.classList.add(className);
+ this._highlightMarks.push({
+ element: lineElement,
+ className: className,
+ lineNumber: lineNum
+ });
+ console.log(`[DEBUG] Applied CSS class ${className} to line ${lineNum} using selector "${usedSelector}"`);
+ }
+ } else {
+ console.warn(`[DEBUG] Line ${lineNum} is out of bounds (max: ${lineElements.length})`);
+ }
+ });
+ } else {
+ console.warn('[DEBUG] Could not find any line elements in editor DOM');
+ console.log('[DEBUG] Editor element structure:', editorElement.innerHTML.substring(0, 500));
+
+ // As a last resort, try to add highlighting by observing the editor
+ this._attemptDelayedHighlighting(lineNumbers, className);
+ }
+ } else {
+ console.warn('[DEBUG] Could not find editor DOM element');
+ this._attemptDelayedHighlighting(lineNumbers, className);
+ }
+ } catch (error) {
+ console.error('[DEBUG] Error in CSS highlighting:', error);
+ }
+ }
+
+ /**
+ * Attempt delayed highlighting as a last resort
+ */
+ private _attemptDelayedHighlighting(lineNumbers: number[], className: string): void {
+ console.log('[DEBUG] Attempting delayed highlighting...');
+
+ let retryCount = 0;
+ const maxRetries = 10;
+
+ const retryHighlighting = () => {
+ retryCount++;
+
+ if (retryCount > maxRetries) {
+ console.warn('[DEBUG] Max retries reached for delayed highlighting');
+ return;
+ }
+
+ console.log(`[DEBUG] Retry ${retryCount}: Looking for line elements...`);
+
+ try {
+ const editor = this._editorWidget?.content?.editor;
+ if (!editor) {
+ setTimeout(retryHighlighting, 500);
+ return;
+ }
+
+ const editorElement = (editor as any).host || (this._editorWidget.content as any).node || this._editorWidget.node;
+ if (!editorElement) {
+ setTimeout(retryHighlighting, 500);
+ return;
+ }
+
+ const lineElements = editorElement.querySelectorAll('.cm-line, .CodeMirror-line');
+ if (lineElements.length === 0) {
+ setTimeout(retryHighlighting, 500);
+ return;
+ }
+
+ console.log(`[DEBUG] Retry ${retryCount}: Found ${lineElements.length} line elements`);
+
+ // Apply highlighting
+ lineNumbers.forEach(lineNum => {
+ const lineIndex = lineNum - 1;
+
+ if (lineIndex >= 0 && lineIndex < lineElements.length) {
+ const lineElement = lineElements[lineIndex];
+ if (lineElement) {
+ lineElement.classList.add(className);
+ this._highlightMarks.push({
+ element: lineElement,
+ className: className,
+ lineNumber: lineNum
+ });
+ console.log(`[DEBUG] Delayed highlighting applied to line ${lineNum}`);
+ }
+ }
+ });
+
+ } catch (error) {
+ console.error(`[DEBUG] Error in retry ${retryCount}:`, error);
+ setTimeout(retryHighlighting, 500);
+ }
+ };
+
+ // Start the retry process
+ setTimeout(retryHighlighting, 500);
+ }
+
+ /**
+ * Clear all line highlights
+ */
+ clearHighlights(): void {
+ console.log('[DEBUG] Clearing highlights...');
+
+ // Clear stored highlight data
+ if (this._persistentHighlights) {
+ this._persistentHighlights.clear();
+ }
+
+ // Clear highlight marks
+ if (this._highlightMarks && this._highlightMarks.length > 0) {
+ this._highlightMarks.forEach(mark => {
+ try {
+ if (mark && typeof mark.clear === 'function') {
+ // CodeMirror style line class handle
+ mark.clear();
+ } else if (mark && mark.element && mark.className) {
+ // CSS-based highlighting - remove the class
+ mark.element.classList.remove(mark.className);
+ console.log(`[DEBUG] Removed CSS class ${mark.className} from line ${mark.lineNumber}`);
+ }
+ } catch (error) {
+ console.warn('[DEBUG] Error clearing highlight mark:', error);
+ }
+ });
+ this._highlightMarks = [];
+ }
+
+ // Additional cleanup: remove all our highlight classes from the editor DOM
+ const editor = this._editorWidget?.content?.editor;
+ if (editor) {
+ const editorElement = (editor as any).host || (this._editorWidget.content as any).node;
+
+ if (editorElement) {
+ const highlightClasses = [
+ 'jp-dyno-highlighted-line',
+ 'jp-dyno-error-line',
+ 'jp-dyno-warning-line',
+ 'jp-dyno-success-line'
+ ];
+
+ // Remove highlight classes from all line elements
+ highlightClasses.forEach(className => {
+ const highlightedElements = editorElement.querySelectorAll(`.${className}`);
+ highlightedElements.forEach((element: Element) => {
+ element.classList.remove(className);
+ });
+ });
+
+ console.log('[DEBUG] Cleaned up CSS classes from editor DOM');
+ }
+ }
+
+ console.log('[DEBUG] Cleared all highlights');
+ }
+
+ /**
+ * Set the reference to the associated editor widget
+ */
+ setEditorWidget(editorWidget: any): void {
+ console.log('[DEBUG] setEditorWidget called with:', editorWidget);
+ this._editorWidget = editorWidget;
+
+ // Set the correct MIME type for the editor immediately
+ this._setEditorMimeType();
+
+ // Wait for the editor to be fully loaded
+ this._waitForEditorReady().then(() => {
+ console.log('[DEBUG] Editor is ready for highlighting');
+
+ // Apply syntax highlighting
+ this._applySyntaxHighlighting();
+
+ // Don't automatically test highlighting - let it be triggered by actual data
+ }).catch(error => {
+ console.warn('[DEBUG] Error waiting for editor ready:', error);
+ });
+ }
+
+ /**
+ * Force set the language mode via JupyterLab's language registry
+ */
+ private _forceLanguageMode(filePath: string): void {
+ console.log('[DEBUG] Forcing language mode for:', filePath);
+
+ try {
+ const editor = this._editorWidget.content.editor;
+ let languageName = '';
+
+ if (filePath.endsWith('.dyno') || filePath.endsWith('.π¦') || filePath.endsWith('.dyno.yaml')) {
+ languageName = 'dyno';
+ } else if (filePath.endsWith('.mod') || filePath.endsWith('.dynare.mod')) {
+ languageName = 'mod';
+ }
+
+ if (languageName) {
+ // Try to get the editor's language support and force set it
+ const editorView = (editor as any).editor;
+ if (editorView && editorView.state) {
+ console.log('[DEBUG] Attempting to force language mode:', languageName);
+
+ // Check if the language is already applied
+ const currentLang = editorView.state.facet ? 'has facets' : 'no facets';
+ console.log('[DEBUG] Current editor language state:', currentLang);
+
+ // Try to get language from global registry
+ if ((window as any).jupyterlab) {
+ const app = (window as any).jupyterlab;
+ if (app.serviceManager && app.serviceManager.language) {
+ console.log('[DEBUG] Found language service, attempting to set language');
+ // This would be the ideal way but may not be available
+ }
+ }
+ }
+ }
+ } catch (error) {
+ console.warn('[DEBUG] Failed to force language mode:', error);
+ }
+ }
+
+ /**
+ * Set the correct MIME type for the editor based on file extension
+ */
+ private _setEditorMimeType(): void {
+ if (!this._editorWidget || !this._editorWidget.content || !this._editorWidget.content.editor) {
+ return;
+ }
+
+ const filePath = this._editorWidget.context?.path || '';
+ let mimeType = '';
+
+ console.log('[DEBUG] Setting MIME type for file:', filePath);
+
+ if (filePath.endsWith('.dyno') || filePath.endsWith('.π¦') || filePath.endsWith('.dyno.yaml')) {
+ mimeType = 'text/x-dyno';
+ } else if (filePath.endsWith('.mod') || filePath.endsWith('.dynare.mod')) {
+ mimeType = 'text/x-mod';
+ }
+
+ if (mimeType) {
+ try {
+ const editor = this._editorWidget.content.editor;
+ console.log('[DEBUG] Setting editor MIME type to:', mimeType);
+
+ // For JupyterLab 4.x, try to set the mode directly
+ if ((editor as any).setOption) {
+ (editor as any).setOption('mode', mimeType);
+ } else if ((editor as any).model && (editor as any).model.mimeType) {
+ (editor as any).model.mimeType = mimeType;
+ }
+
+ // Also try to set it via the document model
+ if (this._editorWidget.context && this._editorWidget.context.model) {
+ (this._editorWidget.context.model as any).mimeType = mimeType;
+ }
+
+ console.log('[DEBUG] Editor MIME type set successfully');
+ } catch (error) {
+ console.warn('[DEBUG] Failed to set editor MIME type:', error);
+ }
+ }
+ }
+
+ /**
+ * Apply syntax highlighting to the editor
+ */
+ private _applySyntaxHighlighting(): void {
+ if (!this._editorWidget || !this._editorWidget.content || !this._editorWidget.content.editor) {
+ console.warn('[DEBUG] No editor available for syntax highlighting');
+ return;
+ }
+
+ try {
+ const editor = this._editorWidget.content.editor;
+ const filePath = this._editorWidget.context?.path || '';
+
+ console.log('[DEBUG] Applying syntax highlighting for file:', filePath);
+
+ // First, try to force set the language via JupyterLab's language registry
+ this._forceLanguageMode(filePath);
+
+ // Determine which language mode to use based on file extension
+ let languageMode = null;
+ if (filePath.endsWith('.dyno') || filePath.endsWith('.π¦') || filePath.endsWith('.dyno.yaml')) {
+ languageMode = dyno();
+ console.log('[DEBUG] Using DYNO language mode');
+ } else if (filePath.endsWith('.mod') || filePath.endsWith('.dynare.mod')) {
+ languageMode = mod();
+ console.log('[DEBUG] Using MOD language mode');
+ }
+
+ if (languageMode) {
+ // Try multiple approaches to apply the language mode
+ const editorView = (editor as any).editor;
+ console.log('[DEBUG] Editor view:', editorView);
+
+ if (editorView && editorView.state && editorView.dispatch) {
+ console.log('[DEBUG] Attempting to apply language mode via CodeMirror 6 API');
+
+ try {
+ // Approach 1: Try direct language reconfiguration
+ import('@codemirror/state').then(({ Compartment, StateEffect }) => {
+ console.log('[DEBUG] Loaded CodeMirror state module');
+
+ if (!this._languageCompartment) {
+ this._languageCompartment = new Compartment();
+
+ // Apply initial configuration
+ const transaction = editorView.state.update({
+ effects: this._languageCompartment.reconfigure(languageMode)
+ });
+ editorView.dispatch(transaction);
+ console.log('[DEBUG] Language mode applied with new compartment');
+ } else {
+ // Reconfigure existing
+ const transaction = editorView.state.update({
+ effects: this._languageCompartment.reconfigure(languageMode)
+ });
+ editorView.dispatch(transaction);
+ console.log('[DEBUG] Language mode reconfigured');
+ }
+ }).catch(error => {
+ console.error('[DEBUG] Error with Compartment approach:', error);
+
+ // Approach 2: Try extension approach
+ try {
+ const newExtensions = [languageMode];
+ const transaction = editorView.state.update({
+ effects: { reconfigure: newExtensions }
+ });
+ editorView.dispatch(transaction);
+ console.log('[DEBUG] Language mode applied via extension reconfiguration');
+ } catch (extError) {
+ console.error('[DEBUG] Extension approach failed:', extError);
+
+ // Approach 3: Try replacing the entire configuration
+ this._tryAdvancedLanguageApplication(editorView, languageMode, filePath);
+ }
+ });
+ } catch (mainError) {
+ console.error('[DEBUG] Main language application failed:', mainError);
+ this._tryAdvancedLanguageApplication(editorView, languageMode, filePath);
+ }
+ } else {
+ console.warn('[DEBUG] Could not access CodeMirror editor view');
+ this._trySimpleSyntaxHighlighting(filePath);
+ }
+ } else {
+ console.log('[DEBUG] No language mode needed for file:', filePath);
+ }
+ } catch (error) {
+ console.error('[DEBUG] Error applying syntax highlighting:', error);
+ }
+ }
+
+ /**
+ * Try advanced language application techniques
+ */
+ private _tryAdvancedLanguageApplication(editorView: any, languageMode: any, filePath: string): void {
+ console.log('[DEBUG] Trying advanced language application');
+
+ try {
+ // Try getting the current document and creating a new state
+ const currentDoc = editorView.state.doc;
+
+ import('@codemirror/state').then(({ EditorState }) => {
+ const newState = EditorState.create({
+ doc: currentDoc,
+ extensions: [languageMode]
+ });
+
+ // Replace the entire state
+ editorView.setState(newState);
+ console.log('[DEBUG] Applied language mode by replacing editor state');
+ }).catch(error => {
+ console.error('[DEBUG] Advanced application failed:', error);
+ this._trySimpleSyntaxHighlighting(filePath);
+ });
+ } catch (error) {
+ console.error('[DEBUG] Advanced language application error:', error);
+ this._trySimpleSyntaxHighlighting(filePath);
+ }
+ }
+
+ /**
+ * Fallback to simple CSS-based syntax highlighting
+ */
+ private _trySimpleSyntaxHighlighting(filePath: string): void {
+ console.log('[DEBUG] Falling back to simple syntax highlighting for:', filePath);
+
+ setTimeout(() => {
+ try {
+ const editorElement = this._editorWidget?.content?.node;
+ if (editorElement) {
+ const lines = editorElement.querySelectorAll('.cm-line, .CodeMirror-line');
+ console.log(`[DEBUG] Found ${lines.length} lines for CSS highlighting`);
+
+ // Apply simple regex-based highlighting
+ lines.forEach((line: Element, index: number) => {
+ const htmlLine = line as HTMLElement;
+ let content = htmlLine.textContent || '';
+
+ if (content.trim()) {
+ // Apply basic highlighting patterns
+ if (filePath.endsWith('.dyno') || filePath.endsWith('.π¦') || filePath.endsWith('.dyno.yaml')) {
+ content = this._applyDynoHighlighting(content);
+ } else if (filePath.endsWith('.mod') || filePath.endsWith('.dynare.mod')) {
+ content = this._applyModHighlighting(content);
+ }
+
+ if (content !== htmlLine.textContent) {
+ htmlLine.innerHTML = content;
+ console.log(`[DEBUG] Applied CSS highlighting to line ${index + 1}`);
+ }
+ }
+ });
+ }
+ } catch (error) {
+ console.error('[DEBUG] Simple syntax highlighting failed:', error);
+ }
+ }, 500);
+ }
+
+ /**
+ * Apply DYNO-specific highlighting patterns
+ */
+ private _applyDynoHighlighting(content: string): string {
+ return content
+ .replace(/\b(var|varexo|parameters|model|steady_state_model|shocks|end)\b/g, '$1')
+ .replace(/\b(log|exp|sin|cos|tan|sqrt|abs|max|min)\b/g, '$1')
+ .replace(/#.*$/gm, '')
+ .replace(/\b\d*\.?\d+([eE][+-]?\d+)?\b/g, '$&')
+ .replace(/<-/g, '$&');
+ }
+
+ /**
+ * Apply MOD-specific highlighting patterns
+ */
+ private _applyModHighlighting(content: string): string {
+ return content
+ .replace(/\b(var|varexo|parameters|model|end|initval|steady|stoch_simul)\b/g, '$1')
+ .replace(/\b(log|exp|sin|cos|tan|sqrt|abs|max|min)\b/g, '$1')
+ .replace(/\/\/.*$/gm, '')
+ .replace(/\/\*[\s\S]*?\*\//g, '')
+ .replace(/\b\d*\.?\d+([eE][+-]?\d+)?\b/g, '$&')
+ .replace(/=/g, '$&');
+ }
+
+ /**
+ * Test highlighting functionality - can be called manually for debugging
+ */
+ testHighlighting(): void {
+ console.log('[DEBUG] === TESTING HIGHLIGHTING ===');
+
+ try {
+ // Test different highlight styles
+ console.log('[DEBUG] Testing default highlighting on lines 1-2');
+ this.highlightLines([1, 2], 'jp-dyno-highlighted-line');
+
+ // Test with a delay for error highlighting
+ setTimeout(() => {
+ console.log('[DEBUG] Testing error highlighting on line 3');
+ this.highlightLines([3], 'jp-dyno-error-line');
+ }, 2000);
+
+ // Test with another delay for warning highlighting
+ setTimeout(() => {
+ console.log('[DEBUG] Testing warning highlighting on line 4');
+ this.highlightLines([4], 'jp-dyno-warning-line');
+ }, 4000);
+
+ } catch (error) {
+ console.error('[DEBUG] Error in testHighlighting:', error);
+ }
+ }
+
+ /**
+ * Wait for the editor to be fully ready
+ */
+ private async _waitForEditorReady(): Promise {
+ return new Promise((resolve, reject) => {
+ const checkEditor = () => {
+ if (this._editorWidget &&
+ this._editorWidget.content &&
+ this._editorWidget.content.editor &&
+ this._editorWidget.content.editor.host) {
+
+ const editorElement = this._editorWidget.content.editor.host;
+ const lineElements = editorElement.querySelectorAll('.cm-line, .CodeMirror-line');
+
+ if (lineElements.length > 0) {
+ console.log('[DEBUG] Editor is ready with', lineElements.length, 'lines');
+ resolve();
+ return;
+ }
+ }
+
+ // If not ready, check again after a short delay
+ setTimeout(checkEditor, 100);
+ };
+
+ checkEditor();
+
+ // Timeout after 10 seconds
+ setTimeout(() => {
+ reject(new Error('Editor ready timeout'));
+ }, 10000);
+ });
+ }
+
+ /**
+ * Perform highlighting based on rendering results
+ * First checks for custom MIME type data, then falls back to content analysis
+ */
+ private _performHighlightingBasedOnResults(outputs: any[]): void {
+ console.log('[DEBUG] _performHighlightingBasedOnResults called with outputs:', outputs);
+ console.log('[DEBUG] Outputs count:', outputs.length);
+
+ // First, check for our custom MIME type in the outputs
+ for (let i = 0; i < outputs.length; i++) {
+ const output = outputs[i];
+ console.log(`[DEBUG] Output ${i}:`, output);
+ console.log(`[DEBUG] Output ${i} type:`, output.output_type);
+
+ if (output.output_type === 'display_data' && output.data) {
+ console.log(`[DEBUG] Output ${i} data keys:`, Object.keys(output.data));
+
+ // Check for our custom MIME type
+ const mimeType = 'application/vnd.jupyterlab-dyno.highlighting+json';
+
+ if (mimeType in output.data) {
+ const highlightData = output.data[mimeType];
+ console.log('[DEBUG] *** FOUND HIGHLIGHTING MIME DATA ***:', highlightData);
+
+ // Handle array of highlight objects (new format)
+ if (Array.isArray(highlightData)) {
+ console.log('[DEBUG] *** PROCESSING ARRAY OF HIGHLIGHT OBJECTS ***');
+
+ // Clear existing highlights first
+ this.clearHighlights();
+
+ // Group lines by type for efficient highlighting
+ const linesByType = new Map();
+
+ highlightData.forEach(item => {
+ if (item.line && item.type) {
+ const type = item.type;
+ if (!linesByType.has(type)) {
+ linesByType.set(type, []);
+ }
+ linesByType.get(type)!.push(item.line);
+ console.log(`[DEBUG] Added line ${item.line} with type ${type}, message: ${item.message || 'none'}`);
+ }
+ });
+
+ // Apply highlighting for each type with increasing delays to avoid clearing each other
+ let delay = 200;
+ linesByType.forEach((lines, type) => {
+ const className = this._getHighlightClassName(type);
+ console.log(`[DEBUG] *** APPLYING HIGHLIGHTING ***: type=${type}, lines=${lines}, className=${className}`);
+
+ // Apply highlighting with a delay to ensure DOM is ready
+ // Use a separate delay for each type and don't call clearHighlights in highlightLines
+ setTimeout(() => {
+ this._applyHighlightingWithoutClear(lines, className);
+ }, delay);
+ delay += 50; // Stagger the highlighting calls
+ });
+
+ return; // Found and applied highlighting, exit early
+ }
+ }
+ }
+ }
+
+ console.log('[DEBUG] No MIME highlighting data found. No fallback highlighting will be applied.');
+ console.log('[DEBUG] Highlighting check completed - only MIME type highlighting is active.');
+ }
+
+
+
// Dispose of resources held by the widget
dispose(): void {
+ // Clear any line highlights
+ this.clearHighlights();
+
+ // Clean up comm targets
+ this._cleanupComm();
+
// Disconnect activity monitor first
if (this._monitor) {
this._monitor.dispose();
@@ -411,6 +1377,28 @@ dsge_report(txt=txt, filename=filename, **options)`;
null;
private _rendermime: IRenderMimeRegistry;
private _isFirstRender = true;
+ /**
+ * Clean up comm targets when disposing
+ */
+ private _cleanupComm(): void {
+ if (this._sessionContext?.session?.kernel) {
+ try {
+ // Note: removeCommTarget may not exist or may have different signature
+ const kernel = this._sessionContext.session.kernel;
+ if (typeof (kernel as any).removeCommTarget === 'function') {
+ (kernel as any).removeCommTarget('jupyterlab-dyno-highlighting', () => {});
+ }
+ console.log('[DEBUG] Comm target cleaned up');
+ } catch (e) {
+ // Ignore if target doesn't exist or method signature is different
+ }
+ }
+ }
+
+ private _editorWidget: any = null; // Reference to the associated editor widget
+ private _highlightMarks: any[] = []; // Store highlight marks for cleanup
+ private _persistentHighlights: Map = new Map(); // Store persistent highlight info
+ private _languageCompartment: any = null; // CodeMirror language compartment
}
/**
@@ -465,18 +1453,61 @@ const FACTORY = 'Dyno extension';
/**
* Initialization data for the jupyterlab-dyno extension.
*/
-const plugin: JupyterFrontEndPlugin = {
+const plugin: JupyterFrontEndPlugin> = {
id: PLUGIN_ID,
description: 'A JupyterLab extension for solving DSGE models',
autoStart: true,
- requires: [ILayoutRestorer, IRenderMimeRegistry, ISettingRegistry],
+ provides: IDynareTracker,
+ requires: [ILayoutRestorer, IRenderMimeRegistry, ISettingRegistry, IEditorLanguageRegistry],
+ optional: [],
activate: (
app: JupyterFrontEnd,
restorer: ILayoutRestorer,
rendermime: IRenderMimeRegistry,
- settings: ISettingRegistry
- ) => {
+ settings: ISettingRegistry,
+ editorLanguages: IEditorLanguageRegistry
+ ): IWidgetTracker => {
console.log('JupyterLab extension jupyterlab-dyno is activated!');
+
+ // Register syntax highlighting for our custom languages with JupyterLab's editor system
+ console.log('Registering DYNO and MOD language modes with editor language registry...');
+
+ try {
+ // Register DYNO language mode
+ editorLanguages.addLanguage({
+ name: 'dyno',
+ mime: 'text/x-dyno',
+ load: async () => {
+ console.log('[DEBUG] Loading DYNO language mode');
+ return dyno();
+ }
+ });
+
+ // Register MOD language mode
+ editorLanguages.addLanguage({
+ name: 'mod',
+ mime: 'text/x-mod',
+ load: async () => {
+ console.log('[DEBUG] Loading MOD language mode');
+ return mod();
+ }
+ });
+
+ // Also register for the existing MIME type used by the extension
+ editorLanguages.addLanguage({
+ name: 'dyno-alt',
+ mime: 'text/mod', // This is your existing MIME type
+ load: async () => {
+ console.log('[DEBUG] Loading DYNO language mode for text/mod MIME type');
+ return dyno();
+ }
+ });
+
+ console.log('Language modes registered successfully');
+ } catch (error) {
+ console.error('Error registering language modes:', error);
+ }
+
const { commands, shell } = app;
// Tracker
const namespace = 'jupyterlab-dyno';
@@ -512,6 +1543,10 @@ const plugin: JupyterFrontEndPlugin = {
// Add widget to tracker when created
widgetFactory.widgetCreated.connect(async (sender, widget) => {
+ // Make the widget globally accessible for debugging
+ (window as any).currentDynoWidget = widget;
+ console.log('[DEBUG] Widget is now accessible as window.currentDynoWidget');
+
// Notify instance tracker if restore data needs to be updated
widget.context.pathChanged.connect(() => {
tracker.save(widget);
@@ -537,6 +1572,9 @@ const plugin: JupyterFrontEndPlugin = {
splitDone = true;
leftEditorRefId = editor.id;
rightViewerRefId = widget.id;
+
+ // Store editor reference in the widget for highlighting
+ widget.setEditorWidget(editor);
} else {
if (rightViewerRefId) {
shell.add(widget, 'main', {
@@ -545,11 +1583,14 @@ const plugin: JupyterFrontEndPlugin = {
});
}
if (leftEditorRefId) {
- await commands.execute('docmanager:open', {
+ const editor = await commands.execute('docmanager:open', {
path: widget.context.path,
factory: 'Editor',
options: { mode: 'tab-after', ref: leftEditorRefId }
});
+
+ // Store editor reference in the widget for highlighting
+ widget.setEditorWidget(editor);
}
}
@@ -562,7 +1603,10 @@ const plugin: JupyterFrontEndPlugin = {
global_setting = setting.composite as any;
preserveScrollPosition = (setting.get('preserve-scroll-position')
.composite as boolean) ?? true;
- console.log(global_setting);
+ console.log('Settings loaded:', {
+ preserveScrollPosition,
+ global_setting
+ });
}
/**
@@ -580,14 +1624,14 @@ const plugin: JupyterFrontEndPlugin = {
// Register widget and model factories
app.docRegistry.addWidgetFactory(widgetFactory);
- // Register file type
+ // Register file types with proper MIME types for syntax highlighting
app.docRegistry.addFileType({
name: 'mod',
displayName: 'Mod',
extensions: ['.mod', '.dynare.mod'],
fileFormat: 'text',
contentType: 'file',
- mimeTypes: [MIME_TYPE]
+ mimeTypes: ['text/x-mod', MIME_TYPE]
});
app.docRegistry.addFileType({
name: 'dyno',
@@ -595,7 +1639,7 @@ const plugin: JupyterFrontEndPlugin = {
extensions: ['.dyno', '.π¦'],
fileFormat: 'text',
contentType: 'file',
- mimeTypes: [MIME_TYPE]
+ mimeTypes: ['text/x-dyno', MIME_TYPE]
});
app.docRegistry.addFileType({
name: 'dynoYAML',
@@ -603,8 +1647,10 @@ const plugin: JupyterFrontEndPlugin = {
extensions: ['.dyno.yaml'],
fileFormat: 'text',
contentType: 'file',
- mimeTypes: [MIME_TYPE]
+ mimeTypes: ['text/x-dyno', MIME_TYPE]
});
+
+ return tracker;
}
};
diff --git a/src/languages/dyno-language.ts b/src/languages/dyno-language.ts
new file mode 100644
index 0000000..3936a8c
--- /dev/null
+++ b/src/languages/dyno-language.ts
@@ -0,0 +1,190 @@
+import { LanguageSupport, StreamLanguage } from '@codemirror/language';
+
+// Mode definition for DYNO syntax highlighting
+export const dynoMode = {
+ name: 'dyno',
+ startState: () => ({ inComment: false }),
+ token: (stream: any) => {
+ // Comments starting with #
+ if (stream.match(/^#.*/)) {
+ return 'comment';
+ }
+
+ // Section headers (comments that define sections)
+ if (stream.match(/^#\s*(parameters|equations|steady state|shocks)/i)) {
+ return 'meta';
+ }
+
+ // Keywords for model blocks
+ if (stream.match(/\b(var|varexo|parameters|model|steady_state_model|shocks|end)\b/)) {
+ return 'keyword';
+ }
+
+ // Mathematical functions
+ if (stream.match(/\b(log|exp|sin|cos|tan|sqrt|abs|max|min)\b/)) {
+ return 'builtin';
+ }
+
+ // Parameter assignment arrow
+ if (stream.match(/<-/)) {
+ return 'operator';
+ }
+
+ // Numbers (integers, decimals, scientific notation)
+ if (stream.match(/\b\d*\.?\d+([eE][+-]?\d+)?\b/)) {
+ return 'number';
+ }
+
+ // Time subscripts content (t, t+1, t-1, ~, 1, 2, etc.) - match the content inside brackets
+ if (stream.match(/\b([t~]([+\-]\d+)?|\d+)\b/)) {
+ return 'time-subscript';
+ }
+
+ // Opening and closing brackets (will inherit variable color when following variables)
+ if (stream.match(/[\[\]]/)) {
+ return 'bracket';
+ }
+
+ // Common economic variables (can be customized)
+ if (stream.match(/\b(c|k|y|n|r|w|i|a|beta|delta|alpha|rho|khi|eta|nss|epsilon|leta)\b/)) {
+ return 'variable';
+ }
+
+ // Distribution notation for shocks N(0, sigma)
+ if (stream.match(/\bN\(/)) {
+ return 'builtin';
+ }
+
+ // Operators and punctuation
+ if (stream.match(/[+\-*/=<>^()[\]{}]/)) {
+ return 'operator';
+ }
+
+ // Skip whitespace
+ if (stream.match(/\s+/)) {
+ return null;
+ }
+
+ // Identifiers (variables not in the common list)
+ if (stream.match(/[a-zA-Z_]\w*/)) {
+ return 'variable-2';
+ }
+
+ // Skip any unrecognized character
+ stream.next();
+ return null;
+ },
+
+ languageData: {
+ commentTokens: { line: '#' },
+ indentOnInput: /^\s*end\s*$/,
+ closeBrackets: { brackets: ['(', '[', '{', '"', "'"] }
+ }
+};
+
+// Mode definition for MOD files (Dynare syntax)
+export const modMode = {
+ name: 'mod',
+ startState: () => ({ inComment: false, inBlock: null }),
+ token: (stream: any, state: any) => {
+ // Block comments /* ... */
+ if (state.inComment) {
+ if (stream.match(/.*?\*\//)) {
+ state.inComment = false;
+ return 'comment';
+ }
+ stream.skipToEnd();
+ return 'comment';
+ }
+
+ if (stream.match(/\/\*/)) {
+ state.inComment = true;
+ return 'comment';
+ }
+
+ // Line comments //
+ if (stream.match(/\/\/.*/)) {
+ return 'comment';
+ }
+
+ // Dynare block keywords
+ if (stream.match(/\b(var|varexo|varendo|parameters|model|initval|endval|steady_state_model|shocks|estimated_params|end)\b/)) {
+ const word = stream.current();
+ if (word === 'model' || word === 'steady_state_model' || word === 'shocks') {
+ state.inBlock = word;
+ } else if (word === 'end') {
+ state.inBlock = null;
+ }
+ return 'keyword';
+ }
+
+ // Mathematical functions
+ if (stream.match(/\b(log|exp|sin|cos|tan|sqrt|abs|max|min|steady_state|normcdf|normpdf)\b/)) {
+ return 'builtin';
+ }
+
+ // Numbers
+ if (stream.match(/\b\d*\.?\d+([eE][+-]?\d+)?\b/)) {
+ return 'number';
+ }
+
+ // Time subscripts for MOD files: (+1), (-1) or [t], [t+1], etc.
+ if (stream.match(/\([+\-]\d+\)/)) {
+ return 'time-subscript';
+ }
+
+ // Time subscripts content for bracket notation (t, t+1, t-1, ~, 1, 2, etc.)
+ if (stream.match(/\b([t~]([+\-]\d+)?|\d+)\b/)) {
+ return 'time-subscript';
+ }
+
+ // Opening and closing brackets
+ if (stream.match(/[\[\]]/)) {
+ return 'bracket';
+ }
+
+ // Assignment and comparison operators
+ if (stream.match(/[=<>]=?|<-/)) {
+ return 'operator';
+ }
+
+ // Arithmetic operators
+ if (stream.match(/[+\-*/^]/)) {
+ return 'operator';
+ }
+
+ // Punctuation
+ if (stream.match(/[()[\]{},.;]/)) {
+ return 'punctuation';
+ }
+
+ // Variables
+ if (stream.match(/[a-zA-Z_]\w*/)) {
+ return 'variable';
+ }
+
+ // Skip whitespace
+ if (stream.match(/\s+/)) {
+ return null;
+ }
+
+ // Skip any unrecognized character
+ stream.next();
+ return null;
+ },
+
+ languageData: {
+ commentTokens: { line: '//', block: { open: '/*', close: '*/' } },
+ indentOnInput: /^\s*end\s*$/,
+ closeBrackets: { brackets: ['(', '[', '{', '"', "'"] }
+ }
+};
+
+// Create language supports
+export function dyno(): LanguageSupport {
+ return new LanguageSupport(StreamLanguage.define(dynoMode));
+}
+
+export function mod(): LanguageSupport {
+ return new LanguageSupport(StreamLanguage.define(modMode));
+}
\ No newline at end of file
diff --git a/src/languages/index.ts b/src/languages/index.ts
new file mode 100644
index 0000000..086390c
--- /dev/null
+++ b/src/languages/index.ts
@@ -0,0 +1,34 @@
+import { IEditorLanguageRegistry } from '@jupyterlab/codemirror';
+import { dyno, mod } from './dyno-language';
+
+/**
+ * Register the custom language modes with JupyterLab's editor system
+ */
+export function registerLanguages(editorLanguages: IEditorLanguageRegistry): void {
+ // Register DYNO language mode
+ editorLanguages.addLanguage({
+ name: 'dyno',
+ mime: 'text/x-dyno',
+ load: async () => {
+ return dyno();
+ }
+ });
+
+ // Register MOD language mode
+ editorLanguages.addLanguage({
+ name: 'mod',
+ mime: 'text/x-mod',
+ load: async () => {
+ return mod();
+ }
+ });
+
+ // Also register for the existing MIME type
+ editorLanguages.addLanguage({
+ name: 'dyno-alt',
+ mime: 'text/mod', // This is your existing MIME type
+ load: async () => {
+ return dyno();
+ }
+ });
+}
\ No newline at end of file
diff --git a/style/base.css b/style/base.css
index 278a8f6..2d1f508 100644
--- a/style/base.css
+++ b/style/base.css
@@ -48,8 +48,201 @@
text-align: center;
}
+/* Line highlighting styles */
+.jp-dyno-highlighted-line {
+ background-color: rgba(255, 235, 59, 0.3) !important; /* Light yellow highlight */
+ border-left: 3px solid #ffc107 !important; /* Golden left border */
+ transition: background-color 0.2s ease-in-out;
+}
+
+.jp-dyno-highlighted-line:hover {
+ background-color: rgba(255, 235, 59, 0.4) !important; /* Slightly more opaque on hover */
+}
+
+/* Alternative highlight styles for different types of highlighting */
+.jp-dyno-error-line {
+ background-color: rgba(244, 67, 54, 0.1) !important; /* Light red for errors */
+ border-left: 3px solid #f44336 !important;
+}
+
+.jp-dyno-warning-line {
+ background-color: rgba(255, 152, 0, 0.1) !important; /* Light orange for warnings */
+ border-left: 3px solid #ff9800 !important;
+}
+
+.jp-dyno-success-line {
+ background-color: rgba(76, 175, 80, 0.1) !important; /* Light green for success */
+ border-left: 3px solid #4caf50 !important;
+}
+
+/* Ensure highlighting works with CodeMirror 6 line elements */
+.cm-line.jp-dyno-highlighted-line,
+.CodeMirror-line.jp-dyno-highlighted-line {
+ background-color: rgba(255, 235, 59, 0.3) !important;
+ border-left: 3px solid #ffc107 !important;
+}
+
+.cm-line.jp-dyno-error-line,
+.CodeMirror-line.jp-dyno-error-line {
+ background-color: rgba(244, 67, 54, 0.1) !important;
+ border-left: 3px solid #f44336 !important;
+}
+
+.cm-line.jp-dyno-warning-line,
+.CodeMirror-line.jp-dyno-warning-line {
+ background-color: rgba(255, 152, 0, 0.1) !important;
+ border-left: 3px solid #ff9800 !important;
+}
+
+.cm-line.jp-dyno-success-line,
+.CodeMirror-line.jp-dyno-success-line {
+ background-color: rgba(76, 175, 80, 0.1) !important;
+ border-left: 3px solid #4caf50 !important;
+}
+
+/* Ensure highlighting persists during selection and focus */
+.cm-focused .cm-line.jp-dyno-highlighted-line,
+.CodeMirror-focused .CodeMirror-line.jp-dyno-highlighted-line {
+ background-color: rgba(255, 235, 59, 0.3) !important;
+ border-left: 3px solid #ffc107 !important;
+}
+
+.cm-focused .cm-line.jp-dyno-error-line,
+.CodeMirror-focused .CodeMirror-line.jp-dyno-error-line {
+ background-color: rgba(244, 67, 54, 0.1) !important;
+ border-left: 3px solid #f44336 !important;
+}
+
+.cm-focused .cm-line.jp-dyno-warning-line,
+.CodeMirror-focused .CodeMirror-line.jp-dyno-warning-line {
+ background-color: rgba(255, 152, 0, 0.1) !important;
+ border-left: 3px solid #ff9800 !important;
+}
+
+.cm-focused .cm-line.jp-dyno-success-line,
+.CodeMirror-focused .CodeMirror-line.jp-dyno-success-line {
+ background-color: rgba(76, 175, 80, 0.1) !important;
+ border-left: 3px solid #4caf50 !important;
+}
+
/* Make sure the widget container is positioned relative for absolute positioning */
.jupyterlab-dyno {
position: relative;
min-height: 200px;
}
+
+/* Syntax highlighting styles for DYNO and MOD languages */
+
+/* Comments */
+.cm-editor .cm-line .cm-comment {
+ color: #6a9955;
+ font-style: italic;
+}
+
+/* Keywords (var, model, end, etc.) */
+.cm-editor .cm-line .cm-keyword {
+ color: #569cd6;
+ font-weight: bold;
+}
+
+/* Built-in functions (log, exp, etc.) */
+.cm-editor .cm-line .cm-builtin {
+ color: #4ec9b0;
+ font-weight: 500;
+}
+
+/* Numbers */
+.cm-editor .cm-line .cm-number {
+ color: #b5cea8;
+}
+
+/* Variables */
+.cm-editor .cm-line .cm-variable {
+ color: #9cdcfe;
+}
+
+/* Secondary variables (user-defined) */
+.cm-editor .cm-line .cm-variable-2 {
+ color: #dcdcaa;
+}
+
+/* Operators */
+.cm-editor .cm-line .cm-operator {
+ color: #d4d4d4;
+}
+
+/* Special atoms (time subscripts [t], [t+1], etc.) */
+.cm-editor .cm-line .cm-atom {
+ color: #ffd700;
+ font-weight: bold;
+}
+
+/* Time subscripts (t, t+1, t-1, ~, (+1), (-1)) */
+.cm-editor .cm-line .cm-time-subscript {
+ color: #ff6b6b;
+ font-weight: bold;
+}
+
+/* Brackets (inherit variable color) */
+.cm-editor .cm-line .cm-bracket {
+ color: #9cdcfe;
+ font-weight: normal;
+}
+
+/* Meta (section headers) */
+.cm-editor .cm-line .cm-meta {
+ color: #c586c0;
+ font-weight: bold;
+}
+
+/* Punctuation */
+.cm-editor .cm-line .cm-punctuation {
+ color: #cccccc;
+}
+
+/* Light theme syntax highlighting */
+[data-jp-theme-light] .cm-editor .cm-line .cm-comment {
+ color: #008000;
+}
+
+[data-jp-theme-light] .cm-editor .cm-line .cm-keyword {
+ color: #0000ff;
+}
+
+[data-jp-theme-light] .cm-editor .cm-line .cm-builtin {
+ color: #795e26;
+}
+
+[data-jp-theme-light] .cm-editor .cm-line .cm-number {
+ color: #098658;
+}
+
+[data-jp-theme-light] .cm-editor .cm-line .cm-variable {
+ color: #001080;
+}
+
+[data-jp-theme-light] .cm-editor .cm-line .cm-variable-2 {
+ color: #795e26;
+}
+
+[data-jp-theme-light] .cm-editor .cm-line .cm-operator {
+ color: #000000;
+}
+
+[data-jp-theme-light] .cm-editor .cm-line .cm-atom {
+ color: #0451a5;
+}
+
+[data-jp-theme-light] .cm-editor .cm-line .cm-time-subscript {
+ color: #d63384;
+ font-weight: bold;
+}
+
+[data-jp-theme-light] .cm-editor .cm-line .cm-bracket {
+ color: #001080;
+ font-weight: normal;
+}
+
+[data-jp-theme-light] .cm-editor .cm-line .cm-meta {
+ color: #800080;
+}
diff --git a/test.mod b/test.mod
index 571a257..ff079fa 100644
--- a/test.mod
+++ b/test.mod
@@ -2,7 +2,7 @@ var y, c, k, a, h, b;
varexo e, u;
parameters beta, rho, alpha, delta, theta, psi, tau;
-
+
alpha = 0.36;
rho = 0.95;
tau = 0.025;
diff --git a/tsconfig.json b/tsconfig.json
index 25af040..aab1342 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -21,5 +21,5 @@
"target": "ES2018",
"types": ["jest"]
},
- "include": ["src/*"]
+ "include": ["src/**/*"]
}
diff --git a/yarn.lock b/yarn.lock
index 77b8e22..2d95ed0 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1521,7 +1521,7 @@ __metadata:
languageName: node
linkType: hard
-"@codemirror/state@npm:^6.0.0, @codemirror/state@npm:^6.4.0, @codemirror/state@npm:^6.5.0, @codemirror/state@npm:^6.5.2":
+"@codemirror/state@npm:^6.0.0, @codemirror/state@npm:^6.2.0, @codemirror/state@npm:^6.4.0, @codemirror/state@npm:^6.5.0, @codemirror/state@npm:^6.5.2":
version: 6.5.2
resolution: "@codemirror/state@npm:6.5.2"
dependencies:
@@ -2078,6 +2078,35 @@ __metadata:
languageName: node
linkType: hard
+"@jupyterlab/apputils@npm:^4.5.9":
+ version: 4.5.9
+ resolution: "@jupyterlab/apputils@npm:4.5.9"
+ dependencies:
+ "@jupyterlab/coreutils": ^6.4.9
+ "@jupyterlab/observables": ^5.4.9
+ "@jupyterlab/rendermime-interfaces": ^3.12.9
+ "@jupyterlab/services": ^7.4.9
+ "@jupyterlab/settingregistry": ^4.4.9
+ "@jupyterlab/statedb": ^4.4.9
+ "@jupyterlab/statusbar": ^4.4.9
+ "@jupyterlab/translation": ^4.4.9
+ "@jupyterlab/ui-components": ^4.4.9
+ "@lumino/algorithm": ^2.0.3
+ "@lumino/commands": ^2.3.2
+ "@lumino/coreutils": ^2.2.1
+ "@lumino/disposable": ^2.1.4
+ "@lumino/domutils": ^2.0.3
+ "@lumino/messaging": ^2.0.3
+ "@lumino/signaling": ^2.1.4
+ "@lumino/virtualdom": ^2.0.3
+ "@lumino/widgets": ^2.7.1
+ "@types/react": ^18.0.26
+ react: ^18.2.0
+ sanitize-html: ~2.12.1
+ checksum: 19c75e607ca9c5422cb0128d8c4c279d7c75d3d9681c9d45112e0291323279034550f19754a203ed0c09c3dc51b3eb16ee2c0c29be1777dddcf499ef4e6d4b5f
+ languageName: node
+ linkType: hard
+
"@jupyterlab/attachments@npm:^4.4.7":
version: 4.4.7
resolution: "@jupyterlab/attachments@npm:4.4.7"
@@ -2193,6 +2222,72 @@ __metadata:
languageName: node
linkType: hard
+"@jupyterlab/codeeditor@npm:^4.4.9":
+ version: 4.4.9
+ resolution: "@jupyterlab/codeeditor@npm:4.4.9"
+ dependencies:
+ "@codemirror/state": ^6.5.2
+ "@jupyter/ydoc": ^3.1.0
+ "@jupyterlab/apputils": ^4.5.9
+ "@jupyterlab/coreutils": ^6.4.9
+ "@jupyterlab/nbformat": ^4.4.9
+ "@jupyterlab/observables": ^5.4.9
+ "@jupyterlab/statusbar": ^4.4.9
+ "@jupyterlab/translation": ^4.4.9
+ "@jupyterlab/ui-components": ^4.4.9
+ "@lumino/coreutils": ^2.2.1
+ "@lumino/disposable": ^2.1.4
+ "@lumino/dragdrop": ^2.1.6
+ "@lumino/messaging": ^2.0.3
+ "@lumino/signaling": ^2.1.4
+ "@lumino/widgets": ^2.7.1
+ react: ^18.2.0
+ checksum: 1e1e374a3fadf12c30b6239b20d19c00e704403c5ac1dc70f9a168f460bf67610525b4f3c4da606ada17eff5940fe28cf022415d6bd3aa1714751e00a0eddfe4
+ languageName: node
+ linkType: hard
+
+"@jupyterlab/codemirror@npm:^4.4.5":
+ version: 4.4.9
+ resolution: "@jupyterlab/codemirror@npm:4.4.9"
+ dependencies:
+ "@codemirror/autocomplete": ^6.18.6
+ "@codemirror/commands": ^6.8.1
+ "@codemirror/lang-cpp": ^6.0.2
+ "@codemirror/lang-css": ^6.3.1
+ "@codemirror/lang-html": ^6.4.9
+ "@codemirror/lang-java": ^6.0.1
+ "@codemirror/lang-javascript": ^6.2.3
+ "@codemirror/lang-json": ^6.0.1
+ "@codemirror/lang-markdown": ^6.3.2
+ "@codemirror/lang-php": ^6.0.1
+ "@codemirror/lang-python": ^6.2.0
+ "@codemirror/lang-rust": ^6.0.1
+ "@codemirror/lang-sql": ^6.8.0
+ "@codemirror/lang-wast": ^6.0.2
+ "@codemirror/lang-xml": ^6.1.0
+ "@codemirror/language": ^6.11.0
+ "@codemirror/legacy-modes": ^6.5.1
+ "@codemirror/search": ^6.5.10
+ "@codemirror/state": ^6.5.2
+ "@codemirror/view": ^6.38.1
+ "@jupyter/ydoc": ^3.1.0
+ "@jupyterlab/codeeditor": ^4.4.9
+ "@jupyterlab/coreutils": ^6.4.9
+ "@jupyterlab/documentsearch": ^4.4.9
+ "@jupyterlab/nbformat": ^4.4.9
+ "@jupyterlab/translation": ^4.4.9
+ "@lezer/common": ^1.2.1
+ "@lezer/generator": ^1.7.0
+ "@lezer/highlight": ^1.2.0
+ "@lezer/markdown": ^1.3.0
+ "@lumino/coreutils": ^2.2.1
+ "@lumino/disposable": ^2.1.4
+ "@lumino/signaling": ^2.1.4
+ yjs: ^13.5.40
+ checksum: 68cc6f265c990e33b2fd4122ca28cc7fc5b039d8a829a7513415ac7245ce9a9ff0183515e48b1bac0085507bddfd5666e45ae8fbfef6de90347a421d4341e4a4
+ languageName: node
+ linkType: hard
+
"@jupyterlab/codemirror@npm:^4.4.7":
version: 4.4.7
resolution: "@jupyterlab/codemirror@npm:4.4.7"
@@ -2249,6 +2344,20 @@ __metadata:
languageName: node
linkType: hard
+"@jupyterlab/coreutils@npm:^6.4.9":
+ version: 6.4.9
+ resolution: "@jupyterlab/coreutils@npm:6.4.9"
+ dependencies:
+ "@lumino/coreutils": ^2.2.1
+ "@lumino/disposable": ^2.1.4
+ "@lumino/signaling": ^2.1.4
+ minimist: ~1.2.0
+ path-browserify: ^1.0.0
+ url-parse: ~1.5.4
+ checksum: 50c92dca8750c3a6bbe16c3a8af150db786636f15b0a0eba1e1f5ed2c0ae8ce06884cc7a580991c9d5f141000616c0fc5aa537e70974b0e19ad981a5cf21886b
+ languageName: node
+ linkType: hard
+
"@jupyterlab/docmanager@npm:^4.4.7":
version: 4.4.7
resolution: "@jupyterlab/docmanager@npm:4.4.7"
@@ -2319,6 +2428,25 @@ __metadata:
languageName: node
linkType: hard
+"@jupyterlab/documentsearch@npm:^4.4.9":
+ version: 4.4.9
+ resolution: "@jupyterlab/documentsearch@npm:4.4.9"
+ dependencies:
+ "@jupyterlab/apputils": ^4.5.9
+ "@jupyterlab/translation": ^4.4.9
+ "@jupyterlab/ui-components": ^4.4.9
+ "@lumino/commands": ^2.3.2
+ "@lumino/coreutils": ^2.2.1
+ "@lumino/disposable": ^2.1.4
+ "@lumino/messaging": ^2.0.3
+ "@lumino/polling": ^2.1.4
+ "@lumino/signaling": ^2.1.4
+ "@lumino/widgets": ^2.7.1
+ react: ^18.2.0
+ checksum: a2a8e5016300cd3c88dbd931a148a5394d0f20ab638b26dd43eb131a72b14d820fe2f955dc9f7afd01383ce0d8b4cb8cd1e1642e298c9f8044b7e2e54124b937
+ languageName: node
+ linkType: hard
+
"@jupyterlab/filebrowser@npm:^4.4.7":
version: 4.4.7
resolution: "@jupyterlab/filebrowser@npm:4.4.7"
@@ -2380,6 +2508,15 @@ __metadata:
languageName: node
linkType: hard
+"@jupyterlab/nbformat@npm:^4.4.9":
+ version: 4.4.9
+ resolution: "@jupyterlab/nbformat@npm:4.4.9"
+ dependencies:
+ "@lumino/coreutils": ^2.2.1
+ checksum: 59c73ac19ebd8d121e85916af91fc2b42e71f24d52bb7b1ac3efe58965d279edd8050934bc1079d7986c1fc061aae007e741e6889ea9a4e2f58f56b8e9c42e83
+ languageName: node
+ linkType: hard
+
"@jupyterlab/notebook@npm:^4.4.7":
version: 4.4.7
resolution: "@jupyterlab/notebook@npm:4.4.7"
@@ -2431,6 +2568,19 @@ __metadata:
languageName: node
linkType: hard
+"@jupyterlab/observables@npm:^5.4.9":
+ version: 5.4.9
+ resolution: "@jupyterlab/observables@npm:5.4.9"
+ dependencies:
+ "@lumino/algorithm": ^2.0.3
+ "@lumino/coreutils": ^2.2.1
+ "@lumino/disposable": ^2.1.4
+ "@lumino/messaging": ^2.0.3
+ "@lumino/signaling": ^2.1.4
+ checksum: ce7705d469bb1d1358c15c8797cb89cb4a5f22171c17f503cfab72f19e6c73ebeae627d8b26b0e75b68a7b749c463357ea32ee8fdb9689608d03da68d501e88d
+ languageName: node
+ linkType: hard
+
"@jupyterlab/outputarea@npm:^4.4.7":
version: 4.4.7
resolution: "@jupyterlab/outputarea@npm:4.4.7"
@@ -2463,6 +2613,16 @@ __metadata:
languageName: node
linkType: hard
+"@jupyterlab/rendermime-interfaces@npm:^3.12.9":
+ version: 3.12.9
+ resolution: "@jupyterlab/rendermime-interfaces@npm:3.12.9"
+ dependencies:
+ "@lumino/coreutils": ^1.11.0 || ^2.2.1
+ "@lumino/widgets": ^1.37.2 || ^2.7.1
+ checksum: c0db30ed6ea584d59d397857bb61ef36a15b166bbdaf80eafdf1a731c5a95589663ed7c3a7de698397b16348251b22e23dc90399a41d19d4993fba98964d4dea
+ languageName: node
+ linkType: hard
+
"@jupyterlab/rendermime@npm:^4.4.7":
version: 4.4.7
resolution: "@jupyterlab/rendermime@npm:4.4.7"
@@ -2502,6 +2662,25 @@ __metadata:
languageName: node
linkType: hard
+"@jupyterlab/services@npm:^7.4.9":
+ version: 7.4.9
+ resolution: "@jupyterlab/services@npm:7.4.9"
+ dependencies:
+ "@jupyter/ydoc": ^3.1.0
+ "@jupyterlab/coreutils": ^6.4.9
+ "@jupyterlab/nbformat": ^4.4.9
+ "@jupyterlab/settingregistry": ^4.4.9
+ "@jupyterlab/statedb": ^4.4.9
+ "@lumino/coreutils": ^2.2.1
+ "@lumino/disposable": ^2.1.4
+ "@lumino/polling": ^2.1.4
+ "@lumino/properties": ^2.0.3
+ "@lumino/signaling": ^2.1.4
+ ws: ^8.11.0
+ checksum: b1af994a2b752ed0ea60e5a53b85da3bb8a1d702407029a2ea747877a36aed142bc1d605bdef8e8f2002dc3d1ed516c2d77945dc9906cfcb58b957b9b2f6de22
+ languageName: node
+ linkType: hard
+
"@jupyterlab/settingregistry@npm:^4.4.5, @jupyterlab/settingregistry@npm:^4.4.7":
version: 4.4.7
resolution: "@jupyterlab/settingregistry@npm:4.4.7"
@@ -2521,6 +2700,25 @@ __metadata:
languageName: node
linkType: hard
+"@jupyterlab/settingregistry@npm:^4.4.9":
+ version: 4.4.9
+ resolution: "@jupyterlab/settingregistry@npm:4.4.9"
+ dependencies:
+ "@jupyterlab/nbformat": ^4.4.9
+ "@jupyterlab/statedb": ^4.4.9
+ "@lumino/commands": ^2.3.2
+ "@lumino/coreutils": ^2.2.1
+ "@lumino/disposable": ^2.1.4
+ "@lumino/signaling": ^2.1.4
+ "@rjsf/utils": ^5.13.4
+ ajv: ^8.12.0
+ json5: ^2.2.3
+ peerDependencies:
+ react: ">=16"
+ checksum: f1937b8ba0486d2ebd1a7c5573c8b1cdf42aaacdfd644f1697e30c3c6d36c66faf6218908102287571d095b4e4c5d647feb1364290213c9d3f9a3ff4c74f3c73
+ languageName: node
+ linkType: hard
+
"@jupyterlab/statedb@npm:^4.4.7":
version: 4.4.7
resolution: "@jupyterlab/statedb@npm:4.4.7"
@@ -2534,6 +2732,19 @@ __metadata:
languageName: node
linkType: hard
+"@jupyterlab/statedb@npm:^4.4.9":
+ version: 4.4.9
+ resolution: "@jupyterlab/statedb@npm:4.4.9"
+ dependencies:
+ "@lumino/commands": ^2.3.2
+ "@lumino/coreutils": ^2.2.1
+ "@lumino/disposable": ^2.1.4
+ "@lumino/properties": ^2.0.3
+ "@lumino/signaling": ^2.1.4
+ checksum: ec53df2570c03f3ba7e40fb0a30eb2da441c196d6261a7f347529e211b71775fa90e9174d8d3f473a0af6bc1a4e269f3edceffe5755f7f0f0557a7a645ace8be
+ languageName: node
+ linkType: hard
+
"@jupyterlab/statusbar@npm:^4.4.7":
version: 4.4.7
resolution: "@jupyterlab/statusbar@npm:4.4.7"
@@ -2550,6 +2761,22 @@ __metadata:
languageName: node
linkType: hard
+"@jupyterlab/statusbar@npm:^4.4.9":
+ version: 4.4.9
+ resolution: "@jupyterlab/statusbar@npm:4.4.9"
+ dependencies:
+ "@jupyterlab/ui-components": ^4.4.9
+ "@lumino/algorithm": ^2.0.3
+ "@lumino/coreutils": ^2.2.1
+ "@lumino/disposable": ^2.1.4
+ "@lumino/messaging": ^2.0.3
+ "@lumino/signaling": ^2.1.4
+ "@lumino/widgets": ^2.7.1
+ react: ^18.2.0
+ checksum: c74382d378990e34323ad046d79985da7885af154d6bdaaad1c8e12175058978c9b2698956bad32a9592d6d543968567af1cd1eb7412d594e8ee3279675617fc
+ languageName: node
+ linkType: hard
+
"@jupyterlab/testing@npm:^4.4.7":
version: 4.4.7
resolution: "@jupyterlab/testing@npm:4.4.7"
@@ -2622,6 +2849,19 @@ __metadata:
languageName: node
linkType: hard
+"@jupyterlab/translation@npm:^4.4.9":
+ version: 4.4.9
+ resolution: "@jupyterlab/translation@npm:4.4.9"
+ dependencies:
+ "@jupyterlab/coreutils": ^6.4.9
+ "@jupyterlab/rendermime-interfaces": ^3.12.9
+ "@jupyterlab/services": ^7.4.9
+ "@jupyterlab/statedb": ^4.4.9
+ "@lumino/coreutils": ^2.2.1
+ checksum: 9747def9f9d6d0cf4400e615ac837ccc759e0a43adc87a97e4fa91220215bfd5ce88f3af777f9bbc9fe07f950fb85714c7ff555f2df02dc8aa30a2dcda71e3c1
+ languageName: node
+ linkType: hard
+
"@jupyterlab/ui-components@npm:^4.4.7":
version: 4.4.7
resolution: "@jupyterlab/ui-components@npm:4.4.7"
@@ -2653,6 +2893,37 @@ __metadata:
languageName: node
linkType: hard
+"@jupyterlab/ui-components@npm:^4.4.9":
+ version: 4.4.9
+ resolution: "@jupyterlab/ui-components@npm:4.4.9"
+ dependencies:
+ "@jupyter/react-components": ^0.16.6
+ "@jupyter/web-components": ^0.16.6
+ "@jupyterlab/coreutils": ^6.4.9
+ "@jupyterlab/observables": ^5.4.9
+ "@jupyterlab/rendermime-interfaces": ^3.12.9
+ "@jupyterlab/translation": ^4.4.9
+ "@lumino/algorithm": ^2.0.3
+ "@lumino/commands": ^2.3.2
+ "@lumino/coreutils": ^2.2.1
+ "@lumino/disposable": ^2.1.4
+ "@lumino/messaging": ^2.0.3
+ "@lumino/polling": ^2.1.4
+ "@lumino/properties": ^2.0.3
+ "@lumino/signaling": ^2.1.4
+ "@lumino/virtualdom": ^2.0.3
+ "@lumino/widgets": ^2.7.1
+ "@rjsf/core": ^5.13.4
+ "@rjsf/utils": ^5.13.4
+ react: ^18.2.0
+ react-dom: ^18.2.0
+ typestyle: ^2.0.4
+ peerDependencies:
+ react: ^18.2.0
+ checksum: 84c3e71b27a4a8031963c1e0f27b2409b781a1bc2ade569fa08e05a1263172ef7cd2664fe8e670ce3f704e2bec7a56fd21ecff1b6616062d34ddd632f049d606
+ languageName: node
+ linkType: hard
+
"@lezer/common@npm:^1.0.0, @lezer/common@npm:^1.0.2, @lezer/common@npm:^1.1.0, @lezer/common@npm:^1.2.0, @lezer/common@npm:^1.2.1":
version: 1.2.3
resolution: "@lezer/common@npm:1.2.3"
@@ -6794,10 +7065,14 @@ __metadata:
version: 0.0.0-use.local
resolution: "jupyterlab-dyno@workspace:."
dependencies:
+ "@codemirror/language": ^6.0.0
+ "@codemirror/state": ^6.2.0
"@jupyterlab/application": ^4.4.5
"@jupyterlab/builder": ^4.4.5
+ "@jupyterlab/codemirror": ^4.4.5
"@jupyterlab/settingregistry": ^4.4.5
"@jupyterlab/testutils": ^4.4.5
+ "@lezer/highlight": ^1.0.0
"@types/jest": ^29.5.14
"@types/json-schema": ^7.0.15
"@types/react": ^18.3.23