diff --git a/clj/test/vim/syntax_test.clj b/clj/test/vim/syntax_test.clj index 13a938e..abf9cf6 100644 --- a/clj/test/vim/syntax_test.clj +++ b/clj/test/vim/syntax_test.clj @@ -2,13 +2,54 @@ ;; Joel Holdbrooks (ns vim.syntax-test - (:require [vim.test :refer [defpredicates defsyntaxtest]])) + (:require [vim.test :refer [defpredicates defsyntaxtest def-eq-predicates]])) ;; defpredicates also register not-equal vars, this is just for clj-kondo (declare !number !regexp-escape !regexp-posix-char-class !regexp-quantifier) (defpredicates number :clojureNumber) -(defpredicates kw :clojureKeyword) +(def-eq-predicates kw [:clojureKeywordNsColon :clojureKeyword]) +(def-eq-predicates kwCurrentNs [:clojureKeywordNsColon :clojureKeywordNsColon :clojureKeyword]) +(def-eq-predicates kwWithNs [:clojureKeywordNsColon :clojureKeywordNs :clojureKeywordNsSeparator :clojureKeyword]) +(def-eq-predicates kwWithNs3_4 [:clojureKeywordNsColon + :clojureKeywordNs + :clojureKeywordNs + :clojureKeywordNs + :clojureKeywordNsSeparator + :clojureKeyword + :clojureKeyword + :clojureKeyword + :clojureKeyword]) +(def-eq-predicates sym [:clojureSymbol]) +(def-eq-predicates symWithNs [:clojureSymbol]) +(def-eq-predicates symWithNs_tripleBody [:clojureKeywordNsColon + :clojureKeywordNs :clojureKeywordNsSeparator + :clojureKeywordNs :clojureKeywordNsSeparator + :clojureKeywordNs :clojureKeywordNsSeparator + :clojureKeyword]) +(def-eq-predicates kwWithNamedNs [:clojureKeywordNsColon :clojureKeywordNsColon + :clojureKeywordNs :clojureKeywordNsSeparator :clojureKeyword]) +(def-eq-predicates dispatchWithSymbolInside [:clojureDispatch + :clojureSymbol + :clojureSymbol + :clojureSymbol + :clojureSymbol + :clojureSymbol + :clojureSymbol + :clojureSymbol + :clojureSymbol + :clojureParen + :clojureSymbolNs + :clojureSymbolNs + :clojureSymbolNs + :clojureSymbolNs + :clojureSymbolNsSeparator + :clojureSymbol + :clojureSymbol + :clojureSymbol + :clojureSymbol + :clojureSymbol + :clojureParen]) (defpredicates character :clojureCharacter) (defpredicates regexp :clojureRegexp) (defpredicates regexp-delimiter :clojureRegexpDelimiter) @@ -108,23 +149,78 @@ (comment (test #'test-character-literals)) +(def emptyKeyword (keyword "")) + (defsyntaxtest keywords-test ["%s" [":1" kw ":A" kw ":a" kw - ":αβγ" kw - "::a" kw - ":a/b" kw - ":a:b" kw - ":a:b/:c:b" kw - ":a/b/c/d" kw - "::a/b" kw - "::" !kw - ":a:" !kw - ":a/" !kw - ; ":/" !kw ; This is legal, but for simplicity we do not match it - ":" !kw]]) + ":αβγ" (partial = [:clojureKeywordNsColon :clojureKeyword :clojureKeyword :clojureKeyword]) + "::a" kwCurrentNs + ":a/b" kwWithNs + ":a:b/:c:b" kwWithNs3_4 + ":a/b/c/d" symWithNs_tripleBody + "::a/b" kwWithNamedNs + "::" (partial = [emptyKeyword emptyKeyword]) + ":a:" (partial = [emptyKeyword :clojureSymbol emptyKeyword]) + ":a/" (partial = [:clojureKeywordNsColon :clojureKeywordNs :clojureKeywordNsSeparator]) + ":/" (partial = [:clojureKeywordNsColon :clojureKeywordNsSeparator]) + ":" (partial = [emptyKeyword]) + "a[:b/c]" (partial = [:clojureSymbol + :clojureParen + :clojureKeywordNsColon + :clojureKeywordNs + :clojureKeywordNsSeparator + :clojureKeyword + :clojureParen]) + ":a[:b/c]" (partial = [:clojureKeywordNsColon + :clojureKeyword + :clojureParen + :clojureKeywordNsColon + :clojureKeywordNs + :clojureKeywordNsSeparator + :clojureKeyword + :clojureParen])]]) + +(defsyntaxtest symbols-test + ["%s" + ["1" !sym + "1" !symWithNs + "A" sym + "a" sym + "αβγ" (partial = [:clojureSymbol :clojureSymbol :clojureSymbol]) + "a/b" (partial = [:clojureSymbolNs :clojureSymbolNsSeparator :clojureSymbol]) + "a:b" (partial = [:clojureSymbol :clojureSymbol :clojureSymbol]) + "a:b/:c:b" (partial = [:clojureSymbolNs + :clojureSymbolNs + :clojureSymbolNs + :clojureSymbolNsSeparator + :clojureSymbol + :clojureSymbol + :clojureSymbol + :clojureSymbol]) + "a/b/c/d" (partial = [:clojureSymbolNs :clojureSymbolNsSeparator + :clojureSymbolNs :clojureSymbolNsSeparator + :clojureSymbolNs :clojureSymbolNsSeparator + :clojureSymbol]) + "a:" !sym + "a:" !symWithNs + "a/" !sym + "a/" !symWithNs + "/" !sym + "#function[test/hello]" dispatchWithSymbolInside + "a[b/c]" (partial = [:clojureSymbol + :clojureParen + :clojureSymbolNs + :clojureSymbolNsSeparator + :clojureSymbol + :clojureParen]) + "#'a/b" (partial = [:clojureDispatch + :clojureDispatch + :clojureSymbolNs + :clojureSymbolNsSeparator + :clojureSymbol])]]) (comment (test #'keywords-test)) @@ -403,8 +499,7 @@ ;; (?>X) X, as an independent, non-capturing group "(?>X)" regexp-mod - "(?X)" !regexp-mod - ]] + "(?X)" !regexp-mod]] ["#%s" [;; Backslashes with character classes "\"[\\\\]\"" (partial = [:clojureRegexpDelimiter :clojureRegexpCharClass :clojureRegexpCharClass :clojureRegexpCharClass :clojureRegexpCharClass :clojureRegexpDelimiter]) diff --git a/clj/test/vim/test.clj b/clj/test/vim/test.clj index 7dd5bf3..cb8f539 100644 --- a/clj/test/vim/test.clj +++ b/clj/test/vim/test.clj @@ -90,21 +90,35 @@ ss λs))) contexts))))) -(defmacro defpredicates +(defmacro defpredicates-general "Create two complementary predicate vars, `sym` and `!sym`, which test if all members of a passed collection are equal to `kw`" - [sym kw] + [pred-eq pred-neq sym kw] `(do (defn ~sym ~(str "Returns true if all elements of coll equal " kw) - {:arglists '~'[coll]} + {:arglists (list '~'[coll])} [coll#] - (every? (partial = ~kw) coll#)) + (~pred-eq ~kw coll#)) (defn ~(symbol (str \! sym)) ~(str "Returns true if any elements of coll do not equal " kw) - {:arglists '~'[coll]} + {:arglists (list '~'[coll])} [coll#] - (boolean (some (partial not= ~kw) coll#))))) + (~pred-neq ~kw coll#)))) + +(defmacro defpredicates + "Create two complementary predicate vars, `sym` and `!sym`, which test if + all members of a passed collection are equal to `kw`" + [sym kw] + (let [pred-eq (fn [expected results] (every? (partial = expected) results)) + pred-neq (fn [expected results] (boolean (some (partial not= expected) results)))] + `(defpredicates-general ~pred-eq ~pred-neq ~sym ~kw))) + +(defmacro def-eq-predicates + "Create two complementary predicate vars, `sym` and `!sym`, which test if + input and result are equal" + [sym kw] + `(defpredicates-general = not= ~sym ~kw)) (defn benchmark [n file buf & exprs] (vim-exec file buf (format "Benchmark(%d, %s)" diff --git a/syntax/clojure.vim b/syntax/clojure.vim index d534200..5db618b 100644 --- a/syntax/clojure.vim +++ b/syntax/clojure.vim @@ -62,13 +62,16 @@ endif unlet! s:key delfunction s:syntax_keyword +syntax match clojureKeywordNs contained "\v[^ \n\r\t()\[\]{}";@^`~\\\/'#]+\ze\/" +syntax match clojureKeywordNsSeparator contained "/" +syntax match clojureKeywordNsColon contained "\v<:{1,2}" " Keywords are symbols: " static Pattern symbolPat = Pattern.compile("[:]?([\\D&&[^/]].*/)?([\\D&&[^/]][^/]*)"); " But they: " * Must not end in a : or / " * Must not have two adjacent colons except at the beginning " * Must not contain any reader metacharacters except for ' and # -syntax match clojureKeyword "\v<:{1,2}([^ \n\r\t()\[\]{}";@^`~\\/]+/)*[^ \n\r\t()\[\]{}";@^`~\\/]+:@1" +syntax match clojureKeyword "\v<:{1,2}([^ \n\r\t()\[\]{}";@^`~\\/]*/)*[^ \n\r\t()\[\]{}";@^`~\\/]*:@1" contains=clojureKeywordNs,clojureKeywordNsSeparator,clojureKeywordNsColon syntax match clojureStringEscape "\v\\%([\\btnfr"]|u\x{4}|[0-3]\o{2}|\o{1,2})" contained @@ -76,7 +79,9 @@ syntax region clojureString matchgroup=clojureStringDelimiter start=/"/ skip=/\\ syntax match clojureCharacter "\v\\%(o%([0-3]\o{2}|\o{1,2})|u\x{4}|newline|tab|space|return|backspace|formfeed|.)" -syntax match clojureSymbol "\v%([a-zA-Z!$&*_+=|<.>?-]|[^\x00-\x7F])+%(:?%([a-zA-Z0-9!#$%&*_+=|'<.>/?-]|[^\x00-\x7F]))*[#:]@1?-]|[^\x00-\x7F])+%(:?%([a-zA-Z0-9!#$%&*_+=|'<.>/?-]|[^\x00-\x7F]))*[#:]@1" @@ -162,12 +167,17 @@ syntax sync fromstart highlight default link clojureConstant Constant highlight default link clojureBoolean Boolean highlight default link clojureCharacter Character -highlight default link clojureKeyword Keyword highlight default link clojureNumber Number highlight default link clojureString String highlight default link clojureStringDelimiter String highlight default link clojureStringEscape Character +highlight default link clojureKeyword Keyword +highlight default link clojureKeywordNsColon clojureKeyword +highlight default link clojureKeywordNs clojureKeyword + +highlight default link clojureSymbolNs clojureSymbol + highlight default link clojureRegexp Constant highlight default link clojureRegexpDelimiter Constant highlight default link clojureRegexpEscape Character