reagent/demo/reagentdemo/syntax.cljs

85 lines
3.1 KiB
Plaintext
Raw Normal View History

2014-01-18 10:43:56 +00:00
(ns reagentdemo.syntax
2014-01-06 11:46:58 +00:00
(:require [clojure.string :as string]))
(def builtins #{"def" "defn" "ns" "atom" "let" "if" "when"
"cond" "merge" "assoc" "swap!" "reset!" "for"
2014-01-07 11:45:08 +00:00
"range" "nil?" "int" "or" "->" "->>" "%" "fn" "if-not"
"empty?" "case" "str" "pos?" "zero?" "map" "remove"
"empty" "into" "assoc-in" "dissoc" "get-in" "when-not"
"filter" "vals" "count" "complement" "identity" "dotimes"
"update-in" "sorted-map" "inc" "dec" "false" "true" "not"
2014-01-19 09:25:16 +00:00
"=" "partial" "first" "second" "rest" "list" "conj"
2014-02-22 16:24:22 +00:00
"drop" "when-let" "if-let" "add-watch" "mod" "quot"
"bit-test" "vector"})
2014-01-07 11:45:08 +00:00
(def styles {:comment {:style {:color "gray"
:font-style "italic"}}
:str-litt {:style {:color "green"}}
:keyw {:style {:color "blue"}}
:builtin {:style {:font-weight "bold"
:color "#687868"}}
:def {:style {:color "#55c"
:font-weight "bold"}}})
(def paren-styles [{:style {:color "#272"}}
{:style {:color "#940"}}
{:style {:color "#44a"}}])
2014-01-06 11:46:58 +00:00
(defn tokenize [src]
(let [ws " \\t\\n"
open "[({"
close ")\\]}"
sep (str ws open close)
2014-01-06 21:27:22 +00:00
comment-p ";.*"
str-p "\"[^\"]*\""
2014-01-06 11:46:58 +00:00
open-p (str "[" open "]")
close-p (str "[" close "]")
iden-p (str "[^" sep "]+")
2014-01-07 11:45:08 +00:00
meta-p (str "\\^" iden-p)
any-p (str "[" ws "]+" "|\\^[^" sep "]+|.")
2014-01-06 11:46:58 +00:00
patt (re-pattern (str "("
2014-01-06 21:27:22 +00:00
(string/join ")|(" [comment-p str-p open-p
2014-01-07 11:45:08 +00:00
close-p meta-p iden-p any-p])
2014-01-06 11:46:58 +00:00
")"))
keyw-re #"^:"]
2014-01-07 11:45:08 +00:00
(for [[s comment str-litt open close met iden any] (re-seq patt src)]
2014-01-06 11:46:58 +00:00
(cond
2014-01-06 21:27:22 +00:00
comment [:comment s]
2014-01-06 11:46:58 +00:00
str-litt [:str-litt s]
open [:open s]
close [:close s]
2014-01-07 11:45:08 +00:00
met [:other s]
2014-01-06 11:46:58 +00:00
iden (cond
(re-find keyw-re s) [:keyw s]
(builtins s) [:builtin s]
:else [:iden s])
any [:other s]))))
(defn syntaxify [src]
(let [def-re #"^def|^ns\b"
2014-01-07 11:45:08 +00:00
ncol (count paren-styles)
2014-01-06 11:46:58 +00:00
paren-style (fn [level]
2014-01-07 11:45:08 +00:00
(nth paren-styles (mod level ncol)))]
2014-01-06 11:46:58 +00:00
(loop [tokens (tokenize src)
prev nil
level 0
res []]
(let [[kind val] (first tokens)
level' (case kind
:open (inc level)
:close (dec level)
level)
style (case kind
2014-01-07 11:45:08 +00:00
:iden (when (and prev (re-find def-re prev))
(:def styles))
:open (paren-style level)
:close (paren-style level')
(styles kind))
2014-01-06 11:46:58 +00:00
remain (rest tokens)]
(if-not (empty? remain)
(recur remain
(if (= kind :other) prev val)
level'
(conj res [:span style val]))
(apply vector :pre res))))))