From 4d25e17f65784f1fe55d77a4a29c450a1bc1aeee Mon Sep 17 00:00:00 2001 From: Mark Qvist Date: Mon, 4 May 2026 01:18:37 +0200 Subject: [PATCH] Added table rendering to micron --- nomadnet/ui/textui/Guide.py | 24 ++++++++++++ nomadnet/ui/textui/MicronParser.py | 59 ++++++++++++++++++++++++++++++ setup.py | 2 +- 3 files changed, 84 insertions(+), 1 deletion(-) diff --git a/nomadnet/ui/textui/Guide.py b/nomadnet/ui/textui/Guide.py index ddb2cb3..03becdd 100644 --- a/nomadnet/ui/textui/Guide.py +++ b/nomadnet/ui/textui/Guide.py @@ -1302,6 +1302,30 @@ Here is `F00f`_`[a more visible link`72914442a3689add83a09a767963f57c:/page/inde When links like these are displayed in the built-in browser, clicking on them or activating them using the keyboard will cause the browser to load the specified URL. +>Tables + +You can include rendered tables by enclosing them in \\`t tags. Optionally, you can also specify alignment and max rendering width by adding these properties to the opening \\`t tag, like \\`tc30. Here's an example: + +`Faaa +`= +`t +| Name | Price | Qty | +| ---- | :---: | --: | +| `F3a3Apple`f | Free | `!5`! | +| Orange | Ask, nicely | 3 | +`t +`= +`` + +The above markup produces the following table: + +`t +| Name | Price | Qty | +| ---- | :---: | --: | +| `F3a3Apple`f | Free | `!5`! | +| Orange | Ask, nicely | 3 | +`t + >Fields & Requests Nomad Network let's you use simple input fields for submitting data to node-side applications. Submitted data, along with other session variables will be available to the node-side script / program as environment variables. diff --git a/nomadnet/ui/textui/MicronParser.py b/nomadnet/ui/textui/MicronParser.py index 6327cb8..75fa13b 100644 --- a/nomadnet/ui/textui/MicronParser.py +++ b/nomadnet/ui/textui/MicronParser.py @@ -5,6 +5,7 @@ import time import RNS from urwid.util import is_mouse_press from urwid.text_layout import calc_coords +from RNS.Utilities.rngit.util import MarkdownToMicron DEFAULT_FG_DARK = "ddd" DEFAULT_FG_LIGHT = "222" @@ -31,12 +32,17 @@ SYNTH_SPECS = {} SECTION_INDENT = 2 INDENT_RIGHT = 1 +MAX_TABLE_WIDTH = 100 def default_state(fg=None, bg=None): if fg == None: fg = SELECTED_STYLES["plain"]["fg"] if bg == None: bg = DEFAULT_BG state = { "literal": False, + "table_mode": False, + "table_buffer": [], + "table_align": None, + "table_maxwidth": MAX_TABLE_WIDTH, "depth": 0, "fg_color": fg, "bg_color": bg, @@ -134,6 +140,29 @@ def parse_partial(line): except Exception as e: return None +def render_table(lines, state, url_delegate): + if len(lines) < 2: return None + if state["table_maxwidth"]: max_width = state["table_maxwidth"] + else: max_width = MAX_TABLE_WIDTH + if state["table_align"]: align = state["table_align"] + else: align = None + + converter = MarkdownToMicron(max_width=max_width) + micron_lines = converter.format_table_raw(lines, align=align) + + widgets = [] + for line in micron_lines: + # Disable table mode to avoid recursion + was_table_mode = state["table_mode"] + state["table_mode"] = False + + line_widgets = parse_line(line, state, url_delegate) + state["table_mode"] = was_table_mode + + if line_widgets: widgets.extend(line_widgets) + + return widgets if widgets else None + def parse_line(line, state, url_delegate): pre_escape = False if len(line) > 0: @@ -161,6 +190,36 @@ def parse_line(line, state, url_delegate): elif first_char == "#": return None + # Check for tables + if line.startswith("`t"): + line = line[2:] + align = line[0] if len(line) and line[0] in ["l", "c", "r"] else None + max_width = None + if align: line = line[1:] + if len(line): + try: max_width = int(line) + except: pass + + if state["table_mode"]: + widgets = render_table(state["table_buffer"], state, url_delegate) + state["table_mode"] = False + state["table_buffer"] = [] + state["table_align"] = None + state["table_maxwidth"] = MAX_TABLE_WIDTH + return widgets + + else: + state["table_mode"] = True + state["table_buffer"] = [] + state["table_align"] = align + state["table_maxwidth"] = max_width + return None + + # Buffer the line if in table mode + if state["table_mode"]: + state["table_buffer"].append(line) + return None + # Check for partials elif line.startswith("`{"): return parse_partial(line[2:]) diff --git a/setup.py b/setup.py index bbdd4f9..a880c39 100644 --- a/setup.py +++ b/setup.py @@ -31,6 +31,6 @@ setuptools.setup( entry_points= { 'console_scripts': ['nomadnet=nomadnet.nomadnet:main'] }, - install_requires=["rns>=1.2.0", "lxmf>=0.9.6", "urwid>=2.6.16", "qrcode"], + install_requires=["rns>=1.2.1", "lxmf>=0.9.6", "urwid>=2.6.16", "qrcode"], python_requires=">=3.7", )