irongit

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

regex-file/src/regexButtons.ts
172 lines3.9 KBJavaScript
1import * as vscode from "vscode";
2import { getConfig } from "./global";
3import { highlighter } from "./highlighter";
4
5type FlagChar = "g" | "i" | "m" | "s" | "u" | "y" | "x";
6type FlagState = "on" | "off";
7type FlagDict = { [key in FlagChar]: Flag };
8type Flag = {
9 char: FlagChar;
10 tooltip: string;
11 button?: vscode.StatusBarItem;
12 state?: FlagState;
13};
14
15const FLAG_ICONS = {
16 on: "$(check)",
17 off: "$(x)",
18};
19
20const FLAG_COLORS = {
21 on: "#00FF00",
22 off: "#FF0000",
23};
24
25const FLAG_CHARS: Flag[] = [
26 { char: "g", tooltip: "Global search: find all matches in the string" },
27 {
28 char: "i",
29 tooltip:
30 "Case-insensitive search: match both uppercase and lowercase characters",
31 },
32 {
33 char: "m",
34 tooltip: "Multi-line search: ^ and $ match the start and end of each line",
35 },
36 { char: "s", tooltip: "Dot matches newline: . matches newline characters" },
37 { char: "u", tooltip: "Unicode: enable full Unicode matching" },
38 {
39 char: "y",
40 tooltip:
41 "Sticky search: start at the last index where the previous match ended",
42 },
43 {
44 char: "x",
45 tooltip:
46 "Extended: allow whitespace and comments within the pattern (non-standard in JavaScript)",
47 },
48];
49
50class RegexButtons {
51 context: vscode.ExtensionContext | undefined;
52 flags: FlagDict;
53
54 constructor() {
55 this.flags = FLAG_CHARS.reduce((acc, flag) => {
56 flag.state = "off";
57 acc[flag.char] = flag;
58 return acc;
59 }, {} as { [key in FlagChar]: Flag });
60 }
61
62 activate(context: vscode.ExtensionContext) {
63 this.loadConfigFlags();
64 this.context = context;
65 this.createButtons();
66 }
67
68 getFlagString() {
69 return Object.entries(this.flags)
70 .filter(([_, flag]) => flag.state === "on")
71 .map(([key, _]) => key)
72 .join("")
73 .replace("x", "")
74 .replace("y", "")
75 .concat("d");
76 }
77
78 hasXFlag() {
79 return this.flags.x.state === "on";
80 }
81
82 hasYFlag() {
83 return this.flags.y.state === "on";
84 }
85
86 loadConfigFlags() {
87 for (const flag of getConfig().get("flags") as FlagChar[]) {
88 this.flags[flag].state = "on";
89 }
90 }
91
92 toggleFlag(flag: Flag) {
93 // output.log(`Toggling flag ${flag.char}`);
94 flag.state = flag.state === "on" ? "off" : "on";
95 this.decorateFlag(flag);
96 highlighter.run();
97 }
98
99 decorateFlag(flag: Flag) {
100 if (flag.button && flag.state) {
101 flag.button.text = `${FLAG_ICONS[flag.state]} ${flag.char.toUpperCase()}`;
102 flag.button.color = FLAG_COLORS[flag.state];
103 flag.button.tooltip = flag.tooltip;
104 }
105 }
106
107 createButton(flag: Flag) {
108 // output.log(`Creating button for ${flag}`);
109 flag.button = vscode.window.createStatusBarItem(
110 vscode.StatusBarAlignment.Left
111 );
112 this.decorateFlag(flag);
113 flag.button.command = `regex.toggleFlag${flag.char.toUpperCase()}`;
114 let disposable = vscode.commands.registerCommand(
115 `regex.toggleFlag${flag.char.toUpperCase()}`,
116 () => {
117 this.toggleFlag(flag);
118 }
119 );
120 flag.button.show();
121 this.context?.subscriptions.push(flag.button);
122 this.context?.subscriptions.push(disposable);
123 }
124
125 createButtons() {
126 // output.log("Creating buttons");
127 for (const flag of FLAG_CHARS) {
128 this.createButton(flag);
129 }
130 }
131
132 disposeButtons() {
133 // output.log("Disposing buttons");
134 for (const flag of Object.values(this.flags)) {
135 if (flag.button) {
136 flag.button.dispose();
137 }
138 }
139 }
140
141 hideButtons() {
142 // output.log("Hiding buttons");
143 for (const flag of Object.values(this.flags)) {
144 if (flag.button) {
145 flag.button.hide();
146 }
147 }
148 }
149
150 hide() {
151 this.hideButtons();
152 }
153
154 showFlagButtons() {
155 // output.log("Showing buttons");
156 for (const flag of Object.values(this.flags)) {
157 if (flag.button) {
158 flag.button.show();
159 }
160 }
161 }
162
163 show() {
164 this.showFlagButtons();
165 }
166
167 dispose() {
168 this.disposeButtons();
169 }
170}
171
172export const regexButtons = new RegexButtons();