From e1c75ce38dc841b52b350459f39b84ac21868a4b Mon Sep 17 00:00:00 2001 From: mattirn Date: Sun, 27 Dec 2020 16:06:06 +0100 Subject: [PATCH] NanorcParser: add nano color name extensions and use StyleResolver --- .../main/java/org/jline/builtins/Nano.java | 170 ++++++++---------- 1 file changed, 72 insertions(+), 98 deletions(-) diff --git a/builtins/src/main/java/org/jline/builtins/Nano.java b/builtins/src/main/java/org/jline/builtins/Nano.java index b5299d161..910d0677b 100644 --- a/builtins/src/main/java/org/jline/builtins/Nano.java +++ b/builtins/src/main/java/org/jline/builtins/Nano.java @@ -29,17 +29,8 @@ import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.nio.file.StandardOpenOption; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.EnumSet; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.Map.Entry; -import java.util.Optional; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; @@ -56,11 +47,7 @@ import org.jline.terminal.Terminal; import org.jline.terminal.Terminal.Signal; import org.jline.terminal.Terminal.SignalHandler; -import org.jline.utils.AttributedString; -import org.jline.utils.AttributedStringBuilder; -import org.jline.utils.AttributedStyle; -import org.jline.utils.Display; -import org.jline.utils.Status; +import org.jline.utils.*; import org.jline.utils.InfoCmp.Capability; import org.mozilla.universalchardet.UniversalDetector; @@ -1668,12 +1655,29 @@ public static RuleType evalRuleType(List colorCfg) { private static class NanorcParser { private static final String DEFAULT_SYNTAX = "default"; + private static final List JLINE_NAMED_STYLES = Arrays.asList("blink", "bold", "conceal", "crossed-out" + , "crossedout", "faint", "hidden", "inverse", "inverse-neg", "inverseneg", "italic", "underline"); + private static final List COLORS_8 = Arrays.asList("white", "black", "red", "blue", "green", "yellow", "magenta", "cyan"); + // https://github.com/lhmouse/nano-win/commit/a7aab18dfeef8a0e8073d5fa420677dc8fe548da + private static final Map COLORS_NANO = new HashMap<>(); + static { + COLORS_NANO.put("pink", 204); + COLORS_NANO.put("purple", 163); + COLORS_NANO.put("mauve", 134); + COLORS_NANO.put("lagoon", 38); + COLORS_NANO.put("mint", 48); + COLORS_NANO.put("lime", 148); + COLORS_NANO.put("peach", 215); + COLORS_NANO.put("orange", 208); + COLORS_NANO.put("latte", 137); + } private final String name; private final String target; private final List highlightRules = new ArrayList<>(); private final BufferedReader reader; private boolean matches = false; - private String syntaxName; + private String syntaxName = "unknown"; + private final Map styleSpecs = new HashMap<>(); public NanorcParser(Path file, String name, String target) throws IOException { this(new Source.PathSource(file, null).read(), name, target); @@ -1686,8 +1690,10 @@ public NanorcParser(InputStream in, String name, String target) { } public void parse() throws IOException { - String line = reader.readLine(); - while (line != null) { + String line; + int idx = 0; + while ((line = reader.readLine()) != null) { + idx++; line = line.trim(); if (line.length() > 0 && !line.startsWith("#")) { line = line.replaceAll("\\\\<", "\\\\b") @@ -1731,12 +1737,11 @@ public void parse() throws IOException { matches = true; } } else if (parts.get(0).equals("color")) { - addHighlightRule(parts, false); + addHighlightRule(syntaxName + idx, parts, false); } else if (parts.get(0).equals("icolor")) { - addHighlightRule(parts, true); + addHighlightRule(syntaxName + idx, parts, true); } } - line = reader.readLine(); } reader.close(); } @@ -1753,87 +1758,56 @@ public boolean isDefault() { return syntaxName.equals(DEFAULT_SYNTAX); } - private Integer toColor(String styleString) { - Integer out = null; - if (styleString.length() > 0) { - out = 0; - if (styleString.startsWith("bright")) { - out = AttributedStyle.BRIGHT; - styleString = styleString.substring(6); - } - if (styleString.equals("white")) { - out += AttributedStyle.WHITE; - } else if (styleString.equals("black")) { - out += AttributedStyle.BLACK; - } else if (styleString.equals("red")) { - out += AttributedStyle.RED; - } else if (styleString.equals("blue")) { - out += AttributedStyle.BLUE; - } else if (styleString.equals("green")) { - out += AttributedStyle.GREEN; - } else if (styleString.equals("yellow")) { - out += AttributedStyle.YELLOW; - } else if (styleString.equals("magenta")) { - out += AttributedStyle.MAGENTA; - } else if (styleString.equals("cyan")) { - out += AttributedStyle.CYAN; - } else if (styleString.matches("\\d+")) { - out = Integer.parseInt(styleString); + private String getStyle(String reference) { + StringBuilder out = new StringBuilder(); + boolean first = true; + boolean fg = true; + for (String s : styleSpecs.get(reference)) { + if (s.trim().isEmpty()) { + fg = false; + continue; } + if (!first) { + out.append(","); + } + if (JLINE_NAMED_STYLES.contains(s)) { + out.append(s); + } else if (COLORS_8.contains(s) || COLORS_NANO.containsKey(s) || s.startsWith("light") + || s.startsWith("bright") || s.startsWith("~") || s.startsWith("!") || s.matches("\\d+") + || s.equals("normal") || s.equals("default")) { + if (s.matches("\\d+") || COLORS_NANO.containsKey(s)) { + if (fg) { + out.append("38;5;"); + } else { + out.append("48;5;"); + } + out.append(s.matches("\\d+") ? s : COLORS_NANO.get(s).toString()); + } else { + if (fg) { + out.append("fg:"); + } else { + out.append("bg:"); + } + if (COLORS_8.contains(s) || s.startsWith("~") || s.startsWith("!") || s.startsWith("bright-")) { + out.append(s); + } else if (s.startsWith("light")) { + out.append("!").append(s.substring(5)); + } else if (s.startsWith("bright")) { + out.append("!").append(s.substring(6)); + } else { + out.append("default"); + } + } + fg = false; + } + first = false; } - return out; - } - - private AttributedStyle setStyle(String name, AttributedStyle style) { - AttributedStyle out = style; - switch (name) { - case "blink": - out = style.blink(); - break; - case "bold": - out = style.bold(); - break; - case "conceal": - out = style.conceal(); - break; - case "faint": - out = style.faint(); - break; - case "hidden": - out = style.hidden(); - break; - case "inverse": - out = style.inverse(); - break; - case "italic": - out = style.italic(); - break; - case "underline": - out = style.underline(); - break; - default: - } - return out; + return out.toString(); } - private void addHighlightRule(List parts, boolean caseInsensitive) { - AttributedStyle style = AttributedStyle.DEFAULT.foreground(AttributedStyle.BLACK + AttributedStyle.BRIGHT); - String[] styleStrings = parts.get(1).split(","); - List styles = Arrays.asList("blink", "bold", "conceal", "faint", "hidden", "inverse", "italic", "underline"); - int colorStart = 0; - // GNU nano version >= v5 support styles: bold and italic, rest jline extension - while (styles.contains(styleStrings[colorStart])) { - style = setStyle(styleStrings[colorStart], style); - colorStart++; - } - Integer fcolor = toColor(styleStrings[colorStart]); - Integer bcolor = styleStrings.length > 1 + colorStart ? toColor(styleStrings[colorStart + 1]) : null; - if (fcolor != null) { - style = style.foreground(fcolor); - } - if (bcolor != null) { - style = style.background(bcolor); - } + private void addHighlightRule(String reference, List parts, boolean caseInsensitive) { + styleSpecs.put(reference, parts.get(1).split(",")); + AttributedStyle style = new StyleResolver(this::getStyle).resolve("." + reference); if (HighlightRule.evalRuleType(parts) == HighlightRule.RuleType.PATTERN) { for (int i = 2; i < parts.size(); i++) {