irongit

A Regex file extension that makes it way easier to edit large regex.

highlight works very poorly

huncholanehuncholaneauthored
parent d7b013ccommit a45a41a2bdb56126cdcd970573bef3fbd8cf44ceBrowse files

6 files changed, +178 -1

+1-1package.json
@@ -64,7 +64,7 @@
6464 },
6565 "regex-file.maxMatches": {
6666 "type": "number",
67- "default": 10000,
67+ "default": 1000,
6868 "description": "Maximum matches for your extension"
6969 }
7070 }
+60-0src/decorationGenerator.ts
@@ -0,0 +1,60 @@
1+import * as vscode from "vscode";
2+
3+const BACKGROUND_COLORS = [
4+ "#FF0000",
5+ "#00FF00",
6+ "#0000FF",
7+ "#FFFF00",
8+ "#FF00FF",
9+ "#00FFFF",
10+ "#FFA500",
11+ "#FF1493",
12+ "#4B0082",
13+ "#EE82EE",
14+ "#8A2BE2",
15+ "#5F9EA0",
16+ "#7FFF00",
17+ "#D2691E",
18+ "#FF7F50",
19+ "#6495ED",
20+ "#DC143C",
21+ "#00CED1",
22+ "#9400D3",
23+ "#FFD700",
24+ "#ADFF2F",
25+ "#FF69B4",
26+ "#CD5C5C",
27+ "#F0E68C",
28+ "#E6E6FA",
29+ "#7CFC00",
30+ "#20B2AA",
31+ "#87CEFA",
32+ "#778899",
33+ "#FF6347",
34+];
35+
36+class DecorationGenerator {
37+ backgroundColors: string[];
38+
39+ constructor() {
40+ this.backgroundColors = [...BACKGROUND_COLORS];
41+ }
42+
43+ reset() {
44+ this.backgroundColors = [...BACKGROUND_COLORS];
45+ }
46+
47+ getColor() {
48+ return this.backgroundColors.pop();
49+ }
50+
51+ generate(options?: vscode.DecorationRenderOptions) {
52+ return vscode.window.createTextEditorDecorationType({
53+ backgroundColor: this.getColor(),
54+ ...options,
55+ });
56+ }
57+}
58+
59+const decorationGenerator = new DecorationGenerator();
60+export default decorationGenerator;
+9-0src/extension.ts
@@ -2,21 +2,30 @@ import * as vscode from "vscode";
22 import { output } from "./output";
33 import { editorsContainRegexFile } from "./utils";
44 import { regexButtons } from "./regexButtons";
5+import { highlighter } from "./highlighter";
56
67 export function activate(context: vscode.ExtensionContext) {
78 output.activate();
89 regexButtons.activate(context);
10+ highlighter.activate(context);
911
1012 vscode.window.onDidChangeActiveTextEditor((editor) => {
1113 if (editor && editor.document.uri.scheme === "file") {
1214 if (editor.document.languageId === "regex") {
1315 output.log("Regex file opened");
16+ highlighter.run();
1417 }
1518 }
1619 if (!editorsContainRegexFile()) {
1720 console.log("No regex file opened");
1821 }
1922 });
23+
24+ vscode.workspace.onDidChangeTextDocument((event) => {
25+ if (editorsContainRegexFile() && event.document.uri.scheme === "file") {
26+ highlighter.run();
27+ }
28+ });
2029 }
2130
2231 export function deactivate() {
+89-0src/highlighter.ts
@@ -0,0 +1,89 @@
1+import * as vscode from "vscode";
2+import { output } from "./output";
3+import { getNonRegexEditors, getRegexEditor } from "./utils";
4+import { regexButtons } from "./regexButtons";
5+import decorationGenerator from "./decorationGenerator";
6+import { getConfig } from "./global";
7+
8+type HighlightGroup = {
9+ range: vscode.Range;
10+ decoration: vscode.TextEditorDecorationType;
11+};
12+
13+class Highlighter {
14+ context: vscode.ExtensionContext | undefined;
15+ decorations: vscode.TextEditorDecorationType[] = [];
16+
17+ constructor() {}
18+
19+ activate(context: vscode.ExtensionContext) {
20+ output.log("Highlighter activated");
21+ this.context = context;
22+ }
23+
24+ reset() {
25+ output.log("Resetting decorations");
26+ this.decorations.forEach((decoration) => {
27+ decoration.dispose();
28+ });
29+ this.decorations = [];
30+ decorationGenerator.reset();
31+ }
32+
33+ getHighlightGroups(
34+ regex: string,
35+ flags: string,
36+ document: vscode.TextDocument
37+ ) {
38+ const re = new RegExp(regex, flags);
39+ const matches = document.getText().matchAll(re);
40+ const highlightGroups: HighlightGroup[] = [];
41+ const decorationMap: { [key: string]: vscode.TextEditorDecorationType } =
42+ {};
43+ const outerDecoration = decorationGenerator.generate({ cursor: "pointer" });
44+ this.decorations.push(outerDecoration);
45+ let i = 0;
46+ const maxMatches = getConfig().get("maxMatches") as number;
47+ for (const match of matches) {
48+ if (i >= maxMatches) {
49+ break;
50+ }
51+ const start = document.positionAt(match.index);
52+ const end = document.positionAt(match.index + match[0].length);
53+ highlightGroups.push({
54+ range: new vscode.Range(start, end),
55+ decoration: outerDecoration,
56+ });
57+ i++;
58+ }
59+ return highlightGroups;
60+ }
61+
62+ highlightMatches(regexEditor: vscode.TextEditor, editor: vscode.TextEditor) {
63+ output.log(`Highlighting matches in ${editor.document.fileName}`);
64+ const regex = regexEditor.document.getText();
65+ const flags = regexButtons.getFlagString();
66+ const highlightGroups = this.getHighlightGroups(
67+ regex,
68+ flags,
69+ editor.document
70+ );
71+ for (const group of highlightGroups) {
72+ editor.setDecorations(group.decoration, [group.range]);
73+ }
74+ }
75+
76+ run() {
77+ this.reset();
78+ const regexEditor = getRegexEditor();
79+ if (!regexEditor) {
80+ return;
81+ }
82+ const nonRegexEditors = getNonRegexEditors();
83+ for (const editor of nonRegexEditors) {
84+ this.highlightMatches(regexEditor, editor);
85+ }
86+ }
87+}
88+
89+export const highlighter = new Highlighter();
+1-0src/regexButtons.ts
@@ -88,6 +88,7 @@ class RegexButtons {
8888 if (flag.button && flag.state) {
8989 flag.button.text = `${FLAG_ICONS[flag.state]} ${flag.char.toUpperCase()}`;
9090 flag.button.color = FLAG_COLORS[flag.state];
91+ flag.button.tooltip = flag.tooltip;
9192 }
9293 }
9394
+18-0src/utils.ts
@@ -8,3 +8,21 @@ export function editorsContainRegexFile() {
88 editor.document.uri.scheme === "file"
99 );
1010 }
11+
12+export function getRegexEditor() {
13+ const editors = vscode.window.visibleTextEditors;
14+ return editors.find(
15+ (editor) =>
16+ editor.document.languageId === "regex" &&
17+ editor.document.uri.scheme === "file"
18+ );
19+}
20+
21+export function getNonRegexEditors() {
22+ const editors = vscode.window.visibleTextEditors;
23+ return editors.filter(
24+ (editor) =>
25+ editor.document.languageId !== "regex" ||
26+ editor.document.uri.scheme !== "file"
27+ );
28+}