From 2cec1473e070f575d3b230923e3657192ba162a3 Mon Sep 17 00:00:00 2001 From: Li Guanglin Date: Sat, 12 Apr 2025 15:57:48 +0800 Subject: [PATCH 1/6] add support for common syntax highlighter --- app/build.gradle | 5 +- app/src/main/assets/languages/java.json | 15 ++++ app/src/main/assets/languages/map.properties | 5 ++ .../markor/format/FormatRegistry.java | 17 ++--- .../plaintext/PlaintextSyntaxHighlighter.java | 22 ++++++ .../format/plaintext/highlight/Rule.java | 52 ++++++++++++++ .../format/plaintext/highlight/Syntax.java | 24 +++++++ .../plaintext/highlight/SyntaxCache.java | 47 +++++++++++++ .../plaintext/highlight/SyntaxLoader.java | 69 +++++++++++++++++++ 9 files changed, 246 insertions(+), 10 deletions(-) create mode 100644 app/src/main/assets/languages/java.json create mode 100644 app/src/main/assets/languages/map.properties create mode 100644 app/src/main/java/net/gsantner/markor/format/plaintext/highlight/Rule.java create mode 100644 app/src/main/java/net/gsantner/markor/format/plaintext/highlight/Syntax.java create mode 100644 app/src/main/java/net/gsantner/markor/format/plaintext/highlight/SyntaxCache.java create mode 100644 app/src/main/java/net/gsantner/markor/format/plaintext/highlight/SyntaxLoader.java diff --git a/app/build.gradle b/app/build.gradle index 236cf2446b..ed59113994 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -135,8 +135,6 @@ dependencies { exclude group: 'commons-beanutils', module: 'commons-beanutils' } - - // UI libs implementation 'com.github.Pixplicity:gene-rate:v1.1.8' implementation 'com.github.AppIntro:AppIntro:6.2.0' @@ -150,6 +148,9 @@ dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${version_plugin_kotlin}" } + // https://mvnrepository.com/artifact/com.google.code.gson/gson + implementation 'com.google.code.gson:gson:2.10.1' + // Processors def anpros = [] for (anpro in anpros) { diff --git a/app/src/main/assets/languages/java.json b/app/src/main/assets/languages/java.json new file mode 100644 index 0000000000..7e5884f89c --- /dev/null +++ b/app/src/main/assets/languages/java.json @@ -0,0 +1,15 @@ +{ + "language": "Java", + "rules": [ + { + "type": "KEYWORD", + "regex": "\\b(public|static|void|class)\\b", + "color": "#FF5722" + }, + { + "type": "STRING", + "regex": "\".*\"", + "color": "#4CAF50" + } + ] +} diff --git a/app/src/main/assets/languages/map.properties b/app/src/main/assets/languages/map.properties new file mode 100644 index 0000000000..6c9bd715cf --- /dev/null +++ b/app/src/main/assets/languages/map.properties @@ -0,0 +1,5 @@ +java=java +.java=java +.py=python +markdown=markdown +.md=markdown \ No newline at end of file diff --git a/app/src/main/java/net/gsantner/markor/format/FormatRegistry.java b/app/src/main/java/net/gsantner/markor/format/FormatRegistry.java index 923a9e3414..35189284d2 100644 --- a/app/src/main/java/net/gsantner/markor/format/FormatRegistry.java +++ b/app/src/main/java/net/gsantner/markor/format/FormatRegistry.java @@ -128,19 +128,20 @@ public static FormatRegistry getFormat(int formatId, @NonNull final Context cont final AppSettings appSettings = ApplicationObject.settings(); switch (formatId) { - case FORMAT_CSV: { - format._converter = CONVERTER_CSV; - format._highlighter = new CsvSyntaxHighlighter(appSettings); - - // TODO k3b ???? + case FORMAT_PLAIN: { + format._converter = CONVERTER_PLAINTEXT; + format._highlighter = new PlaintextSyntaxHighlighter(appSettings, document.extension); + // Should implement code action buttons for PlaintextActionButtons format._textActions = new PlaintextActionButtons(context, document); format._autoFormatInputFilter = new AutoTextFormatter(MarkdownReplacePatternGenerator.formatPatterns); format._autoFormatTextWatcher = new ListHandler(MarkdownReplacePatternGenerator.formatPatterns); break; } - case FORMAT_PLAIN: { - format._converter = CONVERTER_PLAINTEXT; - format._highlighter = new PlaintextSyntaxHighlighter(appSettings); + case FORMAT_CSV: { + format._converter = CONVERTER_CSV; + format._highlighter = new CsvSyntaxHighlighter(appSettings); + + // TODO k3b ???? format._textActions = new PlaintextActionButtons(context, document); format._autoFormatInputFilter = new AutoTextFormatter(MarkdownReplacePatternGenerator.formatPatterns); format._autoFormatTextWatcher = new ListHandler(MarkdownReplacePatternGenerator.formatPatterns); diff --git a/app/src/main/java/net/gsantner/markor/format/plaintext/PlaintextSyntaxHighlighter.java b/app/src/main/java/net/gsantner/markor/format/plaintext/PlaintextSyntaxHighlighter.java index e42b9be481..bf5ae804a0 100644 --- a/app/src/main/java/net/gsantner/markor/format/plaintext/PlaintextSyntaxHighlighter.java +++ b/app/src/main/java/net/gsantner/markor/format/plaintext/PlaintextSyntaxHighlighter.java @@ -7,20 +7,42 @@ * #########################################################*/ +import net.gsantner.markor.format.plaintext.highlight.Rule; +import net.gsantner.markor.format.plaintext.highlight.Syntax; +import net.gsantner.markor.format.plaintext.highlight.SyntaxLoader; import net.gsantner.markor.frontend.textview.SyntaxHighlighterBase; import net.gsantner.markor.model.AppSettings; +import java.util.ArrayList; + public class PlaintextSyntaxHighlighter extends SyntaxHighlighterBase { + private final SyntaxLoader syntaxLoader = new SyntaxLoader(); + private Syntax syntax; public PlaintextSyntaxHighlighter(AppSettings as) { super(as); } + public PlaintextSyntaxHighlighter(AppSettings appSettings, String lang) { + super(appSettings); + appSettings.getContext(); + syntax = syntaxLoader.getSyntax(appSettings.getContext(), lang); + } + @Override protected void generateSpans() { createTabSpans(_tabSize); createUnderlineHexColorsSpans(); createSmallBlueLinkSpans(); + + if (syntax == null) { + return; + } + + ArrayList rules = syntax.getRules(); + for (Rule rule : rules) { + createColorSpanForMatches(rule.getPattern(), rule.getParsedColor()); + } } } diff --git a/app/src/main/java/net/gsantner/markor/format/plaintext/highlight/Rule.java b/app/src/main/java/net/gsantner/markor/format/plaintext/highlight/Rule.java new file mode 100644 index 0000000000..d626218760 --- /dev/null +++ b/app/src/main/java/net/gsantner/markor/format/plaintext/highlight/Rule.java @@ -0,0 +1,52 @@ +package net.gsantner.markor.format.plaintext.highlight; + +import android.graphics.Color; + +import java.util.regex.Pattern; + +public class Rule { + private String type; + private String regex; + private Pattern pattern; + private String color; + private Integer parsedColor; + // private boolean bold; + + public String getType() { + return type; + } + + public String getRegex() { + return regex; + } + + public String getColor() { + return color; + } + + public int getParsedColor() { + if (parsedColor == null) { + parsedColor = Color.parseColor(color); + } + return parsedColor; + } + + public Pattern getPattern() { + if (pattern == null) { + pattern = Pattern.compile(regex); + } + return pattern; + } + + public void setType(String type) { + this.type = type; + } + + public void setRegex(String regex) { + this.regex = regex; + } + + public void setColor(String color) { + this.color = color; + } +} diff --git a/app/src/main/java/net/gsantner/markor/format/plaintext/highlight/Syntax.java b/app/src/main/java/net/gsantner/markor/format/plaintext/highlight/Syntax.java new file mode 100644 index 0000000000..d39315a876 --- /dev/null +++ b/app/src/main/java/net/gsantner/markor/format/plaintext/highlight/Syntax.java @@ -0,0 +1,24 @@ +package net.gsantner.markor.format.plaintext.highlight; + +import java.util.ArrayList; + +public class Syntax { + private String language; + private ArrayList rules; + + public String getLanguage() { + return language; + } + + public ArrayList getRules() { + return rules; + } + + public void setLanguage(String language) { + this.language = language; + } + + public void setRules(ArrayList rules) { + this.rules = rules; + } +} diff --git a/app/src/main/java/net/gsantner/markor/format/plaintext/highlight/SyntaxCache.java b/app/src/main/java/net/gsantner/markor/format/plaintext/highlight/SyntaxCache.java new file mode 100644 index 0000000000..14e003a2e4 --- /dev/null +++ b/app/src/main/java/net/gsantner/markor/format/plaintext/highlight/SyntaxCache.java @@ -0,0 +1,47 @@ +package net.gsantner.markor.format.plaintext.highlight; + +import java.util.HashMap; + +public class SyntaxCache { + public static final int CACHE_SIZE = 5; + private final HashMap syntaxMap = new HashMap<>(); + private final HashMap usageMap = new HashMap<>(); + + public Syntax getSyntax(String key) { + Syntax syntax = syntaxMap.get(key); + if (syntax == null) { + return null; + } + + Integer usage = usageMap.get(key); + if (usage == null) { + usageMap.put(key, 1); + } else { + usageMap.put(key, ++usage); + } + + return syntax; + } + + public void putSyntax(String key, Syntax syntax) { + if (syntaxMap.size() > CACHE_SIZE) { + String entryKey = null; + int min = Integer.MAX_VALUE; + for (HashMap.Entry entry : usageMap.entrySet()) { + int value = entry.getValue(); + if (min < value) { + min = value; + entryKey = entry.getKey(); + } + } + + if (entryKey != null) { + syntaxMap.remove(entryKey); + usageMap.remove(entryKey); + } + } + + syntaxMap.put(key, syntax); + usageMap.put(key, 0); + } +} diff --git a/app/src/main/java/net/gsantner/markor/format/plaintext/highlight/SyntaxLoader.java b/app/src/main/java/net/gsantner/markor/format/plaintext/highlight/SyntaxLoader.java new file mode 100644 index 0000000000..33bb6f1c07 --- /dev/null +++ b/app/src/main/java/net/gsantner/markor/format/plaintext/highlight/SyntaxLoader.java @@ -0,0 +1,69 @@ +package net.gsantner.markor.format.plaintext.highlight; + +import android.content.Context; + +import com.google.gson.Gson; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.Properties; + +public class SyntaxLoader { + private final Gson gson = new Gson(); + private final Properties map = new Properties(); + private final SyntaxCache syntaxCache = new SyntaxCache(); + + public static final String MAP_PATH = "languages/map.properties"; + + private void load(InputStream inputStream, String lang) { + try { + Syntax syntax = gson.fromJson(new InputStreamReader(inputStream), Syntax.class); + syntaxCache.putSyntax(lang, syntax); + inputStream.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void load(Context context, String lang) { + try { + load(context.getAssets().open("languages/" + lang + ".json"), lang); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + /** + * Get language syntax. + * + * @param context Android Context. + * @param lang Language name or file extension without dot. + * @return + */ + public Syntax getSyntax(Context context, String lang) { + if (map.isEmpty()) { + try { + map.load(context.getAssets().open(MAP_PATH)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + String key = map.getProperty(lang.toLowerCase()); + Syntax syntax = syntaxCache.getSyntax(key); + if (syntax == null) { + load(context, key); + } + + return syntaxCache.getSyntax(key); + } + + public Syntax getSyntax(String extension, Context context) { + if (extension.startsWith(".")) { + return getSyntax(context, extension.substring(1)); + } else { + return getSyntax(context, extension); + } + } +} From 6a6da32910049026470a9dc7c0182f0f5f098bfd Mon Sep 17 00:00:00 2001 From: Li Guanglin Date: Sat, 12 Apr 2025 18:40:52 +0800 Subject: [PATCH 2/6] improve common syntax highlighter --- .../main/assets/highlight/languages/java.json | 13 ++ .../assets/highlight/languages/map.properties | 8 ++ .../main/assets/highlight/styles/default.json | 13 ++ app/src/main/assets/languages/java.json | 15 --- app/src/main/assets/languages/map.properties | 5 - .../plaintext/PlaintextSyntaxHighlighter.java | 35 +++-- .../highlight/HighlightConfigLoader.java | 121 ++++++++++++++++++ .../format/plaintext/highlight/Rule.java | 52 -------- .../format/plaintext/highlight/Style.java | 37 ++++++ .../format/plaintext/highlight/Syntax.java | 25 +++- .../plaintext/highlight/SyntaxCache.java | 47 ------- .../plaintext/highlight/SyntaxLoader.java | 69 ---------- 12 files changed, 236 insertions(+), 204 deletions(-) create mode 100644 app/src/main/assets/highlight/languages/java.json create mode 100644 app/src/main/assets/highlight/languages/map.properties create mode 100644 app/src/main/assets/highlight/styles/default.json delete mode 100644 app/src/main/assets/languages/java.json delete mode 100644 app/src/main/assets/languages/map.properties create mode 100644 app/src/main/java/net/gsantner/markor/format/plaintext/highlight/HighlightConfigLoader.java delete mode 100644 app/src/main/java/net/gsantner/markor/format/plaintext/highlight/Rule.java create mode 100644 app/src/main/java/net/gsantner/markor/format/plaintext/highlight/Style.java delete mode 100644 app/src/main/java/net/gsantner/markor/format/plaintext/highlight/SyntaxCache.java delete mode 100644 app/src/main/java/net/gsantner/markor/format/plaintext/highlight/SyntaxLoader.java diff --git a/app/src/main/assets/highlight/languages/java.json b/app/src/main/assets/highlight/languages/java.json new file mode 100644 index 0000000000..10a8221ee9 --- /dev/null +++ b/app/src/main/assets/highlight/languages/java.json @@ -0,0 +1,13 @@ +{ + "language": "Java", + "rules": [ + { + "type": "keyword", + "regex": "\\b(public|static|void|class)\\b" + }, + { + "type": "string", + "regex": "\".*\"" + } + ] +} diff --git a/app/src/main/assets/highlight/languages/map.properties b/app/src/main/assets/highlight/languages/map.properties new file mode 100644 index 0000000000..93923c4cba --- /dev/null +++ b/app/src/main/assets/highlight/languages/map.properties @@ -0,0 +1,8 @@ +# C/C++ +c=cpp +cpp=cpp +# Java +java=java +# Python +python=python +py=python diff --git a/app/src/main/assets/highlight/styles/default.json b/app/src/main/assets/highlight/styles/default.json new file mode 100644 index 0000000000..80f11bb487 --- /dev/null +++ b/app/src/main/assets/highlight/styles/default.json @@ -0,0 +1,13 @@ +{ + "name": "default", + "defines": [ + { + "type": "keyword", + "color": "#FF5722" + }, + { + "type": "string", + "color": "#4CAF50" + } + ] +} diff --git a/app/src/main/assets/languages/java.json b/app/src/main/assets/languages/java.json deleted file mode 100644 index 7e5884f89c..0000000000 --- a/app/src/main/assets/languages/java.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "language": "Java", - "rules": [ - { - "type": "KEYWORD", - "regex": "\\b(public|static|void|class)\\b", - "color": "#FF5722" - }, - { - "type": "STRING", - "regex": "\".*\"", - "color": "#4CAF50" - } - ] -} diff --git a/app/src/main/assets/languages/map.properties b/app/src/main/assets/languages/map.properties deleted file mode 100644 index 6c9bd715cf..0000000000 --- a/app/src/main/assets/languages/map.properties +++ /dev/null @@ -1,5 +0,0 @@ -java=java -.java=java -.py=python -markdown=markdown -.md=markdown \ No newline at end of file diff --git a/app/src/main/java/net/gsantner/markor/format/plaintext/PlaintextSyntaxHighlighter.java b/app/src/main/java/net/gsantner/markor/format/plaintext/PlaintextSyntaxHighlighter.java index bf5ae804a0..bccb426113 100644 --- a/app/src/main/java/net/gsantner/markor/format/plaintext/PlaintextSyntaxHighlighter.java +++ b/app/src/main/java/net/gsantner/markor/format/plaintext/PlaintextSyntaxHighlighter.java @@ -7,26 +7,34 @@ * #########################################################*/ -import net.gsantner.markor.format.plaintext.highlight.Rule; +import android.graphics.Paint; + +import net.gsantner.markor.format.plaintext.highlight.HighlightConfigLoader; +import net.gsantner.markor.format.plaintext.highlight.Style; import net.gsantner.markor.format.plaintext.highlight.Syntax; -import net.gsantner.markor.format.plaintext.highlight.SyntaxLoader; import net.gsantner.markor.frontend.textview.SyntaxHighlighterBase; import net.gsantner.markor.model.AppSettings; import java.util.ArrayList; public class PlaintextSyntaxHighlighter extends SyntaxHighlighterBase { - private final SyntaxLoader syntaxLoader = new SyntaxLoader(); + public final static HighlightConfigLoader configLoader = new HighlightConfigLoader(); private Syntax syntax; + private Style style; - public PlaintextSyntaxHighlighter(AppSettings as) { - super(as); + public PlaintextSyntaxHighlighter(AppSettings appSettings) { + super(appSettings); } - public PlaintextSyntaxHighlighter(AppSettings appSettings, String lang) { + public PlaintextSyntaxHighlighter(AppSettings appSettings, String extension) { super(appSettings); - appSettings.getContext(); - syntax = syntaxLoader.getSyntax(appSettings.getContext(), lang); + syntax = configLoader.getSyntax(extension, appSettings.getContext()); + style = configLoader.getStyle(appSettings.getContext(), "default"); + } + + @Override + public SyntaxHighlighterBase configure(Paint paint) { + return super.configure(paint); } @Override @@ -39,9 +47,14 @@ protected void generateSpans() { return; } - ArrayList rules = syntax.getRules(); - for (Rule rule : rules) { - createColorSpanForMatches(rule.getPattern(), rule.getParsedColor()); + ArrayList rules = syntax.getRules(); + ArrayList defines = style.getDefines(); + for (Syntax.Rule rule : rules) { + for (Style.Define define : defines) { + if (define.getType().equals(rule.getType())) { + createColorSpanForMatches(rule.getPattern(), define.getColor()); + } + } } } diff --git a/app/src/main/java/net/gsantner/markor/format/plaintext/highlight/HighlightConfigLoader.java b/app/src/main/java/net/gsantner/markor/format/plaintext/highlight/HighlightConfigLoader.java new file mode 100644 index 0000000000..71f8b13441 --- /dev/null +++ b/app/src/main/java/net/gsantner/markor/format/plaintext/highlight/HighlightConfigLoader.java @@ -0,0 +1,121 @@ +package net.gsantner.markor.format.plaintext.highlight; + +import android.content.Context; + +import com.google.gson.Gson; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.HashMap; +import java.util.Properties; + +public class HighlightConfigLoader { + private final Gson gson = new Gson(); + private final Properties map = new Properties(); + private final SyntaxCache syntaxCache = new SyntaxCache(); + private Style style; + + public static final String MAP_PATH = "highlight/languages/map.properties"; + + private void load(Context context, String lang) { + try (InputStream input = context.getAssets().open("highlight/languages/" + lang + ".json");) { + Syntax syntax = gson.fromJson(new InputStreamReader(input), Syntax.class); + syntaxCache.putSyntax(lang, syntax); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void loadStyle(Context context, String name) { + try (InputStream input = context.getAssets().open("highlight/styles/" + name + ".json");) { + style = gson.fromJson(new InputStreamReader(input), Style.class); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + /** + * Get language syntax. + * + * @param context Android Context. + * @param lang Language name or file extension without dot. + * @return + */ + public Syntax getSyntax(Context context, String lang) { + if (map.isEmpty()) { + try { + map.load(context.getAssets().open(MAP_PATH)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + String key = map.getProperty(lang.toLowerCase()); + Syntax syntax = syntaxCache.getSyntax(key); + if (syntax == null) { + load(context, key); + } + + return syntaxCache.getSyntax(key); + } + + public Syntax getSyntax(String extension, Context context) { + if (extension.startsWith(".")) { + return getSyntax(context, extension.substring(1)); + } else { + return getSyntax(context, extension); + } + } + + public Style getStyle(Context context, String name) { + if (style == null) { + loadStyle(context, name); + } + return style; + } + + class SyntaxCache { + public static final int CACHE_SIZE = 5; + private final HashMap syntaxMap = new HashMap<>(); + private final HashMap usageMap = new HashMap<>(); + + public Syntax getSyntax(String key) { + Syntax syntax = syntaxMap.get(key); + if (syntax == null) { + return null; + } + + Integer usage = usageMap.get(key); + if (usage == null) { + usageMap.put(key, 1); + } else { + usageMap.put(key, ++usage); + } + + return syntax; + } + + public void putSyntax(String key, Syntax syntax) { + if (syntaxMap.size() > CACHE_SIZE) { + String entryKey = null; + int min = Integer.MAX_VALUE; + for (HashMap.Entry entry : usageMap.entrySet()) { + int value = entry.getValue(); + if (min < value) { + min = value; + entryKey = entry.getKey(); + } + } + + if (entryKey != null) { + syntaxMap.remove(entryKey); + usageMap.remove(entryKey); + } + } + + syntaxMap.put(key, syntax); + usageMap.put(key, 0); + } + } +} diff --git a/app/src/main/java/net/gsantner/markor/format/plaintext/highlight/Rule.java b/app/src/main/java/net/gsantner/markor/format/plaintext/highlight/Rule.java deleted file mode 100644 index d626218760..0000000000 --- a/app/src/main/java/net/gsantner/markor/format/plaintext/highlight/Rule.java +++ /dev/null @@ -1,52 +0,0 @@ -package net.gsantner.markor.format.plaintext.highlight; - -import android.graphics.Color; - -import java.util.regex.Pattern; - -public class Rule { - private String type; - private String regex; - private Pattern pattern; - private String color; - private Integer parsedColor; - // private boolean bold; - - public String getType() { - return type; - } - - public String getRegex() { - return regex; - } - - public String getColor() { - return color; - } - - public int getParsedColor() { - if (parsedColor == null) { - parsedColor = Color.parseColor(color); - } - return parsedColor; - } - - public Pattern getPattern() { - if (pattern == null) { - pattern = Pattern.compile(regex); - } - return pattern; - } - - public void setType(String type) { - this.type = type; - } - - public void setRegex(String regex) { - this.regex = regex; - } - - public void setColor(String color) { - this.color = color; - } -} diff --git a/app/src/main/java/net/gsantner/markor/format/plaintext/highlight/Style.java b/app/src/main/java/net/gsantner/markor/format/plaintext/highlight/Style.java new file mode 100644 index 0000000000..b4e3dfadab --- /dev/null +++ b/app/src/main/java/net/gsantner/markor/format/plaintext/highlight/Style.java @@ -0,0 +1,37 @@ +package net.gsantner.markor.format.plaintext.highlight; + +import android.graphics.Color; + +import java.util.ArrayList; + +// Load from JSON +public class Style { + private String name; + private ArrayList defines; + + public String getName() { + return name; + } + + public ArrayList getDefines() { + return defines; + } + + public class Define { + private String type; + private String color; + private Integer color_; + // private boolean bold; + + public String getType() { + return type; + } + + public int getColor() { + if (color_ == null) { + color_ = Color.parseColor(color); + } + return color_; + } + } +} diff --git a/app/src/main/java/net/gsantner/markor/format/plaintext/highlight/Syntax.java b/app/src/main/java/net/gsantner/markor/format/plaintext/highlight/Syntax.java index d39315a876..6f1b370380 100644 --- a/app/src/main/java/net/gsantner/markor/format/plaintext/highlight/Syntax.java +++ b/app/src/main/java/net/gsantner/markor/format/plaintext/highlight/Syntax.java @@ -1,7 +1,9 @@ package net.gsantner.markor.format.plaintext.highlight; import java.util.ArrayList; +import java.util.regex.Pattern; +// Load from JSON public class Syntax { private String language; private ArrayList rules; @@ -14,11 +16,24 @@ public ArrayList getRules() { return rules; } - public void setLanguage(String language) { - this.language = language; - } + public class Rule { + private String type; + private String regex; + private Pattern pattern; + + public String getType() { + return type; + } + + public String getRegex() { + return regex; + } - public void setRules(ArrayList rules) { - this.rules = rules; + public Pattern getPattern() { + if (pattern == null) { + pattern = Pattern.compile(regex); + } + return pattern; + } } } diff --git a/app/src/main/java/net/gsantner/markor/format/plaintext/highlight/SyntaxCache.java b/app/src/main/java/net/gsantner/markor/format/plaintext/highlight/SyntaxCache.java deleted file mode 100644 index 14e003a2e4..0000000000 --- a/app/src/main/java/net/gsantner/markor/format/plaintext/highlight/SyntaxCache.java +++ /dev/null @@ -1,47 +0,0 @@ -package net.gsantner.markor.format.plaintext.highlight; - -import java.util.HashMap; - -public class SyntaxCache { - public static final int CACHE_SIZE = 5; - private final HashMap syntaxMap = new HashMap<>(); - private final HashMap usageMap = new HashMap<>(); - - public Syntax getSyntax(String key) { - Syntax syntax = syntaxMap.get(key); - if (syntax == null) { - return null; - } - - Integer usage = usageMap.get(key); - if (usage == null) { - usageMap.put(key, 1); - } else { - usageMap.put(key, ++usage); - } - - return syntax; - } - - public void putSyntax(String key, Syntax syntax) { - if (syntaxMap.size() > CACHE_SIZE) { - String entryKey = null; - int min = Integer.MAX_VALUE; - for (HashMap.Entry entry : usageMap.entrySet()) { - int value = entry.getValue(); - if (min < value) { - min = value; - entryKey = entry.getKey(); - } - } - - if (entryKey != null) { - syntaxMap.remove(entryKey); - usageMap.remove(entryKey); - } - } - - syntaxMap.put(key, syntax); - usageMap.put(key, 0); - } -} diff --git a/app/src/main/java/net/gsantner/markor/format/plaintext/highlight/SyntaxLoader.java b/app/src/main/java/net/gsantner/markor/format/plaintext/highlight/SyntaxLoader.java deleted file mode 100644 index 33bb6f1c07..0000000000 --- a/app/src/main/java/net/gsantner/markor/format/plaintext/highlight/SyntaxLoader.java +++ /dev/null @@ -1,69 +0,0 @@ -package net.gsantner.markor.format.plaintext.highlight; - -import android.content.Context; - -import com.google.gson.Gson; - -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.Properties; - -public class SyntaxLoader { - private final Gson gson = new Gson(); - private final Properties map = new Properties(); - private final SyntaxCache syntaxCache = new SyntaxCache(); - - public static final String MAP_PATH = "languages/map.properties"; - - private void load(InputStream inputStream, String lang) { - try { - Syntax syntax = gson.fromJson(new InputStreamReader(inputStream), Syntax.class); - syntaxCache.putSyntax(lang, syntax); - inputStream.close(); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - private void load(Context context, String lang) { - try { - load(context.getAssets().open("languages/" + lang + ".json"), lang); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - /** - * Get language syntax. - * - * @param context Android Context. - * @param lang Language name or file extension without dot. - * @return - */ - public Syntax getSyntax(Context context, String lang) { - if (map.isEmpty()) { - try { - map.load(context.getAssets().open(MAP_PATH)); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - String key = map.getProperty(lang.toLowerCase()); - Syntax syntax = syntaxCache.getSyntax(key); - if (syntax == null) { - load(context, key); - } - - return syntaxCache.getSyntax(key); - } - - public Syntax getSyntax(String extension, Context context) { - if (extension.startsWith(".")) { - return getSyntax(context, extension.substring(1)); - } else { - return getSyntax(context, extension); - } - } -} From c92583c1f74b54659637d898bba6fe9e2e77e7d5 Mon Sep 17 00:00:00 2001 From: Li Guanglin Date: Sun, 13 Apr 2025 17:20:07 +0800 Subject: [PATCH 3/6] add several popular language syntax highlight --- .../main/assets/highlight/languages/cpp.json | 37 ++++++++++++ .../main/assets/highlight/languages/java.json | 36 ++++++++++-- .../assets/highlight/languages/map.properties | 4 -- .../assets/highlight/languages/python.json | 41 ++++++++++++++ .../main/assets/highlight/styles/default.json | 56 +++++++++++++++++-- 5 files changed, 162 insertions(+), 12 deletions(-) create mode 100644 app/src/main/assets/highlight/languages/cpp.json create mode 100644 app/src/main/assets/highlight/languages/python.json diff --git a/app/src/main/assets/highlight/languages/cpp.json b/app/src/main/assets/highlight/languages/cpp.json new file mode 100644 index 0000000000..10eec47f45 --- /dev/null +++ b/app/src/main/assets/highlight/languages/cpp.json @@ -0,0 +1,37 @@ +{ + "language": "C/CPP", + "rules": [ + { + "type": "KEYWORDS", + "regex": "\\b(typedef|inline|auto|class|explicit|extern|friend|inline|mutable|operator|register|template|private|protected|public|typeid|virtual|volatile|constexpr|nullptr|decltype)\\b" + }, + { + "type": "KEYWORDS_2", + "regex": "\\b(goto|break|return|continue|asm|case|default|if|else|switch|while|for|do|sizeof|typeof|stdcall|cdecl|const_cast|delete|dynamic_cast|goto|namespace|new|pascal|reinterpret_cast|static_cast|this|throw|try|catch|using|true|false|bitand|and|bitor|or|xor|compl|and_eq|or_eq|xor_eq|not|not_eq|assert|static_assert)\\b" + }, + { + "type": "TYPES", + "regex": "\\b(int|long|short|char|void|signed|unsigned|float|double|size_t|wchar_t|ptrdiff_t|sig_atomic_t|fpos_t|clock_t|time_t|va_list|jmp_buf|FILE|DIR|div_t|ldiv_t|static|mbstate_t|wctrans_t|wint_t|wctype_t|const|bool|complex|struct|union|enum|int8_t|int16_t|int32_t|int64_t|uint8_t|uint16_t|uint32_t|uint64_t|int_least8_t|int_least16_t|int_least32_t|int_least64_t|uint_least8_t|uint_least16_t|uint_least32_t|uint_least64_t|int_fast8_t|int_fast16_t|int_fast32_t|int_fast64_t|uint_fast8_t|uint_fast16_t|uint_fast32_t|uint_fast64_t|intptr_t|uintptr_t|intmax_t|uintmax_t)\\b" + }, + { + "type": "NUMBER", + "regex": "\\b\\d+(\\.\\d*)?(e(\\+|\\-)?\\d+)?\\b" + }, + { + "type": "STRING", + "regex": "(\".*\")|('.*')" + }, + { + "type": "ESCAPE_CHAR", + "regex": "\\\\(?:[btnfr\"'\\\\]|u[0-9a-fA-F]{4}|[0-3][0-7]{2}|[0-7]{1,2})" + }, + { + "type": "LINE_COMMENT", + "regex": "//.*" + }, + { + "type": "BLOCK_COMMENT", + "regex": "/\\*[\\s\\S]*?\\*/" + } + ] +} diff --git a/app/src/main/assets/highlight/languages/java.json b/app/src/main/assets/highlight/languages/java.json index 10a8221ee9..88eb9975d8 100644 --- a/app/src/main/assets/highlight/languages/java.json +++ b/app/src/main/assets/highlight/languages/java.json @@ -2,12 +2,40 @@ "language": "Java", "rules": [ { - "type": "keyword", - "regex": "\\b(public|static|void|class)\\b" + "type": "KEYWORDS", + "regex": "\\b(abstract|assert|class|do|enum|extends|final|implements|import|interface|instanceof|native|new|package|private|protected|public|static|strictfp|super|synchronized|this|throw|throws|transient|void|volatile)\\b" }, { - "type": "string", - "regex": "\".*\"" + "type": "KEYWORDS_2", + "regex": "\\b(if|else|while|for|switch|case|default|continue|break|return|try|catch|finally|goto|const)\\b" + }, + { + "type": "TYPES", + "regex": "\\b(byte|short|char|int|long|float|double|boolean)\\b" + }, + { + "type": "NUMBER", + "regex": "\\b\\d+(\\.\\d*)?(e(\\+|\\-)?\\d+)?\\b" + }, + { + "type": "STRING", + "regex": "(\".*\")|('.*')" + }, + { + "type": "ESCAPE_CHAR", + "regex": "\\\\(?:[btnfr\"'\\\\]|u[0-9a-fA-F]{4}|[0-3][0-7]{2}|[0-7]{1,2})" + }, + { + "type": "SPECIAL_VALUE", + "regex": "\\b(true|false|null)\\b" + }, + { + "type": "LINE_COMMENT", + "regex": "//.*" + }, + { + "type": "BLOCK_COMMENT", + "regex": "/\\*[\\s\\S]*?\\*/" } ] } diff --git a/app/src/main/assets/highlight/languages/map.properties b/app/src/main/assets/highlight/languages/map.properties index 93923c4cba..138d98687c 100644 --- a/app/src/main/assets/highlight/languages/map.properties +++ b/app/src/main/assets/highlight/languages/map.properties @@ -1,8 +1,4 @@ -# C/C++ c=cpp cpp=cpp -# Java java=java -# Python -python=python py=python diff --git a/app/src/main/assets/highlight/languages/python.json b/app/src/main/assets/highlight/languages/python.json new file mode 100644 index 0000000000..81ae9d9592 --- /dev/null +++ b/app/src/main/assets/highlight/languages/python.json @@ -0,0 +1,41 @@ +{ + "language": "Python", + "rules": [ + { + "type": "KEYWORDS", + "regex": "\\b(bool|enumerate|set|frozenset|help|reversed|sorted|sum|Ellipsis|NotImplemented|__import__|abs|apply|buffer|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|eval|execfile|file|filter|float|getattr|globals|hasattr|hash|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|min|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|round|setattr|slice|staticmethod|str|super|tuple|type|unichr|unicode|vars|xrange|zip)\\b" + }, + { + "type": "KEYWORDS_2", + "regex": "\\b(break|continue|del|except|exec|finally|pass|print|raise|return|try|global|assert|lambda|yield|def|class|for|while|if|elif|else|and|in|is|not|or|import|from|as)\\b" + }, + { + "type": "TYPES", + "regex": "\\b(byte|short|char|int|long|float|double|boolean)\\b" + }, + { + "type": "NUMBER", + "regex": "\\b\\d+(\\.\\d*)?(e(\\+|\\-)?\\d+)?\\b" + }, + { + "type": "STRING", + "regex": "(\".+\")|('.+')" + }, + { + "type": "ESCAPE_CHAR", + "regex": "\\\\(?:[btnfr\"'\\\\]|u[0-9a-fA-F]{4}|[0-3][0-7]{2}|[0-7]{1,2})" + }, + { + "type": "SPECIAL_VALUE", + "regex": "\\b(None|True|False)\\b" + }, + { + "type": "LINE_COMMENT", + "regex": "#.*" + }, + { + "type": "BLOCK_COMMENT", + "regex": "('''(.*?)''')|(\"{3}(.*?)\"{3})" + } + ] +} diff --git a/app/src/main/assets/highlight/styles/default.json b/app/src/main/assets/highlight/styles/default.json index 80f11bb487..6f3dad5489 100644 --- a/app/src/main/assets/highlight/styles/default.json +++ b/app/src/main/assets/highlight/styles/default.json @@ -2,12 +2,60 @@ "name": "default", "defines": [ { - "type": "keyword", - "color": "#FF5722" + "type": "FOREGROUND", + "color": "#000000" }, { - "type": "string", - "color": "#4CAF50" + "type": "BACKGROUND", + "color": "#FFFFFF" + }, + { + "type": "KEYWORDS", + "color": "#008AD8" + }, + { + "type": "KEYWORDS_2", + "color": "#C100DB" + }, + { + "type": "TYPES", + "color": "#1339FF" + }, + { + "type": "NUMBER", + "color": "#00A600" + }, + { + "type": "STRING", + "color": "#C36A2B" + }, + { + "type": "ESCAPE_CHAR", + "color": "#008AD8" + }, + { + "type": "SPECIAL_VALUE", + "color": "#FA4616" + }, + { + "type": "LINE_COMMENT", + "color": "#949CAC" + }, + { + "type": "BLOCK_COMMENT", + "color": "#949CAC" + }, + { + "type": "CLASS", + "color": "#F2827F" + }, + { + "type": "METHOD", + "color": "#BE8126" + }, + { + "type": "FUNCTION", + "color": "#BE8126" } ] } From 86f4229f51e68ef69f8a68d0a63f748537b7b4ea Mon Sep 17 00:00:00 2001 From: Li Guanglin Date: Mon, 14 Apr 2025 13:15:52 +0800 Subject: [PATCH 4/6] minor improvements --- .../main/assets/highlight/styles/default.json | 61 ------------------- .../main/assets/highlight/themes/default.json | 47 ++++++++++++++ .../plaintext/PlaintextSyntaxHighlighter.java | 31 +++++----- .../highlight/HighlightConfigLoader.java | 26 ++++---- .../highlight/{Style.java => Theme.java} | 17 ++---- 5 files changed, 83 insertions(+), 99 deletions(-) delete mode 100644 app/src/main/assets/highlight/styles/default.json create mode 100644 app/src/main/assets/highlight/themes/default.json rename app/src/main/java/net/gsantner/markor/format/plaintext/highlight/{Style.java => Theme.java} (62%) diff --git a/app/src/main/assets/highlight/styles/default.json b/app/src/main/assets/highlight/styles/default.json deleted file mode 100644 index 6f3dad5489..0000000000 --- a/app/src/main/assets/highlight/styles/default.json +++ /dev/null @@ -1,61 +0,0 @@ -{ - "name": "default", - "defines": [ - { - "type": "FOREGROUND", - "color": "#000000" - }, - { - "type": "BACKGROUND", - "color": "#FFFFFF" - }, - { - "type": "KEYWORDS", - "color": "#008AD8" - }, - { - "type": "KEYWORDS_2", - "color": "#C100DB" - }, - { - "type": "TYPES", - "color": "#1339FF" - }, - { - "type": "NUMBER", - "color": "#00A600" - }, - { - "type": "STRING", - "color": "#C36A2B" - }, - { - "type": "ESCAPE_CHAR", - "color": "#008AD8" - }, - { - "type": "SPECIAL_VALUE", - "color": "#FA4616" - }, - { - "type": "LINE_COMMENT", - "color": "#949CAC" - }, - { - "type": "BLOCK_COMMENT", - "color": "#949CAC" - }, - { - "type": "CLASS", - "color": "#F2827F" - }, - { - "type": "METHOD", - "color": "#BE8126" - }, - { - "type": "FUNCTION", - "color": "#BE8126" - } - ] -} diff --git a/app/src/main/assets/highlight/themes/default.json b/app/src/main/assets/highlight/themes/default.json new file mode 100644 index 0000000000..f83ab514d7 --- /dev/null +++ b/app/src/main/assets/highlight/themes/default.json @@ -0,0 +1,47 @@ +{ + "name": "default", + "styles": { + "FOREGROUND": { + "color": "#000000" + }, + "BACKGROUND": { + "color": "#FFFFFF" + }, + "KEYWORDS": { + "color": "#008AD8" + }, + "KEYWORDS_2": { + "color": "#C100DB" + }, + "TYPES": { + "color": "#1339FF" + }, + "NUMBER": { + "color": "#00A600" + }, + "STRING": { + "color": "#C36A2B" + }, + "ESCAPE_CHAR": { + "color": "#008AD8" + }, + "SPECIAL_VALUE": { + "color": "#FA4616" + }, + "LINE_COMMENT": { + "color": "#949CAC" + }, + "BLOCK_COMMENT": { + "color": "#949CAC" + }, + "CLASS": { + "color": "#F2827F" + }, + "METHOD": { + "color": "#BE8126" + }, + "FUNCTION": { + "color": "#BE8126" + } + } +} diff --git a/app/src/main/java/net/gsantner/markor/format/plaintext/PlaintextSyntaxHighlighter.java b/app/src/main/java/net/gsantner/markor/format/plaintext/PlaintextSyntaxHighlighter.java index bccb426113..92736b4e47 100644 --- a/app/src/main/java/net/gsantner/markor/format/plaintext/PlaintextSyntaxHighlighter.java +++ b/app/src/main/java/net/gsantner/markor/format/plaintext/PlaintextSyntaxHighlighter.java @@ -10,17 +10,18 @@ import android.graphics.Paint; import net.gsantner.markor.format.plaintext.highlight.HighlightConfigLoader; -import net.gsantner.markor.format.plaintext.highlight.Style; import net.gsantner.markor.format.plaintext.highlight.Syntax; +import net.gsantner.markor.format.plaintext.highlight.Theme; import net.gsantner.markor.frontend.textview.SyntaxHighlighterBase; import net.gsantner.markor.model.AppSettings; import java.util.ArrayList; +import java.util.HashMap; public class PlaintextSyntaxHighlighter extends SyntaxHighlighterBase { public final static HighlightConfigLoader configLoader = new HighlightConfigLoader(); - private Syntax syntax; - private Style style; + private ArrayList rules; + private HashMap styles; public PlaintextSyntaxHighlighter(AppSettings appSettings) { super(appSettings); @@ -28,8 +29,15 @@ public PlaintextSyntaxHighlighter(AppSettings appSettings) { public PlaintextSyntaxHighlighter(AppSettings appSettings, String extension) { super(appSettings); - syntax = configLoader.getSyntax(extension, appSettings.getContext()); - style = configLoader.getStyle(appSettings.getContext(), "default"); + + Syntax syntax = configLoader.getSyntax(extension, appSettings.getContext()); + if (syntax != null) { + rules = syntax.getRules(); + Theme theme = configLoader.getTheme(appSettings.getContext(), "default"); + if (theme != null) { + styles = theme.getStyles(); + } + } } @Override @@ -43,20 +51,15 @@ protected void generateSpans() { createUnderlineHexColorsSpans(); createSmallBlueLinkSpans(); - if (syntax == null) { + if (rules == null || styles == null) { return; } - ArrayList rules = syntax.getRules(); - ArrayList defines = style.getDefines(); for (Syntax.Rule rule : rules) { - for (Style.Define define : defines) { - if (define.getType().equals(rule.getType())) { - createColorSpanForMatches(rule.getPattern(), define.getColor()); - } + Theme.Style style = styles.get(rule.getType()); + if (style != null) { + createColorSpanForMatches(rule.getPattern(), style.getColor()); } } } - } - diff --git a/app/src/main/java/net/gsantner/markor/format/plaintext/highlight/HighlightConfigLoader.java b/app/src/main/java/net/gsantner/markor/format/plaintext/highlight/HighlightConfigLoader.java index 71f8b13441..0b054acce0 100644 --- a/app/src/main/java/net/gsantner/markor/format/plaintext/highlight/HighlightConfigLoader.java +++ b/app/src/main/java/net/gsantner/markor/format/plaintext/highlight/HighlightConfigLoader.java @@ -14,12 +14,12 @@ public class HighlightConfigLoader { private final Gson gson = new Gson(); private final Properties map = new Properties(); private final SyntaxCache syntaxCache = new SyntaxCache(); - private Style style; + private Theme theme; public static final String MAP_PATH = "highlight/languages/map.properties"; private void load(Context context, String lang) { - try (InputStream input = context.getAssets().open("highlight/languages/" + lang + ".json");) { + try (InputStream input = context.getAssets().open("highlight/languages/" + lang + ".json")) { Syntax syntax = gson.fromJson(new InputStreamReader(input), Syntax.class); syntaxCache.putSyntax(lang, syntax); } catch (IOException e) { @@ -27,9 +27,9 @@ private void load(Context context, String lang) { } } - private void loadStyle(Context context, String name) { - try (InputStream input = context.getAssets().open("highlight/styles/" + name + ".json");) { - style = gson.fromJson(new InputStreamReader(input), Style.class); + private void loadTheme(Context context, String name) { + try (InputStream input = context.getAssets().open("highlight/themes/" + name + ".json")) { + theme = gson.fromJson(new InputStreamReader(input), Theme.class); } catch (IOException e) { throw new RuntimeException(e); } @@ -39,8 +39,8 @@ private void loadStyle(Context context, String name) { * Get language syntax. * * @param context Android Context. - * @param lang Language name or file extension without dot. - * @return + * @param lang Language name. + * @return Language syntax. */ public Syntax getSyntax(Context context, String lang) { if (map.isEmpty()) { @@ -68,14 +68,14 @@ public Syntax getSyntax(String extension, Context context) { } } - public Style getStyle(Context context, String name) { - if (style == null) { - loadStyle(context, name); + public Theme getTheme(Context context, String name) { + if (theme == null || !theme.getName().equals(name)) { + loadTheme(context, name); } - return style; + return theme; } - class SyntaxCache { + static class SyntaxCache { public static final int CACHE_SIZE = 5; private final HashMap syntaxMap = new HashMap<>(); private final HashMap usageMap = new HashMap<>(); @@ -102,7 +102,7 @@ public void putSyntax(String key, Syntax syntax) { int min = Integer.MAX_VALUE; for (HashMap.Entry entry : usageMap.entrySet()) { int value = entry.getValue(); - if (min < value) { + if (value < min) { min = value; entryKey = entry.getKey(); } diff --git a/app/src/main/java/net/gsantner/markor/format/plaintext/highlight/Style.java b/app/src/main/java/net/gsantner/markor/format/plaintext/highlight/Theme.java similarity index 62% rename from app/src/main/java/net/gsantner/markor/format/plaintext/highlight/Style.java rename to app/src/main/java/net/gsantner/markor/format/plaintext/highlight/Theme.java index b4e3dfadab..faa4acb907 100644 --- a/app/src/main/java/net/gsantner/markor/format/plaintext/highlight/Style.java +++ b/app/src/main/java/net/gsantner/markor/format/plaintext/highlight/Theme.java @@ -2,31 +2,26 @@ import android.graphics.Color; -import java.util.ArrayList; +import java.util.HashMap; // Load from JSON -public class Style { +public class Theme { private String name; - private ArrayList defines; + private HashMap styles; // public String getName() { return name; } - public ArrayList getDefines() { - return defines; + public HashMap getStyles() { + return styles; } - public class Define { - private String type; + public class Style { private String color; private Integer color_; // private boolean bold; - public String getType() { - return type; - } - public int getColor() { if (color_ == null) { color_ = Color.parseColor(color); From 52a3f27f6da3695503a4e200850e5445626470e9 Mon Sep 17 00:00:00 2001 From: Li Guanglin Date: Thu, 17 Apr 2025 10:47:54 +0800 Subject: [PATCH 5/6] minor improvements --- app/src/main/assets/highlight/languages/cpp.json | 8 ++++++-- .../main/assets/highlight/languages/java.json | 16 ++++++++++++---- .../main/assets/highlight/languages/python.json | 10 +++++++--- .../main/assets/highlight/themes/default.json | 13 +++++-------- 4 files changed, 30 insertions(+), 17 deletions(-) diff --git a/app/src/main/assets/highlight/languages/cpp.json b/app/src/main/assets/highlight/languages/cpp.json index 10eec47f45..696dc470d5 100644 --- a/app/src/main/assets/highlight/languages/cpp.json +++ b/app/src/main/assets/highlight/languages/cpp.json @@ -6,7 +6,7 @@ "regex": "\\b(typedef|inline|auto|class|explicit|extern|friend|inline|mutable|operator|register|template|private|protected|public|typeid|virtual|volatile|constexpr|nullptr|decltype)\\b" }, { - "type": "KEYWORDS_2", + "type": "KEYWORDS_CONTROL", "regex": "\\b(goto|break|return|continue|asm|case|default|if|else|switch|while|for|do|sizeof|typeof|stdcall|cdecl|const_cast|delete|dynamic_cast|goto|namespace|new|pascal|reinterpret_cast|static_cast|this|throw|try|catch|using|true|false|bitand|and|bitor|or|xor|compl|and_eq|or_eq|xor_eq|not|not_eq|assert|static_assert)\\b" }, { @@ -23,7 +23,7 @@ }, { "type": "ESCAPE_CHAR", - "regex": "\\\\(?:[btnfr\"'\\\\]|u[0-9a-fA-F]{4}|[0-3][0-7]{2}|[0-7]{1,2})" + "regex": "\\\\([0bfnrtv'\"]|u[0-9a-fA-F]{4})|[0-7]{3}" }, { "type": "LINE_COMMENT", @@ -32,6 +32,10 @@ { "type": "BLOCK_COMMENT", "regex": "/\\*[\\s\\S]*?\\*/" + }, + { + "type": "FUNCTION", + "regex": "([a-zA-Z0-9_$]+)(?=\\()" } ] } diff --git a/app/src/main/assets/highlight/languages/java.json b/app/src/main/assets/highlight/languages/java.json index 88eb9975d8..1193395d38 100644 --- a/app/src/main/assets/highlight/languages/java.json +++ b/app/src/main/assets/highlight/languages/java.json @@ -6,7 +6,7 @@ "regex": "\\b(abstract|assert|class|do|enum|extends|final|implements|import|interface|instanceof|native|new|package|private|protected|public|static|strictfp|super|synchronized|this|throw|throws|transient|void|volatile)\\b" }, { - "type": "KEYWORDS_2", + "type": "KEYWORDS_CONTROL", "regex": "\\b(if|else|while|for|switch|case|default|continue|break|return|try|catch|finally|goto|const)\\b" }, { @@ -23,11 +23,11 @@ }, { "type": "ESCAPE_CHAR", - "regex": "\\\\(?:[btnfr\"'\\\\]|u[0-9a-fA-F]{4}|[0-3][0-7]{2}|[0-7]{1,2})" + "regex": "\\\\([0bfnrtv'\"]|u[0-9a-fA-F]{4})|[0-7]{3}" }, { - "type": "SPECIAL_VALUE", - "regex": "\\b(true|false|null)\\b" + "type": "CONSTANT", + "regex": "\\b(false|null|true|[A-Z_]+)\\b" }, { "type": "LINE_COMMENT", @@ -36,6 +36,14 @@ { "type": "BLOCK_COMMENT", "regex": "/\\*[\\s\\S]*?\\*/" + }, + { + "type": "CLASS", + "regex": "\\b([A-Z]\\w*)(?=[\\.\\[<>]|(\\s+\\w+\\s*=))\\b" + }, + { + "type": "FUNCTION", + "regex": "([a-zA-Z0-9_$]+)(?=\\()" } ] } diff --git a/app/src/main/assets/highlight/languages/python.json b/app/src/main/assets/highlight/languages/python.json index 81ae9d9592..c6db2646a1 100644 --- a/app/src/main/assets/highlight/languages/python.json +++ b/app/src/main/assets/highlight/languages/python.json @@ -6,7 +6,7 @@ "regex": "\\b(bool|enumerate|set|frozenset|help|reversed|sorted|sum|Ellipsis|NotImplemented|__import__|abs|apply|buffer|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|eval|execfile|file|filter|float|getattr|globals|hasattr|hash|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|min|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|round|setattr|slice|staticmethod|str|super|tuple|type|unichr|unicode|vars|xrange|zip)\\b" }, { - "type": "KEYWORDS_2", + "type": "KEYWORDS_CONTROL", "regex": "\\b(break|continue|del|except|exec|finally|pass|print|raise|return|try|global|assert|lambda|yield|def|class|for|while|if|elif|else|and|in|is|not|or|import|from|as)\\b" }, { @@ -23,10 +23,10 @@ }, { "type": "ESCAPE_CHAR", - "regex": "\\\\(?:[btnfr\"'\\\\]|u[0-9a-fA-F]{4}|[0-3][0-7]{2}|[0-7]{1,2})" + "regex": "\\\\([0bfnrtv'\"]|u[0-9a-fA-F]{4})|[0-7]{3}" }, { - "type": "SPECIAL_VALUE", + "type": "CONSTANT", "regex": "\\b(None|True|False)\\b" }, { @@ -36,6 +36,10 @@ { "type": "BLOCK_COMMENT", "regex": "('''(.*?)''')|(\"{3}(.*?)\"{3})" + }, + { + "type": "FUNCTION", + "regex": "([a-zA-Z0-9_$]+)(?=\\()" } ] } diff --git a/app/src/main/assets/highlight/themes/default.json b/app/src/main/assets/highlight/themes/default.json index f83ab514d7..9076600a96 100644 --- a/app/src/main/assets/highlight/themes/default.json +++ b/app/src/main/assets/highlight/themes/default.json @@ -10,7 +10,7 @@ "KEYWORDS": { "color": "#008AD8" }, - "KEYWORDS_2": { + "KEYWORDS_CONTROL": { "color": "#C100DB" }, "TYPES": { @@ -23,23 +23,20 @@ "color": "#C36A2B" }, "ESCAPE_CHAR": { - "color": "#008AD8" + "color": "#1339FF" }, - "SPECIAL_VALUE": { + "CONSTANT": { "color": "#FA4616" }, "LINE_COMMENT": { - "color": "#949CAC" + "color": "#8F8F88" }, "BLOCK_COMMENT": { - "color": "#949CAC" + "color": "#8F8F88" }, "CLASS": { "color": "#F2827F" }, - "METHOD": { - "color": "#BE8126" - }, "FUNCTION": { "color": "#BE8126" } From e36d29346a649859cb9a68fe90ce83f9c8d397b4 Mon Sep 17 00:00:00 2001 From: Li Guanglin Date: Fri, 18 Apr 2025 07:06:56 +0800 Subject: [PATCH 6/6] improve regex for escape chars --- app/src/main/assets/highlight/languages/cpp.json | 2 +- app/src/main/assets/highlight/languages/java.json | 2 +- app/src/main/assets/highlight/languages/python.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/assets/highlight/languages/cpp.json b/app/src/main/assets/highlight/languages/cpp.json index 696dc470d5..459fef755b 100644 --- a/app/src/main/assets/highlight/languages/cpp.json +++ b/app/src/main/assets/highlight/languages/cpp.json @@ -23,7 +23,7 @@ }, { "type": "ESCAPE_CHAR", - "regex": "\\\\([0bfnrtv'\"]|u[0-9a-fA-F]{4})|[0-7]{3}" + "regex": "\\\\([0bfnrtv'\"]|u[0-9a-fA-F]{4}|[0-7]{3})" }, { "type": "LINE_COMMENT", diff --git a/app/src/main/assets/highlight/languages/java.json b/app/src/main/assets/highlight/languages/java.json index 1193395d38..1b493be6d4 100644 --- a/app/src/main/assets/highlight/languages/java.json +++ b/app/src/main/assets/highlight/languages/java.json @@ -23,7 +23,7 @@ }, { "type": "ESCAPE_CHAR", - "regex": "\\\\([0bfnrtv'\"]|u[0-9a-fA-F]{4})|[0-7]{3}" + "regex": "\\\\([0bfnrtv'\"]|u[0-9a-fA-F]{4}|[0-7]{3})" }, { "type": "CONSTANT", diff --git a/app/src/main/assets/highlight/languages/python.json b/app/src/main/assets/highlight/languages/python.json index c6db2646a1..edf41bb558 100644 --- a/app/src/main/assets/highlight/languages/python.json +++ b/app/src/main/assets/highlight/languages/python.json @@ -23,7 +23,7 @@ }, { "type": "ESCAPE_CHAR", - "regex": "\\\\([0bfnrtv'\"]|u[0-9a-fA-F]{4})|[0-7]{3}" + "regex": "\\\\([0bfnrtv'\"]|u[0-9a-fA-F]{4}|[0-7]{3})" }, { "type": "CONSTANT",