@@ -30,7 +30,6 @@ class LineNumberManager {
3030 readonly NO_DECOR = - 1 ;
3131
3232 context : vscode . ExtensionContext ;
33-
3433 /* decorTypeMap
3534 {
3635 editor0: {
@@ -52,6 +51,7 @@ class LineNumberManager {
5251 Map < number , vscode . TextEditorDecorationType >
5352 > ;
5453 decorNumMap : Map < vscode . TextEditor , Map < number , number > > ;
54+ updateDecorDebounced ! : ( editor : vscode . TextEditor ) => void ;
5555
5656 /**
5757 * Constructor of LineNumberManager
@@ -63,9 +63,30 @@ class LineNumberManager {
6363 this . decorTypeMap = new Map ( ) ;
6464 this . decorNumMap = new Map ( ) ;
6565
66+ this . initializeUpdateDecorDebounced ( ) ;
67+
68+ vscode . workspace . onDidChangeConfiguration ( ( e ) => {
69+ if ( e . affectsConfiguration ( "vscode-double-line-numbers.delay" ) ) {
70+ this . initializeUpdateDecorDebounced ( ) ;
71+ }
72+ } ) ;
73+
6674 this . updateAllDecor ( ) ;
6775 }
6876
77+ /**
78+ * Updates the delay time and debounced function based on configuration
79+ */
80+ private initializeUpdateDecorDebounced ( ) {
81+ const delayTime = vscode . workspace
82+ . getConfiguration ( )
83+ . get ( "vscode-double-line-numbers.delay" , 50 ) ;
84+ this . updateDecorDebounced = this . debounce (
85+ this . updateDecor . bind ( this ) ,
86+ delayTime
87+ ) ;
88+ }
89+
6990 /**
7091 * Getter of right state
7192 * @returns {vscode.TextEditorLineNumbersStyle } right state
@@ -114,7 +135,9 @@ class LineNumberManager {
114135 * @param {string } key left state key, one of "abs_rel", "rel_abs", "abs", "rel", "off"
115136 */
116137 setLeftState ( key : string ) {
117- if ( this . getLeftState ( ) === leftStateMap [ key ] ) return ; // Optimization
138+ if ( this . getLeftState ( ) === leftStateMap [ key ] ) {
139+ return ;
140+ }
118141 this . context . globalState . update ( this . LEFT_STATE_STORE , leftStateMap [ key ] ) ;
119142 this . updateAllDecor ( ) ;
120143 }
@@ -124,7 +147,7 @@ class LineNumberManager {
124147 */
125148 updateAllDecor ( ) {
126149 vscode . window . visibleTextEditors . forEach ( ( editor ) => {
127- this . updateDecor ( editor ) ;
150+ this . updateDecorDebounced ( editor ) ;
128151 } ) ;
129152 }
130153
@@ -141,9 +164,12 @@ class LineNumberManager {
141164 const activeLine = editor . selection . active . line ;
142165
143166 // Create new map
144- if ( ! this . decorTypeMap . has ( editor ) )
167+ if ( ! this . decorTypeMap . has ( editor ) ) {
145168 this . decorTypeMap . set ( editor , new Map ( ) ) ;
146- if ( ! this . decorNumMap . has ( editor ) ) this . decorNumMap . set ( editor , new Map ( ) ) ;
169+ }
170+ if ( ! this . decorNumMap . has ( editor ) ) {
171+ this . decorNumMap . set ( editor , new Map ( ) ) ;
172+ }
147173
148174 for ( let i = start ; i <= end ; ++ i ) {
149175 let num : number ;
@@ -167,10 +193,11 @@ class LineNumberManager {
167193
168194 // apply decor
169195 for ( let i = start ; i <= end ; ++ i ) {
170- if ( this . decorNumMap . get ( editor ) ! . has ( i ) )
196+ if ( this . decorNumMap . get ( editor ) ! . has ( i ) ) {
171197 editor . setDecorations ( this . decorTypeMap . get ( editor ) ! . get ( i ) ! , [
172198 new vscode . Range ( i , 0 , i , 0 ) ,
173199 ] ) ;
200+ }
174201 }
175202 }
176203
@@ -189,6 +216,35 @@ class LineNumberManager {
189216 return vscode . window . createTextEditorDecorationType ( { } ) ;
190217 }
191218 }
219+
220+ /**
221+ * Creates a debounced function that delays invoking the provided function until after a specified wait time has elapsed
222+ * since the last time the debounced function was invoked. Optionally, the function can be invoked immediately on the first call.
223+ *
224+ * @param func - The function to debounce.
225+ * @param wait - The number of milliseconds to delay.
226+ * @param immediate - If `true`, the function will be invoked on the leading edge of the timeout, instead of the trailing.
227+ * @returns A new debounced function.
228+ */
229+ debounce ( func : Function , wait : number , immediate : boolean = false ) {
230+ let timeout : NodeJS . Timeout | null = null ;
231+ return ( ...args : any [ ] ) => {
232+ const later = ( ) => {
233+ timeout = null ;
234+ if ( ! immediate ) {
235+ func ( ...args ) ;
236+ }
237+ } ;
238+ const callNow = immediate && ! timeout ;
239+ if ( timeout ) {
240+ clearTimeout ( timeout ) ;
241+ }
242+ timeout = setTimeout ( later , wait ) ;
243+ if ( callNow ) {
244+ func ( ...args ) ;
245+ }
246+ } ;
247+ }
192248}
193249
194250/**
@@ -271,17 +327,19 @@ export function activate(context: vscode.ExtensionContext) {
271327
272328 // scroll; create/delete new lines
273329 vscode . window . onDidChangeTextEditorVisibleRanges ( ( event ) => {
274- mgr . updateDecor ( event . textEditor ) ;
330+ mgr . updateDecorDebounced ( event . textEditor ) ;
275331 } ) ;
276332
277333 // click into different editor
278334 vscode . window . onDidChangeActiveTextEditor ( ( editor ) => {
279- if ( editor ) mgr . updateDecor ( editor ) ;
335+ if ( editor ) {
336+ mgr . updateDecorDebounced ( editor ) ;
337+ }
280338 } ) ;
281339
282340 // select new lines in editor
283341 vscode . window . onDidChangeTextEditorSelection ( ( event ) => {
284- mgr . updateDecor ( event . textEditor ) ;
342+ mgr . updateDecorDebounced ( event . textEditor ) ;
285343 } ) ;
286344
287345 // open/close editors
0 commit comments