|
2 | 2 | Language: R
|
3 | 3 | Description: R is a free software environment for statistical computing and graphics.
|
4 | 4 | Author: Joe Cheng <[email protected]>
|
| 5 | +Contributors: Konrad Rudolph <[email protected]> |
5 | 6 | Website: https://www.r-project.org
|
6 | 7 | Category: scientific
|
7 | 8 | */
|
8 | 9 |
|
9 | 10 | export default function(hljs) {
|
10 |
| - var IDENT_RE = '([a-zA-Z]|\\.[a-zA-Z.])[a-zA-Z0-9._]*'; |
| 11 | + // Identifiers in R cannot start with `_`, but they can start with `.` if it |
| 12 | + // is not immediately followed by a digit. |
| 13 | + // R also supports quoted identifiers, which are near-arbitrary sequences |
| 14 | + // delimited by backticks (`…`), which may contain escape sequences. These are |
| 15 | + // handled in a separate mode. See `test/markup/r/names.txt` for examples. |
| 16 | + // FIXME: Support Unicode identifiers. |
| 17 | + const IDENT_RE = /(?:(?:[a-zA-Z]|\.[._a-zA-Z])[._a-zA-Z0-9]*)|\.(?!\d)/; |
11 | 18 |
|
12 | 19 | return {
|
13 | 20 | name: 'R',
|
| 21 | + |
| 22 | + keywords: { |
| 23 | + $pattern: IDENT_RE, |
| 24 | + keyword: |
| 25 | + 'function if in break next repeat else for while', |
| 26 | + literal: |
| 27 | + 'NULL NA TRUE FALSE Inf NaN NA_integer_|10 NA_real_|10 ' + |
| 28 | + 'NA_character_|10 NA_complex_|10', |
| 29 | + built_in: |
| 30 | + // Builtin constants |
| 31 | + 'LETTERS letters month.abb month.name pi T F ' + |
| 32 | + // Primitive functions |
| 33 | + // These are all the functions in `base` that are implemented as a |
| 34 | + // `.Primitive`, minus those functions that are also keywords. |
| 35 | + 'abs acos acosh all any anyNA Arg as.call as.character' + |
| 36 | + 'as.complex as.double as.environment as.integer as.logical' + |
| 37 | + 'as.null.default as.numeric as.raw asin asinh atan atanh attr' + |
| 38 | + 'attributes baseenv browser c call ceiling class Conj cos cosh' + |
| 39 | + 'cospi cummax cummin cumprod cumsum digamma dim dimnames' + |
| 40 | + 'emptyenv exp expression floor forceAndCall gamma gc.time' + |
| 41 | + 'globalenv Im interactive invisible is.array is.atomic is.call' + |
| 42 | + 'is.character is.complex is.double is.environment is.expression' + |
| 43 | + 'is.finite is.function is.infinite is.integer is.language' + |
| 44 | + 'is.list is.logical is.matrix is.na is.name is.nan is.null' + |
| 45 | + 'is.numeric is.object is.pairlist is.raw is.recursive is.single' + |
| 46 | + 'is.symbol lazyLoadDBfetch length lgamma list log max min' + |
| 47 | + 'missing Mod names nargs nzchar oldClass on.exit pos.to.env' + |
| 48 | + 'proc.time prod quote range Re rep retracemem return round' + |
| 49 | + 'seq_along seq_len seq.int sign signif sin sinh sinpi sqrt' + |
| 50 | + 'standardGeneric substitute sum switch tan tanh tanpi tracemem' + |
| 51 | + 'trigamma trunc unclass untracemem UseMethod xtfrm', |
| 52 | + }, |
| 53 | + |
14 | 54 | contains: [
|
| 55 | + // Roxygen comments |
| 56 | + hljs.COMMENT( |
| 57 | + /#'/, |
| 58 | + /$/, |
| 59 | + { |
| 60 | + contains: [ |
| 61 | + { |
| 62 | + // Handle `@examples` separately to cause all subsequent code |
| 63 | + // until the next `@`-tag on its own line to be kept as-is, |
| 64 | + // preventing highlighting. This code is example R code, so nested |
| 65 | + // doctags shouldn’t be treated as such. See |
| 66 | + // `test/markup/r/roxygen.txt` for an example. |
| 67 | + className: 'doctag', |
| 68 | + begin: '@examples', |
| 69 | + starts: { |
| 70 | + contains: [ |
| 71 | + { begin: /\n/ }, |
| 72 | + { |
| 73 | + begin: /#'\s*(?=@[a-zA-Z]+)/, |
| 74 | + endsParent: true, |
| 75 | + }, |
| 76 | + { |
| 77 | + begin: /#'/, |
| 78 | + end: /$/, |
| 79 | + excludeBegin: true, |
| 80 | + } |
| 81 | + ] |
| 82 | + } |
| 83 | + }, |
| 84 | + { |
| 85 | + // Handle `@param` to highlight the parameter name following |
| 86 | + // after. |
| 87 | + className: 'doctag', |
| 88 | + begin: '@param', |
| 89 | + end: /$/, |
| 90 | + contains: [ |
| 91 | + { |
| 92 | + className: 'variable', |
| 93 | + variants: [ |
| 94 | + { begin: IDENT_RE }, |
| 95 | + { begin: /`(?:\\.|[^`])+`/ } |
| 96 | + ], |
| 97 | + endsParent: true |
| 98 | + } |
| 99 | + ] |
| 100 | + }, |
| 101 | + { |
| 102 | + className: 'doctag', |
| 103 | + begin: /@[a-zA-Z]+/ |
| 104 | + }, |
| 105 | + { |
| 106 | + className: 'meta-keyword', |
| 107 | + begin: /\\[a-zA-Z]+/, |
| 108 | + } |
| 109 | + ] |
| 110 | + } |
| 111 | + ), |
| 112 | + |
15 | 113 | hljs.HASH_COMMENT_MODE,
|
| 114 | + |
16 | 115 | {
|
17 |
| - begin: IDENT_RE, |
18 |
| - keywords: { |
19 |
| - $pattern: IDENT_RE, |
20 |
| - keyword: |
21 |
| - 'function if in break next repeat else for return switch while try tryCatch ' + |
22 |
| - 'stop warning require library attach detach source setMethod setGeneric ' + |
23 |
| - 'setGroupGeneric setClass ...', |
24 |
| - literal: |
25 |
| - 'NULL NA TRUE FALSE T F Inf NaN NA_integer_|10 NA_real_|10 NA_character_|10 ' + |
26 |
| - 'NA_complex_|10' |
27 |
| - }, |
28 |
| - relevance: 0 |
29 |
| - }, |
30 |
| - { |
31 |
| - // hex value |
32 |
| - className: 'number', |
33 |
| - begin: "0[xX][0-9a-fA-F]+[Li]?\\b", |
34 |
| - relevance: 0 |
35 |
| - }, |
36 |
| - { |
37 |
| - // explicit integer |
38 |
| - className: 'number', |
39 |
| - begin: "\\d+(?:[eE][+\\-]?\\d*)?L\\b", |
40 |
| - relevance: 0 |
41 |
| - }, |
42 |
| - { |
43 |
| - // number with trailing decimal |
44 |
| - className: 'number', |
45 |
| - begin: "\\d+\\.(?!\\d)(?:i\\b)?", |
46 |
| - relevance: 0 |
| 116 | + className: 'string', |
| 117 | + contains: [hljs.BACKSLASH_ESCAPE], |
| 118 | + variants: [ |
| 119 | + hljs.END_SAME_AS_BEGIN({ begin: /[rR]"(-*)\(/, end: /\)(-*)"/ }), |
| 120 | + hljs.END_SAME_AS_BEGIN({ begin: /[rR]"(-*)\{/, end: /\}(-*)"/ }), |
| 121 | + hljs.END_SAME_AS_BEGIN({ begin: /[rR]"(-*)\[/, end: /\](-*)"/ }), |
| 122 | + hljs.END_SAME_AS_BEGIN({ begin: /[rR]'(-*)\(/, end: /\)(-*)'/ }), |
| 123 | + hljs.END_SAME_AS_BEGIN({ begin: /[rR]'(-*)\{/, end: /\}(-*)'/ }), |
| 124 | + hljs.END_SAME_AS_BEGIN({ begin: /[rR]'(-*)\[/, end: /\](-*)'/ }), |
| 125 | + {begin: '"', end: '"', relevance: 0}, |
| 126 | + {begin: "'", end: "'", relevance: 0} |
| 127 | + ], |
47 | 128 | },
|
| 129 | + |
48 | 130 | {
|
49 |
| - // number |
50 | 131 | className: 'number',
|
51 |
| - begin: "\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d*)?i?\\b", |
| 132 | + variants: [ |
| 133 | + // Special case: only hexadecimal binary powers can contain fractions. |
| 134 | + { begin: /(?<![a-zA-Z0-9._])0[xX][0-9a-fA-F]+\.[0-9a-fA-F]*[pP][+-]?\d+i?/ }, |
| 135 | + { begin: /(?<![a-zA-Z0-9._])0[xX][0-9a-fA-F]+([pP][+-]?\d+)?[Li]?/ }, |
| 136 | + { begin: /(?<![a-zA-Z0-9._])(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?[Li]?/ } |
| 137 | + ], |
52 | 138 | relevance: 0
|
53 | 139 | },
|
| 140 | + |
54 | 141 | {
|
55 |
| - // number with leading decimal |
56 |
| - className: 'number', |
57 |
| - begin: "\\.\\d+(?:[eE][+\\-]?\\d*)?i?\\b", |
58 |
| - relevance: 0 |
| 142 | + // infix operator |
| 143 | + begin: '%', |
| 144 | + end: '%' |
59 | 145 | },
|
60 | 146 |
|
61 | 147 | {
|
62 | 148 | // escaped identifier
|
63 | 149 | begin: '`',
|
64 | 150 | end: '`',
|
65 |
| - relevance: 0 |
66 |
| - }, |
67 |
| - |
68 |
| - { |
69 |
| - className: 'string', |
70 |
| - contains: [hljs.BACKSLASH_ESCAPE], |
71 |
| - variants: [ |
72 |
| - {begin: '"', end: '"'}, |
73 |
| - {begin: "'", end: "'"} |
| 151 | + contains: [ |
| 152 | + { begin: /\\./ } |
74 | 153 | ]
|
75 | 154 | }
|
76 | 155 | ]
|
|
0 commit comments