Skip to content

Commit 5cef3ba

Browse files
authoredNov 21, 2021
Nano SystemHighlighter: add theme system (#752)
1 parent 4010953 commit 5cef3ba

File tree

11 files changed

+271
-111
lines changed

11 files changed

+271
-111
lines changed
 

‎builtins/src/main/java/org/jline/builtins/Nano.java

+121-34
Original file line numberDiff line numberDiff line change
@@ -1426,17 +1426,31 @@ protected static SyntaxHighlighter build(List<Path> syntaxFiles, String file, St
14261426
, boolean ignoreErrors) {
14271427
SyntaxHighlighter out = new SyntaxHighlighter();
14281428
List<HighlightRule> defaultRules = new ArrayList<>();
1429+
Map<String, String> colorTheme = new HashMap<>();
14291430
try {
14301431
if (syntaxName == null || (syntaxName != null && !syntaxName.equals("none"))) {
14311432
for (Path p : syntaxFiles) {
14321433
try {
1433-
NanorcParser parser = new NanorcParser(p, syntaxName, file);
1434-
parser.parse();
1435-
if (parser.matches()) {
1436-
out.addRules(parser.getHighlightRules());
1437-
return out;
1438-
} else if (parser.isDefault()) {
1439-
defaultRules.addAll(parser.getHighlightRules());
1434+
if (colorTheme.isEmpty() && p.getFileName().toString().endsWith(".nanorctheme")) {
1435+
try (BufferedReader reader = new BufferedReader(new FileReader(p.toFile()))) {
1436+
String line;
1437+
while ((line = reader.readLine()) != null) {
1438+
line = line.trim();
1439+
if (line.length() > 0 && !line.startsWith("#")) {
1440+
List<String> parts = Arrays.asList(line.split("\\s+", 2));
1441+
colorTheme.put(parts.get(0), parts.get(1));
1442+
}
1443+
}
1444+
}
1445+
} else {
1446+
NanorcParser parser = new NanorcParser(p, syntaxName, file, colorTheme);
1447+
parser.parse();
1448+
if (parser.matches()) {
1449+
out.addRules(parser.getHighlightRules());
1450+
return out;
1451+
} else if (parser.isDefault()) {
1452+
defaultRules.addAll(parser.getHighlightRules());
1453+
}
14401454
}
14411455
} catch (IOException e) {
14421456
// ignore
@@ -1464,8 +1478,8 @@ public static SyntaxHighlighter build(Path nanorc, String syntaxName) {
14641478
List<Path> syntaxFiles = new ArrayList<>();
14651479
try {
14661480
try (BufferedReader reader = new BufferedReader(new FileReader(nanorc.toFile()))) {
1467-
String line = reader.readLine();
1468-
while (line != null) {
1481+
String line;
1482+
while ((line = reader.readLine()) != null) {
14691483
line = line.trim();
14701484
if (line.length() > 0 && !line.startsWith("#")) {
14711485
List<String> parts = Parser.split(line);
@@ -1481,9 +1495,19 @@ public static SyntaxHighlighter build(Path nanorc, String syntaxName) {
14811495
} else {
14821496
syntaxFiles.add(Paths.get(parts.get(1)));
14831497
}
1498+
} else if(parts.get(0).equals("theme")) {
1499+
if (parts.get(1).contains("*") || parts.get(1).contains("?")) {
1500+
PathMatcher pathMatcher = FileSystems.getDefault().getPathMatcher("glob:" + parts.get(1));
1501+
Optional<Path> theme = Files.find(Paths.get(new File(parts.get(1)).getParent()), Integer.MAX_VALUE, (path, f) -> pathMatcher.matches(path))
1502+
.findFirst();
1503+
if (theme.isPresent()) {
1504+
syntaxFiles.add(0, theme.get());
1505+
}
1506+
} else {
1507+
syntaxFiles.add(0, Paths.get(parts.get(1)));
1508+
}
14841509
}
14851510
}
1486-
line = reader.readLine();
14871511
}
14881512
}
14891513
out = build(syntaxFiles, null, syntaxName);
@@ -1678,11 +1702,13 @@ private static class NanorcParser {
16781702
private final String target;
16791703
private final List<HighlightRule> highlightRules = new ArrayList<>();
16801704
private final BufferedReader reader;
1705+
private Map<String, String> colorTheme = new HashMap<>();
16811706
private boolean matches = false;
16821707
private String syntaxName = "unknown";
16831708

1684-
public NanorcParser(Path file, String name, String target) throws IOException {
1709+
public NanorcParser(Path file, String name, String target, Map<String, String> colorTheme) throws IOException {
16851710
this(new Source.PathSource(file, null).read(), name, target);
1711+
this.colorTheme = colorTheme;
16861712
}
16871713

16881714
public NanorcParser(InputStream in, String name, String target) {
@@ -1698,21 +1724,7 @@ public void parse() throws IOException {
16981724
idx++;
16991725
line = line.trim();
17001726
if (line.length() > 0 && !line.startsWith("#")) {
1701-
line = line.replaceAll("\\\\<", "\\\\b")
1702-
.replaceAll("\\\\>", "\\\\b")
1703-
.replaceAll("\\[:alnum:]", "\\\\p{Alnum}")
1704-
.replaceAll("\\[:alpha:]", "\\\\p{Alpha}")
1705-
.replaceAll("\\[:blank:]", "\\\\p{Blank}")
1706-
.replaceAll("\\[:cntrl:]", "\\\\p{Cntrl}")
1707-
.replaceAll("\\[:digit:]", "\\\\p{Digit}")
1708-
.replaceAll("\\[:graph:]", "\\\\p{Graph}")
1709-
.replaceAll("\\[:lower:]", "\\\\p{Lower}")
1710-
.replaceAll("\\[:print:]", "\\\\p{Print}")
1711-
.replaceAll("\\[:punct:]", "\\\\p{Punct}")
1712-
.replaceAll("\\[:space:]", "\\\\s")
1713-
.replaceAll("\\[:upper:]", "\\\\p{Upper}")
1714-
.replaceAll("\\[:xdigit:]", "\\\\p{XDigit}");
1715-
List<String> parts = Parser.split(line);
1727+
List<String> parts = Parser.split(fixRegexes(line));
17161728
if (parts.get(0).equals("syntax")) {
17171729
syntaxName = parts.get(1);
17181730
List<Pattern> filePatterns = new ArrayList<>();
@@ -1726,7 +1738,7 @@ public void parse() throws IOException {
17261738
for (int i = 2; i < parts.size(); i++) {
17271739
filePatterns.add(Pattern.compile(parts.get(i)));
17281740
}
1729-
for (Pattern p: filePatterns) {
1741+
for (Pattern p : filePatterns) {
17301742
if (p.matcher(target).find()) {
17311743
matches = true;
17321744
break;
@@ -1738,16 +1750,81 @@ public void parse() throws IOException {
17381750
} else {
17391751
matches = true;
17401752
}
1741-
} else if (parts.get(0).equals("color")) {
1742-
addHighlightRule(syntaxName + idx, parts, false);
1743-
} else if (parts.get(0).equals("icolor")) {
1744-
addHighlightRule(syntaxName + idx, parts, true);
1753+
} else if (!addHighlightRule(parts, idx) && parts.get(0).matches("\\+[A-Z_]+")) {
1754+
String key = themeKey(parts.get(0));
1755+
if (colorTheme.containsKey(key)) {
1756+
for (String l : colorTheme.get(key).split("\\\\n")) {
1757+
idx++;
1758+
addHighlightRule(Parser.split(fixRegexes(l)), idx);
1759+
}
1760+
} else {
1761+
Log.warn("Unknown token type: ", key);
1762+
}
17451763
}
17461764
}
17471765
}
17481766
reader.close();
17491767
}
17501768

1769+
private String fixRegexes(String line) {
1770+
return line.replaceAll("\\\\<", "\\\\b")
1771+
.replaceAll("\\\\>", "\\\\b")
1772+
.replaceAll("\\[:alnum:]", "\\\\p{Alnum}")
1773+
.replaceAll("\\[:alpha:]", "\\\\p{Alpha}")
1774+
.replaceAll("\\[:blank:]", "\\\\p{Blank}")
1775+
.replaceAll("\\[:cntrl:]", "\\\\p{Cntrl}")
1776+
.replaceAll("\\[:digit:]", "\\\\p{Digit}")
1777+
.replaceAll("\\[:graph:]", "\\\\p{Graph}")
1778+
.replaceAll("\\[:lower:]", "\\\\p{Lower}")
1779+
.replaceAll("\\[:print:]", "\\\\p{Print}")
1780+
.replaceAll("\\[:punct:]", "\\\\p{Punct}")
1781+
.replaceAll("\\[:space:]", "\\\\s")
1782+
.replaceAll("\\[:upper:]", "\\\\p{Upper}")
1783+
.replaceAll("\\[:xdigit:]", "\\\\p{XDigit}");
1784+
}
1785+
1786+
private boolean addHighlightRule(List<String> parts, int idx) {
1787+
boolean out = true;
1788+
if (parts.get(0).equals("color")) {
1789+
addHighlightRule(syntaxName + idx, parts, false);
1790+
} else if (parts.get(0).equals("icolor")) {
1791+
addHighlightRule(syntaxName + idx, parts, true);
1792+
} else if (parts.get(0).matches("[A-Z_]+[:]?")) {
1793+
String key = themeKey(parts.get(0));
1794+
if (colorTheme.containsKey(key)) {
1795+
parts.set(0, "color");
1796+
parts.add(1, colorTheme.get(key));
1797+
addHighlightRule(syntaxName + idx, parts, false);
1798+
} else {
1799+
Log.warn("Unknown token type: ", key);
1800+
}
1801+
} else if (parts.get(0).matches("~[A-Z_]+[:]?")) {
1802+
String key = themeKey(parts.get(0));
1803+
if (colorTheme.containsKey(key)) {
1804+
parts.set(0, "icolor");
1805+
parts.add(1, colorTheme.get(key));
1806+
addHighlightRule(syntaxName + idx, parts, true);
1807+
} else {
1808+
Log.warn("Unknown token type: ", key);
1809+
}
1810+
} else {
1811+
out = false;
1812+
}
1813+
return out;
1814+
}
1815+
1816+
private String themeKey(String key) {
1817+
if (key.startsWith("+")) {
1818+
return key;
1819+
} else {
1820+
int keyEnd = key.endsWith(":") ? key.length() - 1 : key.length();
1821+
if (key.startsWith("~")) {
1822+
return key.substring(1, keyEnd);
1823+
}
1824+
return key.substring(0, keyEnd);
1825+
}
1826+
}
1827+
17511828
public boolean matches() {
17521829
return matches;
17531830
}
@@ -2062,8 +2139,8 @@ public Nano(Terminal terminal, Path root, Options opts, ConfigurationPath config
20622139

20632140
private void parseConfig(Path file) throws IOException {
20642141
try (BufferedReader reader = new BufferedReader(new FileReader(file.toFile()))) {
2065-
String line = reader.readLine();
2066-
while (line != null) {
2142+
String line;
2143+
while ((line = reader.readLine()) != null) {
20672144
line = line.trim();
20682145
if (line.length() > 0 && !line.startsWith("#")) {
20692146
List<String> parts = Parser.split(line);
@@ -2075,6 +2152,17 @@ private void parseConfig(Path file) throws IOException {
20752152
} else {
20762153
syntaxFiles.add(Paths.get(parts.get(1)));
20772154
}
2155+
} else if(parts.get(0).equals("theme")) {
2156+
if (parts.get(1).contains("*") || parts.get(1).contains("?")) {
2157+
PathMatcher pathMatcher = FileSystems.getDefault().getPathMatcher("glob:" + parts.get(1));
2158+
Optional<Path> theme = Files.find(Paths.get(new File(parts.get(1)).getParent()), Integer.MAX_VALUE, (path, f) -> pathMatcher.matches(path))
2159+
.findFirst();
2160+
if (theme.isPresent()) {
2161+
syntaxFiles.add(0, theme.get());
2162+
}
2163+
} else {
2164+
syntaxFiles.add(0, Paths.get(parts.get(1)));
2165+
}
20782166
} else if (parts.size() == 2
20792167
&& (parts.get(0).equals("set") || parts.get(0).equals("unset"))) {
20802168
String option = parts.get(1);
@@ -2136,7 +2224,6 @@ private void parseConfig(Path file) throws IOException {
21362224
errorMessage = "Nano config: Bad configuration '" + line + "'";
21372225
}
21382226
}
2139-
line = reader.readLine();
21402227
}
21412228
}
21422229
}

‎demo/pom.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@
193193
<resource>
194194
<directory>src/main/scripts</directory>
195195
<includes>
196-
<include>*.nanorc</include>
196+
<include>*.nanorc*</include>
197197
</includes>
198198
</resource>
199199
</resources>

‎demo/src/main/java/org/jline/demo/Repl.java

+1
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,7 @@ public static void main(String[] args) {
263263
File jnanorcFile = Paths.get(root, "jnanorc").toFile();
264264
if (!jnanorcFile.exists()) {
265265
try (FileWriter fw = new FileWriter(jnanorcFile)) {
266+
fw.write("theme " + root + "nanorc/*.nanorctheme\n");
266267
fw.write("include " + root + "nanorc/*.nanorc\n");
267268
}
268269
}

‎demo/src/main/scripts/args.nanorc

+10-11
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
syntax "ARGS"
22

3-
color brightblue "\<[-]?[0-9]*([Ee][+-]?[0-9]+)?\>" "\<[-]?[0](\.[0-9]+)?\>"
4-
color yellow ""(\\.|[^"])*"|'(\\.|[^'])*'|[a-zA-Z]+[a-zA-Z0-9]*"
5-
color green "\<(console|grab|inspect)\>"
6-
color cyan "\<null\>"
7-
color brightcyan "\<(true|false)\>"
8-
color brightyellow "\"(\\"|[^"])*\"\s*:" "'(\'|[^'])*'\s*:" "(\[|,)\s*[a-zA-Z0-9]*\s*:"
9-
color white "(:|\[|,|\])"
10-
color magenta "\\u[0-9a-fA-F]{4}|\\[bfnrt'"/\\]"
11-
color blue start="/\*" end="\*/"
12-
color blue "(//.*)"
13-
color ,red " + +| + +"
3+
NUMBER: "\<[-]?[0-9]*([Ee][+-]?[0-9]+)?\>" "\<[-]?[0](\.[0-9]+)?\>"
4+
STRING: ""(\\.|[^"])*"|'(\\.|[^'])*'|[a-zA-Z]+[a-zA-Z0-9]*"
5+
FUNCTION: "\<(console|grab|inspect)\>"
6+
NULL: "\<null\>"
7+
BOOLEAN: "\<(true|false)\>"
8+
VARIABLE: "\"(\\"|[^"])*\"\s*:" "'(\'|[^'])*'\s*:" "(\[|,)\s*[a-zA-Z0-9]*\s*:"
9+
PLAIN: "(:|\[|,|\])"
10+
ESCAPE: "\\u[0-9a-fA-F]{4}|\\[bfnrt'"/\\]"
11+
COMMENT: start="/\*" end="\*/"
12+
COMMENT: "(//.*)"

‎demo/src/main/scripts/command.nanorc

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
syntax "COMMAND"
22

3-
color green "[a-zA-Z]+[a-zA-Z0-9]*"
4-
color yellow ".*="
5-
color white "(\"|'|\.|=|:|\[|,|\])"
6-
color blue start="/\*" end="\*/"
7-
color blue "(^|[[:space:]])#.*$"
3+
FUNCTION: "[a-zA-Z]+[a-zA-Z0-9]*"
4+
VARIABLE: ".*="
5+
PLAIN: "(\"|'|\.|=|:|\[|,|\])"
6+
COMMENT: start="/\*" end="\*/"
7+
COMMENT: "(^|[[:space:]])#.*$"
+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#
2+
# This file describes a default scheme for nanorc syntax highlighting.
3+
#
4+
# Everything after a # character is a comment up to the end of the line.
5+
# Comments are ignored. Empty lines are ignored too. Leading/trailing white
6+
# space characters are removed before theme file is processed.
7+
#
8+
# Each line of the theme file describes a token type and how this token type
9+
# should be colored (highlighted). The first word on each line is the name
10+
# of the token type. After the name of the token type at least one white space
11+
# character must follow, and then a text and background color
12+
# for the highlighting must be specified, separated by a comma. No spaces
13+
# are allowed inside color definition (that is, color definition is considered
14+
# a single word, despite a possible comma).
15+
#
16+
# Background color can be omitted (in which case default background color
17+
# of the terminal will be used). If you are omitting the background color,
18+
# a comma may be omitted also. Likewise, a text color can be omitted,
19+
# but comma must be present in this case.
20+
#
21+
# Author: Yuri Sakhno
22+
# ysakhno at gmail dot com
23+
#
24+
# https://github.com/YSakhno/nanorc/
25+
#
26+
27+
PLAIN white
28+
FUNCTION brightgreen
29+
STRING brightcyan
30+
COMMENT cyan
31+
DOC_COMMENT brightcyan
32+
TYPE brightblue
33+
BOOLEAN brightwhite
34+
NULL cyan
35+
NUMBER blue
36+
VARIABLE brightyellow
37+
PACKAGE green,,faint
38+
CLASS green
39+
CONSTANT yellow
40+
OPERATOR yellow
41+
OPTION yellow
42+
KEYWORD brightwhite
43+
MACRO brightmagenta
44+
REGEXP blue,cyan
45+
ESCAPE black,cyan
46+
DELIMITER brightred
47+
JUMP brightcyan
48+
WARNING brightyellow,red
49+
SECTION brightgreen
50+
TAG brightwhite
51+
ATTRIBUTE green
52+
CHARREF brightred
53+
PATH brightblue
54+
URL brightblue
55+
EMAIL brightblue
56+
WHITESPACE ,green
57+
#
58+
# mixin
59+
#
60+
+FUNCTION FUNCTION: "[A-Za-z_][A-Za-z0-9_]*[[:space:]]*[(]" \n PLAIN: "[(]"
61+
+TODO color brightwhite,cyan "FIXME|TODO|XXX"
62+
+LINT color ,green "[[:space:]]+$" \n color ,red "\t*"
63+
+LONG_LINE_WARNING color ,red "^.{81,}$"

‎demo/src/main/scripts/gron.nanorc

+7-9
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
syntax "GRON" "\.gron$"
22
header "^\[$"
33

4-
color brightblue "\<[-]?[0-9]*([Ee][+-]?[0-9]+)?\>" "\<[-]?[0](\.[0-9]+)?\>"
5-
color yellow ""(\\.|[^"])*"|'(\\.|[^'])*'|[a-zA-Z]+[a-zA-Z0-9]*"
6-
color cyan "\<null\>"
7-
color brightcyan "\<(true|false)\>"
8-
color brightyellow "\"(\\"|[^"])*\"\s*:" "'(\'|[^'])*'\s*:" "(\[|,)\s*[a-zA-Z0-9]*\s*:"
9-
color white "(:|\[|,|\])"
10-
color magenta "\\u[0-9a-fA-F]{4}|\\[bfnrt'"/\\]"
11-
color ,green "[[:space:]]+$"
12-
color ,red " + +| + +"
4+
NUMBER: "\<[-]?[0-9]*([Ee][+-]?[0-9]+)?\>" "\<[-]?[0](\.[0-9]+)?\>"
5+
STRING: ""(\\.|[^"])*"|'(\\.|[^'])*'|[a-zA-Z]+[a-zA-Z0-9]*"
6+
NULL: "\<null\>"
7+
BOOLEAN: "\<(true|false)\>"
8+
VARIABLE: "\"(\\"|[^"])*\"\s*:" "'(\'|[^'])*'\s*:" "(\[|,)\s*[a-zA-Z0-9]*\s*:"
9+
PLAIN: "(:|\[|,|\])"
10+
ESCAPE: "\\u[0-9a-fA-F]{4}|\\[bfnrt'"/\\]"

‎demo/src/main/scripts/groovy.nanorc

+21-17
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,28 @@
11
## Here is an example for Groovy.
22
##
33
syntax "Groovy" "\.groovy$"
4-
color green "\<(boolean|byte|char|double|float|int|long|new|short|this|transient|void|def|it)\>"
5-
color red "\<(break|case|catch|continue|default|do|else|finally|for|if|return|switch|throw|try|while)\>"
6-
color green,,faint "(([a-z]{2,}[.]{1}){2,10}([a-z]{2,}){0,1})"
7-
color green,,faint "\<(print|println|sleep)\>"
8-
color green "\<[A-Z]{0,2}([A-Z]{1}[a-z]+){1,}\>"
9-
color cyan "\<(abstract|class|extends|final|implements|import|instanceof|interface|native|package|private|protected|public|static|strictfp|super|synchronized|throws|volatile)\>"
4+
5+
TYPE: "\<(boolean|byte|char|double|float|int|long|new|short|this|transient|void|def|it)\>"
6+
KEYWORD: "\<(case|catch|default|do|else|finally|for|if|return|switch|throw|try|while)\>"
7+
PACKAGE: "(([a-z]{2,}[.]{1}){2,10}([a-z]{2,}){0,1})"
8+
CLASS: "\<[A-Z]{0,2}([A-Z]{1}[a-z]+){1,}\>"
9+
FUNCTION: "\<(print|println|sleep)\>"
10+
KEYWORD: "\<(abstract|class|extends|final|implements|import|instanceof|interface|native|package|private|protected|public|static|strictfp|super|synchronized|throws|volatile)\>"
11+
JUMP: "\<(break|continue)\>"
1012
# Mono-quoted strings.
11-
color brightgreen "'([^'\\]|\\.)*'|'''"
12-
color brightgreen ""([^"\\]|\\.)*"|""""
13+
STRING: "'([^'\\]|\\.)*'|'''"
14+
STRING: ""([^"\\]|\\.)*"|""""
1315
color normal "'''|""""
1416
# Triple-quoted strings.
15-
color brightgreen start="'''([^'),]|$)" end="(^|[^(\\])'''"
16-
color brightgreen start=""""([^"),]|$)" end="(^|[^(\\])""""
17+
STRING: start="'''([^'),]|$)" end="(^|[^(\\])'''"
18+
STRING: start=""""([^"),]|$)" end="(^|[^(\\])""""
1719
#
18-
color yellow "\<(true|false|null)\>"
19-
color yellow "\<[A-Z]+([_]{1}[A-Z]+){0,}\>"
20-
icolor yellow "\b(([1-9][0-9]+)|0+)\.[0-9]+\b" "\b[1-9][0-9]*\b" "\b0[0-7]*\b" "\b0x[1-9a-f][0-9a-f]*\b"
21-
color blue "//.*"
22-
color blue start="/\*" end="\*/"
23-
color brightblue start="/\*\*" end="\*/"
24-
color brightwhite,yellow "(FIXME|TODO|XXX)"
20+
NULL: "\<(null)\>"
21+
BOOLEAN: "\<(true|false)\>"
22+
CONSTANT: "\<[A-Z]+([_]{1}[A-Z]+){0,}\>"
23+
OPERATOR: "[-+/*=<>?:!~%&|]"
24+
~NUMBER: "\b(([1-9][0-9]+)|0+)\.[0-9]+\b" "\b[1-9][0-9]*\b" "\b0[0-7]*\b" "\b0x[1-9a-f][0-9a-f]*\b"
25+
COMMENT: "//.*"
26+
COMMENT: start="/\*" end="\*/"
27+
DOC_COMMENT: start="/\*\*" end="\*/"
28+
+TODO

‎demo/src/main/scripts/java.nanorc

+25-14
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,28 @@
11
## Here is an example for Java.
22
##
33
syntax "Java" "\.java$"
4-
color green "\<(boolean|byte|char|double|float|int|long|new|short|this|transient|void)\>"
5-
color red "\<(break|case|catch|continue|default|do|else|finally|for|if|return|switch|throw|try|while)\>"
6-
color green,,faint "(([a-z]{2,}[.]{1}){2,10}([a-z]{2,}){0,1})"
7-
color green "\<[A-Z]{0,2}([A-Z]{1}[a-z]+){1,}\>"
8-
color cyan "\<(abstract|class|extends|final|implements|import|instanceof|interface|native|package|private|protected|public|static|strictfp|super|synchronized|throws|volatile)\>"
9-
color red ""[^"]*""
10-
color yellow "\<(true|false|null)\>"
11-
color yellow "\<[A-Z]+([_]{1}[A-Z]+){0,}\>"
12-
icolor yellow "\b(([1-9][0-9]+)|0+)\.[0-9]+\b" "\b[1-9][0-9]*\b" "\b0[0-7]*\b" "\b0x[1-9a-f][0-9a-f]*\b"
13-
color blue "//.*"
14-
color blue start="/\*" end="\*/"
15-
color brightblue start="/\*\*" end="\*/"
16-
color brightwhite,yellow "(FIXME|TODO|XXX)"
17-
color ,green "[[:space:]]+$"
4+
5+
# Class
6+
SECTION: "class +[A-Za-z0-9]+ *((implements|extends) +[A-Za-z0-9.]+)?"
7+
8+
# Annotation
9+
ESCAPE: "@[A-Za-z]+"
10+
11+
# +FUNCTION
12+
TYPE: "\<(boolean|byte|char|double|float|int|long|new|short|this|transient|void)\>"
13+
KEYWORD: "\<(case|catch|default|do|else|finally|for|if|return|switch|throw|try|while)\>"
14+
PACKAGE: "(([a-z]{2,}[.]{1}){2,10}([a-z]{2,}){0,1})"
15+
CLASS: "\<[A-Z]{0,2}([A-Z]{1}[a-z]+){1,}\>"
16+
KEYWORD: "\<(abstract|class|extends|final|implements|import|instanceof|interface|native|package|private|protected|public|static|strictfp|super|synchronized|throws|volatile)\>"
17+
JUMP: "\<(break|continue)\>"
18+
STRING: ""[^"]*""
19+
NULL: "\<(null)\>"
20+
BOOLEAN: "\<(true|false)\>"
21+
CONSTANT: "\<[A-Z]+([_]{1}[A-Z]+){0,}\>"
22+
OPERATOR: "[-+/*=<>?:!~%&|]"
23+
~NUMBER: "\b(([1-9][0-9]+)|0+)\.[0-9]+\b" "\b[1-9][0-9]*\b" "\b0[0-7]*\b" "\b0x[1-9a-f][0-9a-f]*\b"
24+
COMMENT: "//.*"
25+
COMMENT: start="/\*" end="\*/"
26+
DOC_COMMENT: start="/\*\*" end="\*/"
27+
+TODO
28+
+LINT

‎demo/src/main/scripts/json.nanorc

+6-8
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
syntax "JSON" "\.json$"
22
header "^\{$"
33

4-
color brightblue "\<[-]?[0-9]*([Ee][+-]?[0-9]+)?\>" "\<[-]?[0](\.[0-9]+)?\>"
5-
color cyan "\<null\>"
6-
color brightcyan "\<(true|false)\>"
7-
color yellow ""(\\.|[^"])*"|'(\\.|[^'])*'"
8-
color brightyellow "\"(\\"|[^"])*\"[[:space:]]*:" "'(\'|[^'])*'[[:space:]]*:"
9-
color magenta "\\u[0-9a-fA-F]{4}|\\[bfnrt'"/\\]"
10-
color ,green "[[:space:]]+$"
11-
color ,red " + +| + +"
4+
NUMBER: "\<[-]?[0-9]*([Ee][+-]?[0-9]+)?\>" "\<[-]?[0](\.[0-9]+)?\>"
5+
NULL: "\<null\>"
6+
BOOLEAN: "\<(true|false)\>"
7+
STRING: ""(\\.|[^"])*"|'(\\.|[^'])*'"
8+
VARIABLE: "\"(\\"|[^"])*\"[[:space:]]*:" "'(\'|[^'])*'[[:space:]]*:"
9+
ESCAPE: "\\u[0-9a-fA-F]{4}|\\[bfnrt'"/\\]"

‎demo/src/main/scripts/sh-repl.nanorc

+11-12
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,16 @@
33
syntax "SH-REPL"
44

55
## keywords:
6-
color green "\<(case|do|done|elif|else|esac|fi|for|function|if|in|select|then|time|until|while)\>"
7-
color green "(\{|\}|\(|\)|\;|\]|\[|`|\\|\$|<|>|!|=|&|\|)"
8-
color green "-[Lldefgrtuwx]+\>"
9-
color green "-(eq|ne|gt|lt|ge|le|s|n|z)\>"
6+
KEYWORD: "\<(case|do|done|elif|else|esac|fi|for|function|if|in|select|then|time|until|while)\>"
7+
OPERATOR: "(\{|\}|\(|\)|\;|\]|\[|`|\\|\$|<|>|!|=|&|\|)"
8+
OPTION: "-[Lldefgrtuwx]+\>"
9+
OPERATOR: "-(eq|ne|gt|lt|ge|le|s|n|z)\>"
1010
## builtins:
11-
color brightblue "\<(alias|bg|bind|break|builtin|caller|cd|command|compgen|complete|compopt|continue|declare|dirs|disown|echo|enable|eval|exec|exit|export|false|fc|fg|getopts|hash|help|history|jobs|kill|let|local|logout|mapfile|popd|printf|pushd|pwd|read|readarray|readonly|return|set|shift|shopt|source|suspend|test|times|trap|true|type|typeset|ulimit|umask|unalias|unset|wait)\>"
11+
FUNCTION: "\<(alias|bg|bind|break|builtin|caller|cd|command|compgen|complete|compopt|continue|declare|dirs|disown|echo|enable|eval|exec|exit|export|false|fc|fg|getopts|hash|help|history|jobs|kill|let|local|logout|mapfile|popd|printf|pushd|pwd|read|readarray|readonly|return|set|shift|shopt|source|suspend|test|times|trap|true|type|typeset|ulimit|umask|unalias|unset|wait)\>"
1212
## not buitins:
13-
color brightblue "\<(cat|chmod|chown|cp|env|grep|install|ln|make|mkdir|mv|rm|sed|tar|touch|ls)\>"
14-
icolor brightgreen "^\s+[0-9A-Z_]+\s+\(\)"
15-
icolor brightred "\$\{?[0-9A-Z_!@#$*?-]+\}?"
16-
color brightyellow ""(\\.|[^"])*"" "'(\\.|[^'])*'"
17-
color cyan "^([[:space:]])*#.*$"
18-
color cyan start="/\*" end="\*/"
19-
# color ,green "[[:space:]]+$"
13+
FUNCTION: "\<(cat|chmod|chown|cp|env|grep|install|ln|make|mkdir|mv|rm|sed|tar|touch|ls)\>"
14+
~FUNCTION: "^\s+[0-9A-Z_]+\s+\(\)"
15+
~VARIABLE: "\$\{?[0-9A-Z_!@#$*?-]+\}?"
16+
STRING: ""(\\.|[^"])*"" "'(\\.|[^'])*'"
17+
COMMENT: "^([[:space:]])*#.*$"
18+
COMMENT: start="/\*" end="\*/"

0 commit comments

Comments
 (0)
Please sign in to comment.