diff --git a/builtins/src/main/java/org/jline/builtins/Nano.java b/builtins/src/main/java/org/jline/builtins/Nano.java index eaceb9fd0..a812e79ab 100644 --- a/builtins/src/main/java/org/jline/builtins/Nano.java +++ b/builtins/src/main/java/org/jline/builtins/Nano.java @@ -1426,17 +1426,31 @@ protected static SyntaxHighlighter build(List syntaxFiles, String file, St , boolean ignoreErrors) { SyntaxHighlighter out = new SyntaxHighlighter(); List defaultRules = new ArrayList<>(); + Map colorTheme = new HashMap<>(); try { if (syntaxName == null || (syntaxName != null && !syntaxName.equals("none"))) { for (Path p : syntaxFiles) { try { - NanorcParser parser = new NanorcParser(p, syntaxName, file); - parser.parse(); - if (parser.matches()) { - out.addRules(parser.getHighlightRules()); - return out; - } else if (parser.isDefault()) { - defaultRules.addAll(parser.getHighlightRules()); + if (colorTheme.isEmpty() && p.getFileName().toString().endsWith(".nanorctheme")) { + try (BufferedReader reader = new BufferedReader(new FileReader(p.toFile()))) { + String line; + while ((line = reader.readLine()) != null) { + line = line.trim(); + if (line.length() > 0 && !line.startsWith("#")) { + List parts = Arrays.asList(line.split("\\s+", 2)); + colorTheme.put(parts.get(0), parts.get(1)); + } + } + } + } else { + NanorcParser parser = new NanorcParser(p, syntaxName, file, colorTheme); + parser.parse(); + if (parser.matches()) { + out.addRules(parser.getHighlightRules()); + return out; + } else if (parser.isDefault()) { + defaultRules.addAll(parser.getHighlightRules()); + } } } catch (IOException e) { // ignore @@ -1464,8 +1478,8 @@ public static SyntaxHighlighter build(Path nanorc, String syntaxName) { List syntaxFiles = new ArrayList<>(); try { try (BufferedReader reader = new BufferedReader(new FileReader(nanorc.toFile()))) { - String line = reader.readLine(); - while (line != null) { + String line; + while ((line = reader.readLine()) != null) { line = line.trim(); if (line.length() > 0 && !line.startsWith("#")) { List parts = Parser.split(line); @@ -1481,9 +1495,19 @@ public static SyntaxHighlighter build(Path nanorc, String syntaxName) { } else { syntaxFiles.add(Paths.get(parts.get(1))); } + } else if(parts.get(0).equals("theme")) { + if (parts.get(1).contains("*") || parts.get(1).contains("?")) { + PathMatcher pathMatcher = FileSystems.getDefault().getPathMatcher("glob:" + parts.get(1)); + Optional theme = Files.find(Paths.get(new File(parts.get(1)).getParent()), Integer.MAX_VALUE, (path, f) -> pathMatcher.matches(path)) + .findFirst(); + if (theme.isPresent()) { + syntaxFiles.add(0, theme.get()); + } + } else { + syntaxFiles.add(0, Paths.get(parts.get(1))); + } } } - line = reader.readLine(); } } out = build(syntaxFiles, null, syntaxName); @@ -1678,11 +1702,13 @@ private static class NanorcParser { private final String target; private final List highlightRules = new ArrayList<>(); private final BufferedReader reader; + private Map colorTheme = new HashMap<>(); private boolean matches = false; private String syntaxName = "unknown"; - public NanorcParser(Path file, String name, String target) throws IOException { + public NanorcParser(Path file, String name, String target, Map colorTheme) throws IOException { this(new Source.PathSource(file, null).read(), name, target); + this.colorTheme = colorTheme; } public NanorcParser(InputStream in, String name, String target) { @@ -1698,21 +1724,7 @@ public void parse() throws IOException { idx++; line = line.trim(); if (line.length() > 0 && !line.startsWith("#")) { - line = line.replaceAll("\\\\<", "\\\\b") - .replaceAll("\\\\>", "\\\\b") - .replaceAll("\\[:alnum:]", "\\\\p{Alnum}") - .replaceAll("\\[:alpha:]", "\\\\p{Alpha}") - .replaceAll("\\[:blank:]", "\\\\p{Blank}") - .replaceAll("\\[:cntrl:]", "\\\\p{Cntrl}") - .replaceAll("\\[:digit:]", "\\\\p{Digit}") - .replaceAll("\\[:graph:]", "\\\\p{Graph}") - .replaceAll("\\[:lower:]", "\\\\p{Lower}") - .replaceAll("\\[:print:]", "\\\\p{Print}") - .replaceAll("\\[:punct:]", "\\\\p{Punct}") - .replaceAll("\\[:space:]", "\\\\s") - .replaceAll("\\[:upper:]", "\\\\p{Upper}") - .replaceAll("\\[:xdigit:]", "\\\\p{XDigit}"); - List parts = Parser.split(line); + List parts = Parser.split(fixRegexes(line)); if (parts.get(0).equals("syntax")) { syntaxName = parts.get(1); List filePatterns = new ArrayList<>(); @@ -1726,7 +1738,7 @@ public void parse() throws IOException { for (int i = 2; i < parts.size(); i++) { filePatterns.add(Pattern.compile(parts.get(i))); } - for (Pattern p: filePatterns) { + for (Pattern p : filePatterns) { if (p.matcher(target).find()) { matches = true; break; @@ -1738,16 +1750,81 @@ public void parse() throws IOException { } else { matches = true; } - } else if (parts.get(0).equals("color")) { - addHighlightRule(syntaxName + idx, parts, false); - } else if (parts.get(0).equals("icolor")) { - addHighlightRule(syntaxName + idx, parts, true); + } else if (!addHighlightRule(parts, idx) && parts.get(0).matches("\\+[A-Z_]+")) { + String key = themeKey(parts.get(0)); + if (colorTheme.containsKey(key)) { + for (String l : colorTheme.get(key).split("\\\\n")) { + idx++; + addHighlightRule(Parser.split(fixRegexes(l)), idx); + } + } else { + Log.warn("Unknown token type: ", key); + } } } } reader.close(); } + private String fixRegexes(String line) { + return line.replaceAll("\\\\<", "\\\\b") + .replaceAll("\\\\>", "\\\\b") + .replaceAll("\\[:alnum:]", "\\\\p{Alnum}") + .replaceAll("\\[:alpha:]", "\\\\p{Alpha}") + .replaceAll("\\[:blank:]", "\\\\p{Blank}") + .replaceAll("\\[:cntrl:]", "\\\\p{Cntrl}") + .replaceAll("\\[:digit:]", "\\\\p{Digit}") + .replaceAll("\\[:graph:]", "\\\\p{Graph}") + .replaceAll("\\[:lower:]", "\\\\p{Lower}") + .replaceAll("\\[:print:]", "\\\\p{Print}") + .replaceAll("\\[:punct:]", "\\\\p{Punct}") + .replaceAll("\\[:space:]", "\\\\s") + .replaceAll("\\[:upper:]", "\\\\p{Upper}") + .replaceAll("\\[:xdigit:]", "\\\\p{XDigit}"); + } + + private boolean addHighlightRule(List parts, int idx) { + boolean out = true; + if (parts.get(0).equals("color")) { + addHighlightRule(syntaxName + idx, parts, false); + } else if (parts.get(0).equals("icolor")) { + addHighlightRule(syntaxName + idx, parts, true); + } else if (parts.get(0).matches("[A-Z_]+[:]?")) { + String key = themeKey(parts.get(0)); + if (colorTheme.containsKey(key)) { + parts.set(0, "color"); + parts.add(1, colorTheme.get(key)); + addHighlightRule(syntaxName + idx, parts, false); + } else { + Log.warn("Unknown token type: ", key); + } + } else if (parts.get(0).matches("~[A-Z_]+[:]?")) { + String key = themeKey(parts.get(0)); + if (colorTheme.containsKey(key)) { + parts.set(0, "icolor"); + parts.add(1, colorTheme.get(key)); + addHighlightRule(syntaxName + idx, parts, true); + } else { + Log.warn("Unknown token type: ", key); + } + } else { + out = false; + } + return out; + } + + private String themeKey(String key) { + if (key.startsWith("+")) { + return key; + } else { + int keyEnd = key.endsWith(":") ? key.length() - 1 : key.length(); + if (key.startsWith("~")) { + return key.substring(1, keyEnd); + } + return key.substring(0, keyEnd); + } + } + public boolean matches() { return matches; } @@ -2062,8 +2139,8 @@ public Nano(Terminal terminal, Path root, Options opts, ConfigurationPath config private void parseConfig(Path file) throws IOException { try (BufferedReader reader = new BufferedReader(new FileReader(file.toFile()))) { - String line = reader.readLine(); - while (line != null) { + String line; + while ((line = reader.readLine()) != null) { line = line.trim(); if (line.length() > 0 && !line.startsWith("#")) { List parts = Parser.split(line); @@ -2075,6 +2152,17 @@ private void parseConfig(Path file) throws IOException { } else { syntaxFiles.add(Paths.get(parts.get(1))); } + } else if(parts.get(0).equals("theme")) { + if (parts.get(1).contains("*") || parts.get(1).contains("?")) { + PathMatcher pathMatcher = FileSystems.getDefault().getPathMatcher("glob:" + parts.get(1)); + Optional theme = Files.find(Paths.get(new File(parts.get(1)).getParent()), Integer.MAX_VALUE, (path, f) -> pathMatcher.matches(path)) + .findFirst(); + if (theme.isPresent()) { + syntaxFiles.add(0, theme.get()); + } + } else { + syntaxFiles.add(0, Paths.get(parts.get(1))); + } } else if (parts.size() == 2 && (parts.get(0).equals("set") || parts.get(0).equals("unset"))) { String option = parts.get(1); @@ -2136,7 +2224,6 @@ private void parseConfig(Path file) throws IOException { errorMessage = "Nano config: Bad configuration '" + line + "'"; } } - line = reader.readLine(); } } } diff --git a/demo/pom.xml b/demo/pom.xml index fca080266..6b555addd 100644 --- a/demo/pom.xml +++ b/demo/pom.xml @@ -193,7 +193,7 @@ src/main/scripts - *.nanorc + *.nanorc* diff --git a/demo/src/main/java/org/jline/demo/Repl.java b/demo/src/main/java/org/jline/demo/Repl.java index d9d0743f5..03e57605a 100644 --- a/demo/src/main/java/org/jline/demo/Repl.java +++ b/demo/src/main/java/org/jline/demo/Repl.java @@ -263,6 +263,7 @@ public static void main(String[] args) { File jnanorcFile = Paths.get(root, "jnanorc").toFile(); if (!jnanorcFile.exists()) { try (FileWriter fw = new FileWriter(jnanorcFile)) { + fw.write("theme " + root + "nanorc/*.nanorctheme\n"); fw.write("include " + root + "nanorc/*.nanorc\n"); } } diff --git a/demo/src/main/scripts/args.nanorc b/demo/src/main/scripts/args.nanorc index 44f031dcd..a384a726b 100644 --- a/demo/src/main/scripts/args.nanorc +++ b/demo/src/main/scripts/args.nanorc @@ -1,13 +1,12 @@ syntax "ARGS" -color brightblue "\<[-]?[0-9]*([Ee][+-]?[0-9]+)?\>" "\<[-]?[0](\.[0-9]+)?\>" -color yellow ""(\\.|[^"])*"|'(\\.|[^'])*'|[a-zA-Z]+[a-zA-Z0-9]*" -color green "\<(console|grab|inspect)\>" -color cyan "\" -color brightcyan "\<(true|false)\>" -color brightyellow "\"(\\"|[^"])*\"\s*:" "'(\'|[^'])*'\s*:" "(\[|,)\s*[a-zA-Z0-9]*\s*:" -color white "(:|\[|,|\])" -color magenta "\\u[0-9a-fA-F]{4}|\\[bfnrt'"/\\]" -color blue start="/\*" end="\*/" -color blue "(//.*)" -color ,red " + +| + +" \ No newline at end of file +NUMBER: "\<[-]?[0-9]*([Ee][+-]?[0-9]+)?\>" "\<[-]?[0](\.[0-9]+)?\>" +STRING: ""(\\.|[^"])*"|'(\\.|[^'])*'|[a-zA-Z]+[a-zA-Z0-9]*" +FUNCTION: "\<(console|grab|inspect)\>" +NULL: "\" +BOOLEAN: "\<(true|false)\>" +VARIABLE: "\"(\\"|[^"])*\"\s*:" "'(\'|[^'])*'\s*:" "(\[|,)\s*[a-zA-Z0-9]*\s*:" +PLAIN: "(:|\[|,|\])" +ESCAPE: "\\u[0-9a-fA-F]{4}|\\[bfnrt'"/\\]" +COMMENT: start="/\*" end="\*/" +COMMENT: "(//.*)" diff --git a/demo/src/main/scripts/command.nanorc b/demo/src/main/scripts/command.nanorc index fa375ae5f..434caeeb9 100644 --- a/demo/src/main/scripts/command.nanorc +++ b/demo/src/main/scripts/command.nanorc @@ -1,7 +1,7 @@ syntax "COMMAND" -color green "[a-zA-Z]+[a-zA-Z0-9]*" -color yellow ".*=" -color white "(\"|'|\.|=|:|\[|,|\])" -color blue start="/\*" end="\*/" -color blue "(^|[[:space:]])#.*$" +FUNCTION: "[a-zA-Z]+[a-zA-Z0-9]*" +VARIABLE: ".*=" +PLAIN: "(\"|'|\.|=|:|\[|,|\])" +COMMENT: start="/\*" end="\*/" +COMMENT: "(^|[[:space:]])#.*$" diff --git a/demo/src/main/scripts/default.nanorctheme b/demo/src/main/scripts/default.nanorctheme new file mode 100644 index 000000000..ca1f8ee50 --- /dev/null +++ b/demo/src/main/scripts/default.nanorctheme @@ -0,0 +1,63 @@ +# +# This file describes a default scheme for nanorc syntax highlighting. +# +# Everything after a # character is a comment up to the end of the line. +# Comments are ignored. Empty lines are ignored too. Leading/trailing white +# space characters are removed before theme file is processed. +# +# Each line of the theme file describes a token type and how this token type +# should be colored (highlighted). The first word on each line is the name +# of the token type. After the name of the token type at least one white space +# character must follow, and then a text and background color +# for the highlighting must be specified, separated by a comma. No spaces +# are allowed inside color definition (that is, color definition is considered +# a single word, despite a possible comma). +# +# Background color can be omitted (in which case default background color +# of the terminal will be used). If you are omitting the background color, +# a comma may be omitted also. Likewise, a text color can be omitted, +# but comma must be present in this case. +# +# Author: Yuri Sakhno +# ysakhno at gmail dot com +# +# https://github.com/YSakhno/nanorc/ +# + +PLAIN white +FUNCTION brightgreen +STRING brightcyan +COMMENT cyan +DOC_COMMENT brightcyan +TYPE brightblue +BOOLEAN brightwhite +NULL cyan +NUMBER blue +VARIABLE brightyellow +PACKAGE green,,faint +CLASS green +CONSTANT yellow +OPERATOR yellow +OPTION yellow +KEYWORD brightwhite +MACRO brightmagenta +REGEXP blue,cyan +ESCAPE black,cyan +DELIMITER brightred +JUMP brightcyan +WARNING brightyellow,red +SECTION brightgreen +TAG brightwhite +ATTRIBUTE green +CHARREF brightred +PATH brightblue +URL brightblue +EMAIL brightblue +WHITESPACE ,green +# +# mixin +# ++FUNCTION FUNCTION: "[A-Za-z_][A-Za-z0-9_]*[[:space:]]*[(]" \n PLAIN: "[(]" ++TODO color brightwhite,cyan "FIXME|TODO|XXX" ++LINT color ,green "[[:space:]]+$" \n color ,red "\t*" ++LONG_LINE_WARNING color ,red "^.{81,}$" \ No newline at end of file diff --git a/demo/src/main/scripts/gron.nanorc b/demo/src/main/scripts/gron.nanorc index c9b8110ef..b9c8ee4aa 100644 --- a/demo/src/main/scripts/gron.nanorc +++ b/demo/src/main/scripts/gron.nanorc @@ -1,12 +1,10 @@ syntax "GRON" "\.gron$" header "^\[$" -color brightblue "\<[-]?[0-9]*([Ee][+-]?[0-9]+)?\>" "\<[-]?[0](\.[0-9]+)?\>" -color yellow ""(\\.|[^"])*"|'(\\.|[^'])*'|[a-zA-Z]+[a-zA-Z0-9]*" -color cyan "\" -color brightcyan "\<(true|false)\>" -color brightyellow "\"(\\"|[^"])*\"\s*:" "'(\'|[^'])*'\s*:" "(\[|,)\s*[a-zA-Z0-9]*\s*:" -color white "(:|\[|,|\])" -color magenta "\\u[0-9a-fA-F]{4}|\\[bfnrt'"/\\]" -color ,green "[[:space:]]+$" -color ,red " + +| + +" \ No newline at end of file +NUMBER: "\<[-]?[0-9]*([Ee][+-]?[0-9]+)?\>" "\<[-]?[0](\.[0-9]+)?\>" +STRING: ""(\\.|[^"])*"|'(\\.|[^'])*'|[a-zA-Z]+[a-zA-Z0-9]*" +NULL: "\" +BOOLEAN: "\<(true|false)\>" +VARIABLE: "\"(\\"|[^"])*\"\s*:" "'(\'|[^'])*'\s*:" "(\[|,)\s*[a-zA-Z0-9]*\s*:" +PLAIN: "(:|\[|,|\])" +ESCAPE: "\\u[0-9a-fA-F]{4}|\\[bfnrt'"/\\]" diff --git a/demo/src/main/scripts/groovy.nanorc b/demo/src/main/scripts/groovy.nanorc index bc0f74cca..17d268c2a 100644 --- a/demo/src/main/scripts/groovy.nanorc +++ b/demo/src/main/scripts/groovy.nanorc @@ -1,24 +1,28 @@ ## Here is an example for Groovy. ## syntax "Groovy" "\.groovy$" -color green "\<(boolean|byte|char|double|float|int|long|new|short|this|transient|void|def|it)\>" -color red "\<(break|case|catch|continue|default|do|else|finally|for|if|return|switch|throw|try|while)\>" -color green,,faint "(([a-z]{2,}[.]{1}){2,10}([a-z]{2,}){0,1})" -color green,,faint "\<(print|println|sleep)\>" -color green "\<[A-Z]{0,2}([A-Z]{1}[a-z]+){1,}\>" -color cyan "\<(abstract|class|extends|final|implements|import|instanceof|interface|native|package|private|protected|public|static|strictfp|super|synchronized|throws|volatile)\>" + +TYPE: "\<(boolean|byte|char|double|float|int|long|new|short|this|transient|void|def|it)\>" +KEYWORD: "\<(case|catch|default|do|else|finally|for|if|return|switch|throw|try|while)\>" +PACKAGE: "(([a-z]{2,}[.]{1}){2,10}([a-z]{2,}){0,1})" +CLASS: "\<[A-Z]{0,2}([A-Z]{1}[a-z]+){1,}\>" +FUNCTION: "\<(print|println|sleep)\>" +KEYWORD: "\<(abstract|class|extends|final|implements|import|instanceof|interface|native|package|private|protected|public|static|strictfp|super|synchronized|throws|volatile)\>" +JUMP: "\<(break|continue)\>" # Mono-quoted strings. -color brightgreen "'([^'\\]|\\.)*'|'''" -color brightgreen ""([^"\\]|\\.)*"|"""" +STRING: "'([^'\\]|\\.)*'|'''" +STRING: ""([^"\\]|\\.)*"|"""" color normal "'''|"""" # Triple-quoted strings. -color brightgreen start="'''([^'),]|$)" end="(^|[^(\\])'''" -color brightgreen start=""""([^"),]|$)" end="(^|[^(\\])"""" +STRING: start="'''([^'),]|$)" end="(^|[^(\\])'''" +STRING: start=""""([^"),]|$)" end="(^|[^(\\])"""" # -color yellow "\<(true|false|null)\>" -color yellow "\<[A-Z]+([_]{1}[A-Z]+){0,}\>" -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" -color blue "//.*" -color blue start="/\*" end="\*/" -color brightblue start="/\*\*" end="\*/" -color brightwhite,yellow "(FIXME|TODO|XXX)" +NULL: "\<(null)\>" +BOOLEAN: "\<(true|false)\>" +CONSTANT: "\<[A-Z]+([_]{1}[A-Z]+){0,}\>" +OPERATOR: "[-+/*=<>?:!~%&|]" +~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" +COMMENT: "//.*" +COMMENT: start="/\*" end="\*/" +DOC_COMMENT: start="/\*\*" end="\*/" ++TODO diff --git a/demo/src/main/scripts/java.nanorc b/demo/src/main/scripts/java.nanorc index 744dc838e..8f756745c 100644 --- a/demo/src/main/scripts/java.nanorc +++ b/demo/src/main/scripts/java.nanorc @@ -1,17 +1,28 @@ ## Here is an example for Java. ## syntax "Java" "\.java$" -color green "\<(boolean|byte|char|double|float|int|long|new|short|this|transient|void)\>" -color red "\<(break|case|catch|continue|default|do|else|finally|for|if|return|switch|throw|try|while)\>" -color green,,faint "(([a-z]{2,}[.]{1}){2,10}([a-z]{2,}){0,1})" -color green "\<[A-Z]{0,2}([A-Z]{1}[a-z]+){1,}\>" -color cyan "\<(abstract|class|extends|final|implements|import|instanceof|interface|native|package|private|protected|public|static|strictfp|super|synchronized|throws|volatile)\>" -color red ""[^"]*"" -color yellow "\<(true|false|null)\>" -color yellow "\<[A-Z]+([_]{1}[A-Z]+){0,}\>" -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" -color blue "//.*" -color blue start="/\*" end="\*/" -color brightblue start="/\*\*" end="\*/" -color brightwhite,yellow "(FIXME|TODO|XXX)" -color ,green "[[:space:]]+$" + +# Class +SECTION: "class +[A-Za-z0-9]+ *((implements|extends) +[A-Za-z0-9.]+)?" + +# Annotation +ESCAPE: "@[A-Za-z]+" + +# +FUNCTION +TYPE: "\<(boolean|byte|char|double|float|int|long|new|short|this|transient|void)\>" +KEYWORD: "\<(case|catch|default|do|else|finally|for|if|return|switch|throw|try|while)\>" +PACKAGE: "(([a-z]{2,}[.]{1}){2,10}([a-z]{2,}){0,1})" +CLASS: "\<[A-Z]{0,2}([A-Z]{1}[a-z]+){1,}\>" +KEYWORD: "\<(abstract|class|extends|final|implements|import|instanceof|interface|native|package|private|protected|public|static|strictfp|super|synchronized|throws|volatile)\>" +JUMP: "\<(break|continue)\>" +STRING: ""[^"]*"" +NULL: "\<(null)\>" +BOOLEAN: "\<(true|false)\>" +CONSTANT: "\<[A-Z]+([_]{1}[A-Z]+){0,}\>" +OPERATOR: "[-+/*=<>?:!~%&|]" +~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" +COMMENT: "//.*" +COMMENT: start="/\*" end="\*/" +DOC_COMMENT: start="/\*\*" end="\*/" ++TODO ++LINT diff --git a/demo/src/main/scripts/json.nanorc b/demo/src/main/scripts/json.nanorc index fa789bebf..2a78a130d 100644 --- a/demo/src/main/scripts/json.nanorc +++ b/demo/src/main/scripts/json.nanorc @@ -1,11 +1,9 @@ syntax "JSON" "\.json$" header "^\{$" -color brightblue "\<[-]?[0-9]*([Ee][+-]?[0-9]+)?\>" "\<[-]?[0](\.[0-9]+)?\>" -color cyan "\" -color brightcyan "\<(true|false)\>" -color yellow ""(\\.|[^"])*"|'(\\.|[^'])*'" -color brightyellow "\"(\\"|[^"])*\"[[:space:]]*:" "'(\'|[^'])*'[[:space:]]*:" -color magenta "\\u[0-9a-fA-F]{4}|\\[bfnrt'"/\\]" -color ,green "[[:space:]]+$" -color ,red " + +| + +" \ No newline at end of file +NUMBER: "\<[-]?[0-9]*([Ee][+-]?[0-9]+)?\>" "\<[-]?[0](\.[0-9]+)?\>" +NULL: "\" +BOOLEAN: "\<(true|false)\>" +STRING: ""(\\.|[^"])*"|'(\\.|[^'])*'" +VARIABLE: "\"(\\"|[^"])*\"[[:space:]]*:" "'(\'|[^'])*'[[:space:]]*:" +ESCAPE: "\\u[0-9a-fA-F]{4}|\\[bfnrt'"/\\]" diff --git a/demo/src/main/scripts/sh-repl.nanorc b/demo/src/main/scripts/sh-repl.nanorc index 53f911f47..87919b4af 100644 --- a/demo/src/main/scripts/sh-repl.nanorc +++ b/demo/src/main/scripts/sh-repl.nanorc @@ -3,17 +3,16 @@ syntax "SH-REPL" ## keywords: -color green "\<(case|do|done|elif|else|esac|fi|for|function|if|in|select|then|time|until|while)\>" -color green "(\{|\}|\(|\)|\;|\]|\[|`|\\|\$|<|>|!|=|&|\|)" -color green "-[Lldefgrtuwx]+\>" -color green "-(eq|ne|gt|lt|ge|le|s|n|z)\>" +KEYWORD: "\<(case|do|done|elif|else|esac|fi|for|function|if|in|select|then|time|until|while)\>" +OPERATOR: "(\{|\}|\(|\)|\;|\]|\[|`|\\|\$|<|>|!|=|&|\|)" +OPTION: "-[Lldefgrtuwx]+\>" +OPERATOR: "-(eq|ne|gt|lt|ge|le|s|n|z)\>" ## builtins: -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)\>" +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)\>" ## not buitins: -color brightblue "\<(cat|chmod|chown|cp|env|grep|install|ln|make|mkdir|mv|rm|sed|tar|touch|ls)\>" -icolor brightgreen "^\s+[0-9A-Z_]+\s+\(\)" -icolor brightred "\$\{?[0-9A-Z_!@#$*?-]+\}?" -color brightyellow ""(\\.|[^"])*"" "'(\\.|[^'])*'" -color cyan "^([[:space:]])*#.*$" -color cyan start="/\*" end="\*/" -# color ,green "[[:space:]]+$" +FUNCTION: "\<(cat|chmod|chown|cp|env|grep|install|ln|make|mkdir|mv|rm|sed|tar|touch|ls)\>" +~FUNCTION: "^\s+[0-9A-Z_]+\s+\(\)" +~VARIABLE: "\$\{?[0-9A-Z_!@#$*?-]+\}?" +STRING: ""(\\.|[^"])*"" "'(\\.|[^'])*'" +COMMENT: "^([[:space:]])*#.*$" +COMMENT: start="/\*" end="\*/"