A Regex file extension that makes it way easier to edit large regex.
starting new version
16 files changed, +529 -278
+2-2package.json
| @@ -2,10 +2,10 @@ | ||
| 2 | 2 | "name": "regex-file", |
| 3 | 3 | "displayName": "Regex File", |
| 4 | 4 | "icon": "images/icon.png", |
| 5 | - "description": "Made a file type for regex that highlights a second file and adds flags to the status bar.", | |
| 5 | + "description": "Regex File extension for Visual Studio Code.", | |
| 6 | 6 | "version": "0.0.1", |
| 7 | 7 | "repository": "git@github.com:huncholane/regex-file.git", |
| 8 | - "publisher": "Ghost Systems", | |
| 8 | + "publisher": "Hygo", | |
| 9 | 9 | "engines": { |
| 10 | 10 | "vscode": "^1.79.0" |
| 11 | 11 | }, |
+281-0src/backup/backup_extension.ts
| @@ -0,0 +1,281 @@ | ||
| 1 | +import * as vscode from "vscode"; | |
| 2 | + | |
| 3 | +/* GLOBAL CONSTANTS */ | |
| 4 | +const timeout = vscode.workspace | |
| 5 | + .getConfiguration("yourExtension") | |
| 6 | + .get("timeout", 1000); | |
| 7 | +const maxMatches = vscode.workspace | |
| 8 | + .getConfiguration("yourExtension") | |
| 9 | + .get("maxMatches", 10000); | |
| 10 | +const baseEditorStyle = vscode.window.createTextEditorDecorationType({ | |
| 11 | + backgroundColor: "yellow", | |
| 12 | + color: "black", | |
| 13 | +}); | |
| 14 | + | |
| 15 | +/* GLOBAL VARIABLES */ | |
| 16 | +let textDecorations = [baseEditorStyle]; | |
| 17 | +let outputChannel: vscode.OutputChannel; | |
| 18 | +let lastRegex = ""; | |
| 19 | +let lastText = ""; | |
| 20 | +let decorationType: vscode.TextEditorDecorationType | undefined; | |
| 21 | +const flagButtons: { [key: string]: InnerMapValue } = {}; | |
| 22 | + | |
| 23 | +/* TYPES */ | |
| 24 | +type GroupMatches = { | |
| 25 | + style: vscode.TextEditorDecorationType; | |
| 26 | + matches: vscode.Range[]; | |
| 27 | +}; | |
| 28 | +type GroupMatchMap = { | |
| 29 | + [key: string]: GroupMatches; | |
| 30 | +}; | |
| 31 | +interface InnerMapValue { | |
| 32 | + state: "on" | "off"; | |
| 33 | + button: vscode.StatusBarItem; | |
| 34 | +} | |
| 35 | +const states: Record<"on" | "off", string> = { | |
| 36 | + on: "$(check)", | |
| 37 | + off: "$(x)", | |
| 38 | +}; | |
| 39 | + | |
| 40 | +function getConfigFlags(): string { | |
| 41 | + const config = vscode.workspace.getConfiguration("regex-file"); | |
| 42 | + return config.get("flags") as string; | |
| 43 | +} | |
| 44 | + | |
| 45 | +function getRandomColor() { | |
| 46 | + // Generate a random hex color | |
| 47 | + const letters = "0123456789ABCDEF"; | |
| 48 | + let color = "#"; | |
| 49 | + for (let i = 0; i < 6; i++) { | |
| 50 | + color += letters[Math.floor(Math.random() * 16)]; | |
| 51 | + } | |
| 52 | + return color; | |
| 53 | +} | |
| 54 | + | |
| 55 | +function getReEditor(): vscode.TextEditor | undefined { | |
| 56 | + const editors = vscode.window.visibleTextEditors; | |
| 57 | + | |
| 58 | + for (const editor of editors) { | |
| 59 | + const fileName = editor.document.fileName; | |
| 60 | + if (fileName.endsWith(".re")) { | |
| 61 | + return editor; | |
| 62 | + } | |
| 63 | + } | |
| 64 | + console.log("No regex document."); | |
| 65 | +} | |
| 66 | + | |
| 67 | +function getTextEditor(): vscode.TextEditor | undefined { | |
| 68 | + const editors = vscode.window.visibleTextEditors; | |
| 69 | + | |
| 70 | + for (const editor of editors) { | |
| 71 | + const fileName = editor.document.fileName; | |
| 72 | + if (!fileName.endsWith(".re")) { | |
| 73 | + return editor; | |
| 74 | + } | |
| 75 | + } | |
| 76 | + console.log("No search document."); | |
| 77 | +} | |
| 78 | + | |
| 79 | +export function activate(context: vscode.ExtensionContext) { | |
| 80 | + outputChannel = vscode.window.createOutputChannel("regex-file"); | |
| 81 | + createFlagButtons(context); | |
| 82 | + highlightMatches(); | |
| 83 | + vscode.window.onDidChangeVisibleTextEditors(highlightMatches); | |
| 84 | + vscode.workspace.onDidChangeTextDocument(highlightMatches); | |
| 85 | +} | |
| 86 | + | |
| 87 | +function createFlagButtons(context: vscode.ExtensionContext): void { | |
| 88 | + ["g", "i", "m", "s", "u", "y", "x"].forEach((flag) => { | |
| 89 | + const button = vscode.window.createStatusBarItem( | |
| 90 | + vscode.StatusBarAlignment.Left | |
| 91 | + ); | |
| 92 | + let state: "on" | "off" = "off"; | |
| 93 | + if (getConfigFlags().includes(flag)) { | |
| 94 | + state = "on"; | |
| 95 | + } | |
| 96 | + button.text = `${states[state]} ${flag.toUpperCase()}`; | |
| 97 | + button.tooltip = `Toggle ${flag} flag`; | |
| 98 | + button.command = `regex.toggleFlag${flag.toUpperCase()}`; | |
| 99 | + button.show(); | |
| 100 | + flagButtons[flag] = { | |
| 101 | + state, | |
| 102 | + button, | |
| 103 | + }; | |
| 104 | + let disposable = vscode.commands.registerCommand( | |
| 105 | + `regex.toggleFlag${flag.toUpperCase()}`, | |
| 106 | + () => { | |
| 107 | + toggleFlag(flag); | |
| 108 | + } | |
| 109 | + ); | |
| 110 | + context.subscriptions.push(button); | |
| 111 | + context.subscriptions.push(disposable); | |
| 112 | + }); | |
| 113 | +} | |
| 114 | + | |
| 115 | +function getRegexFlags(): [string, boolean] { | |
| 116 | + let flags = ""; | |
| 117 | + let hasX = false; | |
| 118 | + Object.entries(flagButtons).forEach(([flag, info]) => { | |
| 119 | + if (info.state === "on") { | |
| 120 | + if (flag === "x") { | |
| 121 | + hasX = true; | |
| 122 | + } else { | |
| 123 | + flags += flag; | |
| 124 | + } | |
| 125 | + } | |
| 126 | + }); | |
| 127 | + return [flags, hasX]; | |
| 128 | +} | |
| 129 | + | |
| 130 | +function applyGroupMatchDecorations( | |
| 131 | + editor: vscode.TextEditor, | |
| 132 | + groupMatches: GroupMatchMap | |
| 133 | +) { | |
| 134 | + for (const groupName of Object.keys(groupMatches)) { | |
| 135 | + const { style, matches } = groupMatches[groupName]; | |
| 136 | + textDecorations.push(style); | |
| 137 | + | |
| 138 | + const decorations: vscode.DecorationOptions[] = matches.map( | |
| 139 | + (range) => ({ | |
| 140 | + range, | |
| 141 | + hoverMessage: `Group: ${groupName}`, | |
| 142 | + }) | |
| 143 | + ); | |
| 144 | + | |
| 145 | + editor.setDecorations(style, decorations); | |
| 146 | + } | |
| 147 | +} | |
| 148 | + | |
| 149 | +function updateGroupMatches( | |
| 150 | + textEditor: vscode.TextEditor, | |
| 151 | + groupMatches: GroupMatchMap, | |
| 152 | + match: RegExpExecArray | |
| 153 | +) { | |
| 154 | + for (const groupName in match.groups) { | |
| 155 | + const groupMatch = match.groups[groupName]; | |
| 156 | + | |
| 157 | + if (groupMatch) { | |
| 158 | + const startInd = match[0].indexOf(groupMatch); | |
| 159 | + const startPos = textEditor.document.positionAt( | |
| 160 | + match.index + startInd | |
| 161 | + ); | |
| 162 | + const endInd = startInd + groupMatch.length; | |
| 163 | + const endPos = textEditor.document.positionAt(match.index + endInd); | |
| 164 | + const matchRange = new vscode.Range(startPos, endPos); | |
| 165 | + | |
| 166 | + if (!groupMatches[groupName]) { | |
| 167 | + // Generate a random color for the group | |
| 168 | + const randomColor = getRandomColor(); | |
| 169 | + | |
| 170 | + // Define a new TextEditorDecorationType for the group with the random color | |
| 171 | + groupMatches[groupName] = { | |
| 172 | + style: vscode.window.createTextEditorDecorationType({ | |
| 173 | + backgroundColor: randomColor, | |
| 174 | + color: "black", // You can customize the text color | |
| 175 | + }), | |
| 176 | + matches: [matchRange], | |
| 177 | + }; | |
| 178 | + } else { | |
| 179 | + groupMatches[groupName].matches.push(matchRange); | |
| 180 | + } | |
| 181 | + } | |
| 182 | + } | |
| 183 | +} | |
| 184 | + | |
| 185 | +function highlightMatches(): void { | |
| 186 | + const reEditor = getReEditor(); | |
| 187 | + const textEditor = getTextEditor(); | |
| 188 | + if (!reEditor || !textEditor) { | |
| 189 | + outputChannel.appendLine( | |
| 190 | + "Abort highlighting. Missing reEditor or textEditor." | |
| 191 | + ); | |
| 192 | + return; | |
| 193 | + } | |
| 194 | + let reText = reEditor.document.getText(); | |
| 195 | + if (!reText) { | |
| 196 | + outputChannel.appendLine( | |
| 197 | + "Abort highlighting. No text in the regex file." | |
| 198 | + ); | |
| 199 | + } | |
| 200 | + let searchText = textEditor.document.getText(); | |
| 201 | + if (searchText === lastText && reText === lastRegex) { | |
| 202 | + return; | |
| 203 | + } | |
| 204 | + lastText = searchText; | |
| 205 | + lastRegex = reText; | |
| 206 | + outputChannel.appendLine("Ready to begin highlighting."); | |
| 207 | + | |
| 208 | + // Clear all previous text decorations | |
| 209 | + for (const decoration of textDecorations) { | |
| 210 | + textEditor.setDecorations(decoration, []); | |
| 211 | + textDecorations = [baseEditorStyle]; | |
| 212 | + } | |
| 213 | + | |
| 214 | + // Perform your matching and highlighting logic here | |
| 215 | + const matches: vscode.Range[] = []; | |
| 216 | + let [flags, hasX] = getRegexFlags(); | |
| 217 | + if (hasX) { | |
| 218 | + reText = reText.replace(/\s/g, ""); | |
| 219 | + } | |
| 220 | + let pattern; | |
| 221 | + try { | |
| 222 | + pattern = new RegExp(reText, flags); | |
| 223 | + } catch { | |
| 224 | + console.log("invalid pattern"); | |
| 225 | + return; | |
| 226 | + } | |
| 227 | + const groupMatches: GroupMatchMap = {}; | |
| 228 | + let match: RegExpExecArray | null; | |
| 229 | + let i = 0; | |
| 230 | + const startTime = new Date().getTime(); | |
| 231 | + while ((match = pattern.exec(searchText))) { | |
| 232 | + if (i > maxMatches) { | |
| 233 | + console.log(`Max matches of ${maxMatches} reached.`); | |
| 234 | + outputChannel.appendLine(`Max matches of ${maxMatches} reached.`); | |
| 235 | + break; | |
| 236 | + } | |
| 237 | + if (new Date().getTime() > startTime + 1000) { | |
| 238 | + console.log(`Timeout of ${timeout} reached.`); | |
| 239 | + outputChannel.appendLine(`Timeout of ${timeout} reached.`); | |
| 240 | + break; | |
| 241 | + } | |
| 242 | + updateGroupMatches(textEditor, groupMatches, match); | |
| 243 | + const startPos = textEditor.document.positionAt(match.index); | |
| 244 | + const endPos = textEditor.document.positionAt( | |
| 245 | + match.index + match[0].length | |
| 246 | + ); | |
| 247 | + const range = new vscode.Range(startPos, endPos); | |
| 248 | + matches.push(range); | |
| 249 | + i++; | |
| 250 | + } | |
| 251 | + | |
| 252 | + // Apply base decorations | |
| 253 | + textEditor.setDecorations(baseEditorStyle, matches); | |
| 254 | + | |
| 255 | + // Apply decorations to the groups | |
| 256 | + applyGroupMatchDecorations(textEditor, groupMatches); | |
| 257 | +} | |
| 258 | + | |
| 259 | +function toggleFlag(flag: string): void { | |
| 260 | + const button = flagButtons[flag].button; | |
| 261 | + const currentState = flagButtons[flag].state; | |
| 262 | + const newState = currentState === "on" ? "off" : "on"; | |
| 263 | + | |
| 264 | + flagButtons[flag].state = newState; | |
| 265 | + button.text = `${states[newState]} ${flag.toUpperCase()}`; | |
| 266 | +} | |
| 267 | + | |
| 268 | +export function deactivate() { | |
| 269 | + disposeFlagButtons(); | |
| 270 | +} | |
| 271 | + | |
| 272 | +function disposeFlagButtons(): void { | |
| 273 | + for (const key in flagButtons) { | |
| 274 | + if (flagButtons.hasOwnProperty(key)) { | |
| 275 | + const innerMapValue = flagButtons[key]; | |
| 276 | + innerMapValue.button.dispose(); | |
| 277 | + } | |
| 278 | + } | |
| 279 | + // Clear the flagButtons dictionary | |
| 280 | + Object.keys(flagButtons).forEach((key) => delete flagButtons[key]); | |
| 281 | +} |
+1-0src/backup/extension.js.map
| @@ -0,0 +1 @@ | ||
| 1 | +{"version":3,"file":"extension.js","sourceRoot":"","sources":["extension.ts"],"names":[],"mappings":";;;AAAA,iCAAiC;AAOjC,MAAM,WAAW,GAAqC,EAAE,CAAC;AACzD,MAAM,MAAM,GAAiC;IAC3C,EAAE,EAAE,UAAU;IACd,GAAG,EAAE,MAAM;CACZ,CAAC;AAEF,SAAS,cAAc;IACrB,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,gBAAgB,CAAC,YAAY,CAAC,CAAC;IAC/D,OAAO,MAAM,CAAC,GAAG,CAAC,OAAO,CAAW,CAAC;AACvC,CAAC;AAED,SAAS,kBAAkB;IACzB,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC,kBAAkB,EAAE;QACrD,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAC1C,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC;YAAE,UAAU,EAAE,CAAC;KAC7C;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAgB,QAAQ,CAAC,OAAgC;IACvD,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAC3B,MAAM,CAAC,SAAS,CAAC,uBAAuB,CACtC,CAAC,KAAqC,EAAE,EAAE;QACxC,+DAA+D;QAC/D,IACE,MAAM,CAAC,MAAM,CAAC,gBAAgB,EAAE,QAAQ,KAAK,KAAK,CAAC,QAAQ;YAC3D,MAAM,CAAC,SAAS,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,EACzC;YACA,kCAAkC;YAClC,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;SAC3D;IACH,CAAC,CACF,CAAC;IACF,MAAM,CAAC,MAAM,CAAC,2BAA2B,CAAC,kBAAkB,CAAC,CAAC;IAC9D,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,kBAAkB,CAAC,CAAC;IACzD,IAAI,MAAM,CAAC,MAAM,CAAC,gBAAgB;QAChC,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;AAC9D,CAAC;AAlBD,4BAkBC;AAED,SAAS,iBAAiB,CAAC,OAAgC;IACzD,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;QACnD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,mBAAmB,CAC9C,MAAM,CAAC,kBAAkB,CAAC,IAAI,CAC/B,CAAC;QACF,IAAI,KAAK,GAAiB,KAAK,CAAC;QAChC,IAAI,cAAc,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC;YAAE,KAAK,GAAG,IAAI,CAAC;QAClD,MAAM,CAAC,IAAI,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;QACvD,MAAM,CAAC,OAAO,GAAG,UAAU,IAAI,OAAO,CAAC;QACvC,MAAM,CAAC,OAAO,GAAG,mBAAmB,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;QACzD,MAAM,CAAC,IAAI,EAAE,CAAC;QACd,WAAW,CAAC,IAAI,CAAC,GAAG;YAClB,KAAK;YACL,MAAM;SACP,CAAC;QACF,IAAI,UAAU,GAAG,MAAM,CAAC,QAAQ,CAAC,eAAe,CAC9C,mBAAmB,IAAI,CAAC,WAAW,EAAE,EAAE,EACvC,GAAG,EAAE;YACH,UAAU,CAAC,IAAI,CAAC,CAAC;QACnB,CAAC,CACF,CAAC;QACF,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACnC,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,aAAa;IACpB,IAAI,KAAK,GAAG,EAAE,CAAC;IACf,IAAI,IAAI,GAAG,KAAK,CAAC;IACjB,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE;QACnD,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI;YACrB,IAAI,IAAI,KAAK,GAAG;gBAAE,IAAI,GAAG,IAAI,CAAC;;gBACzB,KAAK,IAAI,IAAI,CAAC;IACvB,CAAC,CAAC,CAAC;IACH,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;AACvB,CAAC;AAED,IAAI,cAA2D,CAAC;AAEhE,SAAS,gBAAgB,CAAC,QAA6B;IACrD,6CAA6C;IAC7C,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,EAAE,CAAC;IAEtC,mCAAmC;IACnC,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE;QAClD,yBAAyB;QACzB,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ,EAAE;YAChC,OAAO;SACR;QACD,IAAI,cAAc;YAAE,MAAM,CAAC,cAAc,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;QAC9D,IAAI,CAAC,UAAU;YAAE,OAAO;QAExB,kDAAkD;QAClD,IAAI,cAAc,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;QAE/C,oDAAoD;QACpD,MAAM,OAAO,GAAmB,EAAE,CAAC;QACnC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,aAAa,EAAE,CAAC;QACpC,MAAM,OAAO,GAAG,IAAI,MAAM,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QAC9C,IAAI,IAAI;YAAE,cAAc,GAAG,cAAc,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAC7D,IAAI,KAA6B,CAAC;QAClC,OAAO,CAAC,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,EAAE;YAC7C,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACzD,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YACzE,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YACjD,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;SACrB;QAED,kDAAkD;QAClD,IAAI,CAAC,cAAc,EAAE;YACnB,cAAc,GAAG,MAAM,CAAC,MAAM,CAAC,8BAA8B,CAAC;gBAC5D,eAAe,EAAE,QAAQ;gBACzB,KAAK,EAAE,OAAO;aACf,CAAC,CAAC;SACJ;QAED,sCAAsC;QACtC,MAAM,CAAC,cAAc,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,UAAU,CAAC,IAAY;IAC9B,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;IACxC,MAAM,YAAY,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC;IAC7C,MAAM,QAAQ,GAAG,YAAY,KAAK,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;IAEtD,WAAW,CAAC,IAAI,CAAC,CAAC,KAAK,GAAG,QAAQ,CAAC;IACnC,MAAM,CAAC,IAAI,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;AAC5D,CAAC;AAED,SAAgB,UAAU;IACxB,kBAAkB,EAAE,CAAC;AACvB,CAAC;AAFD,gCAEC;AAED,SAAS,kBAAkB;IACzB,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE;QAC7B,IAAI,WAAW,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE;YACnC,MAAM,aAAa,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;YACvC,aAAa,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;SAChC;KACF;IACD,mCAAmC;IACnC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;AACrE,CAAC"} |
+22-0src/backup/test/runTest.js
| @@ -0,0 +1,22 @@ | ||
| 1 | +"use strict"; | |
| 2 | +Object.defineProperty(exports, "__esModule", { value: true }); | |
| 3 | +const path = require("path"); | |
| 4 | +const test_electron_1 = require("@vscode/test-electron"); | |
| 5 | +async function main() { | |
| 6 | + try { | |
| 7 | + // The folder containing the Extension Manifest package.json | |
| 8 | + // Passed to `--extensionDevelopmentPath` | |
| 9 | + const extensionDevelopmentPath = path.resolve(__dirname, '../../'); | |
| 10 | + // The path to test runner | |
| 11 | + // Passed to --extensionTestsPath | |
| 12 | + const extensionTestsPath = path.resolve(__dirname, './suite/index'); | |
| 13 | + // Download VS Code, unzip it and run the integration test | |
| 14 | + await (0, test_electron_1.runTests)({ extensionDevelopmentPath, extensionTestsPath }); | |
| 15 | + } | |
| 16 | + catch (err) { | |
| 17 | + console.error('Failed to run tests', err); | |
| 18 | + process.exit(1); | |
| 19 | + } | |
| 20 | +} | |
| 21 | +main(); | |
| 22 | +//# sourceMappingURL=runTest.js.map |
+1-0src/backup/test/runTest.js.map
| @@ -0,0 +1 @@ | ||
| 1 | +{"version":3,"file":"runTest.js","sourceRoot":"","sources":["runTest.ts"],"names":[],"mappings":";;AAAA,6BAA6B;AAE7B,yDAAiD;AAEjD,KAAK,UAAU,IAAI;IAClB,IAAI;QACH,4DAA4D;QAC5D,yCAAyC;QACzC,MAAM,wBAAwB,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QAEnE,0BAA0B;QAC1B,iCAAiC;QACjC,MAAM,kBAAkB,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;QAEpE,0DAA0D;QAC1D,MAAM,IAAA,wBAAQ,EAAC,EAAE,wBAAwB,EAAE,kBAAkB,EAAE,CAAC,CAAC;KACjE;IAAC,OAAO,GAAG,EAAE;QACb,OAAO,CAAC,KAAK,CAAC,qBAAqB,EAAE,GAAG,CAAC,CAAC;QAC1C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;KAChB;AACF,CAAC;AAED,IAAI,EAAE,CAAC"} |
+23-0src/backup/test/runTest.ts
| @@ -0,0 +1,23 @@ | ||
| 1 | +import * as path from 'path'; | |
| 2 | + | |
| 3 | +import { runTests } from '@vscode/test-electron'; | |
| 4 | + | |
| 5 | +async function main() { | |
| 6 | + try { | |
| 7 | + // The folder containing the Extension Manifest package.json | |
| 8 | + // Passed to `--extensionDevelopmentPath` | |
| 9 | + const extensionDevelopmentPath = path.resolve(__dirname, '../../'); | |
| 10 | + | |
| 11 | + // The path to test runner | |
| 12 | + // Passed to --extensionTestsPath | |
| 13 | + const extensionTestsPath = path.resolve(__dirname, './suite/index'); | |
| 14 | + | |
| 15 | + // Download VS Code, unzip it and run the integration test | |
| 16 | + await runTests({ extensionDevelopmentPath, extensionTestsPath }); | |
| 17 | + } catch (err) { | |
| 18 | + console.error('Failed to run tests', err); | |
| 19 | + process.exit(1); | |
| 20 | + } | |
| 21 | +} | |
| 22 | + | |
| 23 | +main(); |
+15-0src/backup/test/suite/extension.test.js
| @@ -0,0 +1,15 @@ | ||
| 1 | +"use strict"; | |
| 2 | +Object.defineProperty(exports, "__esModule", { value: true }); | |
| 3 | +const assert = require("assert"); | |
| 4 | +// You can import and use all API from the 'vscode' module | |
| 5 | +// as well as import your extension to test it | |
| 6 | +const vscode = require("vscode"); | |
| 7 | +// import * as myExtension from '../../extension'; | |
| 8 | +suite('Extension Test Suite', () => { | |
| 9 | + vscode.window.showInformationMessage('Start all tests.'); | |
| 10 | + test('Sample test', () => { | |
| 11 | + assert.strictEqual(-1, [1, 2, 3].indexOf(5)); | |
| 12 | + assert.strictEqual(-1, [1, 2, 3].indexOf(0)); | |
| 13 | + }); | |
| 14 | +}); | |
| 15 | +//# sourceMappingURL=extension.test.js.map |
+1-0src/backup/test/suite/extension.test.js.map
| @@ -0,0 +1 @@ | ||
| 1 | +{"version":3,"file":"extension.test.js","sourceRoot":"","sources":["extension.test.ts"],"names":[],"mappings":";;AAAA,iCAAiC;AAEjC,0DAA0D;AAC1D,8CAA8C;AAC9C,iCAAiC;AACjC,kDAAkD;AAElD,KAAK,CAAC,sBAAsB,EAAE,GAAG,EAAE;IAClC,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,kBAAkB,CAAC,CAAC;IAEzD,IAAI,CAAC,aAAa,EAAE,GAAG,EAAE;QACxB,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7C,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC"} |
+15-0src/backup/test/suite/extension.test.ts
| @@ -0,0 +1,15 @@ | ||
| 1 | +import * as assert from 'assert'; | |
| 2 | + | |
| 3 | +// You can import and use all API from the 'vscode' module | |
| 4 | +// as well as import your extension to test it | |
| 5 | +import * as vscode from 'vscode'; | |
| 6 | +// import * as myExtension from '../../extension'; | |
| 7 | + | |
| 8 | +suite('Extension Test Suite', () => { | |
| 9 | + vscode.window.showInformationMessage('Start all tests.'); | |
| 10 | + | |
| 11 | + test('Sample test', () => { | |
| 12 | + assert.strictEqual(-1, [1, 2, 3].indexOf(5)); | |
| 13 | + assert.strictEqual(-1, [1, 2, 3].indexOf(0)); | |
| 14 | + }); | |
| 15 | +}); |
+40-0src/backup/test/suite/index.js
| @@ -0,0 +1,40 @@ | ||
| 1 | +"use strict"; | |
| 2 | +Object.defineProperty(exports, "__esModule", { value: true }); | |
| 3 | +exports.run = void 0; | |
| 4 | +const path = require("path"); | |
| 5 | +const Mocha = require("mocha"); | |
| 6 | +const glob = require("glob"); | |
| 7 | +function run() { | |
| 8 | + // Create the mocha test | |
| 9 | + const mocha = new Mocha({ | |
| 10 | + ui: 'tdd', | |
| 11 | + color: true | |
| 12 | + }); | |
| 13 | + const testsRoot = path.resolve(__dirname, '..'); | |
| 14 | + return new Promise((c, e) => { | |
| 15 | + glob('**/**.test.js', { cwd: testsRoot }, (err, files) => { | |
| 16 | + if (err) { | |
| 17 | + return e(err); | |
| 18 | + } | |
| 19 | + // Add files to the test suite | |
| 20 | + files.forEach(f => mocha.addFile(path.resolve(testsRoot, f))); | |
| 21 | + try { | |
| 22 | + // Run the mocha test | |
| 23 | + mocha.run(failures => { | |
| 24 | + if (failures > 0) { | |
| 25 | + e(new Error(`${failures} tests failed.`)); | |
| 26 | + } | |
| 27 | + else { | |
| 28 | + c(); | |
| 29 | + } | |
| 30 | + }); | |
| 31 | + } | |
| 32 | + catch (err) { | |
| 33 | + console.error(err); | |
| 34 | + e(err); | |
| 35 | + } | |
| 36 | + }); | |
| 37 | + }); | |
| 38 | +} | |
| 39 | +exports.run = run; | |
| 40 | +//# sourceMappingURL=index.js.map |
+1-0src/backup/test/suite/index.js.map
| @@ -0,0 +1 @@ | ||
| 1 | +{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;AAAA,6BAA6B;AAC7B,+BAA+B;AAC/B,6BAA6B;AAE7B,SAAgB,GAAG;IAClB,wBAAwB;IACxB,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC;QACvB,EAAE,EAAE,KAAK;QACT,KAAK,EAAE,IAAI;KACX,CAAC,CAAC;IAEH,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAEhD,OAAO,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QAC3B,IAAI,CAAC,eAAe,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE;YACxD,IAAI,GAAG,EAAE;gBACR,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC;aACd;YAED,8BAA8B;YAC9B,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YAE9D,IAAI;gBACH,qBAAqB;gBACrB,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE;oBACpB,IAAI,QAAQ,GAAG,CAAC,EAAE;wBACjB,CAAC,CAAC,IAAI,KAAK,CAAC,GAAG,QAAQ,gBAAgB,CAAC,CAAC,CAAC;qBAC1C;yBAAM;wBACN,CAAC,EAAE,CAAC;qBACJ;gBACF,CAAC,CAAC,CAAC;aACH;YAAC,OAAO,GAAG,EAAE;gBACb,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBACnB,CAAC,CAAC,GAAG,CAAC,CAAC;aACP;QACF,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;AACJ,CAAC;AAjCD,kBAiCC"} |
+38-0src/backup/test/suite/index.ts
| @@ -0,0 +1,38 @@ | ||
| 1 | +import * as path from 'path'; | |
| 2 | +import * as Mocha from 'mocha'; | |
| 3 | +import * as glob from 'glob'; | |
| 4 | + | |
| 5 | +export function run(): Promise<void> { | |
| 6 | + // Create the mocha test | |
| 7 | + const mocha = new Mocha({ | |
| 8 | + ui: 'tdd', | |
| 9 | + color: true | |
| 10 | + }); | |
| 11 | + | |
| 12 | + const testsRoot = path.resolve(__dirname, '..'); | |
| 13 | + | |
| 14 | + return new Promise((c, e) => { | |
| 15 | + glob('**/**.test.js', { cwd: testsRoot }, (err, files) => { | |
| 16 | + if (err) { | |
| 17 | + return e(err); | |
| 18 | + } | |
| 19 | + | |
| 20 | + // Add files to the test suite | |
| 21 | + files.forEach(f => mocha.addFile(path.resolve(testsRoot, f))); | |
| 22 | + | |
| 23 | + try { | |
| 24 | + // Run the mocha test | |
| 25 | + mocha.run(failures => { | |
| 26 | + if (failures > 0) { | |
| 27 | + e(new Error(`${failures} tests failed.`)); | |
| 28 | + } else { | |
| 29 | + c(); | |
| 30 | + } | |
| 31 | + }); | |
| 32 | + } catch (err) { | |
| 33 | + console.error(err); | |
| 34 | + e(err); | |
| 35 | + } | |
| 36 | + }); | |
| 37 | + }); | |
| 38 | +} |
+4-276src/extension.ts
| @@ -1,281 +1,9 @@ | ||
| 1 | 1 | import * as vscode from "vscode"; |
| 2 | - | |
| 3 | -/* GLOBAL CONSTANTS */ | |
| 4 | -const timeout = vscode.workspace | |
| 5 | - .getConfiguration("yourExtension") | |
| 6 | - .get("timeout", 1000); | |
| 7 | -const maxMatches = vscode.workspace | |
| 8 | - .getConfiguration("yourExtension") | |
| 9 | - .get("maxMatches", 10000); | |
| 10 | -const baseEditorStyle = vscode.window.createTextEditorDecorationType({ | |
| 11 | - backgroundColor: "yellow", | |
| 12 | - color: "black", | |
| 13 | -}); | |
| 14 | - | |
| 15 | -/* GLOBAL VARIABLES */ | |
| 16 | -let textDecorations = [baseEditorStyle]; | |
| 17 | -let outputChannel: vscode.OutputChannel; | |
| 18 | -let lastRegex = ""; | |
| 19 | -let lastText = ""; | |
| 20 | -let decorationType: vscode.TextEditorDecorationType | undefined; | |
| 21 | -const flagButtons: { [key: string]: InnerMapValue } = {}; | |
| 22 | - | |
| 23 | -/* TYPES */ | |
| 24 | -type GroupMatches = { | |
| 25 | - style: vscode.TextEditorDecorationType; | |
| 26 | - matches: vscode.Range[]; | |
| 27 | -}; | |
| 28 | -type GroupMatchMap = { | |
| 29 | - [key: string]: GroupMatches; | |
| 30 | -}; | |
| 31 | -interface InnerMapValue { | |
| 32 | - state: "on" | "off"; | |
| 33 | - button: vscode.StatusBarItem; | |
| 34 | -} | |
| 35 | -const states: Record<"on" | "off", string> = { | |
| 36 | - on: "$(check)", | |
| 37 | - off: "$(x)", | |
| 38 | -}; | |
| 39 | - | |
| 40 | -function getConfigFlags(): string { | |
| 41 | - const config = vscode.workspace.getConfiguration("regex-file"); | |
| 42 | - return config.get("flags") as string; | |
| 43 | -} | |
| 44 | - | |
| 45 | -function getRandomColor() { | |
| 46 | - // Generate a random hex color | |
| 47 | - const letters = "0123456789ABCDEF"; | |
| 48 | - let color = "#"; | |
| 49 | - for (let i = 0; i < 6; i++) { | |
| 50 | - color += letters[Math.floor(Math.random() * 16)]; | |
| 51 | - } | |
| 52 | - return color; | |
| 53 | -} | |
| 54 | - | |
| 55 | -function getReEditor(): vscode.TextEditor | undefined { | |
| 56 | - const editors = vscode.window.visibleTextEditors; | |
| 57 | - | |
| 58 | - for (const editor of editors) { | |
| 59 | - const fileName = editor.document.fileName; | |
| 60 | - if (fileName.endsWith(".re")) { | |
| 61 | - return editor; | |
| 62 | - } | |
| 63 | - } | |
| 64 | - console.log("No regex document."); | |
| 65 | -} | |
| 66 | - | |
| 67 | -function getTextEditor(): vscode.TextEditor | undefined { | |
| 68 | - const editors = vscode.window.visibleTextEditors; | |
| 69 | - | |
| 70 | - for (const editor of editors) { | |
| 71 | - const fileName = editor.document.fileName; | |
| 72 | - if (!fileName.endsWith(".re")) { | |
| 73 | - return editor; | |
| 74 | - } | |
| 75 | - } | |
| 76 | - console.log("No search document."); | |
| 77 | -} | |
| 2 | +import { output } from "./output"; | |
| 78 | 3 | |
| 79 | 4 | export function activate(context: vscode.ExtensionContext) { |
| 80 | - outputChannel = vscode.window.createOutputChannel("regex-file"); | |
| 81 | - createFlagButtons(context); | |
| 82 | - highlightMatches(); | |
| 83 | - vscode.window.onDidChangeVisibleTextEditors(highlightMatches); | |
| 84 | - vscode.workspace.onDidChangeTextDocument(highlightMatches); | |
| 85 | -} | |
| 86 | - | |
| 87 | -function createFlagButtons(context: vscode.ExtensionContext): void { | |
| 88 | - ["g", "i", "m", "s", "u", "y", "x"].forEach((flag) => { | |
| 89 | - const button = vscode.window.createStatusBarItem( | |
| 90 | - vscode.StatusBarAlignment.Left | |
| 91 | - ); | |
| 92 | - let state: "on" | "off" = "off"; | |
| 93 | - if (getConfigFlags().includes(flag)) { | |
| 94 | - state = "on"; | |
| 95 | - } | |
| 96 | - button.text = `${states[state]} ${flag.toUpperCase()}`; | |
| 97 | - button.tooltip = `Toggle ${flag} flag`; | |
| 98 | - button.command = `regex.toggleFlag${flag.toUpperCase()}`; | |
| 99 | - button.show(); | |
| 100 | - flagButtons[flag] = { | |
| 101 | - state, | |
| 102 | - button, | |
| 103 | - }; | |
| 104 | - let disposable = vscode.commands.registerCommand( | |
| 105 | - `regex.toggleFlag${flag.toUpperCase()}`, | |
| 106 | - () => { | |
| 107 | - toggleFlag(flag); | |
| 108 | - } | |
| 109 | - ); | |
| 110 | - context.subscriptions.push(button); | |
| 111 | - context.subscriptions.push(disposable); | |
| 112 | - }); | |
| 113 | -} | |
| 114 | - | |
| 115 | -function getRegexFlags(): [string, boolean] { | |
| 116 | - let flags = ""; | |
| 117 | - let hasX = false; | |
| 118 | - Object.entries(flagButtons).forEach(([flag, info]) => { | |
| 119 | - if (info.state === "on") { | |
| 120 | - if (flag === "x") { | |
| 121 | - hasX = true; | |
| 122 | - } else { | |
| 123 | - flags += flag; | |
| 124 | - } | |
| 125 | - } | |
| 126 | - }); | |
| 127 | - return [flags, hasX]; | |
| 5 | + output.activate(); | |
| 6 | + output.log("Starting File Regex extension"); | |
| 128 | 7 | } |
| 129 | 8 | |
| 130 | -function applyGroupMatchDecorations( | |
| 131 | - editor: vscode.TextEditor, | |
| 132 | - groupMatches: GroupMatchMap | |
| 133 | -) { | |
| 134 | - for (const groupName of Object.keys(groupMatches)) { | |
| 135 | - const { style, matches } = groupMatches[groupName]; | |
| 136 | - textDecorations.push(style); | |
| 137 | - | |
| 138 | - const decorations: vscode.DecorationOptions[] = matches.map( | |
| 139 | - (range) => ({ | |
| 140 | - range, | |
| 141 | - hoverMessage: `Group: ${groupName}`, | |
| 142 | - }) | |
| 143 | - ); | |
| 144 | - | |
| 145 | - editor.setDecorations(style, decorations); | |
| 146 | - } | |
| 147 | -} | |
| 148 | - | |
| 149 | -function updateGroupMatches( | |
| 150 | - textEditor: vscode.TextEditor, | |
| 151 | - groupMatches: GroupMatchMap, | |
| 152 | - match: RegExpExecArray | |
| 153 | -) { | |
| 154 | - for (const groupName in match.groups) { | |
| 155 | - const groupMatch = match.groups[groupName]; | |
| 156 | - | |
| 157 | - if (groupMatch) { | |
| 158 | - const startInd = match[0].indexOf(groupMatch); | |
| 159 | - const startPos = textEditor.document.positionAt( | |
| 160 | - match.index + startInd | |
| 161 | - ); | |
| 162 | - const endInd = startInd + groupMatch.length; | |
| 163 | - const endPos = textEditor.document.positionAt(match.index + endInd); | |
| 164 | - const matchRange = new vscode.Range(startPos, endPos); | |
| 165 | - | |
| 166 | - if (!groupMatches[groupName]) { | |
| 167 | - // Generate a random color for the group | |
| 168 | - const randomColor = getRandomColor(); | |
| 169 | - | |
| 170 | - // Define a new TextEditorDecorationType for the group with the random color | |
| 171 | - groupMatches[groupName] = { | |
| 172 | - style: vscode.window.createTextEditorDecorationType({ | |
| 173 | - backgroundColor: randomColor, | |
| 174 | - color: "black", // You can customize the text color | |
| 175 | - }), | |
| 176 | - matches: [matchRange], | |
| 177 | - }; | |
| 178 | - } else { | |
| 179 | - groupMatches[groupName].matches.push(matchRange); | |
| 180 | - } | |
| 181 | - } | |
| 182 | - } | |
| 183 | -} | |
| 184 | - | |
| 185 | -function highlightMatches(): void { | |
| 186 | - const reEditor = getReEditor(); | |
| 187 | - const textEditor = getTextEditor(); | |
| 188 | - if (!reEditor || !textEditor) { | |
| 189 | - outputChannel.appendLine( | |
| 190 | - "Abort highlighting. Missing reEditor or textEditor." | |
| 191 | - ); | |
| 192 | - return; | |
| 193 | - } | |
| 194 | - let reText = reEditor.document.getText(); | |
| 195 | - if (!reText) { | |
| 196 | - outputChannel.appendLine( | |
| 197 | - "Abort highlighting. No text in the regex file." | |
| 198 | - ); | |
| 199 | - } | |
| 200 | - let searchText = textEditor.document.getText(); | |
| 201 | - if (searchText === lastText && reText === lastRegex) { | |
| 202 | - return; | |
| 203 | - } | |
| 204 | - lastText = searchText; | |
| 205 | - lastRegex = reText; | |
| 206 | - outputChannel.appendLine("Ready to begin highlighting."); | |
| 207 | - | |
| 208 | - // Clear all previous text decorations | |
| 209 | - for (const decoration of textDecorations) { | |
| 210 | - textEditor.setDecorations(decoration, []); | |
| 211 | - textDecorations = [baseEditorStyle]; | |
| 212 | - } | |
| 213 | - | |
| 214 | - // Perform your matching and highlighting logic here | |
| 215 | - const matches: vscode.Range[] = []; | |
| 216 | - let [flags, hasX] = getRegexFlags(); | |
| 217 | - if (hasX) { | |
| 218 | - reText = reText.replace(/\s/g, ""); | |
| 219 | - } | |
| 220 | - let pattern; | |
| 221 | - try { | |
| 222 | - pattern = new RegExp(reText, flags); | |
| 223 | - } catch { | |
| 224 | - console.log("invalid pattern"); | |
| 225 | - return; | |
| 226 | - } | |
| 227 | - const groupMatches: GroupMatchMap = {}; | |
| 228 | - let match: RegExpExecArray | null; | |
| 229 | - let i = 0; | |
| 230 | - const startTime = new Date().getTime(); | |
| 231 | - while ((match = pattern.exec(searchText))) { | |
| 232 | - if (i > maxMatches) { | |
| 233 | - console.log(`Max matches of ${maxMatches} reached.`); | |
| 234 | - outputChannel.appendLine(`Max matches of ${maxMatches} reached.`); | |
| 235 | - break; | |
| 236 | - } | |
| 237 | - if (new Date().getTime() > startTime + 1000) { | |
| 238 | - console.log(`Timeout of ${timeout} reached.`); | |
| 239 | - outputChannel.appendLine(`Timeout of ${timeout} reached.`); | |
| 240 | - break; | |
| 241 | - } | |
| 242 | - updateGroupMatches(textEditor, groupMatches, match); | |
| 243 | - const startPos = textEditor.document.positionAt(match.index); | |
| 244 | - const endPos = textEditor.document.positionAt( | |
| 245 | - match.index + match[0].length | |
| 246 | - ); | |
| 247 | - const range = new vscode.Range(startPos, endPos); | |
| 248 | - matches.push(range); | |
| 249 | - i++; | |
| 250 | - } | |
| 251 | - | |
| 252 | - // Apply base decorations | |
| 253 | - textEditor.setDecorations(baseEditorStyle, matches); | |
| 254 | - | |
| 255 | - // Apply decorations to the groups | |
| 256 | - applyGroupMatchDecorations(textEditor, groupMatches); | |
| 257 | -} | |
| 258 | - | |
| 259 | -function toggleFlag(flag: string): void { | |
| 260 | - const button = flagButtons[flag].button; | |
| 261 | - const currentState = flagButtons[flag].state; | |
| 262 | - const newState = currentState === "on" ? "off" : "on"; | |
| 263 | - | |
| 264 | - flagButtons[flag].state = newState; | |
| 265 | - button.text = `${states[newState]} ${flag.toUpperCase()}`; | |
| 266 | -} | |
| 267 | - | |
| 268 | -export function deactivate() { | |
| 269 | - disposeFlagButtons(); | |
| 270 | -} | |
| 271 | - | |
| 272 | -function disposeFlagButtons(): void { | |
| 273 | - for (const key in flagButtons) { | |
| 274 | - if (flagButtons.hasOwnProperty(key)) { | |
| 275 | - const innerMapValue = flagButtons[key]; | |
| 276 | - innerMapValue.button.dispose(); | |
| 277 | - } | |
| 278 | - } | |
| 279 | - // Clear the flagButtons dictionary | |
| 280 | - Object.keys(flagButtons).forEach((key) => delete flagButtons[key]); | |
| 281 | -} | |
| 9 | +export function deactivate() {} |
+5-0src/global.ts
| @@ -0,0 +1,5 @@ | ||
| 1 | +import * as vscode from "vscode"; | |
| 2 | + | |
| 3 | +export function getConfig(): vscode.WorkspaceConfiguration { | |
| 4 | + return vscode.workspace.getConfiguration("regex-file"); | |
| 5 | +} |
+33-0src/output.ts
| @@ -0,0 +1,33 @@ | ||
| 1 | +import * as vscode from "vscode"; | |
| 2 | + | |
| 3 | +class Output { | |
| 4 | + outputChannel: vscode.OutputChannel | undefined; | |
| 5 | + | |
| 6 | + activate() { | |
| 7 | + this.outputChannel = vscode.window.createOutputChannel("Regex File"); | |
| 8 | + this.show(); | |
| 9 | + } | |
| 10 | + | |
| 11 | + show() { | |
| 12 | + this.outputChannel?.show(); | |
| 13 | + } | |
| 14 | + | |
| 15 | + clear() { | |
| 16 | + this.outputChannel?.clear(); | |
| 17 | + } | |
| 18 | + | |
| 19 | + dispose() { | |
| 20 | + this.outputChannel?.dispose(); | |
| 21 | + } | |
| 22 | + | |
| 23 | + hide() { | |
| 24 | + this.outputChannel?.hide(); | |
| 25 | + } | |
| 26 | + | |
| 27 | + log(message: string) { | |
| 28 | + this.outputChannel?.appendLine(message); | |
| 29 | + console.log(message); | |
| 30 | + } | |
| 31 | +} | |
| 32 | + | |
| 33 | +export const output = new Output(); |
+47-0src/regexButtons.ts
| @@ -0,0 +1,47 @@ | ||
| 1 | +import * as vscode from "vscode"; | |
| 2 | +import { getConfig } from "./global"; | |
| 3 | +import { output } from "./output"; | |
| 4 | + | |
| 5 | +const FLAG_CHARS = ["g", "i", "m", "s", "u", "y", "x"]; | |
| 6 | + | |
| 7 | +class RegexButtons { | |
| 8 | + flagButtons: { | |
| 9 | + [key: string]: { | |
| 10 | + state: "on" | "off"; | |
| 11 | + button: vscode.StatusBarItem; | |
| 12 | + }; | |
| 13 | + } = {}; | |
| 14 | + | |
| 15 | + constructor() {} | |
| 16 | + | |
| 17 | + activate(context: vscode.ExtensionContext) { | |
| 18 | + this.createButtons(context); | |
| 19 | + this.updateFlagsFromConfig(); | |
| 20 | + } | |
| 21 | + | |
| 22 | + updateFlagsFromConfig() { | |
| 23 | + output.log("Updating flags"); | |
| 24 | + } | |
| 25 | + | |
| 26 | + updateFlagsFromUI() { | |
| 27 | + output.log("Updating flags from UI"); | |
| 28 | + } | |
| 29 | + | |
| 30 | + createButton(flag: string) { | |
| 31 | + output.log(`Creating button for ${flag}`); | |
| 32 | + } | |
| 33 | + | |
| 34 | + createButtons(context: vscode.ExtensionContext) { | |
| 35 | + output.log("Creating buttons"); | |
| 36 | + } | |
| 37 | + | |
| 38 | + disposeButtons() { | |
| 39 | + output.log("Disposing buttons"); | |
| 40 | + } | |
| 41 | + | |
| 42 | + dispose() { | |
| 43 | + this.disposeButtons(); | |
| 44 | + } | |
| 45 | +} | |
| 46 | + | |
| 47 | +export const regexButtons = new RegexButtons(); |