Skip to content

Commit 06196d8

Browse files
axvrInvertisment
andcommitted
Keyword and Symbol prefix matching (#27)
Co-authored-by: Martynas M <[email protected]>
2 parents b21188c + 7d46e29 commit 06196d8

File tree

3 files changed

+144
-25
lines changed

3 files changed

+144
-25
lines changed

Diff for: clj/test/vim/syntax_test.clj

+111-16
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,54 @@
22
;; Joel Holdbrooks <[email protected]>
33

44
(ns vim.syntax-test
5-
(:require [vim.test :refer [defpredicates defsyntaxtest]]))
5+
(:require [vim.test :refer [defpredicates defsyntaxtest def-eq-predicates]]))
66

77
;; defpredicates also register not-equal vars, this is just for clj-kondo
88
(declare !number !regexp-escape !regexp-posix-char-class !regexp-quantifier)
99

1010
(defpredicates number :clojureNumber)
11-
(defpredicates kw :clojureKeyword)
11+
(def-eq-predicates kw [:clojureKeywordNsColon :clojureKeyword])
12+
(def-eq-predicates kwCurrentNs [:clojureKeywordNsColon :clojureKeywordNsColon :clojureKeyword])
13+
(def-eq-predicates kwWithNs [:clojureKeywordNsColon :clojureKeywordNs :clojureKeywordNsSeparator :clojureKeyword])
14+
(def-eq-predicates kwWithNs3_4 [:clojureKeywordNsColon
15+
:clojureKeywordNs
16+
:clojureKeywordNs
17+
:clojureKeywordNs
18+
:clojureKeywordNsSeparator
19+
:clojureKeyword
20+
:clojureKeyword
21+
:clojureKeyword
22+
:clojureKeyword])
23+
(def-eq-predicates sym [:clojureSymbol])
24+
(def-eq-predicates symWithNs [:clojureSymbol])
25+
(def-eq-predicates symWithNs_tripleBody [:clojureKeywordNsColon
26+
:clojureKeywordNs :clojureKeywordNsSeparator
27+
:clojureKeywordNs :clojureKeywordNsSeparator
28+
:clojureKeywordNs :clojureKeywordNsSeparator
29+
:clojureKeyword])
30+
(def-eq-predicates kwWithNamedNs [:clojureKeywordNsColon :clojureKeywordNsColon
31+
:clojureKeywordNs :clojureKeywordNsSeparator :clojureKeyword])
32+
(def-eq-predicates dispatchWithSymbolInside [:clojureDispatch
33+
:clojureSymbol
34+
:clojureSymbol
35+
:clojureSymbol
36+
:clojureSymbol
37+
:clojureSymbol
38+
:clojureSymbol
39+
:clojureSymbol
40+
:clojureSymbol
41+
:clojureParen
42+
:clojureSymbolNs
43+
:clojureSymbolNs
44+
:clojureSymbolNs
45+
:clojureSymbolNs
46+
:clojureSymbolNsSeparator
47+
:clojureSymbol
48+
:clojureSymbol
49+
:clojureSymbol
50+
:clojureSymbol
51+
:clojureSymbol
52+
:clojureParen])
1253
(defpredicates character :clojureCharacter)
1354
(defpredicates regexp :clojureRegexp)
1455
(defpredicates regexp-delimiter :clojureRegexpDelimiter)
@@ -108,23 +149,78 @@
108149

109150
(comment (test #'test-character-literals))
110151

152+
(def emptyKeyword (keyword ""))
153+
111154
(defsyntaxtest keywords-test
112155
["%s"
113156
[":1" kw
114157
":A" kw
115158
":a" kw
116-
":αβγ" kw
117-
"::a" kw
118-
":a/b" kw
119-
":a:b" kw
120-
":a:b/:c:b" kw
121-
":a/b/c/d" kw
122-
"::a/b" kw
123-
"::" !kw
124-
":a:" !kw
125-
":a/" !kw
126-
; ":/" !kw ; This is legal, but for simplicity we do not match it
127-
":" !kw]])
159+
":αβγ" (partial = [:clojureKeywordNsColon :clojureKeyword :clojureKeyword :clojureKeyword])
160+
"::a" kwCurrentNs
161+
":a/b" kwWithNs
162+
":a:b/:c:b" kwWithNs3_4
163+
":a/b/c/d" symWithNs_tripleBody
164+
"::a/b" kwWithNamedNs
165+
"::" (partial = [emptyKeyword emptyKeyword])
166+
":a:" (partial = [emptyKeyword :clojureSymbol emptyKeyword])
167+
":a/" (partial = [:clojureKeywordNsColon :clojureKeywordNs :clojureKeywordNsSeparator])
168+
":/" (partial = [:clojureKeywordNsColon :clojureKeywordNsSeparator])
169+
":" (partial = [emptyKeyword])
170+
"a[:b/c]" (partial = [:clojureSymbol
171+
:clojureParen
172+
:clojureKeywordNsColon
173+
:clojureKeywordNs
174+
:clojureKeywordNsSeparator
175+
:clojureKeyword
176+
:clojureParen])
177+
":a[:b/c]" (partial = [:clojureKeywordNsColon
178+
:clojureKeyword
179+
:clojureParen
180+
:clojureKeywordNsColon
181+
:clojureKeywordNs
182+
:clojureKeywordNsSeparator
183+
:clojureKeyword
184+
:clojureParen])]])
185+
186+
(defsyntaxtest symbols-test
187+
["%s"
188+
["1" !sym
189+
"1" !symWithNs
190+
"A" sym
191+
"a" sym
192+
"αβγ" (partial = [:clojureSymbol :clojureSymbol :clojureSymbol])
193+
"a/b" (partial = [:clojureSymbolNs :clojureSymbolNsSeparator :clojureSymbol])
194+
"a:b" (partial = [:clojureSymbol :clojureSymbol :clojureSymbol])
195+
"a:b/:c:b" (partial = [:clojureSymbolNs
196+
:clojureSymbolNs
197+
:clojureSymbolNs
198+
:clojureSymbolNsSeparator
199+
:clojureSymbol
200+
:clojureSymbol
201+
:clojureSymbol
202+
:clojureSymbol])
203+
"a/b/c/d" (partial = [:clojureSymbolNs :clojureSymbolNsSeparator
204+
:clojureSymbolNs :clojureSymbolNsSeparator
205+
:clojureSymbolNs :clojureSymbolNsSeparator
206+
:clojureSymbol])
207+
"a:" !sym
208+
"a:" !symWithNs
209+
"a/" !sym
210+
"a/" !symWithNs
211+
"/" !sym
212+
"#function[test/hello]" dispatchWithSymbolInside
213+
"a[b/c]" (partial = [:clojureSymbol
214+
:clojureParen
215+
:clojureSymbolNs
216+
:clojureSymbolNsSeparator
217+
:clojureSymbol
218+
:clojureParen])
219+
"#'a/b" (partial = [:clojureDispatch
220+
:clojureDispatch
221+
:clojureSymbolNs
222+
:clojureSymbolNsSeparator
223+
:clojureSymbol])]])
128224

129225
(comment (test #'keywords-test))
130226

@@ -403,8 +499,7 @@
403499
;; (?>X) X, as an independent, non-capturing group
404500
"(?>X)" regexp-mod
405501

406-
"(?X)" !regexp-mod
407-
]]
502+
"(?X)" !regexp-mod]]
408503
["#%s"
409504
[;; Backslashes with character classes
410505
"\"[\\\\]\"" (partial = [:clojureRegexpDelimiter :clojureRegexpCharClass :clojureRegexpCharClass :clojureRegexpCharClass :clojureRegexpCharClass :clojureRegexpDelimiter])

Diff for: clj/test/vim/test.clj

+20-6
Original file line numberDiff line numberDiff line change
@@ -90,21 +90,35 @@
9090
ss λs)))
9191
contexts)))))
9292

93-
(defmacro defpredicates
93+
(defmacro defpredicates-general
9494
"Create two complementary predicate vars, `sym` and `!sym`, which test if
9595
all members of a passed collection are equal to `kw`"
96-
[sym kw]
96+
[pred-eq pred-neq sym kw]
9797
`(do
9898
(defn ~sym
9999
~(str "Returns true if all elements of coll equal " kw)
100-
{:arglists '~'[coll]}
100+
{:arglists (list '~'[coll])}
101101
[coll#]
102-
(every? (partial = ~kw) coll#))
102+
(~pred-eq ~kw coll#))
103103
(defn ~(symbol (str \! sym))
104104
~(str "Returns true if any elements of coll do not equal " kw)
105-
{:arglists '~'[coll]}
105+
{:arglists (list '~'[coll])}
106106
[coll#]
107-
(boolean (some (partial not= ~kw) coll#)))))
107+
(~pred-neq ~kw coll#))))
108+
109+
(defmacro defpredicates
110+
"Create two complementary predicate vars, `sym` and `!sym`, which test if
111+
all members of a passed collection are equal to `kw`"
112+
[sym kw]
113+
(let [pred-eq (fn [expected results] (every? (partial = expected) results))
114+
pred-neq (fn [expected results] (boolean (some (partial not= expected) results)))]
115+
`(defpredicates-general ~pred-eq ~pred-neq ~sym ~kw)))
116+
117+
(defmacro def-eq-predicates
118+
"Create two complementary predicate vars, `sym` and `!sym`, which test if
119+
input and result are equal"
120+
[sym kw]
121+
`(defpredicates-general = not= ~sym ~kw))
108122

109123
(defn benchmark [n file buf & exprs]
110124
(vim-exec file buf (format "Benchmark(%d, %s)"

Diff for: syntax/clojure.vim

+13-3
Original file line numberDiff line numberDiff line change
@@ -62,21 +62,26 @@ endif
6262
unlet! s:key
6363
delfunction s:syntax_keyword
6464

65+
syntax match clojureKeywordNs contained "\v[^ \n\r\t()\[\]{}";@^`~\\\/'#]+\ze\/"
66+
syntax match clojureKeywordNsSeparator contained "/"
67+
syntax match clojureKeywordNsColon contained "\v<:{1,2}"
6568
" Keywords are symbols:
6669
" static Pattern symbolPat = Pattern.compile("[:]?([\\D&&[^/]].*/)?([\\D&&[^/]][^/]*)");
6770
" But they:
6871
" * Must not end in a : or /
6972
" * Must not have two adjacent colons except at the beginning
7073
" * Must not contain any reader metacharacters except for ' and #
71-
syntax match clojureKeyword "\v<:{1,2}([^ \n\r\t()\[\]{}";@^`~\\/]+/)*[^ \n\r\t()\[\]{}";@^`~\\/]+:@1<!>"
74+
syntax match clojureKeyword "\v<:{1,2}([^ \n\r\t()\[\]{}";@^`~\\/]*/)*[^ \n\r\t()\[\]{}";@^`~\\/]*:@1<!>" contains=clojureKeywordNs,clojureKeywordNsSeparator,clojureKeywordNsColon
7275

7376
syntax match clojureStringEscape "\v\\%([\\btnfr"]|u\x{4}|[0-3]\o{2}|\o{1,2})" contained
7477

7578
syntax region clojureString matchgroup=clojureStringDelimiter start=/"/ skip=/\\\\\|\\"/ end=/"/ contains=clojureStringEscape,@Spell
7679

7780
syntax match clojureCharacter "\v\\%(o%([0-3]\o{2}|\o{1,2})|u\x{4}|newline|tab|space|return|backspace|formfeed|.)"
7881

79-
syntax match clojureSymbol "\v%([a-zA-Z!$&*_+=|<.>?-]|[^\x00-\x7F])+%(:?%([a-zA-Z0-9!#$%&*_+=|'<.>/?-]|[^\x00-\x7F]))*[#:]@1<!"
82+
syntax match clojureSymbolNs contained "\v[^ \n\r\t()\[\]{}";@^`~\\\/'#]+\ze\/"
83+
syntax match clojureSymbolNsSeparator contained "/"
84+
syntax match clojureSymbol "\v%([a-zA-Z!$&*_+=|<.>?-]|[^\x00-\x7F])+%(:?%([a-zA-Z0-9!#$%&*_+=|'<.>/?-]|[^\x00-\x7F]))*[#:]@1<!" contains=clojureSymbolNs,clojureSymbolNsSeparator
8085

8186
" NB. Correct matching of radix literals was removed for better performance.
8287
syntax match clojureNumber "\v<[-+]?%(%([2-9]|[12]\d|3[0-6])[rR][[:alnum:]]+|%(0\o*|0x\x+|[1-9]\d*)N?|%(0|[1-9]\d*|%(0|[1-9]\d*)\.\d*)%(M|[eE][-+]?\d+)?|%(0|[1-9]\d*)/%(0|[1-9]\d*))>"
@@ -162,12 +167,17 @@ syntax sync fromstart
162167
highlight default link clojureConstant Constant
163168
highlight default link clojureBoolean Boolean
164169
highlight default link clojureCharacter Character
165-
highlight default link clojureKeyword Keyword
166170
highlight default link clojureNumber Number
167171
highlight default link clojureString String
168172
highlight default link clojureStringDelimiter String
169173
highlight default link clojureStringEscape Character
170174

175+
highlight default link clojureKeyword Keyword
176+
highlight default link clojureKeywordNsColon clojureKeyword
177+
highlight default link clojureKeywordNs clojureKeyword
178+
179+
highlight default link clojureSymbolNs clojureSymbol
180+
171181
highlight default link clojureRegexp Constant
172182
highlight default link clojureRegexpDelimiter Constant
173183
highlight default link clojureRegexpEscape Character

0 commit comments

Comments
 (0)