diff --git a/src/main/java/de/f0rce/ace/enums/AceCustomModeTokens.java b/src/main/java/de/f0rce/ace/enums/AceCustomModeTokens.java index 9d58651..126c6a4 100644 --- a/src/main/java/de/f0rce/ace/enums/AceCustomModeTokens.java +++ b/src/main/java/de/f0rce/ace/enums/AceCustomModeTokens.java @@ -101,6 +101,8 @@ public enum AceCustomModeTokens { /** the name of an attribute (mainly in tags) */ ENTITY_OTHER_ATTRIBUTE_NAME("entity.other.attribute-name"), + IDENTIFIER("identifier"), + /** stuff which is "invalid" */ INVALID("invalid"), diff --git a/src/main/java/de/f0rce/ace/util/AceCustomModeRule.java b/src/main/java/de/f0rce/ace/util/AceCustomModeRule.java index 146d5f8..9172258 100644 --- a/src/main/java/de/f0rce/ace/util/AceCustomModeRule.java +++ b/src/main/java/de/f0rce/ace/util/AceCustomModeRule.java @@ -2,6 +2,7 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.Map; import java.util.stream.Collectors; import de.f0rce.ace.enums.AceCustomModeTokens; @@ -19,6 +20,8 @@ public class AceCustomModeRule { private Object token; private String regex; + private String start; + private String end; private String next; private String defaultToken; @@ -49,6 +52,15 @@ public void setTokens(AceCustomModeTokens... tokens) { .collect(Collectors.toCollection(ArrayList::new)); } + public void setKeywordMapper(Map map, AceCustomModeTokens defaultToken, boolean ignoreCase, String splitChar) { + this.token = Map.of( + "map", map.entrySet().stream().collect(Collectors.toMap(e -> e.getKey().getToken(), Map.Entry::getValue)), + "defaultToken", defaultToken.getToken(), + "ignoreCase", ignoreCase, + "splitChar", splitChar + ); + } + /** @return {@link ArrayList} */ public ArrayList getTokens() { if (this.token instanceof ArrayList) { @@ -76,6 +88,26 @@ public String getRegex() { return this.regex; } + /** @param start {@link String} */ + public void setStart(String start) { + this.start = start; + } + + /** @return {@link String} */ + public String getStart() { + return this.start; + } + + /** @param end {@link String} */ + public void setEnd(String end) { + this.end = end; + } + + /** @return {@link String} */ + public String getEnd() { + return this.end; + } + /** @param next {@link String} */ public void setNext(String next) { this.next = next; diff --git a/src/main/resources/META-INF/resources/frontend/@f0rce/lit-ace/lit-ace.js b/src/main/resources/META-INF/resources/frontend/@f0rce/lit-ace/lit-ace.js index 3219c83..437f59f 100644 --- a/src/main/resources/META-INF/resources/frontend/@f0rce/lit-ace/lit-ace.js +++ b/src/main/resources/META-INF/resources/frontend/@f0rce/lit-ace/lit-ace.js @@ -1271,6 +1271,23 @@ class LitAce extends LitElement { var customModeFunction = function () { this.$rules = parsed.states; + // Convert objects to keyword mappers + for (var key in this.$rules) { + var state = this.$rules[key]; + for (var i = 0; i < state.length; i++) { + var rule = state[i]; + let token = rule.token; + if (typeof token === "object") { + rule.token = this.createKeywordMapper( + token.map, + token.defaultToken, + token.ignoreCase, + token.splitChar + ) + } + } + } + this.normalizeRules(); } diff --git a/src/test/java/de/f0rce/View.java b/src/test/java/de/f0rce/View.java index 6abcdcb..cb6f4b1 100644 --- a/src/test/java/de/f0rce/View.java +++ b/src/test/java/de/f0rce/View.java @@ -1,7 +1,5 @@ package de.f0rce; -import com.vaadin.flow.component.Key; -import com.vaadin.flow.component.Shortcuts; import com.vaadin.flow.component.button.Button; import com.vaadin.flow.component.checkbox.Checkbox; import com.vaadin.flow.component.combobox.ComboBox; @@ -16,12 +14,17 @@ import com.vaadin.flow.theme.Theme; import com.vaadin.flow.theme.lumo.Lumo; import de.f0rce.ace.AceEditor; +import de.f0rce.ace.enums.AceCustomModeTokens; import de.f0rce.ace.enums.AceExportType; import de.f0rce.ace.enums.AceMode; import de.f0rce.ace.enums.AceTheme; +import de.f0rce.ace.util.AceCustomMode; +import de.f0rce.ace.util.AceCustomModeRule; + import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; @Theme(themeClass = Lumo.class, variant = Lumo.DARK) @Route("") @@ -126,6 +129,37 @@ public View() { // aceEditor.addCustomAutocompletion(l3, "food", true); aceEditor.addDynamicAutocompletion(map, ".", "not dynmaic", true); + AceCustomMode customMode = new AceCustomMode(); + + AceCustomModeRule keywords = new AceCustomModeRule(); + keywords.setRegex("[a-zA-Z_$][a-zA-Z0-9_$]*\\b"); + keywords.setKeywordMapper( + Map.of( + AceCustomModeTokens.KEYWORD, String.join("|", custom) + ), + AceCustomModeTokens.IDENTIFIER, + true, + "|" + ); + + AceCustomModeRule lineComment = new AceCustomModeRule(); + lineComment.setRegex("--.*$"); + lineComment.setToken(AceCustomModeTokens.COMMENT); + + AceCustomModeRule blockComment = new AceCustomModeRule(); + blockComment.setStart("/\\*"); + blockComment.setEnd("\\*/"); + blockComment.setToken(AceCustomModeTokens.COMMENT); + + customMode.addState( + "start", + lineComment, + blockComment, + keywords + ); + + aceEditor.addCustomMode("custom", customMode); + aceEditor.addFocusListener( evt -> { // aceEditor.openAutocompletion(); @@ -185,7 +219,12 @@ public View() { modesComboBox.addValueChangeListener( event -> { if (event.getValue() != null) { - aceEditor.setMode(event.getValue()); + AceMode mode = event.getValue(); + if (mode == AceMode.custom) { + aceEditor.setCustomMode("custom"); + } else { + aceEditor.setMode(mode); + } } });