diff --git a/components.js b/components.js index 4e9fd0fe71..7b178375f7 100644 --- a/components.js +++ b/components.js @@ -156,6 +156,10 @@ var components = { "require": "javascript", "owner": "R-osey" }, + "clojure": { + "title": "Clojure", + "owner": "troglotit" + }, "crystal": { "title": "Crystal", "require": "ruby", diff --git a/components/prism-clojure.js b/components/prism-clojure.js new file mode 100644 index 0000000000..89c63941d3 --- /dev/null +++ b/components/prism-clojure.js @@ -0,0 +1,13 @@ +// Copied from https://github.com/jeluard/prism-clojure +Prism.languages.clojure = { + comment: /;+.*/, + string: /"(?:\\.|[^\\"\r\n])*"/, + operator: /(?:::|[:|'])\b[a-z][\w*+!?-]*\b/i, //used for symbols and keywords + keyword: { + pattern: /([^\w+*'?-])(?:def|if|do|let|\.\.|quote|var|->>|->|fn|loop|recur|throw|try|monitor-enter|\.|new|set!|def\-|defn|defn\-|defmacro|defmulti|defmethod|defstruct|defonce|declare|definline|definterface|defprotocol|==|defrecord|>=|deftype|<=|defproject|ns|\*|\+|\-|\/|<|=|>|accessor|agent|agent-errors|aget|alength|all-ns|alter|and|append-child|apply|array-map|aset|aset-boolean|aset-byte|aset-char|aset-double|aset-float|aset-int|aset-long|aset-short|assert|assoc|await|await-for|bean|binding|bit-and|bit-not|bit-or|bit-shift-left|bit-shift-right|bit-xor|boolean|branch\?|butlast|byte|cast|char|children|class|clear-agent-errors|comment|commute|comp|comparator|complement|concat|conj|cons|constantly|cond|if-not|construct-proxy|contains\?|count|create-ns|create-struct|cycle|dec|deref|difference|disj|dissoc|distinct|doall|doc|dorun|doseq|dosync|dotimes|doto|double|down|drop|drop-while|edit|end\?|ensure|eval|every\?|false\?|ffirst|file-seq|filter|find|find-doc|find-ns|find-var|first|float|flush|for|fnseq|frest|gensym|get-proxy-class|get|hash-map|hash-set|identical\?|identity|if-let|import|in-ns|inc|index|insert-child|insert-left|insert-right|inspect-table|inspect-tree|instance\?|int|interleave|intersection|into|into-array|iterate|join|key|keys|keyword|keyword\?|last|lazy-cat|lazy-cons|left|lefts|line-seq|list\*|list|load|load-file|locking|long|loop|macroexpand|macroexpand-1|make-array|make-node|map|map-invert|map\?|mapcat|max|max-key|memfn|merge|merge-with|meta|min|min-key|name|namespace|neg\?|new|newline|next|nil\?|node|not|not-any\?|not-every\?|not=|ns-imports|ns-interns|ns-map|ns-name|ns-publics|ns-refers|ns-resolve|ns-unmap|nth|nthrest|or|parse|partial|path|peek|pop|pos\?|pr|pr-str|print|print-str|println|println-str|prn|prn-str|project|proxy|proxy-mappings|quot|rand|rand-int|range|re-find|re-groups|re-matcher|re-matches|re-pattern|re-seq|read|read-line|reduce|ref|ref-set|refer|rem|remove|remove-method|remove-ns|rename|rename-keys|repeat|replace|replicate|resolve|rest|resultset-seq|reverse|rfirst|right|rights|root|rrest|rseq|second|select|select-keys|send|send-off|seq|seq-zip|seq\?|set|short|slurp|some|sort|sort-by|sorted-map|sorted-map-by|sorted-set|special-symbol\?|split-at|split-with|str|string\?|struct|struct-map|subs|subvec|symbol|symbol\?|sync|take|take-nth|take-while|test|time|to-array|to-array-2d|tree-seq|true\?|union|up|update-proxy|val|vals|var-get|var-set|var\?|vector|vector-zip|vector\?|when|when-first|when-let|when-not|with-local-vars|with-meta|with-open|with-out-str|xml-seq|xml-zip|zero\?|zipmap|zipper)(?=[^\w+*'?-])/, + lookbehind: true + }, + boolean: /\b(?:true|false|nil)\b/, + number: /\b[0-9A-Fa-f]+\b/, + punctuation: /[{}\[\](),]/ +}; diff --git a/components/prism-clojure.min.js b/components/prism-clojure.min.js new file mode 100644 index 0000000000..de256db528 --- /dev/null +++ b/components/prism-clojure.min.js @@ -0,0 +1 @@ +Prism.languages.clojure={comment:/;+.*/,string:/"(?:\\.|[^\\"\r\n])*"/,operator:/(?:::|[:|'])\b[a-z][\w*+!?-]*\b/i,keyword:{pattern:/([^\w+*'?-])(?:def|if|do|let|\.\.|quote|var|->>|->|fn|loop|recur|throw|try|monitor-enter|\.|new|set!|def\-|defn|defn\-|defmacro|defmulti|defmethod|defstruct|defonce|declare|definline|definterface|defprotocol|==|defrecord|>=|deftype|<=|defproject|ns|\*|\+|\-|\/|<|=|>|accessor|agent|agent-errors|aget|alength|all-ns|alter|and|append-child|apply|array-map|aset|aset-boolean|aset-byte|aset-char|aset-double|aset-float|aset-int|aset-long|aset-short|assert|assoc|await|await-for|bean|binding|bit-and|bit-not|bit-or|bit-shift-left|bit-shift-right|bit-xor|boolean|branch\?|butlast|byte|cast|char|children|class|clear-agent-errors|comment|commute|comp|comparator|complement|concat|conj|cons|constantly|cond|if-not|construct-proxy|contains\?|count|create-ns|create-struct|cycle|dec|deref|difference|disj|dissoc|distinct|doall|doc|dorun|doseq|dosync|dotimes|doto|double|down|drop|drop-while|edit|end\?|ensure|eval|every\?|false\?|ffirst|file-seq|filter|find|find-doc|find-ns|find-var|first|float|flush|for|fnseq|frest|gensym|get-proxy-class|get|hash-map|hash-set|identical\?|identity|if-let|import|in-ns|inc|index|insert-child|insert-left|insert-right|inspect-table|inspect-tree|instance\?|int|interleave|intersection|into|into-array|iterate|join|key|keys|keyword|keyword\?|last|lazy-cat|lazy-cons|left|lefts|line-seq|list\*|list|load|load-file|locking|long|loop|macroexpand|macroexpand-1|make-array|make-node|map|map-invert|map\?|mapcat|max|max-key|memfn|merge|merge-with|meta|min|min-key|name|namespace|neg\?|new|newline|next|nil\?|node|not|not-any\?|not-every\?|not=|ns-imports|ns-interns|ns-map|ns-name|ns-publics|ns-refers|ns-resolve|ns-unmap|nth|nthrest|or|parse|partial|path|peek|pop|pos\?|pr|pr-str|print|print-str|println|println-str|prn|prn-str|project|proxy|proxy-mappings|quot|rand|rand-int|range|re-find|re-groups|re-matcher|re-matches|re-pattern|re-seq|read|read-line|reduce|ref|ref-set|refer|rem|remove|remove-method|remove-ns|rename|rename-keys|repeat|replace|replicate|resolve|rest|resultset-seq|reverse|rfirst|right|rights|root|rrest|rseq|second|select|select-keys|send|send-off|seq|seq-zip|seq\?|set|short|slurp|some|sort|sort-by|sorted-map|sorted-map-by|sorted-set|special-symbol\?|split-at|split-with|str|string\?|struct|struct-map|subs|subvec|symbol|symbol\?|sync|take|take-nth|take-while|test|time|to-array|to-array-2d|tree-seq|true\?|union|up|update-proxy|val|vals|var-get|var-set|var\?|vector|vector-zip|vector\?|when|when-first|when-let|when-not|with-local-vars|with-meta|with-open|with-out-str|xml-seq|xml-zip|zero\?|zipmap|zipper)(?=[^\w+*'?-])/,lookbehind:!0},"boolean":/\b(?:true|false|nil)\b/,number:/\b[0-9A-Fa-f]+\b/,punctuation:/[{}\[\](),]/}; \ No newline at end of file diff --git a/examples/prism-clojure.html b/examples/prism-clojure.html new file mode 100644 index 0000000000..9d01ea31c3 --- /dev/null +++ b/examples/prism-clojure.html @@ -0,0 +1,389 @@ +

Clojure

+

To use this language, use the class "language-clojure".

+ +

Full example

+

+; This code is copied from https://learnxinyminutes.com/docs/clojure/
+
+; Comments start with semicolons.
+
+; Clojure is written in "forms", which are just
+; lists of things inside parentheses, separated by whitespace.
+;
+; The clojure reader assumes that the first thing is a
+; function or macro to call, and the rest are arguments.
+
+; The first call in a file should be ns, to set the namespace
+(ns learnclojure)
+
+; More basic examples:
+
+; str will create a string out of all its arguments
+(str "Hello" " " "World") ; => "Hello World"
+
+; Math is straightforward
+(+ 1 1) ; => 2
+(- 2 1) ; => 1
+(* 1 2) ; => 2
+(/ 2 1) ; => 2
+
+; Equality is =
+(= 1 1) ; => true
+(= 2 1) ; => false
+
+; You need not for logic, too
+(not true) ; => false
+
+; Nesting forms works as you expect
+(+ 1 (- 3 2)) ; = 1 + (3 - 2) => 2
+
+; Types
+;;;;;;;;;;;;;
+
+; Clojure uses Java's object types for booleans, strings and numbers.
+; Use `class` to inspect them.
+(class 1) ; Integer literals are java.lang.Long by default
+(class 1.); Float literals are java.lang.Double
+(class ""); Strings always double-quoted, and are java.lang.String
+(class false) ; Booleans are java.lang.Boolean
+(class nil); The "null" value is called nil
+
+; If you want to create a literal list of data, use ' to stop it from
+; being evaluated
+'(+ 1 2) ; => (+ 1 2)
+; (shorthand for (quote (+ 1 2)))
+
+; You can eval a quoted list
+(eval '(+ 1 2)) ; => 3
+
+; Collections & Sequences
+;;;;;;;;;;;;;;;;;;;
+
+; Lists are linked-list data structures, while Vectors are array-backed.
+; Vectors and Lists are java classes too!
+(class [1 2 3]); => clojure.lang.PersistentVector
+(class '(1 2 3)); => clojure.lang.PersistentList
+
+; A list would be written as just (1 2 3), but we have to quote
+; it to stop the reader thinking it's a function.
+; Also, (list 1 2 3) is the same as '(1 2 3)
+
+; "Collections" are just groups of data
+; Both lists and vectors are collections:
+(coll? '(1 2 3)) ; => true
+(coll? [1 2 3]) ; => true
+
+; "Sequences" (seqs) are abstract descriptions of lists of data.
+; Only lists are seqs.
+(seq? '(1 2 3)) ; => true
+(seq? [1 2 3]) ; => false
+
+; A seq need only provide an entry when it is accessed.
+; So, seqs which can be lazy -- they can define infinite series:
+(range 4) ; => (0 1 2 3)
+(range) ; => (0 1 2 3 4 ...) (an infinite series)
+(take 4 (range)) ;  (0 1 2 3)
+
+; Use cons to add an item to the beginning of a list or vector
+(cons 4 [1 2 3]) ; => (4 1 2 3)
+(cons 4 '(1 2 3)) ; => (4 1 2 3)
+
+; Conj will add an item to a collection in the most efficient way.
+; For lists, they insert at the beginning. For vectors, they insert at the end.
+(conj [1 2 3] 4) ; => [1 2 3 4]
+(conj '(1 2 3) 4) ; => (4 1 2 3)
+
+; Use concat to add lists or vectors together
+(concat [1 2] '(3 4)) ; => (1 2 3 4)
+
+; Use filter, map to interact with collections
+(map inc [1 2 3]) ; => (2 3 4)
+(filter even? [1 2 3]) ; => (2)
+
+; Use reduce to reduce them
+(reduce + [1 2 3 4])
+; = (+ (+ (+ 1 2) 3) 4)
+; => 10
+
+; Reduce can take an initial-value argument too
+(reduce conj [] '(3 2 1))
+; = (conj (conj (conj [] 3) 2) 1)
+; => [3 2 1]
+
+; Functions
+;;;;;;;;;;;;;;;;;;;;;
+
+; Use fn to create new functions. A function always returns
+; its last statement.
+(fn [] "Hello World") ; => fn
+
+; (You need extra parens to call it)
+((fn [] "Hello World")) ; => "Hello World"
+
+; You can create a var using def
+(def x 1)
+x ; => 1
+
+; Assign a function to a var
+(def hello-world (fn [] "Hello World"))
+(hello-world) ; => "Hello World"
+
+; You can shorten this process by using defn
+(defn hello-world [] "Hello World")
+
+; The [] is the list of arguments for the function.
+(defn hello [name]
+  (str "Hello " name))
+(hello "Steve") ; => "Hello Steve"
+
+; You can also use this shorthand to create functions:
+(def hello2 #(str "Hello " %1))
+(hello2 "Fanny") ; => "Hello Fanny"
+
+; You can have multi-variadic functions, too
+(defn hello3
+  ([] "Hello World")
+  ([name] (str "Hello " name)))
+(hello3 "Jake") ; => "Hello Jake"
+(hello3) ; => "Hello World"
+
+; Functions can pack extra arguments up in a seq for you
+(defn count-args [& args]
+  (str "You passed " (count args) " args: " args))
+(count-args 1 2 3) ; => "You passed 3 args: (1 2 3)"
+
+; You can mix regular and packed arguments
+(defn hello-count [name & args]
+  (str "Hello " name ", you passed " (count args) " extra args"))
+(hello-count "Finn" 1 2 3)
+; => "Hello Finn, you passed 3 extra args"
+
+
+; Maps
+;;;;;;;;;;
+
+; Hash maps and array maps share an interface. Hash maps have faster lookups
+; but don't retain key order.
+(class {:a 1 :b 2 :c 3}) ; => clojure.lang.PersistentArrayMap
+(class (hash-map :a 1 :b 2 :c 3)) ; => clojure.lang.PersistentHashMap
+
+; Arraymaps will automatically become hashmaps through most operations
+; if they get big enough, so you don't need to worry.
+
+; Maps can use any hashable type as a key, but usually keywords are best
+; Keywords are like strings with some efficiency bonuses
+(class :a) ; => clojure.lang.Keyword
+
+(def stringmap {"a" 1, "b" 2, "c" 3})
+stringmap  ; => {"a" 1, "b" 2, "c" 3}
+
+(def keymap {:a 1, :b 2, :c 3})
+keymap ; => {:a 1, :c 3, :b 2}
+
+; By the way, commas are always treated as whitespace and do nothing.
+
+; Retrieve a value from a map by calling it as a function
+(stringmap "a") ; => 1
+(keymap :a) ; => 1
+
+; Keywords can be used to retrieve their value from a map, too!
+(:b keymap) ; => 2
+
+; Don't try this with strings.
+;("a" stringmap)
+; => Exception: java.lang.String cannot be cast to clojure.lang.IFn
+
+; Retrieving a non-present key returns nil
+(stringmap "d") ; => nil
+
+; Use assoc to add new keys to hash-maps
+(def newkeymap (assoc keymap :d 4))
+newkeymap ; => {:a 1, :b 2, :c 3, :d 4}
+
+; But remember, clojure types are immutable!
+keymap ; => {:a 1, :b 2, :c 3}
+
+; Use dissoc to remove keys
+(dissoc keymap :a :b) ; => {:c 3}
+
+; Sets
+;;;;;;
+
+(class #{1 2 3}) ; => clojure.lang.PersistentHashSet
+(set [1 2 3 1 2 3 3 2 1 3 2 1]) ; => #{1 2 3}
+
+; Add a member with conj
+(conj #{1 2 3} 4) ; => #{1 2 3 4}
+
+; Remove one with disj
+(disj #{1 2 3} 1) ; => #{2 3}
+
+; Test for existence by using the set as a function:
+(#{1 2 3} 1) ; => 1
+(#{1 2 3} 4) ; => nil
+
+; There are more functions in the clojure.sets namespace.
+
+; Useful forms
+;;;;;;;;;;;;;;;;;
+
+; Logic constructs in clojure are just macros, and look like
+; everything else
+(if false "a" "b") ; => "b"
+(if false "a") ; => nil
+
+; Use let to create temporary bindings
+(let [a 1 b 2]
+  (> a b)) ; => false
+
+; Group statements together with do
+(do
+  (print "Hello")
+  "World") ; => "World" (prints "Hello")
+
+; Functions have an implicit do
+(defn print-and-say-hello [name]
+  (print "Saying hello to " name)
+  (str "Hello " name))
+(print-and-say-hello "Jeff") ;=> "Hello Jeff" (prints "Saying hello to Jeff")
+
+; So does let
+(let [name "Urkel"]
+  (print "Saying hello to " name)
+  (str "Hello " name)) ; => "Hello Urkel" (prints "Saying hello to Urkel")
+
+
+; Use the threading macros (-> and ->>) to express transformations of
+; data more clearly.
+
+; The "Thread-first" macro (->) inserts into each form the result of
+; the previous, as the first argument (second item)
+(->  
+   {:a 1 :b 2} 
+   (assoc :c 3) ;=> (assoc {:a 1 :b 2} :c 3)
+   (dissoc :b)) ;=> (dissoc (assoc {:a 1 :b 2} :c 3) :b)
+
+; This expression could be written as:
+; (dissoc (assoc {:a 1 :b 2} :c 3) :b)
+; and evaluates to {:a 1 :c 3}
+
+; The double arrow does the same thing, but inserts the result of
+; each line at the *end* of the form. This is useful for collection
+; operations in particular:
+(->>
+   (range 10)
+   (map inc)     ;=> (map inc (range 10)
+   (filter odd?) ;=> (filter odd? (map inc (range 10))
+   (into []))    ;=> (into [] (filter odd? (map inc (range 10)))
+                 ; Result: [1 3 5 7 9]
+
+; When you are in a situation where you want more freedom as where to
+; put the result of previous data transformations in an 
+; expression, you can use the as-> macro. With it, you can assign a
+; specific name to transformations' output and use it as a
+; placeholder in your chained expressions:
+
+(as-> [1 2 3] input
+  (map inc input);=> You can use last transform's output at the last position
+  (nth input 2) ;=>  and at the second position, in the same expression
+  (conj [4 5 6] input [8 9 10])) ;=> or in the middle !
+
+
+
+; Modules
+;;;;;;;;;;;;;;;
+
+; Use "use" to get all functions from the module
+(use 'clojure.set)
+
+; Now we can use set operations
+(intersection #{1 2 3} #{2 3 4}) ; => #{2 3}
+(difference #{1 2 3} #{2 3 4}) ; => #{1}
+
+; You can choose a subset of functions to import, too
+(use '[clojure.set :only [intersection]])
+
+; Use require to import a module
+(require 'clojure.string)
+
+; Use / to call functions from a module
+; Here, the module is clojure.string and the function is blank?
+(clojure.string/blank? "") ; => true
+
+; You can give a module a shorter name on import
+(require '[clojure.string :as str])
+(str/replace "This is a test." #"[a-o]" str/upper-case) ; => "THIs Is A tEst."
+; (#"" denotes a regular expression literal)
+
+; You can use require (and use, but don't) from a namespace using :require.
+; You don't need to quote your modules if you do it this way.
+(ns test
+  (:require
+    [clojure.string :as str]
+    [clojure.set :as set]))
+
+; Java
+;;;;;;;;;;;;;;;;;
+
+; Java has a huge and useful standard library, so
+; you'll want to learn how to get at it.
+
+; Use import to load a java module
+(import java.util.Date)
+
+; You can import from an ns too.
+(ns test
+  (:import java.util.Date
+           java.util.Calendar))
+
+; Use the class name with a "." at the end to make a new instance
+(Date.) ; 
+
+; Use . to call methods. Or, use the ".method" shortcut
+(. (Date.) getTime) ; 
+(.getTime (Date.)) ; exactly the same thing.
+
+; Use / to call static methods
+(System/currentTimeMillis) ;  (system is always present)
+
+; Use doto to make dealing with (mutable) classes more tolerable
+(import java.util.Calendar)
+(doto (Calendar/getInstance)
+  (.set 2000 1 1 0 0 0)
+  .getTime) ; => A Date. set to 2000-01-01 00:00:00
+
+; STM
+;;;;;;;;;;;;;;;;;
+
+; Software Transactional Memory is the mechanism clojure uses to handle
+; persistent state. There are a few constructs in clojure that use this.
+
+; An atom is the simplest. Pass it an initial value
+(def my-atom (atom {}))
+
+; Update an atom with swap!.
+; swap! takes a function and calls it with the current value of the atom
+; as the first argument, and any trailing arguments as the second
+(swap! my-atom assoc :a 1) ; Sets my-atom to the result of (assoc {} :a 1)
+(swap! my-atom assoc :b 2) ; Sets my-atom to the result of (assoc {:a 1} :b 2)
+
+; Use '@' to dereference the atom and get the value
+my-atom  ;=> Atom<#...> (Returns the Atom object)
+@my-atom ; => {:a 1 :b 2}
+
+; Here's a simple counter using an atom
+(def counter (atom 0))
+(defn inc-counter []
+  (swap! counter inc))
+
+(inc-counter)
+(inc-counter)
+(inc-counter)
+(inc-counter)
+(inc-counter)
+
+@counter ; => 5
+
+; Other STM constructs are refs and agents.
+; Refs: http://clojure.org/refs
+; Agents: http://clojure.org/agents
\ No newline at end of file diff --git a/tests/languages/clojure/boolean_feature.test b/tests/languages/clojure/boolean_feature.test new file mode 100644 index 0000000000..55720b4f46 --- /dev/null +++ b/tests/languages/clojure/boolean_feature.test @@ -0,0 +1,15 @@ +false +true +nil + +---------------------------------------------------- + +[ + ["boolean", "false"], + ["boolean", "true"], + ["boolean", "nil"] +] + +---------------------------------------------------- + +Checks for booleans. \ No newline at end of file diff --git a/tests/languages/clojure/comment_feature.test b/tests/languages/clojure/comment_feature.test new file mode 100644 index 0000000000..c4f5c7d182 --- /dev/null +++ b/tests/languages/clojure/comment_feature.test @@ -0,0 +1,13 @@ +;; this is comment +; this is another comment + +---------------------------------------------------- + +[ + ["comment", ";; this is comment"], + ["comment", "; this is another comment"] +] + +---------------------------------------------------- + +Checks for comments. \ No newline at end of file diff --git a/tests/languages/clojure/keyword_feature.test b/tests/languages/clojure/keyword_feature.test new file mode 100644 index 0000000000..0c32cd2db4 --- /dev/null +++ b/tests/languages/clojure/keyword_feature.test @@ -0,0 +1,175 @@ +(def) +(if) +(do) +(let) +(var) +(fn) +(quote) +(->>) +(->) +(loop) +(recur) +(throw) +(try) +(monitor-enter) +(.) +(new) +(set!) +(defn) +(defn-) +(defmacro) +(defmulti) +(defmethod) +(defstruct) +(defonce) +(declare) +(definline) +(definterface) +(defprotocol) +(defrecord) +(deftype) +(defproject) +(ns) +(*) +(+) +(-) +(/) +(<) +(<=) +(>=) +(=) +(==) +(..) +(>) +(accessor) +(agent) +(agent-errors) +(aget) +(alength) +(all-ns) +(alter) +(and) +(append-child) +(apply) +(array-map) +(aset) +(aset-boolean) +(aset-byte) +(aset-char) +(aset-double) +(aset-float) +(aset-int) +(aset-long) +(aset-short) +(assert) +(assoc) +(await) +(await-for) +(bean) +(binding) +(bit-and) +(bit-not) +(branch?) +(contains?) +(end?) +(every?) +(false?) +(identical?) +(instance?) +(keyword?) +(list*) +(not-any?) +(true?) +(zero?) + +---------------------------------------------------- + +[ + ["punctuation", "("], ["keyword", "def"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "if"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "do"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "let"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "var"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "fn"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "quote"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "->>"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "->"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "loop"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "recur"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "throw"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "try"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "monitor-enter"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "."], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "new"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "set!"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "defn"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "defn-"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "defmacro"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "defmulti"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "defmethod"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "defstruct"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "defonce"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "declare"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "definline"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "definterface"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "defprotocol"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "defrecord"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "deftype"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "defproject"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "ns"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "*"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "+"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "-"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "/"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "<"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "<="], ["punctuation", ")"], + ["punctuation", "("], ["keyword", ">="], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "="], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "=="], ["punctuation", ")"], + ["punctuation", "("], ["keyword", ".."], ["punctuation", ")"], + ["punctuation", "("], ["keyword", ">"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "accessor"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "agent"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "agent-errors"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "aget"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "alength"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "all-ns"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "alter"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "and"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "append-child"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "apply"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "array-map"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "aset"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "aset-boolean"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "aset-byte"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "aset-char"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "aset-double"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "aset-float"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "aset-int"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "aset-long"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "aset-short"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "assert"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "assoc"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "await"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "await-for"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "bean"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "binding"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "bit-and"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "bit-not"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "branch?"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "contains?"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "end?"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "every?"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "false?"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "identical?"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "instance?"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "keyword?"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "list*"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "not-any?"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "true?"], ["punctuation", ")"], + ["punctuation", "("], ["keyword", "zero?"], ["punctuation", ")"] +] + +---------------------------------------------------- + +Checks for keywords. diff --git a/tests/languages/clojure/operator_and_punctuation.test b/tests/languages/clojure/operator_and_punctuation.test new file mode 100644 index 0000000000..e90acb631d --- /dev/null +++ b/tests/languages/clojure/operator_and_punctuation.test @@ -0,0 +1,20 @@ +(::example [x y] (:kebab-case x y)) + +---------------------------------------------------- + +[ + ["punctuation", "("], + ["operator", "::example"], + ["punctuation", "["], + "x y", + ["punctuation", "]"], + ["punctuation", "("], + ["operator", ":kebab-case"], + " x y", + ["punctuation", ")"], + ["punctuation", ")"] +] + +---------------------------------------------------- + +Checks for operators and punctuation. \ No newline at end of file diff --git a/tests/languages/clojure/string_feature.test b/tests/languages/clojure/string_feature.test new file mode 100644 index 0000000000..13a966cf7e --- /dev/null +++ b/tests/languages/clojure/string_feature.test @@ -0,0 +1,13 @@ +"" +"Fo\"obar" + +---------------------------------------------------- + +[ + ["string", "\"\""], + ["string", "\"Fo\\\"obar\""] +] + +---------------------------------------------------- + +Checks for strings. \ No newline at end of file