HLisp is a lisp implementation built atop ClojureScript.
You may want to:
- Look at the demo.
- See the design document.
Here is the example index.html
file:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>hlisp test</title>
<style type="text/css">
ul.control-tabs { padding: 0; list-style-type: none; }
ul.control-tabs li { display: inline; padding-right: 5px; }
ul.control-tabs li.checked { color: red; }
</style>
</head>
<body>
<script type="text/hlisp">
;; Namespace declaration. Each page must have a unique namespace.
;; The ns macro is also pulling in functions defined in other name-
;; spaces, like the make-radio and make-tabs functions defined in
;; the mytest.ui namespace (src/cljs/mytest/ui.cljs).
(ns holyshit
(:use
[flapjax.core :only [sync-e]]
[mytest.ui :only [make-radio make-tabs]])
(:use-macros
[hlisp.macros :only [def-values]]))
;; Create a "tabs" set with two trigger elements and two container
;; elements. When the trigger element is clicked the associated
;; container element is shown and all other containers are hidden.
(def-values
[mytabs questiontab question answertab answer]
(make-tabs "one" li div "one" li div "two"))
;; Define a var to save a little typing.
(def a-void (a {:href "javascript:void (0)"}))
;; Create a "radio button" set with two elements (anchors, in this
;; case). The myradio event stream carries values of "one" and "two"
;; when the first or second element is clicked on, respectively.
(def-values
[myradio showquestion showanswer]
(make-radio "one" a-void "one" a-void "two"))
;; Keep myradio and mytabs synced: when one changes state the other
;; does, too.
(sync-e myradio mytabs)
</script>
<div>
<ul class="control-tabs">
<questiontab>question</questiontab>
<answertab>answer</answertab>
</ul>
<div>
<question>
<p>
<b>Q.</b> Why did the chicken cross the road? <showanswer>A</showanswer>
</p>
</question>
<answer>
<p>
<b>A.</b> To get to the other side! <showquestion>Q</showquestion>
</p>
</answer>
</div>
</div>
</body>
</html>
Install Leiningen2
Install dependencies:
lein deps
Start a server to serve the app on port 4000:
script/serve
In another tab, you can start watcher-based ClojureScript compilation:
script/autobuild
Visit http://localhost:4000/ to see the app.
The ClojureScript REPL compiles ClojureScript forms into JavaScript locally and sends them to the browser to be evaluated.
C-x d
to thehlisp-starter
directoryM-x set-variable
, and set the variableinferior-lisp-program
toscript/cljsrepl
M-x run-lisp
and you should see an inferior-lisp buffer running a ClojureScript REPL.- Visit or reload http://localhost:4000/ in the browser.
- If you know of a good inferior lisp setup for vi I'd like to hear about it!
- Hlisp defines vars for all the DOM elements in the following namespaces:
- Project HTML page namespaces.
- The
hlisp.env
namespace.
- Hlisp nodes in the REPL are printed as lists.
- The REPL also prints hlisp nodes in the browser console as DOM elements.
ClojureScript:cljs.user> (in-ns 'hlisp.env)
ClojureScript:hlisp.env> (div {:id "main"} (h1 ($text "Hello, world!")) (p ($text "How do you do?")))
(div {:id "main"} (h1 ($text "Hello, world!")) (p ($text "How do you do?")))
ClojureScript:hlisp.env> (defn f [x] (div {:class "foo"} x))
#<function f(x){ ... }>
ClojureScript:hlisp.env> (f (p ($text "I am wrapped in a div?")))
(div {:class "foo"} (p ($text "I am wrapped in a div?")))
ClojureScript:hlisp.env> (def test1 (f (label ($text "Name:"))))
(div {:class "foo"} (label ($text "Name:")))
ClojureScript:hlisp.env> (test1 br (input {:type "text"}))
(div {:class "foo"} (label ($text "Name:")) br (input {:type "text"}))
Have a look at the project.clj
file:
;; ---------------------------------------------------------------------------
;; Leiningen Plugins
;; ---------------------------------------------------------------------------
;;
;; 1. lein-cljsbuild To get a ClojureScript REPL going.
;; 2. lein-ring To get a local dev server going.
;; 3. lein-hlisp The hlisp compiler---produces main.js.
;;
;; ---------------------------------------------------------------------------
;; Dependencies
;; ---------------------------------------------------------------------------
;;
;; 1. clojure Goes without saying.
;; 2. compojure For the dev server setup.
;; 3. hlisp-macros Some handy Clojure macros to use in cljs.
;;
;; ---------------------------------------------------------------------------
;; Hlisp Configuration
;; ---------------------------------------------------------------------------
;;
;; 1. html-src Directory containing the HTML source files.
;; 2. cljs-src Directory containing cljs source files.
;; 3. html-out Directory into which processed HTML and JS will go.
;; 4. base-dir URL path of deployed HTML if HTML is not served from
;; the document root.
;; 5. includes Vector of JS files to prepend (in order) to main.js.
;; 6. cljsc-opts ClojureScript compiler options.
(defproject
hlisp-starter "0.1.0-SNAPSHOT"
:description "Example hlisp project."
:url "https://github.com/tailrecursion/hlisp-starter"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:source-paths ["src/clj"]
:plugins [[lein-cljsbuild "0.2.7"]
[lein-ring "0.7.1"]
[lein-hlisp "0.1.0-SNAPSHOT"]]
:dependencies [[org.clojure/clojure "1.4.0"]
[compojure "1.0.4"]
[hlisp-macros "0.1.0-SNAPSHOT"]]
:eval-in :leiningen
:ring {:handler example.routes/app}
:cljsbuild {:builds []}
:hlisp {:html-src "src/html"
:cljs-src "src/cljs"
:html-out "resources/public"
:base-dir ""
:includes ["src/jslib/jquery.js"
"src/jslib/flapjax.js"]
:cljsc-opts {:optimizations :whitespace
:externs ["src/extern/jquery.js"
"src/extern/flapjax.js"]}})