86 lines
2.4 KiB
Scheme
86 lines
2.4 KiB
Scheme
(define-macro (mithril:init)
|
|
"(mithril:init)
|
|
|
|
Loads Mithril into the document head and sets the
|
|
pragma->sxml function."
|
|
`(begin (get-resource "https://cdnjs.cloudflare.com/ajax/libs/mithril/2.2.2/mithril.min.js")
|
|
(pragma->sxml m)))
|
|
|
|
(mithril:init)
|
|
|
|
(define-macro (mithril:comp view . args)
|
|
"(mithril:comp view . args)
|
|
|
|
Creates a Mithril component object, where VIEW is
|
|
a function body used to display the component, and
|
|
ARGS is a list of keyword-value pairs that specify
|
|
additional values on the component object.
|
|
|
|
For example, the following code creates a stateful
|
|
heading component:
|
|
```
|
|
(define Heading
|
|
(component
|
|
(sxml
|
|
(h1 ~vnode.state.title))
|
|
:title \"Title Text\"))
|
|
```"
|
|
(when (and (not (null? args))
|
|
(= (remainder (length args) 2 1)))
|
|
(error (format
|
|
"mithril:comp-> Component macro expects even length args list.
|
|
|
|
Call: (mithril:comp ~s ~s)"
|
|
view args)))
|
|
`(object
|
|
:view
|
|
(lambda (vnode) (,@view))
|
|
,@args))
|
|
|
|
(define (mithril:repl prompt)
|
|
"(mithril:repl prompt preamble)
|
|
|
|
Returns a REPL Mithril component that allows evaluating
|
|
custom LIPS code. The environment used by this REPL is
|
|
the same as the application execution environment, meaning
|
|
that the DOM and running scripts can be modified.
|
|
|
|
PROMPT specifies the user prompt."
|
|
(let* ((add-line (lambda (state text prompt?)
|
|
(set! state.lines (cons `&(:text ,text :prompt ,prompt?) state.lines))))
|
|
(evaluate (lambda (state cmd)
|
|
(add-line state (format "~a~a" prompt cmd) #t)
|
|
(let ((res (eval (with-input-from-string cmd read))))
|
|
(when res
|
|
(add-line state res #f)))))
|
|
(handle-key-down (lambda (state e)
|
|
(cond
|
|
((equal? e.key "Enter")
|
|
(e.preventDefault)
|
|
(let ((cmd state.input))
|
|
(set! state.input "")
|
|
(evaluate state cmd)))))))
|
|
(mithril:comp
|
|
(let ((state vnode.state))
|
|
(sxml
|
|
(div.repl
|
|
(div.repl-output
|
|
~(list->array
|
|
(map
|
|
(lambda (line)
|
|
(m ".line" line.text))
|
|
(reverse state.lines))))
|
|
(div.repl-input
|
|
(span.prompt ~prompt)
|
|
(input (@ (type "text")
|
|
(value state.input)
|
|
(oninput (lambda (e) (set! state.input e.target.value)))
|
|
(onkeydown (lambda (e) (handle-key-down state e)))
|
|
(oncreate (lambda (vnode)
|
|
(set! state.inputRef vnode.dome)
|
|
(vnode.dom.focus)))
|
|
(onfocus (lambda () (object)))
|
|
(autofocus #t)))))))
|
|
:oninit (lambda (vnode)
|
|
(set! vnode.state.lines '())
|
|
(set! vnode.state.input "")))))
|