Skip to content

Commit e8f84a6

Browse files
authoredOct 5, 2021
Lisp: Improved defun (#3130)
1 parent 4dde2e2 commit e8f84a6

File tree

4 files changed

+323
-50
lines changed

4 files changed

+323
-50
lines changed
 

‎components/prism-lisp.js

+35-35
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,37 @@
11
(function (Prism) {
2-
// Functions to construct regular expressions
3-
// simple form
4-
// e.g. (interactive ... or (interactive)
2+
/**
3+
* Functions to construct regular expressions
4+
* e.g. (interactive ... or (interactive)
5+
*
6+
* @param {string} name
7+
* @returns {RegExp}
8+
*/
59
function simple_form(name) {
6-
return RegExp('(\\()' + name + '(?=[\\s\\)])');
10+
return RegExp(/(\()/.source + '(?:' + name + ')' + /(?=[\s\)])/.source);
711
}
8-
// booleans and numbers
12+
/**
13+
* booleans and numbers
14+
*
15+
* @param {string} pattern
16+
* @returns {RegExp}
17+
*/
918
function primitive(pattern) {
10-
return RegExp('([\\s([])' + pattern + '(?=[\\s)])');
19+
return RegExp(/([\s([])/.source + '(?:' + pattern + ')' + /(?=[\s)])/.source);
1120
}
1221

1322
// Patterns in regular expressions
1423

1524
// Symbol name. See https://www.gnu.org/software/emacs/manual/html_node/elisp/Symbol-Type.html
1625
// & and : are excluded as they are usually used for special purposes
17-
var symbol = '[-+*/~!@$%^=<>{}\\w]+';
26+
var symbol = /(?!\d)[-+*/~!@$%^=<>{}\w]+/.source;
1827
// symbol starting with & used in function arguments
1928
var marker = '&' + symbol;
2029
// Open parenthesis for look-behind
2130
var par = '(\\()';
2231
var endpar = '(?=\\))';
2332
// End the pattern with look-ahead space
2433
var space = '(?=\\s)';
34+
var nestedPar = /(?:[^()]|\((?:[^()]|\((?:[^()]|\((?:[^()]|\((?:[^()]|\([^()]*\))*\))*\))*\))*\))*/.source;
2535

2636
var language = {
2737
// Three or four semicolons are considered a heading.
@@ -68,21 +78,21 @@
6878
},
6979
],
7080
declare: {
71-
pattern: simple_form('declare'),
81+
pattern: simple_form(/declare/.source),
7282
lookbehind: true,
7383
alias: 'keyword'
7484
},
7585
interactive: {
76-
pattern: simple_form('interactive'),
86+
pattern: simple_form(/interactive/.source),
7787
lookbehind: true,
7888
alias: 'keyword'
7989
},
8090
boolean: {
81-
pattern: primitive('(?:t|nil)'),
91+
pattern: primitive(/nil|t/.source),
8292
lookbehind: true
8393
},
8494
number: {
85-
pattern: primitive('[-+]?\\d+(?:\\.\\d*)?'),
95+
pattern: primitive(/[-+]?\d+(?:\.\d*)?/.source),
8696
lookbehind: true
8797
},
8898
defvar: {
@@ -94,13 +104,9 @@
94104
}
95105
},
96106
defun: {
97-
pattern: RegExp(
98-
par +
99-
'(?:cl-)?(?:defmacro|defun\\*?)\\s+' +
100-
symbol +
101-
'\\s+\\([\\s\\S]*?\\)'
102-
),
107+
pattern: RegExp(par + /(?:cl-)?(?:defmacro|defun\*?)\s+/.source + symbol + /\s+\(/.source + nestedPar + /\)/.source),
103108
lookbehind: true,
109+
greedy: true,
104110
inside: {
105111
keyword: /^(?:cl-)?def\S+/,
106112
// See below, this property needs to be defined later so that it can
@@ -116,6 +122,7 @@
116122
lambda: {
117123
pattern: RegExp(par + 'lambda\\s+\\(\\s*(?:&?' + symbol + '(?:\\s+&?' + symbol + ')*\\s*)?\\)'),
118124
lookbehind: true,
125+
greedy: true,
119126
inside: {
120127
keyword: /^lambda/,
121128
// See below, this property needs to be defined later so that it can
@@ -141,29 +148,22 @@
141148

142149
var arg = {
143150
'lisp-marker': RegExp(marker),
144-
rest: {
145-
argument: {
146-
pattern: RegExp(symbol),
147-
alias: 'variable'
148-
},
149-
varform: {
150-
pattern: RegExp(par + symbol + '\\s+\\S[\\s\\S]*' + endpar),
151-
lookbehind: true,
152-
inside: {
153-
string: language.string,
154-
boolean: language.boolean,
155-
number: language.number,
156-
symbol: language.symbol,
157-
punctuation: /[()]/
158-
}
159-
}
160-
}
151+
'varform': {
152+
pattern: RegExp(/\(/.source + symbol + /\s+(?=\S)/.source + nestedPar + /\)/.source),
153+
inside: language
154+
},
155+
'argument': {
156+
pattern: RegExp(/(^|[\s(])/.source + symbol),
157+
lookbehind: true,
158+
alias: 'variable'
159+
},
160+
rest: language
161161
};
162162

163163
var forms = '\\S+(?:\\s+\\S+)*';
164164

165165
var arglist = {
166-
pattern: RegExp(par + '[\\s\\S]*' + endpar),
166+
pattern: RegExp(par + nestedPar + endpar),
167167
lookbehind: true,
168168
inside: {
169169
'rest-vars': {

‎components/prism-lisp.min.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
+280-10
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,297 @@
11
(defun foo ())
22
(defun foo (bar))
3+
34
(defun foo (bar &body arg1) )
5+
46
(defun foo (bar &rest arg1) )
7+
58
(defun foo (bar &body arg1 arg2) )
9+
610
(defun foo (bar &key arg1) )
711
(defun foo (bar &key arg1 &allow-other-keys) )
12+
813
(defun foo (&optional arg1) )
14+
915
(defun defabc ())
1016

17+
(defun show-members (a b &rest values) (write (list a b values)))
18+
(cl-defun find-thing (thing &rest rest &key need &allow-other-keys)
19+
(or (apply 'cl-member thing thing-list :allow-other-keys t rest)
20+
(if need (error "Thing not found"))))
21+
22+
(defun foo (a b &optional (c 3 c-supplied-p))
23+
(list a b c c-supplied-p))
24+
25+
(defun foo (&key ((:apple a)) ((:box b) 0) ((:charlie c) 0 c-supplied-p))
26+
(list a b c c-supplied-p))
27+
1128
----------------------------------------------------
1229

1330
[
14-
["punctuation", "("], ["defun", [ ["keyword", "defun" ], ["function", "foo"], ["punctuation", "("], ["arguments", []], ["punctuation", ")"]]], ["punctuation", ")"],
15-
["punctuation", "("], ["defun", [ ["keyword", "defun" ], ["function", "foo"], ["punctuation", "("], ["arguments", [[ "argument", "bar" ]]], ["punctuation", ")"]]], ["punctuation", ")"],
16-
["punctuation", "("], ["defun", [ ["keyword", "defun" ], ["function", "foo"], ["punctuation", "("], ["arguments", [[ "argument", "bar" ], ["rest-vars", [["lisp-marker", "&body" ], ["argument", "arg1"]]]]], ["punctuation", ")"]] ], ["punctuation", ")"],
17-
["punctuation", "("], ["defun", [ ["keyword", "defun" ], ["function", "foo"], ["punctuation", "("], ["arguments", [[ "argument", "bar" ], ["rest-vars", [["lisp-marker", "&rest" ], ["argument", "arg1"]]]]], ["punctuation", ")"]] ], ["punctuation", ")"],
18-
["punctuation", "("], ["defun", [ ["keyword", "defun" ], ["function", "foo"], ["punctuation", "("], ["arguments", [[ "argument", "bar" ], ["rest-vars", [["lisp-marker", "&body" ], ["argument", "arg1"], ["argument", "arg2"]]]]], ["punctuation", ")"]] ], ["punctuation", ")"],
19-
["punctuation", "("], ["defun", [ ["keyword", "defun" ], ["function", "foo"], ["punctuation", "("], ["arguments", [[ "argument", "bar" ], ["keys", [["lisp-marker", "&key" ], ["argument", "arg1"]]]]], ["punctuation", ")"]] ], ["punctuation", ")"],
20-
["punctuation", "("], ["defun", [ ["keyword", "defun" ], ["function", "foo"], ["punctuation", "("], ["arguments", [[ "argument", "bar" ], ["keys", [["lisp-marker", "&key" ], ["argument", "arg1"], ["lisp-marker", "&allow-other-keys"]]]]], ["punctuation", ")"]] ], ["punctuation", ")"],
21-
["punctuation", "("], ["defun", [ ["keyword", "defun" ], ["function", "foo"], ["punctuation", "("], ["arguments", [["other-marker-vars", [["lisp-marker", "&optional" ], ["argument", "arg1"]]]]], ["punctuation", ")"]] ], ["punctuation", ")"],
22-
["punctuation", "("], ["defun", [ ["keyword", "defun" ], ["function", "defabc"], ["punctuation", "("], ["arguments", []], ["punctuation", ")"]]], ["punctuation", ")"]
31+
["punctuation", "("],
32+
["defun", [
33+
["keyword", "defun"],
34+
["function", "foo"],
35+
["punctuation", "("],
36+
["arguments", [
37+
]],
38+
["punctuation", ")"]
39+
]],
40+
["punctuation", ")"],
41+
42+
["punctuation", "("],
43+
["defun", [
44+
["keyword", "defun"],
45+
["function", "foo"],
46+
["punctuation", "("],
47+
["arguments", [
48+
["argument", "bar"]
49+
]],
50+
["punctuation", ")"]
51+
]],
52+
["punctuation", ")"],
53+
54+
["punctuation", "("],
55+
["defun", [
56+
["keyword", "defun"],
57+
["function", "foo"],
58+
["punctuation", "("],
59+
["arguments", [
60+
["argument", "bar"],
61+
["rest-vars", [
62+
["lisp-marker", "&body"],
63+
["argument", "arg1"]
64+
]]
65+
]],
66+
["punctuation", ")"]
67+
]],
68+
["punctuation", ")"],
69+
70+
["punctuation", "("],
71+
["defun", [
72+
["keyword", "defun"],
73+
["function", "foo"],
74+
["punctuation", "("],
75+
["arguments", [
76+
["argument", "bar"],
77+
["rest-vars", [
78+
["lisp-marker", "&rest"],
79+
["argument", "arg1"]
80+
]]
81+
]],
82+
["punctuation", ")"]
83+
]],
84+
["punctuation", ")"],
85+
86+
["punctuation", "("],
87+
["defun", [
88+
["keyword", "defun"],
89+
["function", "foo"],
90+
["punctuation", "("],
91+
["arguments", [
92+
["argument", "bar"],
93+
["rest-vars", [
94+
["lisp-marker", "&body"],
95+
["argument", "arg1"],
96+
["argument", "arg2"]
97+
]]
98+
]],
99+
["punctuation", ")"]
100+
]],
101+
["punctuation", ")"],
102+
103+
["punctuation", "("],
104+
["defun", [
105+
["keyword", "defun"],
106+
["function", "foo"],
107+
["punctuation", "("],
108+
["arguments", [
109+
["argument", "bar"],
110+
["keys", [
111+
["lisp-marker", "&key"],
112+
["argument", "arg1"]
113+
]]
114+
]],
115+
["punctuation", ")"]
116+
]],
117+
["punctuation", ")"],
118+
119+
["punctuation", "("],
120+
["defun", [
121+
["keyword", "defun"],
122+
["function", "foo"],
123+
["punctuation", "("],
124+
["arguments", [
125+
["argument", "bar"],
126+
["keys", [
127+
["lisp-marker", "&key"],
128+
["argument", "arg1"],
129+
["lisp-marker", "&allow-other-keys"]
130+
]]
131+
]],
132+
["punctuation", ")"]
133+
]],
134+
["punctuation", ")"],
135+
136+
["punctuation", "("],
137+
["defun", [
138+
["keyword", "defun"],
139+
["function", "foo"],
140+
["punctuation", "("],
141+
["arguments", [
142+
["other-marker-vars", [
143+
["lisp-marker", "&optional"],
144+
["argument", "arg1"]
145+
]]
146+
]],
147+
["punctuation", ")"]
148+
]],
149+
["punctuation", ")"],
150+
151+
["punctuation", "("],
152+
["defun", [
153+
["keyword", "defun"],
154+
["function", "defabc"],
155+
["punctuation", "("],
156+
["arguments", [
157+
]],
158+
["punctuation", ")"]
159+
]],
160+
["punctuation", ")"],
161+
162+
["punctuation", "("],
163+
["defun", [
164+
["keyword", "defun"],
165+
["function", "show-members"],
166+
["punctuation", "("],
167+
["arguments", [
168+
["argument", "a"],
169+
["argument", "b"],
170+
["rest-vars", [
171+
["lisp-marker", "&rest"],
172+
["argument", "values"]
173+
]]
174+
]],
175+
["punctuation", ")"]
176+
]],
177+
["punctuation", "("],
178+
["car", "write"],
179+
["punctuation", "("],
180+
["car", "list"],
181+
" a b values",
182+
["punctuation", ")"],
183+
["punctuation", ")"],
184+
["punctuation", ")"],
185+
186+
["punctuation", "("],
187+
["defun", [
188+
["keyword", "cl-defun"],
189+
["function", "find-thing"],
190+
["punctuation", "("],
191+
["arguments", [
192+
["argument", "thing"],
193+
["rest-vars", [
194+
["lisp-marker", "&rest"],
195+
["argument", "rest"],
196+
["lisp-marker", "&key"],
197+
["argument", "need"],
198+
["lisp-marker", "&allow-other-keys"]
199+
]]
200+
]],
201+
["punctuation", ")"]
202+
]],
203+
204+
["punctuation", "("],
205+
["keyword", "or"],
206+
["punctuation", "("],
207+
["car", "apply"],
208+
["quoted-symbol", "'cl-member"],
209+
" thing thing-list ",
210+
["lisp-property", ":allow-other-keys"],
211+
["boolean", "t"],
212+
" rest",
213+
["punctuation", ")"],
214+
215+
["punctuation", "("],
216+
["keyword", "if"],
217+
" need ",
218+
["punctuation", "("],
219+
["keyword", "error"],
220+
["string", ["\"Thing not found\""]],
221+
["punctuation", ")"],
222+
["punctuation", ")"],
223+
["punctuation", ")"],
224+
["punctuation", ")"],
225+
226+
["punctuation", "("],
227+
["defun", [
228+
["keyword", "defun"],
229+
["function", "foo"],
230+
["punctuation", "("],
231+
["arguments", [
232+
["argument", "a"],
233+
["argument", "b"],
234+
["other-marker-vars", [
235+
["lisp-marker", "&optional"],
236+
["varform", [
237+
["punctuation", "("],
238+
["car", "c"],
239+
["number", "3"],
240+
" c-supplied-p",
241+
["punctuation", ")"]
242+
]]
243+
]]
244+
]],
245+
["punctuation", ")"]
246+
]],
247+
248+
["punctuation", "("],
249+
["car", "list"],
250+
" a b c c-supplied-p",
251+
["punctuation", ")"],
252+
["punctuation", ")"],
253+
254+
["punctuation", "("],
255+
["defun", [
256+
["keyword", "defun"],
257+
["function", "foo"],
258+
["punctuation", "("],
259+
["arguments", [
260+
["keys", [
261+
["lisp-marker", "&key"],
262+
["punctuation", "("],
263+
["punctuation", "("],
264+
["lisp-property", ":apple"],
265+
["argument", "a"],
266+
["punctuation", ")"],
267+
["punctuation", ")"],
268+
["punctuation", "("],
269+
["punctuation", "("],
270+
["lisp-property", ":box"],
271+
["argument", "b"],
272+
["punctuation", ")"],
273+
["number", "0"],
274+
["punctuation", ")"],
275+
["punctuation", "("],
276+
["punctuation", "("],
277+
["lisp-property", ":charlie"],
278+
["argument", "c"],
279+
["punctuation", ")"],
280+
["number", "0"],
281+
["argument", "c-supplied-p"],
282+
["punctuation", ")"]
283+
]]
284+
]],
285+
["punctuation", ")"]
286+
]],
287+
288+
["punctuation", "("],
289+
["car", "list"],
290+
" a b c c-supplied-p",
291+
["punctuation", ")"],
292+
["punctuation", ")"]
23293
]
24294

25295
----------------------------------------------------
26296

27-
Checks for defun.
297+
Checks for defun.
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
11
()
22
( )
33
[]
4+
.
45
(
56

67
----------------------------------------------------
78

89
[
9-
["punctuation", "("], ["punctuation", ")"],
10-
["punctuation", "("], ["punctuation", ")"],
11-
["punctuation", "["], ["punctuation", "]"],
10+
["punctuation", "("], ["punctuation", ")"],
11+
["punctuation", "("], ["punctuation", ")"],
12+
["punctuation", "["], ["punctuation", "]"],
13+
["punctuation", "."],
1214
["punctuation", "("]
1315
]
16+
1417
----------------------------------------------------
1518

16-
Checks for punctuation.
19+
Checks for punctuation.

0 commit comments

Comments
 (0)
Please sign in to comment.