-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathgrammar.js
71 lines (60 loc) · 1.67 KB
/
grammar.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
const NEWLINE = /\r?\n/;
const ANYTHING = /[^\r\n]+/;
const ANYTHING_STARTING_NON_WHITESPACE = /\S[^\r\n]*/;
const LINE_CONTENT = /\S[^\r\n]*\r?\n/;
module.exports = grammar({
name: 'man',
// Control whitespace explicitly
extras: ($) => [],
externals: ($) => [$.footer],
rules: {
manual: ($) => seq(alias(ANYTHING, $.title), NEWLINE, $._body),
_body: ($) =>
repeat1(
choice(
$.section_heading,
$.footer,
NEWLINE,
),
),
block: ($) =>
prec.right(seq($._content, repeat(choice($._content, NEWLINE)))),
_content: ($) =>
seq(
// NOTE: `/ {7,}/` doesn't work?
/ {7} */,
choice(
$.reference,
token(prec(-1, /\S+/)),
),
repeat(choice(token(prec(-1, /\S+/)), $.reference, / +/)),
NEWLINE,
),
section_heading: ($) =>
seq(
alias(LINE_CONTENT, $.section_title),
repeat(choice($.block, $.subsection_heading, $.option_section)),
),
subsection_heading: ($) =>
prec.right(
seq(
/ {3}/,
alias(LINE_CONTENT, $.subsection_title),
repeat(choice($.block, $.option_section, NEWLINE)),
),
),
// TODO: Handle when a reference is hyphenated, as seen in `man 2 wait`
reference: ($) => /[a-zA-Z0-9_]+\(\d+\)/,
// extremely simple heuristic to highlight most option sections
option_section: ($) =>
prec.right(seq(
alias(
/ {7}([-+]\S+( +[A-Z]+| +<\S+>)?, +)*[-+]\S+( +[A-Z]+\s*\r?\n| +<\S+>\s*\r?\n)?/,
$.option,
),
optional(ANYTHING),
NEWLINE,
optional($.block),
)),
},
});