"""µFrame Keyword Registrations — single source of truth for all DSL keywords. Each keyword is registered here with its metadata (section, detail, snippet, highlight values). The actual parse/measure/layout/paint/codegen functions remain in their respective modules for now — this file serves as the registry that the frontend reads via GET /api/dsl-meta. To add a new keyword: 1. Define its IR node in ir.py 2. Add a register_keyword() call here 3. Add parse logic in parser.py 4. Add measure/layout/paint logic in their respective files 5. That's it — syntax highlighting and slash commands auto-update from the registry """ from uframe.registry import register_keyword, ALL_THEME_NAMES from uframe.ir import ( Page, Box, Row, Col, Spacer, Pad, Heading, Text, Label, Divider, Link, ListNode, ListItem, Gauge, Sparkline, Status, Table, Form, Field, Password, Radio, Checkbox, FormButton, Let, Source, IfBlock, ForLoop, CacheControl, OnSubmit, StateDecl, BigTitle, ImageNode, HNav, VNav, ComponentDef, ComponentUse, ) from uframe.themes import BUILTIN_THEMES # --------------------------------------------------------------------------- # Layout # --------------------------------------------------------------------------- register_keyword("page", node_class=Page, section="Layout", detail='page "Title" 64', snippet='page "${1:Title}" ${2:64}', is_container=True) register_keyword("box", node_class=Box, section="Layout", detail='box light "Title"', snippet='box ${1:light} "${2:Title}"', highlight_values=["light", "heavy", "double", "rounded"], is_container=True) register_keyword("row", node_class=Row, section="Layout", detail="row [gap]", snippet="row ${1:2}", is_container=True) register_keyword("col", node_class=Col, section="Layout", detail="col [width]", snippet="col ${1}", is_container=True) register_keyword("spacer", node_class=Spacer, section="Layout", detail="spacer [lines]", snippet="spacer", is_leaf=True) register_keyword("pad", node_class=Pad, section="Layout", detail="pad t r b l", snippet="pad ${1:1} ${2:1} ${3:1} ${4:1}", is_container=True) # --------------------------------------------------------------------------- # Content # --------------------------------------------------------------------------- register_keyword("heading", node_class=Heading, section="Content", detail='heading 1 "Text"', snippet='heading ${1:1} "${2:Text}"', is_leaf=True) register_keyword("text", node_class=Text, section="Content", detail='text "Content"', snippet='text "${1:Content}"', is_leaf=True) register_keyword("label", node_class=Label, section="Content", detail='label "Key" "Value"', snippet='label "${1:Key}" "${2:Value}"', is_leaf=True) register_keyword("divider", node_class=Divider, section="Content", detail="divider heavy", snippet="divider ${1:light}", highlight_values=["light", "heavy", "double", "dash", "dot"], is_leaf=True) register_keyword("link", node_class=Link, section="Content", detail='link "Text" "/path.mu"', snippet='link "${1:Text}" "${2:/page/dest.mu}"', is_leaf=True) register_keyword("list", node_class=ListNode, section="Content", detail="list bullet", snippet='list ${1:bullet}\n item "${2:Entry}"', highlight_values=["bullet", "dash", "number", "arrow"], is_container=True) register_keyword("item", node_class=ListItem, section="", detail="", snippet="", # not shown in slash commands (child of list) is_leaf=True) # --------------------------------------------------------------------------- # Data Visualization # --------------------------------------------------------------------------- register_keyword("gauge", node_class=Gauge, section="Data", detail="gauge label val max width", snippet='gauge "${1:Label}" ${2:0} ${3:100} ${4:28} warn=${5:75} crit=${6:90}', is_leaf=True) register_keyword("sparkline", node_class=Sparkline, section="Data", detail="sparkline label values width", snippet='sparkline "${1:Label}" "${2:1,2,3,4}" ${3:20}', is_leaf=True) register_keyword("status", node_class=Status, section="Data", detail="status label state", snippet='status "${1:Label}" ${2:online}', highlight_values=["online", "offline", "degraded", "unknown", "alert"], is_leaf=True) register_keyword("table", node_class=Table, section="Data", detail="table + columns + rows", snippet='table "Title"\n columns "Name" 20 | "Value" 10\n row "entry" | "data"', is_leaf=True) # table handles its own children (columns/row pseudo-nodes) register_keyword("columns", section="", detail="", snippet="") # child of table, not shown in slash commands # --------------------------------------------------------------------------- # Big Text # --------------------------------------------------------------------------- register_keyword("hnav", node_class=HNav, section="Layout", detail='hnav bar', snippet='hnav ${1:bar}\n item "${2:Label}" "${3:/page/dest.mu}" active', highlight_values=["bar", "tabs", "pills", "breadcrumb", "underline"], is_container=True) register_keyword("vnav", node_class=VNav, section="Layout", detail='vnav list', snippet='vnav ${1:list}\n item "${2:Label}" "${3:/page/dest.mu}"', highlight_values=["list", "boxed", "tree", "sidebar", "minimal"], is_container=True) register_keyword("image", node_class=ImageNode, section="Content", detail='image "path.png" braille 30', snippet='image "${1:path.png}" ${2:braille} ${3:30}', highlight_values=["braille", "block", "ascii", "halfblock"], is_leaf=True) register_keyword("dither", section="", detail="", snippet="", highlight_values=["floyd", "threshold", "none"], is_style_directive=True) register_keyword("invert", section="", detail="", snippet="", is_style_directive=True) register_keyword("caption", section="", detail="", snippet="", is_style_directive=True) register_keyword("bigtitle", node_class=BigTitle, section="Content", detail='bigtitle "TEXT" block', snippet='bigtitle "${1:TEXT}" ${2:block}', highlight_values=["block", "thin", "pixel"], is_leaf=True) # --------------------------------------------------------------------------- # Style # --------------------------------------------------------------------------- register_keyword("align", section="Style", detail="align center", snippet="align ${1:center}", highlight_values=["left", "center", "right"], is_style_directive=True) register_keyword("color", section="Style", detail="color hex", snippet="color ${1:0cf}", is_style_directive=True) register_keyword("bg", section="Style", detail="", snippet="", is_style_directive=True) register_keyword("bold", section="Style", detail="bold", snippet="bold", is_style_directive=True) register_keyword("italic", section="Style", detail="", snippet="", is_style_directive=True) register_keyword("underline", section="Style", detail="", snippet="", is_style_directive=True) # --------------------------------------------------------------------------- # Forms # --------------------------------------------------------------------------- register_keyword("form", node_class=Form, section="Form", detail='form "name"', snippet='form "${1:name}"', is_container=True) register_keyword("field", node_class=Field, section="Form", detail='field "name" 24 "placeholder"', snippet='field "${1:name}" ${2:24} "${3:placeholder}"', is_leaf=True) register_keyword("password", node_class=Password, section="Form", detail='password "name" 24 "placeholder"', snippet='password "${1:name}" ${2:24} "${3:placeholder}"', is_leaf=True) register_keyword("radio", node_class=Radio, section="Form", detail='radio "group" "A" | "B" | "C"', snippet='radio "${1:group}" "${2:Option A}" | "${3:Option B}"', is_leaf=True) register_keyword("checkbox", node_class=Checkbox, section="Form", detail='checkbox "name" "Label"', snippet='checkbox "${1:name}" "${2:Label}"', is_leaf=True) register_keyword("button", node_class=FormButton, section="Form", detail='button "Label" "/action"', snippet='button "${1:Label}" "${2:/page/action.mu}"', is_leaf=True) # --------------------------------------------------------------------------- # Dynamic # --------------------------------------------------------------------------- register_keyword("let", node_class=Let, section="Dynamic", detail='let name = "value"', snippet='let ${1:name} = "${2:value}"', is_metadata=True) register_keyword("source", node_class=Source, section="Dynamic", detail='source name : shell "cmd"', snippet='source ${1:name} : shell "${2:command}"', highlight_values=["shell", "file", "json", "python", "rns", "param"], is_metadata=True) register_keyword("if", node_class=IfBlock, section="Dynamic", detail="if $var > threshold", snippet="if ${1:condition}", is_container=True) register_keyword("elif", section="Dynamic", detail="", snippet="") register_keyword("else", section="Dynamic", detail="", snippet="") register_keyword("for", node_class=ForLoop, section="Dynamic", detail="for item in $list", snippet='for ${1:item} in ${2:\\$list}', is_container=True) register_keyword("cache", node_class=CacheControl, section="Dynamic", detail="cache 0", snippet="cache ${1:0}", is_metadata=True) register_keyword("on_submit", node_class=OnSubmit, section="Dynamic", detail='on_submit "form"', snippet='on_submit "${1:form_name}"', is_container=True) register_keyword("state", node_class=StateDecl, section="Dynamic", detail='state "name" "/path.json"', snippet='state "${1:name}" "${2:/tmp/state.json}"', is_metadata=True) register_keyword("set", section="Dynamic", detail="", snippet="") register_keyword("append", section="Dynamic", detail="", snippet="") register_keyword("prepend", section="Dynamic", detail="", snippet="") # --------------------------------------------------------------------------- # Themes # --------------------------------------------------------------------------- register_keyword("theme", section="Theme", detail="", snippet="", is_style_directive=True) # Register each built-in theme as a named entry for _theme_name, _theme_def in BUILTIN_THEMES.items(): register_keyword(f"theme_{_theme_name}", section="Theme", detail=f"{_theme_def.description}", snippet=f"theme {_theme_name}") ALL_THEME_NAMES.append(_theme_name) # --------------------------------------------------------------------------- # Components # --------------------------------------------------------------------------- register_keyword("component", node_class=ComponentDef, section="", detail="", snippet="", is_container=True) register_keyword("use", section="", detail="", snippet="")