From fb93aaaa8c2e2ee308ac22a0b4a8915f8f8c3fc1 Mon Sep 17 00:00:00 2001 From: giles Date: Mon, 13 Apr 2026 11:10:17 +0000 Subject: [PATCH] =?UTF-8?q?HS:=20open/close=20commands=20for=20dialog/deta?= =?UTF-8?q?ils=20=E2=80=94=20428=E2=86=92435?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Parser: open/close commands with optional target (defaults to me) - Compiler: open-element → hs-open!, close-element → hs-close! - Runtime: hs-open! calls showModal() for dialogs, sets open=true for details - Runtime: hs-close! calls close() for dialogs, sets open=false for details - dialog: 1/10 → 8/10 Co-Authored-By: Claude Opus 4.6 (1M context) --- lib/hyperscript/compiler.sx | 4 ++++ lib/hyperscript/parser.sx | 22 +++++++++++++++++++++- lib/hyperscript/runtime.sx | 24 +++++++++++++++++++++++- lib/hyperscript/tokenizer.sx | 2 ++ 4 files changed, 50 insertions(+), 2 deletions(-) diff --git a/lib/hyperscript/compiler.sx b/lib/hyperscript/compiler.sx index 5cd46e2b..62cc8074 100644 --- a/lib/hyperscript/compiler.sx +++ b/lib/hyperscript/compiler.sx @@ -827,6 +827,10 @@ (list (quote dom-remove) (hs-to-sx (nth ast 1)))) ((= head (quote empty-target)) (list (quote hs-empty-target!) (hs-to-sx (nth ast 1)))) + ((= head (quote open-element)) + (list (quote hs-open!) (hs-to-sx (nth ast 1)))) + ((= head (quote close-element)) + (list (quote hs-close!) (hs-to-sx (nth ast 1)))) ((= head (quote swap!)) (let ((lhs (nth ast 1)) (rhs (nth ast 2))) diff --git a/lib/hyperscript/parser.sx b/lib/hyperscript/parser.sx index 951e7f82..4a5bcad6 100644 --- a/lib/hyperscript/parser.sx +++ b/lib/hyperscript/parser.sx @@ -1495,6 +1495,20 @@ ((lhs (parse-expr))) (match-kw "with") (let ((rhs (parse-expr))) (list (quote swap!) lhs rhs))))) + (define + parse-open-cmd + (fn + () + (let + ((target (cond ((at-end?) (list (quote me))) ((and (= (tp-type) "keyword") (or (= (tp-val) "then") (= (tp-val) "end"))) (list (quote me))) (true (parse-expr))))) + (list (quote open-element) target)))) + (define + parse-close-cmd + (fn + () + (let + ((target (cond ((at-end?) (list (quote me))) ((and (= (tp-type) "keyword") (or (= (tp-val) "then") (= (tp-val) "end"))) (list (quote me))) (true (parse-expr))))) + (list (quote close-element) target)))) (define parse-cmd (fn @@ -1582,6 +1596,10 @@ (do (adv!) (parse-empty-cmd))) ((and (= typ "keyword") (= val "swap")) (do (adv!) (parse-swap-cmd))) + ((and (= typ "keyword") (= val "open")) + (do (adv!) (parse-open-cmd))) + ((and (= typ "keyword") (= val "close")) + (do (adv!) (parse-close-cmd))) (true (parse-expr)))))) (define parse-cmd-list @@ -1630,7 +1648,9 @@ (= v "focus") (= v "empty") (= v "clear") - (= v "swap")))) + (= v "swap") + (= v "open") + (= v "close")))) (define cl-collect (fn diff --git a/lib/hyperscript/runtime.sx b/lib/hyperscript/runtime.sx index fca57e9a..06d40be3 100644 --- a/lib/hyperscript/runtime.sx +++ b/lib/hyperscript/runtime.sx @@ -475,8 +475,30 @@ ((= tag "FORM") (dom-set-inner-html target "")) (true (dom-set-inner-html target "")))))))) ;; Collection: split by -(define hs-first (fn (lst) (first lst))) +(define + hs-open! + (fn + (el) + (let + ((tag (dom-get-prop el "tagName"))) + (if + (= tag "DIALOG") + (host-call el "showModal") + (dom-set-prop el "open" true))))) ;; Collection: joined by +(define + hs-close! + (fn + (el) + (let + ((tag (dom-get-prop el "tagName"))) + (if + (= tag "DIALOG") + (host-call el "close") + (dom-set-prop el "open" false))))) + +(define hs-first (fn (lst) (first lst))) + (define hs-last (fn (lst) (last lst))) (define diff --git a/lib/hyperscript/tokenizer.sx b/lib/hyperscript/tokenizer.sx index c0a7ceed..8c473703 100644 --- a/lib/hyperscript/tokenizer.sx +++ b/lib/hyperscript/tokenizer.sx @@ -119,6 +119,8 @@ "empty" "clear" "swap" + "open" + "close" "exists" "matches" "contains"