i-c-fn-head 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json ADDED
@@ -0,0 +1,211 @@
1
+ {
2
+ "name": "i-c-fn-head",
3
+ "displayName": "i_c_fn_head",
4
+ "description": "Dear Dev, this extension just shows function's name in breadcrumbs of VSCode for C, CPP, D & Rust. Have a nice day, Dear Dev 🤟🙂",
5
+ "publisher": "SarK0Y",
6
+ "repository": "https://github.com/SarK0Y/i_c_fn_head",
7
+ "version": "0.0.5",
8
+ "engines": {
9
+ "vscode": "^1.105.0"
10
+ },
11
+ "categories": [
12
+ "Other"
13
+ ],
14
+ "activationEvents": [
15
+ "onStartupFinished"
16
+ ],
17
+ "main": "./dist/extension.js",
18
+ "contributes": {
19
+ "contributes": {
20
+ "configuration": {
21
+ "title": "i_c_fn_head",
22
+ "properties": {
23
+ "i_c_fn_head.configurations": {
24
+ "description": "Specifies the color and style configuration.",
25
+ "type": "array",
26
+ "items": {
27
+ "type": "object",
28
+ "additionalProperties": false,
29
+ "properties": {
30
+ "paths": {
31
+ "markdownDescription": "Specifies the list of file path patterns e.g. `[\"*.log\", \"todos/**/*.todo\"]`.",
32
+ "type": "array",
33
+ "items": {
34
+ "type": "string"
35
+ }
36
+ },
37
+ "rules": {
38
+ "type": "array",
39
+ "description": "Specifies the list of text decoration rules.",
40
+ "items": {
41
+ "type": "object",
42
+ "additionalProperties": false,
43
+ "properties": {
44
+ "patterns": {
45
+ "markdownDescription": "Specifies the list of regular expressions for matching the text e.g. `[\"Critical .*\", \"Error .*\"]`.",
46
+ "type": "array",
47
+ "items": {
48
+ "type": "string"
49
+ }
50
+ },
51
+ "matchCase": {
52
+ "description": "Specifies whether to perform case-sensitive match.",
53
+ "type": "boolean"
54
+ },
55
+ "multiLine": {
56
+ "description": "Specifies whether the regular expression patterns can match across multiple lines.",
57
+ "type": "boolean"
58
+ },
59
+ "color": {
60
+ "markdownDescription": "Specifies the text color. Accepts terminal ANSI color names (e.g., `Red`, `BrightBlue`) or hex color codes (e.g., `#RGB`, `#RRGGBB`, `#RRGGBBAA`). _Do not specify to retain original text color._",
61
+ "anyOf": [
62
+ {
63
+ "type": "string",
64
+ "enum": [
65
+ "Black",
66
+ "Blue",
67
+ "BrightBlack",
68
+ "BrightBlue",
69
+ "BrightCyan",
70
+ "BrightGreen",
71
+ "BrightMagenta",
72
+ "BrightRed",
73
+ "BrightWhite",
74
+ "BrightYellow",
75
+ "Cyan",
76
+ "Green",
77
+ "Magenta",
78
+ "Red",
79
+ "White",
80
+ "Yellow"
81
+ ]
82
+ },
83
+ {
84
+ "type": "string",
85
+ "format": "color-hex"
86
+ }
87
+ ]
88
+ },
89
+ "bold": {
90
+ "markdownDescription": "Specifies whether to **bold** or unbold text. _Do not specify to retain original font weights._",
91
+ "type": "boolean"
92
+ },
93
+ "italic": {
94
+ "markdownDescription": "Specifies whether to _italicize_ or unitalicize text. _Do not specify to retain original font style._",
95
+ "type": "boolean"
96
+ },
97
+ "underline": {
98
+ "markdownDescription": "Specifies whether to add or remove underline from text. _Do not specify to retain original text decoration._",
99
+ "type": "boolean"
100
+ },
101
+ "strikeThrough": {
102
+ "markdownDescription": "Specifies whether to add or remove ~~strike through~~ from text. _Do not specify to retain original text decoration._",
103
+ "type": "boolean"
104
+ }
105
+ },
106
+ "required": [
107
+ "patterns"
108
+ ],
109
+ "anyOf": [
110
+ {
111
+ "required": [
112
+ "color"
113
+ ]
114
+ },
115
+ {
116
+ "required": [
117
+ "bold"
118
+ ]
119
+ },
120
+ {
121
+ "required": [
122
+ "italic"
123
+ ]
124
+ },
125
+ {
126
+ "required": [
127
+ "underline"
128
+ ]
129
+ },
130
+ {
131
+ "required": [
132
+ "strikeThrough"
133
+ ]
134
+ }
135
+ ],
136
+ "title": "Setting"
137
+ }
138
+ }
139
+ },
140
+ "required": [
141
+ "paths",
142
+ "rules"
143
+ ]
144
+ }
145
+ }
146
+ }
147
+ }
148
+ },
149
+ "languages": [{
150
+ "id": "C",
151
+ "extensions": [".c"],
152
+ "aliases": ["C"]
153
+ },
154
+ {
155
+ "id": "D",
156
+ "extensions": [".d"],
157
+ "aliases": ["D"]
158
+ },
159
+ {
160
+ "id": "Rust",
161
+ "extensions": [".rs"],
162
+ "aliases": ["Rust"]
163
+ },
164
+ {
165
+ "id": "CPP",
166
+ "extensions": [".cpp"],
167
+ "aliases": ["C++"]
168
+ }
169
+ ],
170
+ "commands": [
171
+ {
172
+ "command": "i-c-fn-head.helloWorld",
173
+ "title": "Hello World"
174
+ },
175
+ {
176
+ "command": "i-c-i_c_fn_head.ShowDocumentSymbols",
177
+ "title": "tst Document Symbols"
178
+ }
179
+ ]
180
+ },
181
+ "views": {
182
+ "explorer": [{
183
+ "id": "documentSymbolsView",
184
+ "name": "Document Symbols"
185
+ }]
186
+ },
187
+ "scripts": {
188
+ "vscode:prepublish": "npm run package",
189
+ "compile": "webpack",
190
+ "watch": "webpack --watch",
191
+ "package": "webpack --mode production --devtool hidden-source-map",
192
+ "compile-tests": "tsc -p . --outDir out",
193
+ "watch-tests": "tsc -p . -w --outDir out",
194
+ "pretest": "npm run compile-tests && npm run compile && npm run lint",
195
+ "lint": "eslint src",
196
+ "test": "vscode-test"
197
+ },
198
+ "devDependencies": {
199
+ "@types/mocha": "^10.0.10",
200
+ "@types/node": "22.x",
201
+ "@types/vscode": "^1.105.0",
202
+ "@vscode/test-cli": "^0.0.11",
203
+ "@vscode/test-electron": "^2.5.2",
204
+ "eslint": "^9.39.2",
205
+ "ts-loader": "^9.5.4",
206
+ "typescript": "^5.9.3",
207
+ "typescript-eslint": "^8.54.0",
208
+ "webpack": "^5.104.1",
209
+ "webpack-cli": "^6.0.1"
210
+ }
211
+ }
@@ -0,0 +1,120 @@
1
+ import * as vscode from 'vscode';
2
+ import { uri_to_file_of_opts } from './init';
3
+ class set_cmd_type {
4
+ static v: string = "rgx";
5
+ }
6
+ export function prnt(msg: string) {
7
+ console_msg.show(msg);
8
+ }
9
+ export class console_msg {
10
+ static #outputChannel = vscode.window.createOutputChannel('i-c-fn-head');
11
+ static show(msg: string) {
12
+ this.#outputChannel.appendLine(msg);
13
+ this.#outputChannel.show();
14
+ }
15
+ }
16
+ export function getCMD(set_placeholder0?: string | null, _txt?: string | undefined | null, cmd_type?: string): RegExp[] | null {
17
+ const txt = _txt ? _txt : vscode.window.activeTextEditor?.document.getText();
18
+ set_cmd_type.v = cmd_type ? cmd_type : set_cmd_type.v;
19
+ cmd_rgx.set_collect_rgx_from_doc();
20
+ if (txt == undefined) { return null}
21
+ const ret = set_placeholder0 ? cmd_rgx._collect_rgx_from_doc(txt, set_placeholder0) : cmd_rgx._collect_rgx_from_doc(txt);
22
+ let phldr = set_placeholder0 ? set_placeholder0 : "no phldr";
23
+ prnt("calc num of cmds: " + ret.length.toString());
24
+ // prnt (ewt)
25
+ return ret;
26
+ }
27
+ export class cmd_rgx {
28
+ static collect_rgx_from_doc: RegExp = /\/\/\s*rgx:\s*(\/.*:::[gmis]*)\s*\/\//g;
29
+ static placeholder0: string = "@663@";
30
+ static placeholder0_max_len: number = 200;
31
+ static open_rgx: string = "/";
32
+ static close_rgx: string = ":::";
33
+ static set_collect_rgx_from_doc(
34
+ open_rgx?: string,
35
+ close_rgx?: string,
36
+ ): RegExp {
37
+ this.open_rgx = open_rgx ?? this.open_rgx;
38
+ this.close_rgx = close_rgx ?? this.close_rgx;
39
+ let cmd_type = set_cmd_type.v ?? "rgx";
40
+ let construct_rgx: string = "//\\s*" + cmd_type + ":\\s*(" + this.open_rgx + ".*" + this.close_rgx + "[gmis]*)\\s*//";
41
+ this.collect_rgx_from_doc = new RegExp(construct_rgx, "g");
42
+ prnt("set_collect_rgx_from_doc: "+this.collect_rgx_from_doc.source);
43
+ return this.collect_rgx_from_doc;
44
+ }
45
+ static _collect_rgx_from_doc(txt: string, set_placeholder0?: string): RegExp[] {
46
+ if (set_placeholder0) { return this._collect_rgx_from_doc0(txt, set_placeholder0) }
47
+ let m: RegExpExecArray | null;
48
+ let ret: RegExp[] = [];
49
+ while ((m = this.collect_rgx_from_doc.exec(txt)) != null) {
50
+ let try_it = this.strn_2_rgx(m[1]);
51
+ if (try_it == null) {
52
+ prnt("_collect_rgx_from_doc: try_it is null");
53
+ break
54
+ }
55
+ prnt("_collect_rgx_from_doc:" + m[1]);
56
+ ret.push(try_it);
57
+ }
58
+ return ret;
59
+ }
60
+ static _collect_rgx_from_doc0(txt: string, set_placeholder0: string): RegExp[] {
61
+ let m: RegExpExecArray | null;
62
+ let ret: RegExp[] = [];
63
+ while ((m = this.collect_rgx_from_doc.exec(txt)) != null) {
64
+ let _m = m[1].replaceAll(this.placeholder0, set_placeholder0);
65
+ let try_it = this.strn_2_rgx(_m);
66
+ prnt("1st class cmd_rgx");
67
+ if (try_it == null) {
68
+ prnt("_collect_rgx_from_doc: try_it is null");
69
+ break
70
+ }
71
+ prnt("_collect_rgx_from_doc:" + m[1]);
72
+ ret.push(try_it);
73
+ }
74
+ return ret;
75
+ }
76
+ static strn_2_rgx(strn: string): RegExp | null {
77
+ let check_end_of_rgx = this.close_rgx + "[gmis]*$";
78
+ let flags = strn.match(new RegExp(check_end_of_rgx));
79
+ let _flags = flags != null ? flags[0].slice(this.close_rgx.length) : "";
80
+ let regex = strn.slice(1).replaceAll(this.close_rgx + _flags, "");
81
+ try {
82
+ let ret = new RegExp(regex, _flags);
83
+ prnt("strn to rgx: " + ret.source + " " + ret.flags);
84
+ return ret;
85
+ } catch (error) {
86
+ const msg = error instanceof Error ? error.message : String(error);
87
+ vscode.window.showInformationMessage(msg);
88
+ return null;
89
+ }
90
+ }
91
+ }
92
+ export async function exclude_paths(uris: vscode.Uri[]): Promise<vscode.Uri[] | undefined> {
93
+ try {
94
+ let ret: vscode.Uri[] = [];
95
+ const file_of_opts = await uri_to_file_of_opts();
96
+ const txt = (await vscode.workspace.openTextDocument(file_of_opts[0])).getText();
97
+ prnt(txt);
98
+ let exclude_paths0 = getCMD(
99
+ null,
100
+ txt,
101
+ "exclude_path"
102
+ );
103
+ if (exclude_paths0 == null) { return; }
104
+ for (let exc of exclude_paths0) {
105
+ ret = exclude_path(uris, exc);
106
+ }
107
+ return ret.length == 0? uris: ret;
108
+ } catch (err) {
109
+ prnt(String(err))
110
+ return
111
+ }
112
+ }
113
+ function exclude_path(uris: vscode.Uri[], rgx: RegExp): vscode.Uri[] {
114
+ let ret: vscode.Uri[] = [];
115
+ for (let uri of uris) {
116
+ prnt(rgx.source);
117
+ if (!uri.fsPath.match(rgx)) { ret.push (uri)}
118
+ }
119
+ return ret;
120
+ }
@@ -0,0 +1,276 @@
1
+ import * as vscode from 'vscode';
2
+ import { minimatch } from 'minimatch';
3
+
4
+ type Configuration = {
5
+ paths?: string[];
6
+ rules?: Rule[];
7
+ };
8
+ export function extra_activate(): string {
9
+ return activate_;
10
+ }
11
+ const activate_: string = `
12
+ // console.log('Extension "color-my-text" is activated.');
13
+
14
+ let allConfigData: ConfigData[] = [];
15
+
16
+ // todoEditors need (re)decoration; doneEditors are already up to date.
17
+ // Tracking both avoids re-decorating unchanged editors when unrelated ones become visible.
18
+ let todoEditors: vscode.TextEditor[] = [];
19
+ let doneEditors: vscode.TextEditor[] = [];
20
+
21
+ // Disposes old decoration types and rebuilds allConfigData from current settings.
22
+ function resetDecorations(): void {
23
+ todoEditors = vscode.window.visibleTextEditors.slice();
24
+ doneEditors = [];
25
+
26
+ allConfigData.forEach(configData => configData.ruleData.forEach(ruleData => ruleData.decorationType.dispose()));
27
+
28
+ const configurations = vscode.workspace.getConfiguration('i_c_fn_head').get<Configuration[]>('configurations');
29
+ allConfigData = toArray(configurations).map(configuration => ({
30
+ globs: toArray(configuration.paths),
31
+ ruleData: toArray(configuration.rules).map(buildRuleData),
32
+ }));
33
+ }
34
+
35
+ // Applies decorations to all queued editors. Runs on a 500ms timer to batch rapid edits.
36
+
37
+
38
+ vscode.workspace.onDidChangeConfiguration(
39
+ event => {
40
+ if (event.affectsConfiguration('i_c_fn_head.configurations')) {
41
+ resetDecorations();
42
+ }
43
+ },
44
+ null,
45
+ context.subscriptions);
46
+
47
+ vscode.window.onDidChangeVisibleTextEditors(
48
+ visibleEditors => {
49
+ // Queue newly visible editors; prune editors that were closed.
50
+ todoEditors = visibleEditors.filter(editor => !doneEditors.includes(editor));
51
+ doneEditors = doneEditors.filter(editor => visibleEditors.includes(editor));
52
+ updateDecorations();
53
+ },
54
+ null,
55
+ context.subscriptions);
56
+
57
+ vscode.workspace.onDidChangeTextDocument(
58
+ event => {
59
+ // Re-queue any visible editor showing the changed document.
60
+ vscode.window.visibleTextEditors.forEach(visibleEditor => {
61
+ if (visibleEditor.document === event.document && !todoEditors.includes(visibleEditor)) {
62
+ todoEditors.push(visibleEditor);
63
+ }
64
+ });
65
+
66
+ doneEditors = doneEditors.filter(editor => !todoEditors.includes(editor));
67
+ },
68
+ null,
69
+ context.subscriptions);
70
+
71
+ resetDecorations();
72
+ function updateDecorations(): void {
73
+ return _updateDecorations(
74
+ allConfigData,
75
+ todoEditors,
76
+ doneEditors
77
+ );
78
+ }
79
+ const intervalId = setInterval(updateDecorations, 500);
80
+ context.subscriptions.push({ dispose: () => clearInterval(intervalId) });
81
+
82
+ `
83
+ type Rule = {
84
+ patterns?: string[];
85
+ color?: string;
86
+ matchCase?: boolean;
87
+ multiLine?: boolean;
88
+ bold?: boolean;
89
+ italic?: boolean;
90
+ underline?: boolean;
91
+ strikeThrough?: boolean;
92
+ };
93
+
94
+ // Precomputed data for a single rule.
95
+ type RuleData = {
96
+ decorationType: vscode.TextEditorDecorationType;
97
+ regexes: RegExp[];
98
+ multiLine: boolean;
99
+ };
100
+
101
+ // Precomputed data for a single configuration entry, rebuilt whenever settings change.
102
+ type ConfigData = {
103
+ globs: string[];
104
+ ruleData: RuleData[];
105
+ };
106
+
107
+ function toArray<T>(value: T[] | undefined): T[] {
108
+ return Array.isArray(value) ? value : [];
109
+ }
110
+
111
+ // ANSI color names map to VS Code terminal theme tokens ('terminal.ansi<Name>').
112
+ const ansiColorNames = new Set<string>([
113
+ 'Black', 'Blue', 'BrightBlack', 'BrightBlue', 'BrightCyan', 'BrightGreen',
114
+ 'BrightMagenta', 'BrightRed', 'BrightWhite', 'BrightYellow',
115
+ 'Cyan', 'Green', 'Magenta', 'Red', 'White', 'Yellow',
116
+ ]);
117
+
118
+ function buildRuleData(rule: Rule): RuleData {
119
+ const color = typeof rule.color !== 'string' ? undefined
120
+ : ansiColorNames.has(rule.color) ? new vscode.ThemeColor('terminal.ansi' + rule.color)
121
+ : rule.color;
122
+
123
+ // 'none' explicitly removes any theme-inherited decoration when either flag is false.
124
+ const textDecoration =
125
+ rule.underline === true && rule.strikeThrough === true ? 'underline line-through'
126
+ : rule.underline === true ? 'underline'
127
+ : rule.strikeThrough === true ? 'line-through'
128
+ : rule.underline === false || rule.strikeThrough === false ? 'none'
129
+ : undefined;
130
+
131
+ const decorationType = vscode.window.createTextEditorDecorationType({
132
+ color,
133
+ fontWeight: typeof rule.bold !== 'boolean' ? undefined : rule.bold ? 'bold' : 'normal',
134
+ fontStyle: typeof rule.italic !== 'boolean' ? undefined : rule.italic ? 'italic' : 'normal',
135
+ textDecoration,
136
+ });
137
+
138
+ const flags = 'g' + (rule.matchCase === true ? '' : 'i') + (rule.multiLine === true ? 's' : '') + 'u';
139
+
140
+ const regexes = toArray(rule.patterns).flatMap(pattern => {
141
+ try {
142
+ return [new RegExp(pattern, flags)];
143
+ } catch {
144
+ return []; // Skip invalid regex patterns.
145
+ }
146
+ });
147
+
148
+ return { decorationType, regexes, multiLine: rule.multiLine === true };
149
+ }
150
+
151
+ export function activate0(context: vscode.ExtensionContext): void {
152
+ // console.log('Extension "color-my-text" is activated.');
153
+
154
+ let allConfigData: ConfigData[] = [];
155
+
156
+ // todoEditors need (re)decoration; doneEditors are already up to date.
157
+ // Tracking both avoids re-decorating unchanged editors when unrelated ones become visible.
158
+ let todoEditors: vscode.TextEditor[] = [];
159
+ let doneEditors: vscode.TextEditor[] = [];
160
+
161
+ // Disposes old decoration types and rebuilds allConfigData from current settings.
162
+ function resetDecorations(): void {
163
+ todoEditors = vscode.window.visibleTextEditors.slice();
164
+ doneEditors = [];
165
+
166
+ allConfigData.forEach(configData => configData.ruleData.forEach(ruleData => ruleData.decorationType.dispose()));
167
+
168
+ const configurations = vscode.workspace.getConfiguration('i_c_fn_head').get<Configuration[]>('configurations');
169
+ allConfigData = toArray(configurations).map(configuration => ({
170
+ globs: toArray(configuration.paths),
171
+ ruleData: toArray(configuration.rules).map(buildRuleData),
172
+ }));
173
+ }
174
+
175
+ // Applies decorations to all queued editors. Runs on a 500ms timer to batch rapid edits.
176
+
177
+
178
+ vscode.workspace.onDidChangeConfiguration(
179
+ event => {
180
+ if (event.affectsConfiguration('i_c_fn_head.configurations')) {
181
+ resetDecorations();
182
+ }
183
+ },
184
+ null,
185
+ context.subscriptions);
186
+
187
+ vscode.window.onDidChangeVisibleTextEditors(
188
+ visibleEditors => {
189
+ // Queue newly visible editors; prune editors that were closed.
190
+ todoEditors = visibleEditors.filter(editor => !doneEditors.includes(editor));
191
+ doneEditors = doneEditors.filter(editor => visibleEditors.includes(editor));
192
+ updateDecorations();
193
+ },
194
+ null,
195
+ context.subscriptions);
196
+
197
+ vscode.workspace.onDidChangeTextDocument(
198
+ event => {
199
+ // Re-queue any visible editor showing the changed document.
200
+ vscode.window.visibleTextEditors.forEach(visibleEditor => {
201
+ if (visibleEditor.document === event.document && !todoEditors.includes(visibleEditor)) {
202
+ todoEditors.push(visibleEditor);
203
+ }
204
+ });
205
+
206
+ doneEditors = doneEditors.filter(editor => !todoEditors.includes(editor));
207
+ },
208
+ null,
209
+ context.subscriptions);
210
+
211
+ resetDecorations();
212
+ function updateDecorations(): void {
213
+ return _updateDecorations(
214
+ allConfigData,
215
+ todoEditors,
216
+ doneEditors
217
+ );
218
+ }
219
+ const intervalId = setInterval(updateDecorations, 500);
220
+ context.subscriptions.push({ dispose: () => clearInterval(intervalId) });
221
+ }
222
+ function _updateDecorations(
223
+ allConfigData: &ConfigData[],
224
+ todoEditors: & vscode.TextEditor[],
225
+ doneEditors: vscode.TextEditor[]
226
+ ): void {
227
+ if (allConfigData.every(configData => configData.ruleData.length === 0)) { return; }
228
+ if (todoEditors.length === 0) { return; }
229
+
230
+ todoEditors.forEach(editor => {
231
+ const filePath = vscode.workspace.asRelativePath(editor.document.fileName);
232
+
233
+ // Collect rule data from all configurations whose path globs match this editor's file.
234
+ const matchingRuleData = allConfigData.flatMap(configData =>
235
+ configData.globs.some(glob => {
236
+ // A bare filename (no path separators) is matched against any directory level.
237
+ const pattern = glob.includes('/') || glob.includes('\\') ? glob : '**/' + glob;
238
+ return minimatch(filePath, pattern, { nocase: process.platform === 'win32' });
239
+ }) ? configData.ruleData : []);
240
+
241
+ if (matchingRuleData.length === 0) { return; }
242
+
243
+ let documentText: string | undefined;
244
+
245
+ matchingRuleData.forEach(({ decorationType, regexes, multiLine }) => {
246
+ const ranges: vscode.Range[] = [];
247
+
248
+ if (multiLine) {
249
+ documentText ??= editor.document.getText();
250
+ for (const regex of regexes) {
251
+ for (const match of documentText.matchAll(regex)) {
252
+ if (match.index === undefined || match[0].length === 0) { continue; }
253
+ const startPos = editor.document.positionAt(match.index);
254
+ const endPos = editor.document.positionAt(match.index + match[0].length);
255
+ ranges.push(new vscode.Range(startPos, endPos));
256
+ }
257
+ }
258
+ } else {
259
+ for (const regex of regexes) {
260
+ for (let lineNum = 0; lineNum < editor.document.lineCount; lineNum++) {
261
+ for (const match of editor.document.lineAt(lineNum).text.matchAll(regex)) {
262
+ if (match.index === undefined || match[0].length === 0) { continue; }
263
+ ranges.push(new vscode.Range(lineNum, match.index, lineNum, match.index + match[0].length));
264
+ }
265
+ }
266
+ }
267
+ }
268
+
269
+ editor.setDecorations(decorationType, ranges);
270
+ });
271
+
272
+ doneEditors.push(editor);
273
+ });
274
+
275
+ todoEditors = [];
276
+ }