@@ -9,9 +9,83 @@ function getCommentSymbol(document) {
99 const ext = path . extname ( document . fileName ) . slice ( 1 ) . toLowerCase ( ) ;
1010 return commentStyles [ ext ] || null ;
1111}
12- //------- WHOLE FILE BASED DYNAMIC REGULAR-EXPRESSION--------//
1312
14- //------- WHOLE FILE BASED DYNAMIC REGULAR-EXPRESSION--------//
13+ function escapeRegex ( source ) {
14+ return source . replace ( / [ . * + ? ^ $ { } ( ) | [ \] \\ ] / g, "\\$&" ) ;
15+ }
16+
17+ function buildKeywordRegex ( commentPrefix ) {
18+ const escapedPrefix = escapeRegex ( commentPrefix ) ;
19+ return new RegExp (
20+ `^[ \\t]*${ escapedPrefix } [ \\t]*@([a-zA-Z_][a-zA-Z0-9_]*)[:][^\\n]*$` ,
21+ "gm" ,
22+ ) ;
23+ }
24+
25+ function findPredefinedKeyword ( keyword ) {
26+ return predefinedKeywordColors . find ( ( item ) => item . keyword === keyword ) ;
27+ }
28+
29+ function getBackgroundColorForKeyword ( keyword ) {
30+ const predefined = findPredefinedKeyword ( keyword ) ;
31+ if ( predefined ) {
32+ return predefined . color ;
33+ }
34+ return getKeywordHighlightColor ( keyword ) . backgroundColor ;
35+ }
36+
37+ function getOrCreateDecorationType ( keyword ) {
38+ if ( ! decorationTypes . has ( keyword ) ) {
39+ decorationTypes . set (
40+ keyword ,
41+ vscode . window . createTextEditorDecorationType ( {
42+ backgroundColor : getBackgroundColorForKeyword ( keyword ) ,
43+ color : "white" ,
44+ fontWeight : "bold" ,
45+ } ) ,
46+ ) ;
47+ }
48+
49+ return decorationTypes . get ( keyword ) ;
50+ }
51+
52+ function clearAllDecorationsInActiveEditor ( ) {
53+ const editor = vscode . window . activeTextEditor ;
54+ if ( ! editor ) {
55+ return ;
56+ }
57+
58+ decorationTypes . forEach ( ( decoration ) => {
59+ editor . setDecorations ( decoration , [ ] ) ;
60+ } ) ;
61+ }
62+
63+ function applyDecorations ( editor , keywordRanges ) {
64+ clearAllDecorationsInActiveEditor ( ) ;
65+
66+ keywordRanges . forEach ( ( ranges , keyword ) => {
67+ const decoration = decorationTypes . get ( keyword ) ;
68+ if ( decoration ) {
69+ editor . setDecorations ( decoration , ranges ) ;
70+ }
71+ } ) ;
72+ }
73+
74+ async function normalizeKeywordInDocument (
75+ editor ,
76+ startPos ,
77+ endPos ,
78+ keyword ,
79+ upperKeyword ,
80+ ) {
81+ if ( keyword === upperKeyword ) {
82+ return ;
83+ }
84+
85+ await editor . edit ( ( editBuilder ) => {
86+ editBuilder . replace ( new vscode . Range ( startPos , endPos ) , upperKeyword ) ;
87+ } ) ;
88+ }
1589
1690// Database related
1791const {
@@ -28,135 +102,82 @@ let decorationTypes = new Map();
28102// Watch for changes in preDefinedKeywords.js
29103const keywordsFilePath = path . join (
30104 __dirname ,
31- "../utility/highlight_word_required/preDefinedKeywords.js"
105+ "../utility/highlight_word_required/preDefinedKeywords.js" ,
32106) ;
33107fs . watchFile ( keywordsFilePath , ( curr , prev ) => {
108+ void curr ;
109+ void prev ;
110+
34111 delete require . cache [
35112 require . resolve ( "../utility/highlight_word_required/preDefinedKeywords" )
36113 ] ;
37114 predefinedKeywordColors = require ( "../utility/highlight_word_required/preDefinedKeywords" ) ;
38115
39- // Reset decorations
40- decorationTypes . forEach ( ( decoration ) => {
41- vscode . window . activeTextEditor ?. setDecorations ( decoration , [ ] ) ;
42- } ) ;
116+ // Predefined colors changed. Clear and rebuild decoration types on next run.
117+ clearAllDecorationsInActiveEditor ( ) ;
43118 decorationTypes . clear ( ) ; // Clear all old decorations
44- highlightWords ( ) ; // Call to reassign color
45- } ) ;
119+ void highlightWords ( ) ; // Call to reassign color
120+ } ; ) ;
46121
47122async function highlightWords ( context ) {
48123 if ( isEditing ) return ;
49124 isEditing = true ;
50125
51- const editor = vscode . window . activeTextEditor ;
52- if ( ! editor ) {
53- isEditing = false ;
54- return ;
55- }
56-
57- const text = editor . document . getText ( ) ;
58- // const regex = /^[ \t]*\/\/[ \t]*([a-zA-Z_][a-zA-Z0-9_]*):[^\n]*$/gm; -- 100% working
59- //const regex = getHighlightRegex(); // testing -- 100% working
60- const commentPrefix = getCommentSymbol ( editor . document ) ;
61- if ( ! commentPrefix ) return ;
62-
63- const escapedPrefix = commentPrefix . replace ( / [ . * + ? ^ $ { } ( ) | [ \] \\ ] / g, "\\$&" ) ;
64-
65- const regex = new RegExp (
66- `^[ \\t]*${ escapedPrefix } [ \\t]*@([a-zA-Z_][a-zA-Z0-9_]*)[:][^\\n]*$` ,
67- "gm"
68- ) ;
69- let keywordRanges = new Map ( ) ;
70- let existingKeywords = new Set ( ) ; // For Keyword Tracking purpose
71-
72- let match ;
73- while ( ( match = regex . exec ( text ) ) ) {
74- let keyword = match [ 1 ] + ":" ;
75- const uppercaseKeyword = keyword . toUpperCase ( ) ;
76-
77- const wordStartIndex = match . index + match [ 0 ] . indexOf ( match [ 1 ] ) ;
78- const wordEndIndex = wordStartIndex + keyword . length ;
79- const startPos = editor . document . positionAt ( wordStartIndex ) ;
80- const endPos = editor . document . positionAt ( wordEndIndex ) ;
126+ try {
127+ const editor = vscode . window . activeTextEditor ;
128+ if ( ! editor ) {
129+ return ;
130+ }
81131
82- const fileName = editor . document . fileName ;
83- const line = startPos . line ;
132+ const commentPrefix = getCommentSymbol ( editor . document ) ;
133+ if ( ! commentPrefix ) {
134+ return ;
135+ }
84136
85- const uniqueKey = generateKeywordKey ( uppercaseKeyword , fileName , line ) ;
86- existingKeywords . add ( uniqueKey ) ; // Track Seen Keyword
137+ const text = editor . document . getText ( ) ;
138+ const regex = buildKeywordRegex ( commentPrefix ) ;
139+ const keywordRanges = new Map ( ) ;
87140
88- // Safe DB call
89- if ( ! highlightTimeStamps . has ( uniqueKey ) ) {
90- await saveTimestamp ( uppercaseKeyword , fileName , line , context ) ;
91- }
141+ let match ;
142+ while ( ( match = regex . exec ( text ) ) ) {
143+ const keyword = ` ${ match [ 1 ] } :` ;
144+ const upperKeyword = keyword . toUpperCase ( ) ;
92145
93- // Ensure keyword is converted to uppercase in the document
94- if ( keyword !== uppercaseKeyword ) {
95- await editor . edit ( ( editBuilder ) => {
96- editBuilder . replace (
97- new vscode . Range ( startPos , endPos ) ,
98- uppercaseKeyword
99- ) ;
100- } ) ;
101- }
146+ const wordStartIndex = match . index + match [ 0 ] . indexOf ( match [ 1 ] ) ;
147+ const wordEndIndex = wordStartIndex + keyword . length ;
148+ const startPos = editor . document . positionAt ( wordStartIndex ) ;
149+ const endPos = editor . document . positionAt ( wordEndIndex ) ;
102150
103- // Checking & applying predefined custom Keyword style, if present
104- // console.log("predefinedKeywordColors:InsideHW.js", predefinedKeywordColors);
151+ const fileName = editor . document . fileName ;
152+ const line = startPos . line ;
153+ const uniqueKey = generateKeywordKey ( upperKeyword , fileName , line ) ;
105154
106- let foundKeyword ;
107- for ( const item of predefinedKeywordColors ) {
108- if ( item . keyword === uppercaseKeyword ) {
109- foundKeyword = item ;
110- break ;
155+ // Keep DB state and text normalization in sync with each matched keyword.
156+ if ( ! highlightTimeStamps . has ( uniqueKey ) ) {
157+ await saveTimestamp ( upperKeyword , fileName , line , context ) ;
111158 }
112- }
113159
114- let bgColor ;
115- if ( foundKeyword ) {
116- bgColor = foundKeyword . color ;
117- } else {
118- bgColor = getKeywordHighlightColor ( uppercaseKeyword ) . backgroundColor ;
119- }
120-
121- if ( ! decorationTypes . has ( uppercaseKeyword ) ) {
122- decorationTypes . set (
123- uppercaseKeyword ,
124- vscode . window . createTextEditorDecorationType ( {
125- backgroundColor : bgColor ,
126- color : "white" ,
127- fontWeight : "bold" ,
128- } )
160+ await normalizeKeywordInDocument (
161+ editor ,
162+ startPos ,
163+ endPos ,
164+ keyword ,
165+ upperKeyword ,
129166 ) ;
130- }
131-
132- if ( ! keywordRanges . has ( uppercaseKeyword ) ) {
133- keywordRanges . set ( uppercaseKeyword , [ ] ) ;
134- }
135- keywordRanges
136- . get ( uppercaseKeyword )
137- . push ( new vscode . Range ( startPos , endPos ) ) ;
138- }
139167
140- // // Remove timestamps for deleted keywords
141- // for (const key of highlightTimeStamps.keys()) {
142- // if (!existingKeywords.has(key)) {
143- // await deleteTimestamp(key, context);
144- // }
145- // }
168+ getOrCreateDecorationType ( upperKeyword ) ;
146169
147- // Apply decorations (RESET before applying new ones)
148- decorationTypes . forEach ( ( decoration ) => {
149- editor . setDecorations ( decoration , [ ] ) ;
150- } ) ;
170+ if ( ! keywordRanges . has ( upperKeyword ) ) {
171+ keywordRanges . set ( upperKeyword , [ ] ) ;
172+ }
151173
152- keywordRanges . forEach ( ( ranges , keyword ) => {
153- const decoration = decorationTypes . get ( keyword ) ;
154- if ( decoration ) {
155- editor . setDecorations ( decoration , ranges ) ;
174+ keywordRanges . get ( upperKeyword ) . push ( new vscode . Range ( startPos , endPos ) ) ;
156175 }
157- } ) ;
158176
159- isEditing = false ;
177+ applyDecorations ( editor , keywordRanges ) ;
178+ } finally {
179+ isEditing = false ;
180+ }
160181}
161182
162183// **Activation Function**
@@ -168,13 +189,13 @@ async function activate(context) {
168189 if ( vscode . window . activeTextEditor ?. document === event . document ) {
169190 await highlightWords ( context ) ;
170191 }
171- }
192+ } ,
172193 ) ;
173194
174195 const disposableEditorChange = vscode . window . onDidChangeActiveTextEditor (
175196 async ( ) => {
176197 await highlightWords ( context ) ;
177- }
198+ } ,
178199 ) ;
179200
180201 context . subscriptions . push ( disposableTextChange , disposableEditorChange ) ;
@@ -185,3 +206,4 @@ module.exports = {
185206 highlightWords,
186207 highlightTimeStamps,
187208} ;
209+
0 commit comments