1 | const NEWLINE = /\r?\n/;
|
2 | const WHITE_SPACE = /[\t\f\v ]+/;
|
3 | const ANYTHING = /[^\r\n]+/;
|
4 |
|
5 | module.exports = grammar({
|
6 | name: "gitdiff",
|
7 |
|
8 | extras: ($) => [WHITE_SPACE],
|
9 |
|
10 | rules: {
|
11 | source: ($) => repeat(seq($._line, NEWLINE)),
|
12 |
|
13 | _line: ($) =>
|
14 | choice(
|
15 | $.command,
|
16 | $.file_change,
|
17 | $.binary_change,
|
18 | $.index,
|
19 | $.similarity,
|
20 | $.file,
|
21 | $.location,
|
22 | $.addition,
|
23 | $.deletion,
|
24 | $.context
|
25 | ),
|
26 |
|
27 | command: ($) => iseq("diff", "--git", $.filename),
|
28 |
|
29 | file_change: ($) =>
|
30 | iseq(
|
31 | field("kind", choice("new", "deleted", "rename")),
|
32 | choice(
|
33 | seq("file", "mode", $.mode),
|
34 | seq(choice("from", "to"), $.filename)
|
35 | )
|
36 | ),
|
37 |
|
38 | binary_change: ($) =>
|
39 | iseq("Binary", "files", $.filename, "and", $.filename, "differ"),
|
40 |
|
41 | index: ($) => iseq("index", $.commit, "..", $.commit, optional($.mode)),
|
42 |
|
43 | similarity: ($) => iseq("similarity", "index", field("score", /\d+/), "%"),
|
44 |
|
45 | file: ($) => iseq(field("kind", choice("---", "+++")), $.filename),
|
46 |
|
47 | location: ($) => iseq("@@", $.linerange, $.linerange, "@@", ANYTHING),
|
48 |
|
49 | addition: ($) => iseq("+", optional(ANYTHING)),
|
50 |
|
51 | deletion: ($) => iseq("-", optional(ANYTHING)),
|
52 |
|
53 | context: ($) => token(prec(-1, ANYTHING)),
|
54 |
|
55 | linerange: ($) => /[-\+]\d+,\d+/,
|
56 | filename: ($) => repeat1(/\S+/),
|
57 | commit: ($) => /[a-f0-9]{7,40}/,
|
58 | mode: ($) => /\d+/,
|
59 | },
|
60 | });
|
61 |
|
62 | function iseq(start_token, ...tokens) {
|
63 | return seq(token.immediate(start_token), ...tokens);
|
64 | }
|