From 6fddfd04e5b9bbc0cd2a4f5ec8dd9a428d2a013c Mon Sep 17 00:00:00 2001 From: Neil <4138956+nwparker@users.noreply.github.com> Date: Wed, 2 Sep 2026 21:36:13 -0700 Subject: [PATCH] perf(terminal): stop terminal search rescanning every row of a wrapped line SearchEngine's forward scans walk every buffer row and _findInLine rewinds each wrapped row back to the start of its line, so a single long un-newlined line costs O(rows^2) on the renderer's main thread. The find bar re-runs that scan on every keystroke and again 200ms after every onWriteParsed, so a pane holding one long line freezes repeatedly rather than searching. A wrapped row's text was already searched when the first row of its line was, so skip it. Only sound for a plain search: wholeWord and regex can reject at one offset and match at a later one in the same line, so both keep the old walk. Measured, one un-newlined line at 80 cols filling the default 5000-row scrollback, no match (real Terminal + SearchAddon, happy-dom): upstream 17046 ms with the recursion fix 18500 ms with this commit 6 ms --- ...@xterm__addon-search@0.17.0-beta.300.patch | 72 ++++++++++++++++--- ...rm__addon-search@0.17.0-beta.300.src.patch | 54 +++++++++++++- pnpm-lock.yaml | 6 +- .../terminal-search-long-wrapped-line.test.ts | 58 ++++++++++++++- 4 files changed, 173 insertions(+), 17 deletions(-) diff --git a/config/patches/@xterm__addon-search@0.17.0-beta.300.patch b/config/patches/@xterm__addon-search@0.17.0-beta.300.patch index 6e61d95a10a..d9d08885c3e 100644 --- a/config/patches/@xterm__addon-search@0.17.0-beta.300.patch +++ b/config/patches/@xterm__addon-search@0.17.0-beta.300.patch @@ -1,23 +1,23 @@ diff --git a/lib/addon-search.js b/lib/addon-search.js -index d939cf1a65f3de449059efbf4fc5c3c3515f533f..271f4e5602f53081f6854d0d39786c0bb8bea5cc 100644 +index d939cf1a65f3de449059efbf4fc5c3c3515f533f..a19fb3e3faad2b6c7bbd31adfd6298cf71e52414 100644 --- a/lib/addon-search.js +++ b/lib/addon-search.js @@ -1,2 +1,2 @@ -!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.SearchAddon=t():e.SearchAddon=t()}(globalThis,()=>(()=>{"use strict";var e={578(e,t,s){Object.defineProperty(t,"__esModule",{value:!0}),t.IntervalTimer=t.MicrotaskTimer=t.TimeoutTimer=void 0,t.timeout=function(e){return new Promise(t=>setTimeout(t,e))},t.disposableTimeout=function(e,t=0,s){const r=setTimeout(()=>{e(),s&&n.dispose()},t),n=(0,i.toDisposable)(()=>{clearTimeout(r)});return s?.add(n),n};const i=s(426);t.TimeoutTimer=class{constructor(){this._token=-1,this._isDisposed=!1}dispose(){this.cancel(),this._isDisposed=!0}cancel(){-1!==this._token&&(clearTimeout(this._token),this._token=-1)}cancelAndSet(e,t){if(this._isDisposed)throw new Error("Calling cancelAndSet on a disposed TimeoutTimer");this.cancel(),this._token=setTimeout(()=>{this._token=-1,e()},t)}setIfNotSet(e,t){if(this._isDisposed)throw new Error("Calling setIfNotSet on a disposed TimeoutTimer");-1===this._token&&(this._token=setTimeout(()=>{this._token=-1,e()},t))}},t.MicrotaskTimer=class{constructor(){this._isScheduled=!1,this._isDisposed=!1}dispose(){this.cancel(),this._isDisposed=!0}cancel(){this._isScheduled=!1}set(e){if(this._isDisposed)throw new Error("Calling set on a disposed MicrotaskTimer");this._isScheduled||(this._isScheduled=!0,queueMicrotask(()=>{this._isScheduled&&(this._isScheduled=!1,e())}))}},t.IntervalTimer=class{constructor(){this._isDisposed=!1}cancel(){this._disposable?.dispose(),this._disposable=void 0}cancelAndSet(e,t,s=globalThis){if(this._isDisposed)throw new Error("Calling cancelAndSet on a disposed IntervalTimer");this.cancel();const i=s.setInterval(()=>{e()},t);this._disposable={dispose:()=>{s.clearInterval(i),this._disposable=void 0}}}dispose(){this.cancel(),this._isDisposed=!0}}},414(e,t,s){Object.defineProperty(t,"__esModule",{value:!0}),t.EventUtils=t.Emitter=void 0;const i=s(426);var r;t.Emitter=class{constructor(){this._listeners=[],this._disposed=!1}get event(){return this._event||(this._event=(e,t,s)=>{if(this._disposed)return(0,i.toDisposable)(()=>{});const r={fn:e,thisArgs:t};this._listeners=this._listeners.slice(),this._listeners.push(r);const n=(0,i.toDisposable)(()=>{const e=this._listeners.indexOf(r);-1!==e&&(this._listeners=this._listeners.slice(),this._listeners.splice(e,1))});return s&&(Array.isArray(s)?s.push(n):s.add(n)),n}),this._event}fire(e){if(this._disposed||!this._listeners.length)return;if(1===this._listeners.length)return void this._listeners[0].fn.call(this._listeners[0].thisArgs,e);const t=this._listeners;for(let s=0,i=t.length;st.fire(e))},e.map=function(e,t){return(s,i,r)=>e(e=>s.call(i,t(e)),void 0,r)},e.any=function(...e){return(t,s,r)=>{const n=new i.DisposableStore;for(const i of e)n.add(i(e=>t.call(s,e)));return r&&(Array.isArray(r)?r.push(n):r.add(n)),n}},e.runAndSubscribe=function(e,t,s){return t(s),e(e=>t(e))}}(r||(t.EventUtils=r={}))},426(e,t){function s(e){return{dispose:e}}function i(e){if(!e)return e;if(Array.isArray(e)){for(const t of e)t.dispose();return[]}return e.dispose(),e}Object.defineProperty(t,"__esModule",{value:!0}),t.MutableDisposable=t.Disposable=t.DisposableStore=void 0,t.toDisposable=s,t.dispose=i,t.combinedDisposable=function(...e){return s(()=>i(e))};class r{constructor(){this._disposables=new Set,this._isDisposed=!1}get isDisposed(){return this._isDisposed}add(e){return this._isDisposed?e.dispose():this._disposables.add(e),e}dispose(){if(!this._isDisposed){this._isDisposed=!0;for(const e of this._disposables)e.dispose();this._disposables.clear()}}clear(){for(const e of this._disposables)e.dispose();this._disposables.clear()}}t.DisposableStore=r;class n{constructor(){this._store=new r}dispose(){this._store.dispose()}_register(e){return this._store.add(e)}}t.Disposable=n,n.None=Object.freeze({dispose(){}}),t.MutableDisposable=class{constructor(){this._isDisposed=!1}get value(){return this._isDisposed?void 0:this._value}set value(e){this._isDisposed||e===this._value||(this._value?.dispose(),this._value=e)}clear(){this.value=void 0}dispose(){this._isDisposed=!0,this._value?.dispose(),this._value=void 0}}},864(e,t,s){Object.defineProperty(t,"__esModule",{value:!0}),t.DecorationManager=void 0;const i=s(426);class r extends i.Disposable{constructor(e){super(),this._terminal=e,this._highlightDecorations=[],this._highlightedLines=new Set,this._register((0,i.toDisposable)(()=>this.clearHighlightDecorations()))}createHighlightDecorations(e,t){this.clearHighlightDecorations();for(const s of e){const e=this._createResultDecorations(s,t,!1);if(e)for(const t of e)this._storeDecoration(t,s)}}createActiveDecoration(e,t){const s=this._createResultDecorations(e,t,!0);if(s)return{decorations:s,match:e,dispose(){(0,i.dispose)(s)}}}clearHighlightDecorations(){(0,i.dispose)(this._highlightDecorations),this._highlightDecorations=[],this._highlightedLines.clear()}_storeDecoration(e,t){this._highlightedLines.add(e.marker.line),this._highlightDecorations.push({decoration:e,match:t,dispose(){e.dispose()}})}_applyStyles(e,t,s){e.classList.contains("xterm-find-result-decoration")||(e.classList.add("xterm-find-result-decoration"),t&&(e.style.outline=`1px solid ${t}`)),s&&e.classList.add("xterm-find-active-result-decoration")}_createResultDecorations(e,t,s){const r=[];let n=e.col,o=e.size,a=-this._terminal.buffer.active.baseY-this._terminal.buffer.active.cursorY+e.row;for(;o>0;){const e=Math.min(this._terminal.cols-n,o);r.push([a,n,e]),n=0,o-=e,a++}const h=[];for(const e of r){const r=this._terminal.registerMarker(e[0]),n=this._terminal.registerDecoration({marker:r,x:e[1],width:e[2],layer:s?"top":"bottom",backgroundColor:s?t.activeMatchBackground:t.matchBackground,overviewRulerOptions:this._highlightedLines.has(r.line)?void 0:{color:s?t.activeMatchColorOverviewRuler:t.matchOverviewRuler,position:"center"}});if(n){const e=[];e.push(r),e.push(n.onRender(e=>this._applyStyles(e,s?t.activeMatchBorder:t.matchBorder,!1))),e.push(n.onDispose(()=>(0,i.dispose)(e))),h.push(n)}}return 0===h.length?void 0:h}}t.DecorationManager=r},615(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.SearchEngine=void 0,t.SearchEngine=class{constructor(e,t){this._terminal=e,this._lineCache=t}find(e,t,s,i){if(!e||0===e.length)return void this._terminal.clearSelection();if(s>=this._terminal.cols)throw new Error(`Invalid col: ${s} to search in terminal of ${this._terminal.cols} cols`);this._lineCache.initLinesCache();const r={startRow:t,startCol:s};let n=this._findInLine(e,r,i);if(!n)for(let s=t+1;s=0&&(a.startRow=s,h=this._findInLine(e,a,t,o),!h);s--);}if(!h&&r!==this._terminal.buffer.active.baseY+this._terminal.rows-1)for(let s=this._terminal.buffer.active.baseY+this._terminal.rows-1;s>=r&&(a.startRow=s,h=this._findInLine(e,a,t,o),!h);s--);return h}_isWholeWord(e,t,s){return(0===e||" ~!@#$%^&*()+`-=[]{}|\\;:\"',./<>?".includes(t[e-1]))&&(e+s.length===t.length||" ~!@#$%^&*()+`-=[]{}|\\;:\"',./<>?".includes(t[e+s.length]))}_findInLine(e,t,s={},i=!1){const r=t.startRow,n=t.startCol,o=this._terminal.buffer.active.getLine(r);if(o?.isWrapped)return i?void(t.startCol+=this._terminal.cols):(t.startRow--,t.startCol+=this._terminal.cols,this._findInLine(e,t,s));let a=this._lineCache.getLineFromCache(r);a||(a=this._lineCache.translateBufferLineToStringWithWrap(r,!0),this._lineCache.setLineInCache(r,a));const[h,l]=a,c=this._bufferColsToStringOffset(r,n);let d=e,_=h;s.regex||(d=s.caseSensitive?e:e.toLowerCase(),_=s.caseSensitive?h:h.toLowerCase());let u=-1;if(s.regex){const t=RegExp(d,s.caseSensitive?"g":"gi");let r;if(i)for(;r=t.exec(_.slice(0,c));)u=t.lastIndex-r[0].length,e=r[0],t.lastIndex-=e.length-1;else r=t.exec(_.slice(c)),r&&r[0].length>0&&(u=c+(t.lastIndex-r[0].length),e=r[0])}else i?c-d.length>=0&&(u=_.lastIndexOf(d,c-d.length)):u=_.indexOf(d,c);if(u>=0){if(s.wholeWord&&!this._isWholeWord(u,_,e))return;let t=0;for(;t=l[t+1];)t++;let i=t;for(;i=l[i+1];)i++;const n=u-l[t],o=u+e.length-l[i],a=this._stringLengthToBufferSize(r+t,n);return{term:e,col:a,row:r+t,size:this._stringLengthToBufferSize(r+i,o)-a+this._terminal.cols*(i-t)}}}_stringLengthToBufferSize(e,t){const s=this._terminal.buffer.active.getLine(e);if(!s)return 0;for(let e=0;e1&&(t-=r.length-1);const n=s.getCell(e+1);n&&0===n.getWidth()&&t++}return t}_bufferColsToStringOffset(e,t){let s=e,i=0,r=this._terminal.buffer.active.getLine(s);for(;t>0&&r;){for(let e=0;ethis._destroyLinesCache()))}initLinesCache(){this._linesCache||(this._linesCache=new Array(this._terminal.buffer.active.length),this._linesCacheDisposables.value=(0,i.combinedDisposable)(this._terminal.onLineFeed(()=>this._destroyLinesCache()),this._terminal.onCursorMove(()=>this._destroyLinesCache()),this._terminal.onResize(()=>this._destroyLinesCache()))),this._lastAccessTimestamp=Date.now(),this._linesCacheTimeout.value||this._scheduleLinesCacheTimeout(15e3)}_destroyLinesCache(){this._linesCache=void 0,this._lastAccessTimestamp=0,this._linesCacheDisposables.clear(),this._linesCacheTimeout.clear()}_scheduleLinesCacheTimeout(e){this._linesCacheTimeout.value=(0,r.disposableTimeout)(()=>{if(!this._linesCache)return;const e=Date.now()-this._lastAccessTimestamp;e>=15e3?this._destroyLinesCache():this._scheduleLinesCacheTimeout(15e3-e)},e)}getLineFromCache(e){return this._linesCache?.[e]}setLineInCache(e,t){this._linesCache&&(this._linesCache[e]=t)}translateBufferLineToStringWithWrap(e,t){const s=[],i=[0];let r=this._terminal.buffer.active.getLine(e);for(;r;){const n=this._terminal.buffer.active.getLine(e+1),o=!!n&&n.isWrapped;let a=r.translateToString(!o&&t);if(o&&n){const e=r.getCell(r.length-1);e&&0===e.getCode()&&1===e.getWidth()&&2===n.getCell(0)?.getWidth()&&(a=a.slice(0,-1))}if(s.push(a),!o)break;i.push(i[i.length-1]+a.length),e++,r=n}return[s.join(""),i]}}t.SearchLineCache=n},438(e,t,s){Object.defineProperty(t,"__esModule",{value:!0}),t.SearchResultTracker=void 0;const i=s(414),r=s(426);class n extends r.Disposable{constructor(){super(...arguments),this._searchResults=[],this._onDidChangeResults=this._register(new i.Emitter)}get onDidChangeResults(){return this._onDidChangeResults.event}get searchResults(){return this._searchResults}get selectedDecoration(){return this._selectedDecoration}set selectedDecoration(e){this._selectedDecoration=e}updateResults(e,t){this._searchResults=e.slice(0,t)}clearResults(){this._searchResults=[]}clearSelectedDecoration(){this._selectedDecoration&&(this._selectedDecoration.dispose(),this._selectedDecoration=void 0)}findResultIndex(e){for(let t=0;t0)}didOptionsChange(e){return!this._lastSearchOptions||!!e&&(this._lastSearchOptions.caseSensitive!==e.caseSensitive||this._lastSearchOptions.regex!==e.regex||this._lastSearchOptions.wholeWord!==e.wholeWord)}shouldUpdateHighlighting(e,t){return!!t?.decorations&&(void 0===this._cachedSearchTerm||e!==this._cachedSearchTerm||this.didOptionsChange(t))}clearCachedTerm(){this._cachedSearchTerm=void 0}reset(){this._cachedSearchTerm=void 0,this._lastSearchOptions=void 0}}}},t={};function s(i){var r=t[i];if(void 0!==r)return r.exports;var n=t[i]={exports:{}};return e[i](n,n.exports,s),n.exports}var i={};return(()=>{var e=i;Object.defineProperty(e,"__esModule",{value:!0}),e.SearchAddon=void 0;const t=s(414),r=s(426),n=s(578),o=s(149),a=s(772),h=s(615),l=s(864),c=s(438);class d extends r.Disposable{get onDidChangeResults(){return this._resultTracker.onDidChangeResults}constructor(e){super(),this._highlightTimeout=this._register(new r.MutableDisposable),this._lineCache=this._register(new r.MutableDisposable),this._state=new a.SearchState,this._resultTracker=this._register(new c.SearchResultTracker),this._onAfterSearch=this._register(new t.Emitter),this.onAfterSearch=this._onAfterSearch.event,this._onBeforeSearch=this._register(new t.Emitter),this.onBeforeSearch=this._onBeforeSearch.event,this._highlightLimit=e?.highlightLimit??1e3}activate(e){this._terminal=e,this._lineCache.value=new o.SearchLineCache(e),this._engine=new h.SearchEngine(e,this._lineCache.value),this._decorationManager=new l.DecorationManager(e),this._register(this._terminal.onWriteParsed(()=>this._updateMatches())),this._register(this._terminal.onResize(()=>this._updateMatches())),this._register((0,r.toDisposable)(()=>this.clearDecorations()))}_updateMatches(){this._highlightTimeout.clear(),this._state.cachedSearchTerm&&this._state.lastSearchOptions?.decorations&&(this._highlightTimeout.value=(0,n.disposableTimeout)(()=>{const e=this._state.cachedSearchTerm;this._state.clearCachedTerm(),this.findPrevious(e,{...this._state.lastSearchOptions,incremental:!0},{noScroll:!0})},200))}clearDecorations(e){this._resultTracker.clearSelectedDecoration(),this._decorationManager?.clearHighlightDecorations(),this._resultTracker.clearResults(),e||this._state.clearCachedTerm()}clearActiveDecoration(){this._resultTracker.clearSelectedDecoration()}findNext(e,t,s){if(!this._terminal||!this._engine)throw new Error("Cannot use addon until it has been loaded");this._onBeforeSearch.fire(),this._state.lastSearchOptions=t,this._state.shouldUpdateHighlighting(e,t)&&this._highlightAllMatches(e,t);const i=this._findNextAndSelect(e,t,s);return this._fireResults(t),this._state.cachedSearchTerm=e,this._onAfterSearch.fire(),i}_highlightAllMatches(e,t){if(!this._terminal||!this._engine||!this._decorationManager)throw new Error("Cannot use addon until it has been loaded");if(!this._state.isValidSearchTerm(e))return void this.clearDecorations();this.clearDecorations(!0);const s=[];let i,r=this._engine.find(e,0,0,t);for(;r&&(i?.row!==r.row||i?.col!==r.col)&&!(s.length>=this._highlightLimit);){i=r,s.push(i);const n=this._terminal.cols;let o=i.col+i.size,a=i.row;o>=n&&(a+=Math.floor(o/n),o%=n),r=this._engine.find(e,a,o,t)}this._resultTracker.updateResults(s,this._highlightLimit),t.decorations&&this._decorationManager.createHighlightDecorations(s,t.decorations)}_findNextAndSelect(e,t,s){if(!this._terminal||!this._engine)return!1;if(!this._state.isValidSearchTerm(e))return this._terminal.clearSelection(),this.clearDecorations(),!1;const i=this._engine.findNextWithSelection(e,t,this._state.cachedSearchTerm);return this._selectResult(i,t?.decorations,s?.noScroll)}findPrevious(e,t,s){if(!this._terminal||!this._engine)throw new Error("Cannot use addon until it has been loaded");this._onBeforeSearch.fire(),this._state.lastSearchOptions=t,this._state.shouldUpdateHighlighting(e,t)&&this._highlightAllMatches(e,t);const i=this._findPreviousAndSelect(e,t,s);return this._fireResults(t),this._state.cachedSearchTerm=e,this._onAfterSearch.fire(),i}_fireResults(e){this._resultTracker.fireResultsChanged(!!e?.decorations)}_findPreviousAndSelect(e,t,s){if(!this._terminal||!this._engine)return!1;if(!this._state.isValidSearchTerm(e))return this._terminal.clearSelection(),this.clearDecorations(),!1;const i=this._engine.findPreviousWithSelection(e,t,this._state.cachedSearchTerm);return this._selectResult(i,t?.decorations,s?.noScroll)}_selectResult(e,t,s){if(!this._terminal||!this._decorationManager)return!1;if(this._resultTracker.clearSelectedDecoration(),!e)return this._terminal.clearSelection(),!1;if(this._terminal.select(e.col,e.row,e.size),t){const s=this._decorationManager.createActiveDecoration(e,t);s&&(this._resultTracker.selectedDecoration=s)}if(!s&&(e.row>=this._terminal.buffer.active.viewportY+this._terminal.rows||e.row(()=>{"use strict";var e={578(e,t,s){Object.defineProperty(t,"__esModule",{value:!0}),t.IntervalTimer=t.MicrotaskTimer=t.TimeoutTimer=void 0,t.timeout=function(e){return new Promise(t=>setTimeout(t,e))},t.disposableTimeout=function(e,t=0,s){const r=setTimeout(()=>{e(),s&&n.dispose()},t),n=(0,i.toDisposable)(()=>{clearTimeout(r)});return s?.add(n),n};const i=s(426);t.TimeoutTimer=class{constructor(){this._token=-1,this._isDisposed=!1}dispose(){this.cancel(),this._isDisposed=!0}cancel(){-1!==this._token&&(clearTimeout(this._token),this._token=-1)}cancelAndSet(e,t){if(this._isDisposed)throw new Error("Calling cancelAndSet on a disposed TimeoutTimer");this.cancel(),this._token=setTimeout(()=>{this._token=-1,e()},t)}setIfNotSet(e,t){if(this._isDisposed)throw new Error("Calling setIfNotSet on a disposed TimeoutTimer");-1===this._token&&(this._token=setTimeout(()=>{this._token=-1,e()},t))}},t.MicrotaskTimer=class{constructor(){this._isScheduled=!1,this._isDisposed=!1}dispose(){this.cancel(),this._isDisposed=!0}cancel(){this._isScheduled=!1}set(e){if(this._isDisposed)throw new Error("Calling set on a disposed MicrotaskTimer");this._isScheduled||(this._isScheduled=!0,queueMicrotask(()=>{this._isScheduled&&(this._isScheduled=!1,e())}))}},t.IntervalTimer=class{constructor(){this._isDisposed=!1}cancel(){this._disposable?.dispose(),this._disposable=void 0}cancelAndSet(e,t,s=globalThis){if(this._isDisposed)throw new Error("Calling cancelAndSet on a disposed IntervalTimer");this.cancel();const i=s.setInterval(()=>{e()},t);this._disposable={dispose:()=>{s.clearInterval(i),this._disposable=void 0}}}dispose(){this.cancel(),this._isDisposed=!0}}},414(e,t,s){Object.defineProperty(t,"__esModule",{value:!0}),t.EventUtils=t.Emitter=void 0;const i=s(426);var r;t.Emitter=class{constructor(){this._listeners=[],this._disposed=!1}get event(){return this._event||(this._event=(e,t,s)=>{if(this._disposed)return(0,i.toDisposable)(()=>{});const r={fn:e,thisArgs:t};this._listeners=this._listeners.slice(),this._listeners.push(r);const n=(0,i.toDisposable)(()=>{const e=this._listeners.indexOf(r);-1!==e&&(this._listeners=this._listeners.slice(),this._listeners.splice(e,1))});return s&&(Array.isArray(s)?s.push(n):s.add(n)),n}),this._event}fire(e){if(this._disposed||!this._listeners.length)return;if(1===this._listeners.length)return void this._listeners[0].fn.call(this._listeners[0].thisArgs,e);const t=this._listeners;for(let s=0,i=t.length;st.fire(e))},e.map=function(e,t){return(s,i,r)=>e(e=>s.call(i,t(e)),void 0,r)},e.any=function(...e){return(t,s,r)=>{const n=new i.DisposableStore;for(const i of e)n.add(i(e=>t.call(s,e)));return r&&(Array.isArray(r)?r.push(n):r.add(n)),n}},e.runAndSubscribe=function(e,t,s){return t(s),e(e=>t(e))}}(r||(t.EventUtils=r={}))},426(e,t){function s(e){return{dispose:e}}function i(e){if(!e)return e;if(Array.isArray(e)){for(const t of e)t.dispose();return[]}return e.dispose(),e}Object.defineProperty(t,"__esModule",{value:!0}),t.MutableDisposable=t.Disposable=t.DisposableStore=void 0,t.toDisposable=s,t.dispose=i,t.combinedDisposable=function(...e){return s(()=>i(e))};class r{constructor(){this._disposables=new Set,this._isDisposed=!1}get isDisposed(){return this._isDisposed}add(e){return this._isDisposed?e.dispose():this._disposables.add(e),e}dispose(){if(!this._isDisposed){this._isDisposed=!0;for(const e of this._disposables)e.dispose();this._disposables.clear()}}clear(){for(const e of this._disposables)e.dispose();this._disposables.clear()}}t.DisposableStore=r;class n{constructor(){this._store=new r}dispose(){this._store.dispose()}_register(e){return this._store.add(e)}}t.Disposable=n,n.None=Object.freeze({dispose(){}}),t.MutableDisposable=class{constructor(){this._isDisposed=!1}get value(){return this._isDisposed?void 0:this._value}set value(e){this._isDisposed||e===this._value||(this._value?.dispose(),this._value=e)}clear(){this.value=void 0}dispose(){this._isDisposed=!0,this._value?.dispose(),this._value=void 0}}},864(e,t,s){Object.defineProperty(t,"__esModule",{value:!0}),t.DecorationManager=void 0;const i=s(426);class r extends i.Disposable{constructor(e){super(),this._terminal=e,this._highlightDecorations=[],this._highlightedLines=new Set,this._register((0,i.toDisposable)(()=>this.clearHighlightDecorations()))}createHighlightDecorations(e,t){this.clearHighlightDecorations();for(const s of e){const e=this._createResultDecorations(s,t,!1);if(e)for(const t of e)this._storeDecoration(t,s)}}createActiveDecoration(e,t){const s=this._createResultDecorations(e,t,!0);if(s)return{decorations:s,match:e,dispose(){(0,i.dispose)(s)}}}clearHighlightDecorations(){(0,i.dispose)(this._highlightDecorations),this._highlightDecorations=[],this._highlightedLines.clear()}_storeDecoration(e,t){this._highlightedLines.add(e.marker.line),this._highlightDecorations.push({decoration:e,match:t,dispose(){e.dispose()}})}_applyStyles(e,t,s){e.classList.contains("xterm-find-result-decoration")||(e.classList.add("xterm-find-result-decoration"),t&&(e.style.outline=`1px solid ${t}`)),s&&e.classList.add("xterm-find-active-result-decoration")}_createResultDecorations(e,t,s){const r=[];let n=e.col,o=e.size,a=-this._terminal.buffer.active.baseY-this._terminal.buffer.active.cursorY+e.row;for(;o>0;){const e=Math.min(this._terminal.cols-n,o);r.push([a,n,e]),n=0,o-=e,a++}const h=[];for(const e of r){const r=this._terminal.registerMarker(e[0]),n=this._terminal.registerDecoration({marker:r,x:e[1],width:e[2],layer:s?"top":"bottom",backgroundColor:s?t.activeMatchBackground:t.matchBackground,overviewRulerOptions:this._highlightedLines.has(r.line)?void 0:{color:s?t.activeMatchColorOverviewRuler:t.matchOverviewRuler,position:"center"}});if(n){const e=[];e.push(r),e.push(n.onRender(e=>this._applyStyles(e,s?t.activeMatchBorder:t.matchBorder,!1))),e.push(n.onDispose(()=>(0,i.dispose)(e))),h.push(n)}}return 0===h.length?void 0:h}}t.DecorationManager=r},615(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.SearchEngine=void 0,t.SearchEngine=class{constructor(e,t){this._terminal=e,this._lineCache=t}find(e,t,s,i){if(!e||0===e.length)return void this._terminal.clearSelection();if(s>=this._terminal.cols)throw new Error(`Invalid col: ${s} to search in terminal of ${this._terminal.cols} cols`);this._lineCache.initLinesCache();const r={startRow:t,startCol:s};let n=this._findInLine(e,r,i);if(!n)for(let s=t+1;s=0&&(a.startRow=s,h=this._findInLine(e,a,t,o),!h);s--);}if(!h&&r!==this._terminal.buffer.active.baseY+this._terminal.rows-1)for(let s=this._terminal.buffer.active.baseY+this._terminal.rows-1;s>=r&&(a.startRow=s,h=this._findInLine(e,a,t,o),!h);s--);return h}_isWholeWord(e,t,s){return(0===e||" ~!@#$%^&*()+`-=[]{}|\\;:\"',./<>?".includes(t[e-1]))&&(e+s.length===t.length||" ~!@#$%^&*()+`-=[]{}|\\;:\"',./<>?".includes(t[e+s.length]))}_findInLine(e,t,s={},i=!1){for(;this._terminal.buffer.active.getLine(t.startRow)?.isWrapped;){if(t.startCol+=this._terminal.cols,i)return;t.startRow--}const r=t.startRow,n=t.startCol;let o=this._lineCache.getLineFromCache(r);o||(o=this._lineCache.translateBufferLineToStringWithWrap(r,!0),this._lineCache.setLineInCache(r,o));const[a,h]=o,l=this._bufferColsToStringOffset(r,n);let c=e,d=a;s.regex||(c=s.caseSensitive?e:e.toLowerCase(),d=s.caseSensitive?a:a.toLowerCase());let _=-1;if(s.regex){const t=RegExp(c,s.caseSensitive?"g":"gi");let r;if(i)for(;r=t.exec(d.slice(0,l));)_=t.lastIndex-r[0].length,e=r[0],t.lastIndex-=e.length-1;else r=t.exec(d.slice(l)),r&&r[0].length>0&&(_=l+(t.lastIndex-r[0].length),e=r[0])}else i?l-c.length>=0&&(_=d.lastIndexOf(c,l-c.length)):_=d.indexOf(c,l);if(_>=0){if(s.wholeWord&&!this._isWholeWord(_,d,e))return;let t=0;for(;t=h[t+1];)t++;let i=t;for(;i=h[i+1];)i++;const n=_-h[t],o=_+e.length-h[i],a=this._stringLengthToBufferSize(r+t,n);return{term:e,col:a,row:r+t,size:this._stringLengthToBufferSize(r+i,o)-a+this._terminal.cols*(i-t)}}}_stringLengthToBufferSize(e,t){const s=this._terminal.buffer.active.getLine(e);if(!s)return 0;for(let e=0;e1&&(t-=r.length-1);const n=s.getCell(e+1);n&&0===n.getWidth()&&t++}return t}_bufferColsToStringOffset(e,t){let s=e,i=0,r=this._terminal.buffer.active.getLine(s);for(;t>0&&r;){for(let e=0;ethis._destroyLinesCache()))}initLinesCache(){this._linesCache||(this._linesCache=new Array(this._terminal.buffer.active.length),this._linesCacheDisposables.value=(0,i.combinedDisposable)(this._terminal.onLineFeed(()=>this._destroyLinesCache()),this._terminal.onCursorMove(()=>this._destroyLinesCache()),this._terminal.onResize(()=>this._destroyLinesCache()))),this._lastAccessTimestamp=Date.now(),this._linesCacheTimeout.value||this._scheduleLinesCacheTimeout(15e3)}_destroyLinesCache(){this._linesCache=void 0,this._lastAccessTimestamp=0,this._linesCacheDisposables.clear(),this._linesCacheTimeout.clear()}_scheduleLinesCacheTimeout(e){this._linesCacheTimeout.value=(0,r.disposableTimeout)(()=>{if(!this._linesCache)return;const e=Date.now()-this._lastAccessTimestamp;e>=15e3?this._destroyLinesCache():this._scheduleLinesCacheTimeout(15e3-e)},e)}getLineFromCache(e){return this._linesCache?.[e]}setLineInCache(e,t){this._linesCache&&(this._linesCache[e]=t)}translateBufferLineToStringWithWrap(e,t){const s=[],i=[0];let r=this._terminal.buffer.active.getLine(e);for(;r;){const n=this._terminal.buffer.active.getLine(e+1),o=!!n&&n.isWrapped;let a=r.translateToString(!o&&t);if(o&&n){const e=r.getCell(r.length-1);e&&0===e.getCode()&&1===e.getWidth()&&2===n.getCell(0)?.getWidth()&&(a=a.slice(0,-1))}if(s.push(a),!o)break;i.push(i[i.length-1]+a.length),e++,r=n}return[s.join(""),i]}}t.SearchLineCache=n},438(e,t,s){Object.defineProperty(t,"__esModule",{value:!0}),t.SearchResultTracker=void 0;const i=s(414),r=s(426);class n extends r.Disposable{constructor(){super(...arguments),this._searchResults=[],this._onDidChangeResults=this._register(new i.Emitter)}get onDidChangeResults(){return this._onDidChangeResults.event}get searchResults(){return this._searchResults}get selectedDecoration(){return this._selectedDecoration}set selectedDecoration(e){this._selectedDecoration=e}updateResults(e,t){this._searchResults=e.slice(0,t)}clearResults(){this._searchResults=[]}clearSelectedDecoration(){this._selectedDecoration&&(this._selectedDecoration.dispose(),this._selectedDecoration=void 0)}findResultIndex(e){for(let t=0;t0)}didOptionsChange(e){return!this._lastSearchOptions||!!e&&(this._lastSearchOptions.caseSensitive!==e.caseSensitive||this._lastSearchOptions.regex!==e.regex||this._lastSearchOptions.wholeWord!==e.wholeWord)}shouldUpdateHighlighting(e,t){return!!t?.decorations&&(void 0===this._cachedSearchTerm||e!==this._cachedSearchTerm||this.didOptionsChange(t))}clearCachedTerm(){this._cachedSearchTerm=void 0}reset(){this._cachedSearchTerm=void 0,this._lastSearchOptions=void 0}}}},t={};function s(i){var r=t[i];if(void 0!==r)return r.exports;var n=t[i]={exports:{}};return e[i](n,n.exports,s),n.exports}var i={};return(()=>{var e=i;Object.defineProperty(e,"__esModule",{value:!0}),e.SearchAddon=void 0;const t=s(414),r=s(426),n=s(578),o=s(149),a=s(772),h=s(615),l=s(864),c=s(438);class d extends r.Disposable{get onDidChangeResults(){return this._resultTracker.onDidChangeResults}constructor(e){super(),this._highlightTimeout=this._register(new r.MutableDisposable),this._lineCache=this._register(new r.MutableDisposable),this._state=new a.SearchState,this._resultTracker=this._register(new c.SearchResultTracker),this._onAfterSearch=this._register(new t.Emitter),this.onAfterSearch=this._onAfterSearch.event,this._onBeforeSearch=this._register(new t.Emitter),this.onBeforeSearch=this._onBeforeSearch.event,this._highlightLimit=e?.highlightLimit??1e3}activate(e){this._terminal=e,this._lineCache.value=new o.SearchLineCache(e),this._engine=new h.SearchEngine(e,this._lineCache.value),this._decorationManager=new l.DecorationManager(e),this._register(this._terminal.onWriteParsed(()=>this._updateMatches())),this._register(this._terminal.onResize(()=>this._updateMatches())),this._register((0,r.toDisposable)(()=>this.clearDecorations()))}_updateMatches(){this._highlightTimeout.clear(),this._state.cachedSearchTerm&&this._state.lastSearchOptions?.decorations&&(this._highlightTimeout.value=(0,n.disposableTimeout)(()=>{const e=this._state.cachedSearchTerm;this._state.clearCachedTerm(),this.findPrevious(e,{...this._state.lastSearchOptions,incremental:!0},{noScroll:!0})},200))}clearDecorations(e){this._resultTracker.clearSelectedDecoration(),this._decorationManager?.clearHighlightDecorations(),this._resultTracker.clearResults(),e||this._state.clearCachedTerm()}clearActiveDecoration(){this._resultTracker.clearSelectedDecoration()}findNext(e,t,s){if(!this._terminal||!this._engine)throw new Error("Cannot use addon until it has been loaded");this._onBeforeSearch.fire(),this._state.lastSearchOptions=t,this._state.shouldUpdateHighlighting(e,t)&&this._highlightAllMatches(e,t);const i=this._findNextAndSelect(e,t,s);return this._fireResults(t),this._state.cachedSearchTerm=e,this._onAfterSearch.fire(),i}_highlightAllMatches(e,t){if(!this._terminal||!this._engine||!this._decorationManager)throw new Error("Cannot use addon until it has been loaded");if(!this._state.isValidSearchTerm(e))return void this.clearDecorations();this.clearDecorations(!0);const s=[];let i,r=this._engine.find(e,0,0,t);for(;r&&(i?.row!==r.row||i?.col!==r.col)&&!(s.length>=this._highlightLimit);){i=r,s.push(i);const n=this._terminal.cols;let o=i.col+i.size,a=i.row;o>=n&&(a+=Math.floor(o/n),o%=n),r=this._engine.find(e,a,o,t)}this._resultTracker.updateResults(s,this._highlightLimit),t.decorations&&this._decorationManager.createHighlightDecorations(s,t.decorations)}_findNextAndSelect(e,t,s){if(!this._terminal||!this._engine)return!1;if(!this._state.isValidSearchTerm(e))return this._terminal.clearSelection(),this.clearDecorations(),!1;const i=this._engine.findNextWithSelection(e,t,this._state.cachedSearchTerm);return this._selectResult(i,t?.decorations,s?.noScroll)}findPrevious(e,t,s){if(!this._terminal||!this._engine)throw new Error("Cannot use addon until it has been loaded");this._onBeforeSearch.fire(),this._state.lastSearchOptions=t,this._state.shouldUpdateHighlighting(e,t)&&this._highlightAllMatches(e,t);const i=this._findPreviousAndSelect(e,t,s);return this._fireResults(t),this._state.cachedSearchTerm=e,this._onAfterSearch.fire(),i}_fireResults(e){this._resultTracker.fireResultsChanged(!!e?.decorations)}_findPreviousAndSelect(e,t,s){if(!this._terminal||!this._engine)return!1;if(!this._state.isValidSearchTerm(e))return this._terminal.clearSelection(),this.clearDecorations(),!1;const i=this._engine.findPreviousWithSelection(e,t,this._state.cachedSearchTerm);return this._selectResult(i,t?.decorations,s?.noScroll)}_selectResult(e,t,s){if(!this._terminal||!this._decorationManager)return!1;if(this._resultTracker.clearSelectedDecoration(),!e)return this._terminal.clearSelection(),!1;if(this._terminal.select(e.col,e.row,e.size),t){const s=this._decorationManager.createActiveDecoration(e,t);s&&(this._resultTracker.selectedDecoration=s)}if(!s&&(e.row>=this._terminal.buffer.active.viewportY+this._terminal.rows||e.row(()=>{"use strict";var e={578(e,t,s){Object.defineProperty(t,"__esModule",{value:!0}),t.IntervalTimer=t.MicrotaskTimer=t.TimeoutTimer=void 0,t.timeout=function(e){return new Promise(t=>setTimeout(t,e))},t.disposableTimeout=function(e,t=0,s){const r=setTimeout(()=>{e(),s&&n.dispose()},t),n=(0,i.toDisposable)(()=>{clearTimeout(r)});return s?.add(n),n};const i=s(426);t.TimeoutTimer=class{constructor(){this._token=-1,this._isDisposed=!1}dispose(){this.cancel(),this._isDisposed=!0}cancel(){-1!==this._token&&(clearTimeout(this._token),this._token=-1)}cancelAndSet(e,t){if(this._isDisposed)throw new Error("Calling cancelAndSet on a disposed TimeoutTimer");this.cancel(),this._token=setTimeout(()=>{this._token=-1,e()},t)}setIfNotSet(e,t){if(this._isDisposed)throw new Error("Calling setIfNotSet on a disposed TimeoutTimer");-1===this._token&&(this._token=setTimeout(()=>{this._token=-1,e()},t))}},t.MicrotaskTimer=class{constructor(){this._isScheduled=!1,this._isDisposed=!1}dispose(){this.cancel(),this._isDisposed=!0}cancel(){this._isScheduled=!1}set(e){if(this._isDisposed)throw new Error("Calling set on a disposed MicrotaskTimer");this._isScheduled||(this._isScheduled=!0,queueMicrotask(()=>{this._isScheduled&&(this._isScheduled=!1,e())}))}},t.IntervalTimer=class{constructor(){this._isDisposed=!1}cancel(){this._disposable?.dispose(),this._disposable=void 0}cancelAndSet(e,t,s=globalThis){if(this._isDisposed)throw new Error("Calling cancelAndSet on a disposed IntervalTimer");this.cancel();const i=s.setInterval(()=>{e()},t);this._disposable={dispose:()=>{s.clearInterval(i),this._disposable=void 0}}}dispose(){this.cancel(),this._isDisposed=!0}}},414(e,t,s){Object.defineProperty(t,"__esModule",{value:!0}),t.EventUtils=t.Emitter=void 0;const i=s(426);var r;t.Emitter=class{constructor(){this._listeners=[],this._disposed=!1}get event(){return this._event||(this._event=(e,t,s)=>{if(this._disposed)return(0,i.toDisposable)(()=>{});const r={fn:e,thisArgs:t};this._listeners=this._listeners.slice(),this._listeners.push(r);const n=(0,i.toDisposable)(()=>{const e=this._listeners.indexOf(r);-1!==e&&(this._listeners=this._listeners.slice(),this._listeners.splice(e,1))});return s&&(Array.isArray(s)?s.push(n):s.add(n)),n}),this._event}fire(e){if(this._disposed||!this._listeners.length)return;if(1===this._listeners.length)return void this._listeners[0].fn.call(this._listeners[0].thisArgs,e);const t=this._listeners;for(let s=0,i=t.length;st.fire(e))},e.map=function(e,t){return(s,i,r)=>e(e=>s.call(i,t(e)),void 0,r)},e.any=function(...e){return(t,s,r)=>{const n=new i.DisposableStore;for(const i of e)n.add(i(e=>t.call(s,e)));return r&&(Array.isArray(r)?r.push(n):r.add(n)),n}},e.runAndSubscribe=function(e,t,s){return t(s),e(e=>t(e))}}(r||(t.EventUtils=r={}))},426(e,t){function s(e){return{dispose:e}}function i(e){if(!e)return e;if(Array.isArray(e)){for(const t of e)t.dispose();return[]}return e.dispose(),e}Object.defineProperty(t,"__esModule",{value:!0}),t.MutableDisposable=t.Disposable=t.DisposableStore=void 0,t.toDisposable=s,t.dispose=i,t.combinedDisposable=function(...e){return s(()=>i(e))};class r{constructor(){this._disposables=new Set,this._isDisposed=!1}get isDisposed(){return this._isDisposed}add(e){return this._isDisposed?e.dispose():this._disposables.add(e),e}dispose(){if(!this._isDisposed){this._isDisposed=!0;for(const e of this._disposables)e.dispose();this._disposables.clear()}}clear(){for(const e of this._disposables)e.dispose();this._disposables.clear()}}t.DisposableStore=r;class n{constructor(){this._store=new r}dispose(){this._store.dispose()}_register(e){return this._store.add(e)}}t.Disposable=n,n.None=Object.freeze({dispose(){}}),t.MutableDisposable=class{constructor(){this._isDisposed=!1}get value(){return this._isDisposed?void 0:this._value}set value(e){this._isDisposed||e===this._value||(this._value?.dispose(),this._value=e)}clear(){this.value=void 0}dispose(){this._isDisposed=!0,this._value?.dispose(),this._value=void 0}}},864(e,t,s){Object.defineProperty(t,"__esModule",{value:!0}),t.DecorationManager=void 0;const i=s(426);class r extends i.Disposable{constructor(e){super(),this._terminal=e,this._highlightDecorations=[],this._highlightedLines=new Set,this._register((0,i.toDisposable)(()=>this.clearHighlightDecorations()))}createHighlightDecorations(e,t){this.clearHighlightDecorations();for(const s of e){const e=this._createResultDecorations(s,t,!1);if(e)for(const t of e)this._storeDecoration(t,s)}}createActiveDecoration(e,t){const s=this._createResultDecorations(e,t,!0);if(s)return{decorations:s,match:e,dispose(){(0,i.dispose)(s)}}}clearHighlightDecorations(){(0,i.dispose)(this._highlightDecorations),this._highlightDecorations=[],this._highlightedLines.clear()}_storeDecoration(e,t){this._highlightedLines.add(e.marker.line),this._highlightDecorations.push({decoration:e,match:t,dispose(){e.dispose()}})}_applyStyles(e,t,s){e.classList.contains("xterm-find-result-decoration")||(e.classList.add("xterm-find-result-decoration"),t&&(e.style.outline=`1px solid ${t}`)),s&&e.classList.add("xterm-find-active-result-decoration")}_createResultDecorations(e,t,s){const r=[];let n=e.col,o=e.size,a=-this._terminal.buffer.active.baseY-this._terminal.buffer.active.cursorY+e.row;for(;o>0;){const e=Math.min(this._terminal.cols-n,o);r.push([a,n,e]),n=0,o-=e,a++}const h=[];for(const e of r){const r=this._terminal.registerMarker(e[0]),n=this._terminal.registerDecoration({marker:r,x:e[1],width:e[2],layer:s?"top":"bottom",backgroundColor:s?t.activeMatchBackground:t.matchBackground,overviewRulerOptions:this._highlightedLines.has(r.line)?void 0:{color:s?t.activeMatchColorOverviewRuler:t.matchOverviewRuler,position:"center"}});if(n){const e=[];e.push(r),e.push(n.onRender(e=>this._applyStyles(e,s?t.activeMatchBorder:t.matchBorder,!1))),e.push(n.onDispose(()=>(0,i.dispose)(e))),h.push(n)}}return 0===h.length?void 0:h}}t.DecorationManager=r},615(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.SearchEngine=void 0,t.SearchEngine=class{constructor(e,t){this._terminal=e,this._lineCache=t}find(e,t,s,i){if(!e||0===e.length)return void this._terminal.clearSelection();if(s>=this._terminal.cols)throw new Error(`Invalid col: ${s} to search in terminal of ${this._terminal.cols} cols`);this._lineCache.initLinesCache();const r={startRow:t,startCol:s};let n=this._findInLine(e,r,i);if(!n)for(let s=t+1;s=0&&(a.startRow=s,h=this._findInLine(e,a,t,o),!h);s--);}if(!h&&r!==this._terminal.buffer.active.baseY+this._terminal.rows-1)for(let s=this._terminal.buffer.active.baseY+this._terminal.rows-1;s>=r&&(a.startRow=s,h=this._findInLine(e,a,t,o),!h);s--);return h}_isWholeWord(e,t,s){return(0===e||" ~!@#$%^&*()+`-=[]{}|\\;:\"',./<>?".includes(t[e-1]))&&(e+s.length===t.length||" ~!@#$%^&*()+`-=[]{}|\\;:\"',./<>?".includes(t[e+s.length]))}_isRowCoveredByLineStart(e,t){return!t?.regex&&!t?.wholeWord&&!0===this._terminal.buffer.active.getLine(e)?.isWrapped}_findInLine(e,t,s={},i=!1){for(;this._terminal.buffer.active.getLine(t.startRow)?.isWrapped;){if(t.startCol+=this._terminal.cols,i)return;t.startRow--}const r=t.startRow,n=t.startCol;let o=this._lineCache.getLineFromCache(r);o||(o=this._lineCache.translateBufferLineToStringWithWrap(r,!0),this._lineCache.setLineInCache(r,o));const[a,h]=o,l=this._bufferColsToStringOffset(r,n);let c=e,d=a;s.regex||(c=s.caseSensitive?e:e.toLowerCase(),d=s.caseSensitive?a:a.toLowerCase());let _=-1;if(s.regex){const t=RegExp(c,s.caseSensitive?"g":"gi");let r;if(i)for(;r=t.exec(d.slice(0,l));)_=t.lastIndex-r[0].length,e=r[0],t.lastIndex-=e.length-1;else r=t.exec(d.slice(l)),r&&r[0].length>0&&(_=l+(t.lastIndex-r[0].length),e=r[0])}else i?l-c.length>=0&&(_=d.lastIndexOf(c,l-c.length)):_=d.indexOf(c,l);if(_>=0){if(s.wholeWord&&!this._isWholeWord(_,d,e))return;let t=0;for(;t=h[t+1];)t++;let i=t;for(;i=h[i+1];)i++;const n=_-h[t],o=_+e.length-h[i],a=this._stringLengthToBufferSize(r+t,n);return{term:e,col:a,row:r+t,size:this._stringLengthToBufferSize(r+i,o)-a+this._terminal.cols*(i-t)}}}_stringLengthToBufferSize(e,t){const s=this._terminal.buffer.active.getLine(e);if(!s)return 0;for(let e=0;e1&&(t-=r.length-1);const n=s.getCell(e+1);n&&0===n.getWidth()&&t++}return t}_bufferColsToStringOffset(e,t){let s=e,i=0,r=this._terminal.buffer.active.getLine(s);for(;t>0&&r;){for(let e=0;ethis._destroyLinesCache()))}initLinesCache(){this._linesCache||(this._linesCache=new Array(this._terminal.buffer.active.length),this._linesCacheDisposables.value=(0,i.combinedDisposable)(this._terminal.onLineFeed(()=>this._destroyLinesCache()),this._terminal.onCursorMove(()=>this._destroyLinesCache()),this._terminal.onResize(()=>this._destroyLinesCache()))),this._lastAccessTimestamp=Date.now(),this._linesCacheTimeout.value||this._scheduleLinesCacheTimeout(15e3)}_destroyLinesCache(){this._linesCache=void 0,this._lastAccessTimestamp=0,this._linesCacheDisposables.clear(),this._linesCacheTimeout.clear()}_scheduleLinesCacheTimeout(e){this._linesCacheTimeout.value=(0,r.disposableTimeout)(()=>{if(!this._linesCache)return;const e=Date.now()-this._lastAccessTimestamp;e>=15e3?this._destroyLinesCache():this._scheduleLinesCacheTimeout(15e3-e)},e)}getLineFromCache(e){return this._linesCache?.[e]}setLineInCache(e,t){this._linesCache&&(this._linesCache[e]=t)}translateBufferLineToStringWithWrap(e,t){const s=[],i=[0];let r=this._terminal.buffer.active.getLine(e);for(;r;){const n=this._terminal.buffer.active.getLine(e+1),o=!!n&&n.isWrapped;let a=r.translateToString(!o&&t);if(o&&n){const e=r.getCell(r.length-1);e&&0===e.getCode()&&1===e.getWidth()&&2===n.getCell(0)?.getWidth()&&(a=a.slice(0,-1))}if(s.push(a),!o)break;i.push(i[i.length-1]+a.length),e++,r=n}return[s.join(""),i]}}t.SearchLineCache=n},438(e,t,s){Object.defineProperty(t,"__esModule",{value:!0}),t.SearchResultTracker=void 0;const i=s(414),r=s(426);class n extends r.Disposable{constructor(){super(...arguments),this._searchResults=[],this._onDidChangeResults=this._register(new i.Emitter)}get onDidChangeResults(){return this._onDidChangeResults.event}get searchResults(){return this._searchResults}get selectedDecoration(){return this._selectedDecoration}set selectedDecoration(e){this._selectedDecoration=e}updateResults(e,t){this._searchResults=e.slice(0,t)}clearResults(){this._searchResults=[]}clearSelectedDecoration(){this._selectedDecoration&&(this._selectedDecoration.dispose(),this._selectedDecoration=void 0)}findResultIndex(e){for(let t=0;t0)}didOptionsChange(e){return!this._lastSearchOptions||!!e&&(this._lastSearchOptions.caseSensitive!==e.caseSensitive||this._lastSearchOptions.regex!==e.regex||this._lastSearchOptions.wholeWord!==e.wholeWord)}shouldUpdateHighlighting(e,t){return!!t?.decorations&&(void 0===this._cachedSearchTerm||e!==this._cachedSearchTerm||this.didOptionsChange(t))}clearCachedTerm(){this._cachedSearchTerm=void 0}reset(){this._cachedSearchTerm=void 0,this._lastSearchOptions=void 0}}}},t={};function s(i){var r=t[i];if(void 0!==r)return r.exports;var n=t[i]={exports:{}};return e[i](n,n.exports,s),n.exports}var i={};return(()=>{var e=i;Object.defineProperty(e,"__esModule",{value:!0}),e.SearchAddon=void 0;const t=s(414),r=s(426),n=s(578),o=s(149),a=s(772),h=s(615),l=s(864),c=s(438);class d extends r.Disposable{get onDidChangeResults(){return this._resultTracker.onDidChangeResults}constructor(e){super(),this._highlightTimeout=this._register(new r.MutableDisposable),this._lineCache=this._register(new r.MutableDisposable),this._state=new a.SearchState,this._resultTracker=this._register(new c.SearchResultTracker),this._onAfterSearch=this._register(new t.Emitter),this.onAfterSearch=this._onAfterSearch.event,this._onBeforeSearch=this._register(new t.Emitter),this.onBeforeSearch=this._onBeforeSearch.event,this._highlightLimit=e?.highlightLimit??1e3}activate(e){this._terminal=e,this._lineCache.value=new o.SearchLineCache(e),this._engine=new h.SearchEngine(e,this._lineCache.value),this._decorationManager=new l.DecorationManager(e),this._register(this._terminal.onWriteParsed(()=>this._updateMatches())),this._register(this._terminal.onResize(()=>this._updateMatches())),this._register((0,r.toDisposable)(()=>this.clearDecorations()))}_updateMatches(){this._highlightTimeout.clear(),this._state.cachedSearchTerm&&this._state.lastSearchOptions?.decorations&&(this._highlightTimeout.value=(0,n.disposableTimeout)(()=>{const e=this._state.cachedSearchTerm;this._state.clearCachedTerm(),this.findPrevious(e,{...this._state.lastSearchOptions,incremental:!0},{noScroll:!0})},200))}clearDecorations(e){this._resultTracker.clearSelectedDecoration(),this._decorationManager?.clearHighlightDecorations(),this._resultTracker.clearResults(),e||this._state.clearCachedTerm()}clearActiveDecoration(){this._resultTracker.clearSelectedDecoration()}findNext(e,t,s){if(!this._terminal||!this._engine)throw new Error("Cannot use addon until it has been loaded");this._onBeforeSearch.fire(),this._state.lastSearchOptions=t,this._state.shouldUpdateHighlighting(e,t)&&this._highlightAllMatches(e,t);const i=this._findNextAndSelect(e,t,s);return this._fireResults(t),this._state.cachedSearchTerm=e,this._onAfterSearch.fire(),i}_highlightAllMatches(e,t){if(!this._terminal||!this._engine||!this._decorationManager)throw new Error("Cannot use addon until it has been loaded");if(!this._state.isValidSearchTerm(e))return void this.clearDecorations();this.clearDecorations(!0);const s=[];let i,r=this._engine.find(e,0,0,t);for(;r&&(i?.row!==r.row||i?.col!==r.col)&&!(s.length>=this._highlightLimit);){i=r,s.push(i);const n=this._terminal.cols;let o=i.col+i.size,a=i.row;o>=n&&(a+=Math.floor(o/n),o%=n),r=this._engine.find(e,a,o,t)}this._resultTracker.updateResults(s,this._highlightLimit),t.decorations&&this._decorationManager.createHighlightDecorations(s,t.decorations)}_findNextAndSelect(e,t,s){if(!this._terminal||!this._engine)return!1;if(!this._state.isValidSearchTerm(e))return this._terminal.clearSelection(),this.clearDecorations(),!1;const i=this._engine.findNextWithSelection(e,t,this._state.cachedSearchTerm);return this._selectResult(i,t?.decorations,s?.noScroll)}findPrevious(e,t,s){if(!this._terminal||!this._engine)throw new Error("Cannot use addon until it has been loaded");this._onBeforeSearch.fire(),this._state.lastSearchOptions=t,this._state.shouldUpdateHighlighting(e,t)&&this._highlightAllMatches(e,t);const i=this._findPreviousAndSelect(e,t,s);return this._fireResults(t),this._state.cachedSearchTerm=e,this._onAfterSearch.fire(),i}_fireResults(e){this._resultTracker.fireResultsChanged(!!e?.decorations)}_findPreviousAndSelect(e,t,s){if(!this._terminal||!this._engine)return!1;if(!this._state.isValidSearchTerm(e))return this._terminal.clearSelection(),this.clearDecorations(),!1;const i=this._engine.findPreviousWithSelection(e,t,this._state.cachedSearchTerm);return this._selectResult(i,t?.decorations,s?.noScroll)}_selectResult(e,t,s){if(!this._terminal||!this._decorationManager)return!1;if(this._resultTracker.clearSelectedDecoration(),!e)return this._terminal.clearSelection(),!1;if(this._terminal.select(e.col,e.row,e.size),t){const s=this._decorationManager.createActiveDecoration(e,t);s&&(this._resultTracker.selectedDecoration=s)}if(!s&&(e.row>=this._terminal.buffer.active.viewportY+this._terminal.rows||e.row {\nreturn ","/**\n * Copyright (c) 2026 The xterm.js authors. All rights reserved.\n * @license MIT\n *\n * Minimal async helpers for xterm.js core.\n */\n\nimport { DisposableStore, IDisposable, toDisposable } from './Lifecycle';\n\nexport function timeout(millis: number): Promise {\n return new Promise(resolve => setTimeout(resolve, millis));\n}\n\n/**\n * Creates a timeout that can be disposed using its returned value.\n * @param handler The timeout handler.\n * @param timeout An optional timeout in milliseconds.\n * @param store An optional {@link DisposableStore} that will have the timeout disposable managed\n * automatically.\n */\nexport function disposableTimeout(handler: () => void, timeout = 0, store?: DisposableStore): IDisposable {\n const timer = setTimeout(() => {\n handler();\n if (store) {\n disposable.dispose();\n }\n }, timeout);\n const disposable = toDisposable(() => {\n clearTimeout(timer);\n });\n store?.add(disposable);\n return disposable;\n}\n\nexport class TimeoutTimer implements IDisposable {\n private _token: any = -1;\n private _isDisposed = false;\n\n public dispose(): void {\n this.cancel();\n this._isDisposed = true;\n }\n\n public cancel(): void {\n if (this._token !== -1) {\n clearTimeout(this._token);\n this._token = -1;\n }\n }\n\n public cancelAndSet(runner: () => void, timeout: number): void {\n if (this._isDisposed) {\n throw new Error('Calling cancelAndSet on a disposed TimeoutTimer');\n }\n this.cancel();\n this._token = setTimeout(() => {\n this._token = -1;\n runner();\n }, timeout);\n }\n\n public setIfNotSet(runner: () => void, timeout: number): void {\n if (this._isDisposed) {\n throw new Error('Calling setIfNotSet on a disposed TimeoutTimer');\n }\n if (this._token !== -1) {\n return;\n }\n this._token = setTimeout(() => {\n this._token = -1;\n runner();\n }, timeout);\n }\n}\n\n/**\n * Schedules a single runner on the microtask queue. Unlike {@link TimeoutTimer}, a scheduled\n * microtask cannot be unqueued; {@link cancel} prevents the runner from executing if it has not\n * run yet.\n */\nexport class MicrotaskTimer implements IDisposable {\n private _isScheduled = false;\n private _isDisposed = false;\n\n public dispose(): void {\n this.cancel();\n this._isDisposed = true;\n }\n\n public cancel(): void {\n this._isScheduled = false;\n }\n\n public set(runner: () => void): void {\n if (this._isDisposed) {\n throw new Error('Calling set on a disposed MicrotaskTimer');\n }\n if (this._isScheduled) {\n return;\n }\n this._isScheduled = true;\n queueMicrotask(() => {\n if (!this._isScheduled) {\n return;\n }\n this._isScheduled = false;\n runner();\n });\n }\n}\n\nexport class IntervalTimer implements IDisposable {\n private _disposable: IDisposable | undefined;\n private _isDisposed = false;\n\n public cancel(): void {\n this._disposable?.dispose();\n this._disposable = undefined;\n }\n\n public cancelAndSet(runner: () => void, interval: number, context: Window | typeof globalThis = globalThis): void {\n if (this._isDisposed) {\n throw new Error('Calling cancelAndSet on a disposed IntervalTimer');\n }\n this.cancel();\n const handle = context.setInterval(() => {\n runner();\n }, interval);\n this._disposable = {\n dispose: () => {\n context.clearInterval(handle as any);\n this._disposable = undefined;\n }\n };\n }\n\n public dispose(): void {\n this.cancel();\n this._isDisposed = true;\n }\n}\n","/**\n * Copyright (c) 2024-2026 The xterm.js authors. All rights reserved.\n * @license MIT\n *\n * Minimal event utilities for xterm.js core.\n * Simplified from VS Code's event.ts - no leak detection/profiling.\n */\n\nimport { IDisposable, DisposableStore, toDisposable } from './Lifecycle';\n\nexport interface IEvent {\n (listener: (e: T) => any, thisArgs?: any, disposables?: IDisposable[] | DisposableStore): IDisposable;\n}\n\nexport class Emitter {\n private _listeners: { fn: (e: T) => any, thisArgs: any }[] = [];\n private _disposed = false;\n private _event: IEvent | undefined;\n\n public get event(): IEvent {\n if (this._event) {\n return this._event;\n }\n this._event = (listener: (e: T) => any, thisArgs?: any, disposables?: IDisposable[] | DisposableStore) => {\n if (this._disposed) {\n return toDisposable(() => {});\n }\n\n const entry = { fn: listener, thisArgs };\n this._listeners = this._listeners.slice();\n this._listeners.push(entry);\n\n const result = toDisposable(() => {\n const idx = this._listeners.indexOf(entry);\n if (idx !== -1) {\n this._listeners = this._listeners.slice();\n this._listeners.splice(idx, 1);\n }\n });\n\n if (disposables) {\n if (Array.isArray(disposables)) {\n disposables.push(result);\n } else {\n disposables.add(result);\n }\n }\n\n return result;\n };\n return this._event;\n }\n\n public fire(event: T): void {\n if (this._disposed || !this._listeners.length) {\n return;\n }\n if (this._listeners.length === 1) {\n this._listeners[0].fn.call(this._listeners[0].thisArgs, event);\n return;\n }\n const listeners = this._listeners;\n for (let i = 0, len = listeners.length; i < len; ++i) {\n listeners[i].fn.call(listeners[i].thisArgs, event);\n }\n }\n\n public dispose(): void {\n if (this._disposed) {\n return;\n }\n this._disposed = true;\n this._listeners.length = 0;\n }\n}\n\nexport namespace EventUtils {\n export function forward(from: IEvent, to: Emitter): IDisposable {\n return from(e => to.fire(e));\n }\n\n export function map(event: IEvent, map: (i: I) => O): IEvent {\n return (listener: (e: O) => any, thisArgs?: any, disposables?: IDisposable[] | DisposableStore) => {\n return event(i => listener.call(thisArgs, map(i)), undefined, disposables);\n };\n }\n\n export function any(...events: IEvent[]): IEvent;\n export function any(...events: IEvent[]): IEvent;\n export function any(...events: IEvent[]): IEvent {\n return (listener: (e: T) => any, thisArgs?: any, disposables?: IDisposable[] | DisposableStore) => {\n const store = new DisposableStore();\n for (const event of events) {\n store.add(event(e => listener.call(thisArgs, e)));\n }\n if (disposables) {\n if (Array.isArray(disposables)) {\n disposables.push(store);\n } else {\n disposables.add(store);\n }\n }\n return store;\n };\n }\n\n export function runAndSubscribe(event: IEvent, handler: (e: T) => void, initial: T): IDisposable;\n export function runAndSubscribe(event: IEvent, handler: (e: T | undefined) => void): IDisposable;\n export function runAndSubscribe(event: IEvent, handler: (e: T | undefined) => void, initial?: T): IDisposable {\n handler(initial);\n return event(e => handler(e));\n }\n}\n","/**\n * Copyright (c) 2024-2026 The xterm.js authors. All rights reserved.\n * @license MIT\n *\n * Minimal lifecycle utilities for xterm.js core.\n * Simplified from VS Code's lifecycle.ts - no tracking/leak detection.\n */\n\nexport interface IDisposable {\n dispose(): void;\n}\n\nexport function toDisposable(fn: () => void): IDisposable {\n return { dispose: fn };\n}\n\nexport function dispose(disposable: T): T;\nexport function dispose(disposable: T | undefined): T | undefined;\nexport function dispose(disposables: T[]): T[];\nexport function dispose(arg: T | T[] | undefined): T | T[] | undefined {\n if (!arg) {\n return arg;\n }\n if (Array.isArray(arg)) {\n for (const d of arg) {\n d.dispose();\n }\n return [];\n }\n arg.dispose();\n return arg;\n}\n\nexport function combinedDisposable(...disposables: IDisposable[]): IDisposable {\n return toDisposable(() => dispose(disposables));\n}\n\nexport class DisposableStore implements IDisposable {\n private readonly _disposables = new Set();\n private _isDisposed = false;\n\n public get isDisposed(): boolean {\n return this._isDisposed;\n }\n\n public add(o: T): T {\n if (this._isDisposed) {\n o.dispose();\n } else {\n this._disposables.add(o);\n }\n return o;\n }\n\n public dispose(): void {\n if (this._isDisposed) {\n return;\n }\n this._isDisposed = true;\n for (const d of this._disposables) {\n d.dispose();\n }\n this._disposables.clear();\n }\n\n public clear(): void {\n for (const d of this._disposables) {\n d.dispose();\n }\n this._disposables.clear();\n }\n}\n\nexport abstract class Disposable implements IDisposable {\n public static readonly None: IDisposable = Object.freeze({ dispose() { } });\n\n protected readonly _store = new DisposableStore();\n\n public dispose(): void {\n this._store.dispose();\n }\n\n protected _register(o: T): T {\n return this._store.add(o);\n }\n}\n\nexport class MutableDisposable implements IDisposable {\n private _value: T | undefined;\n private _isDisposed = false;\n\n public get value(): T | undefined {\n return this._isDisposed ? undefined : this._value;\n }\n\n public set value(value: T | undefined) {\n if (this._isDisposed || value === this._value) {\n return;\n }\n this._value?.dispose();\n this._value = value;\n }\n\n public clear(): void {\n this.value = undefined;\n }\n\n public dispose(): void {\n this._isDisposed = true;\n this._value?.dispose();\n this._value = undefined;\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport type { Terminal, IDisposable, IDecoration } from '@xterm/xterm';\nimport type { ISearchDecorationOptions } from '@xterm/addon-search';\nimport { dispose, Disposable, toDisposable } from 'common/Lifecycle';\nimport type { ISearchResult } from './SearchEngine';\n\n/**\n * Interface for managing a highlight decoration.\n */\ninterface IHighlight extends IDisposable {\n decoration: IDecoration;\n match: ISearchResult;\n}\n\n/**\n * Interface for managing multiple decorations for a single match.\n */\ninterface IMultiHighlight extends IDisposable {\n decorations: IDecoration[];\n match: ISearchResult;\n}\n\n/**\n * Manages visual decorations for search results including highlighting and active selection\n * indicators. This class handles the creation, styling, and disposal of search-related decorations.\n */\nexport class DecorationManager extends Disposable {\n private _highlightDecorations: IHighlight[] = [];\n private _highlightedLines: Set = new Set();\n\n constructor(private readonly _terminal: Terminal) {\n super();\n this._register(toDisposable(() => this.clearHighlightDecorations()));\n }\n\n /**\n * Creates decorations for all provided search results.\n * @param results The search results to create decorations for.\n * @param options The decoration options.\n */\n public createHighlightDecorations(results: ISearchResult[], options: ISearchDecorationOptions): void {\n this.clearHighlightDecorations();\n\n for (const match of results) {\n const decorations = this._createResultDecorations(match, options, false);\n if (decorations) {\n for (const decoration of decorations) {\n this._storeDecoration(decoration, match);\n }\n }\n }\n }\n\n /**\n * Creates decorations for the currently active search result.\n * @param result The active search result.\n * @param options The decoration options.\n * @returns The multi-highlight decoration or undefined if creation failed.\n */\n public createActiveDecoration(result: ISearchResult, options: ISearchDecorationOptions): IMultiHighlight | undefined {\n const decorations = this._createResultDecorations(result, options, true);\n if (decorations) {\n return { decorations, match: result, dispose() { dispose(decorations); } };\n }\n return undefined;\n }\n\n /**\n * Clears all highlight decorations.\n */\n public clearHighlightDecorations(): void {\n dispose(this._highlightDecorations);\n this._highlightDecorations = [];\n this._highlightedLines.clear();\n }\n\n /**\n * Stores a decoration and tracks it for management.\n * @param decoration The decoration to store.\n * @param match The search result this decoration represents.\n */\n private _storeDecoration(decoration: IDecoration, match: ISearchResult): void {\n this._highlightedLines.add(decoration.marker.line);\n this._highlightDecorations.push({ decoration, match, dispose() { decoration.dispose(); } });\n }\n\n /**\n * Applies styles to the decoration when it is rendered.\n * @param element The decoration's element.\n * @param borderColor The border color to apply.\n * @param isActiveResult Whether the element is part of the active search result.\n */\n private _applyStyles(element: HTMLElement, borderColor: string | undefined, isActiveResult: boolean): void {\n if (!element.classList.contains('xterm-find-result-decoration')) {\n element.classList.add('xterm-find-result-decoration');\n if (borderColor) {\n element.style.outline = `1px solid ${borderColor}`;\n }\n }\n if (isActiveResult) {\n element.classList.add('xterm-find-active-result-decoration');\n }\n }\n\n /**\n * Creates a decoration for the result and applies styles\n * @param result the search result for which to create the decoration\n * @param options the options for the decoration\n * @param isActiveResult whether this is the currently active result\n * @returns the decorations or undefined if the marker has already been disposed of\n */\n private _createResultDecorations(result: ISearchResult, options: ISearchDecorationOptions, isActiveResult: boolean): IDecoration[] | undefined {\n // Gather decoration ranges for this match as it could wrap\n const decorationRanges: [number, number, number][] = [];\n let currentCol = result.col;\n let remainingSize = result.size;\n let markerOffset = -this._terminal.buffer.active.baseY - this._terminal.buffer.active.cursorY + result.row;\n while (remainingSize > 0) {\n const amountThisRow = Math.min(this._terminal.cols - currentCol, remainingSize);\n decorationRanges.push([markerOffset, currentCol, amountThisRow]);\n currentCol = 0;\n remainingSize -= amountThisRow;\n markerOffset++;\n }\n\n // Create the decorations\n const decorations: IDecoration[] = [];\n for (const range of decorationRanges) {\n const marker = this._terminal.registerMarker(range[0]);\n const decoration = this._terminal.registerDecoration({\n marker,\n x: range[1],\n width: range[2],\n layer: isActiveResult ? 'top' : 'bottom',\n backgroundColor: isActiveResult ? options.activeMatchBackground : options.matchBackground,\n overviewRulerOptions: this._highlightedLines.has(marker.line) ? undefined : {\n color: isActiveResult ? options.activeMatchColorOverviewRuler : options.matchOverviewRuler,\n position: 'center'\n }\n });\n if (decoration) {\n const disposables: IDisposable[] = [];\n disposables.push(marker);\n disposables.push(decoration.onRender((e) => this._applyStyles(e, isActiveResult ? options.activeMatchBorder : options.matchBorder, false)));\n disposables.push(decoration.onDispose(() => dispose(disposables)));\n decorations.push(decoration);\n }\n }\n\n return decorations.length === 0 ? undefined : decorations;\n }\n}\n\n\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport type { Terminal } from '@xterm/xterm';\nimport type { ISearchOptions } from '@xterm/addon-search';\nimport type { SearchLineCache } from './SearchLineCache';\n\n/**\n * Represents the position to start a search from.\n */\ninterface ISearchPosition {\n startCol: number;\n startRow: number;\n}\n\n/**\n * Represents a search result with its position and content.\n */\nexport interface ISearchResult {\n term: string;\n col: number;\n row: number;\n size: number;\n}\n\n/**\n * Configuration constants for the search engine functionality.\n */\nconst enum Constants {\n /**\n * Characters that are considered non-word characters for search boundary detection. These\n * characters are used to determine word boundaries when performing whole-word searches. Includes\n * common punctuation, symbols, and whitespace characters.\n */\n NON_WORD_CHARACTERS = ' ~!@#$%^&*()+`-=[]{}|\\\\;:\"\\',./<>?'\n}\n\n/**\n * Core search engine that handles finding text within terminal content.\n * This class is responsible for the actual search algorithms and position calculations.\n */\nexport class SearchEngine {\n constructor(\n private readonly _terminal: Terminal,\n private readonly _lineCache: SearchLineCache\n ) {}\n\n /**\n * Find the first occurrence of a term starting from a specific position.\n * @param term The search term.\n * @param startRow The row to start searching from.\n * @param startCol The column to start searching from.\n * @param searchOptions Search options.\n * @returns The search result if found, undefined otherwise.\n */\n public find(term: string, startRow: number, startCol: number, searchOptions?: ISearchOptions): ISearchResult | undefined {\n if (!term || term.length === 0) {\n this._terminal.clearSelection();\n return undefined;\n }\n if (startCol >= this._terminal.cols) {\n throw new Error(`Invalid col: ${startCol} to search in terminal of ${this._terminal.cols} cols`);\n }\n\n this._lineCache.initLinesCache();\n\n const searchPosition: ISearchPosition = {\n startRow,\n startCol\n };\n\n // Search startRow\n let result = this._findInLine(term, searchPosition, searchOptions);\n // Search from startRow + 1 to end\n if (!result) {\n for (let y = startRow + 1; y < this._terminal.buffer.active.baseY + this._terminal.rows; y++) {\n searchPosition.startRow = y;\n searchPosition.startCol = 0;\n result = this._findInLine(term, searchPosition, searchOptions);\n if (result) {\n break;\n }\n }\n }\n return result;\n }\n\n /**\n * Find the next occurrence of a term with wrapping and selection management.\n * @param term The search term.\n * @param searchOptions Search options.\n * @param cachedSearchTerm The cached search term to determine incremental behavior.\n * @returns The search result if found, undefined otherwise.\n */\n public findNextWithSelection(term: string, searchOptions?: ISearchOptions, cachedSearchTerm?: string): ISearchResult | undefined {\n if (!term || term.length === 0) {\n this._terminal.clearSelection();\n return undefined;\n }\n\n const prevSelectedPos = this._terminal.getSelectionPosition();\n this._terminal.clearSelection();\n\n let startCol = 0;\n let startRow = 0;\n if (prevSelectedPos) {\n if (cachedSearchTerm === term) {\n startCol = prevSelectedPos.end.x;\n startRow = prevSelectedPos.end.y;\n } else {\n startCol = prevSelectedPos.start.x;\n startRow = prevSelectedPos.start.y;\n }\n }\n\n this._lineCache.initLinesCache();\n\n const searchPosition: ISearchPosition = {\n startRow,\n startCol\n };\n\n // Search startRow\n let result = this._findInLine(term, searchPosition, searchOptions);\n // Search from startRow + 1 to end\n if (!result) {\n for (let y = startRow + 1; y < this._terminal.buffer.active.baseY + this._terminal.rows; y++) {\n searchPosition.startRow = y;\n searchPosition.startCol = 0;\n result = this._findInLine(term, searchPosition, searchOptions);\n if (result) {\n break;\n }\n }\n }\n // If we hit the bottom and didn't search from the very top wrap back up\n if (!result && startRow !== 0) {\n for (let y = 0; y < startRow; y++) {\n searchPosition.startRow = y;\n searchPosition.startCol = 0;\n result = this._findInLine(term, searchPosition, searchOptions);\n if (result) {\n break;\n }\n }\n }\n\n // If there is only one result, wrap back and return selection if it exists.\n if (!result && prevSelectedPos) {\n searchPosition.startRow = prevSelectedPos.start.y;\n searchPosition.startCol = 0;\n result = this._findInLine(term, searchPosition, searchOptions);\n }\n\n return result;\n }\n\n /**\n * Find the previous occurrence of a term with wrapping and selection management.\n * @param term The search term.\n * @param searchOptions Search options.\n * @param cachedSearchTerm The cached search term to determine if expansion should occur.\n * @returns The search result if found, undefined otherwise.\n */\n public findPreviousWithSelection(term: string, searchOptions?: ISearchOptions, cachedSearchTerm?: string): ISearchResult | undefined {\n if (!term || term.length === 0) {\n this._terminal.clearSelection();\n return undefined;\n }\n\n const prevSelectedPos = this._terminal.getSelectionPosition();\n this._terminal.clearSelection();\n\n let startRow = this._terminal.buffer.active.baseY + this._terminal.rows - 1;\n const startCol = this._terminal.cols;\n const isReverseSearch = true;\n\n this._lineCache.initLinesCache();\n const searchPosition: ISearchPosition = {\n startRow,\n startCol\n };\n\n let result: ISearchResult | undefined;\n if (prevSelectedPos) {\n searchPosition.startRow = startRow = prevSelectedPos.start.y;\n searchPosition.startCol = prevSelectedPos.start.x;\n if (cachedSearchTerm !== term) {\n // Try to expand selection to right first.\n result = this._findInLine(term, searchPosition, searchOptions, false);\n if (!result) {\n // If selection was not able to be expanded to the right, then try reverse search\n searchPosition.startRow = startRow = prevSelectedPos.end.y;\n searchPosition.startCol = prevSelectedPos.end.x;\n }\n }\n }\n\n result ??= this._findInLine(term, searchPosition, searchOptions, isReverseSearch);\n\n // Search from startRow - 1 to top\n if (!result) {\n searchPosition.startCol = Math.max(searchPosition.startCol, this._terminal.cols);\n for (let y = startRow - 1; y >= 0; y--) {\n searchPosition.startRow = y;\n result = this._findInLine(term, searchPosition, searchOptions, isReverseSearch);\n if (result) {\n break;\n }\n }\n }\n // If we hit the top and didn't search from the very bottom wrap back down\n if (!result && startRow !== (this._terminal.buffer.active.baseY + this._terminal.rows - 1)) {\n for (let y = (this._terminal.buffer.active.baseY + this._terminal.rows - 1); y >= startRow; y--) {\n searchPosition.startRow = y;\n result = this._findInLine(term, searchPosition, searchOptions, isReverseSearch);\n if (result) {\n break;\n }\n }\n }\n\n return result;\n }\n\n /**\n * A found substring is a whole word if it doesn't have an alphanumeric character directly\n * adjacent to it.\n * @param searchIndex starting index of the potential whole word substring\n * @param line entire string in which the potential whole word was found\n * @param term the substring that starts at searchIndex\n */\n private _isWholeWord(searchIndex: number, line: string, term: string): boolean {\n return ((searchIndex === 0) || (Constants.NON_WORD_CHARACTERS.includes(line[searchIndex - 1]))) &&\n (((searchIndex + term.length) === line.length) || (Constants.NON_WORD_CHARACTERS.includes(line[searchIndex + term.length])));\n }\n\n /**\n * Searches a line for a search term. Takes the provided terminal line and searches the text line,\n * which may contain subsequent terminal lines if the text is wrapped. If the provided line number\n * is part of a wrapped text line that started on an earlier line then it is skipped since it will\n * be properly searched when the terminal line that the text starts on is searched.\n * @param term The search term.\n * @param searchPosition The position to start the search.\n * @param searchOptions Search options.\n * @param isReverseSearch Whether the search should start from the right side of the terminal and\n * search to the left.\n * @returns The search result if it was found.\n */\n private _findInLine(term: string, searchPosition: ISearchPosition, searchOptions: ISearchOptions = {}, isReverseSearch: boolean = false): ISearchResult | undefined {\n const row = searchPosition.startRow;\n const col = searchPosition.startCol;\n\n // Ignore wrapped lines, only consider on unwrapped line (first row of command string).\n const firstLine = this._terminal.buffer.active.getLine(row);\n if (firstLine?.isWrapped) {\n if (isReverseSearch) {\n searchPosition.startCol += this._terminal.cols;\n return;\n }\n\n // This will iterate until we find the line start.\n // When we find it, we will search using the calculated start column.\n searchPosition.startRow--;\n searchPosition.startCol += this._terminal.cols;\n return this._findInLine(term, searchPosition, searchOptions);\n }\n let cache = this._lineCache.getLineFromCache(row);\n if (!cache) {\n cache = this._lineCache.translateBufferLineToStringWithWrap(row, true);\n this._lineCache.setLineInCache(row, cache);\n }\n const [stringLine, offsets] = cache;\n\n const offset = this._bufferColsToStringOffset(row, col);\n let searchTerm = term;\n let searchStringLine = stringLine;\n if (!searchOptions.regex) {\n searchTerm = searchOptions.caseSensitive ? term : term.toLowerCase();\n searchStringLine = searchOptions.caseSensitive ? stringLine : stringLine.toLowerCase();\n }\n\n let resultIndex = -1;\n if (searchOptions.regex) {\n const searchRegex = RegExp(searchTerm, searchOptions.caseSensitive ? 'g' : 'gi');\n let foundTerm: RegExpExecArray | null;\n if (isReverseSearch) {\n // This loop will get the resultIndex of the _last_ regex match in the range 0..offset\n while (foundTerm = searchRegex.exec(searchStringLine.slice(0, offset))) {\n resultIndex = searchRegex.lastIndex - foundTerm[0].length;\n term = foundTerm[0];\n searchRegex.lastIndex -= (term.length - 1);\n }\n } else {\n foundTerm = searchRegex.exec(searchStringLine.slice(offset));\n if (foundTerm && foundTerm[0].length > 0) {\n resultIndex = offset + (searchRegex.lastIndex - foundTerm[0].length);\n term = foundTerm[0];\n }\n }\n } else {\n if (isReverseSearch) {\n if (offset - searchTerm.length >= 0) {\n resultIndex = searchStringLine.lastIndexOf(searchTerm, offset - searchTerm.length);\n }\n } else {\n resultIndex = searchStringLine.indexOf(searchTerm, offset);\n }\n }\n\n if (resultIndex >= 0) {\n if (searchOptions.wholeWord && !this._isWholeWord(resultIndex, searchStringLine, term)) {\n return;\n }\n\n // Adjust the row number and search index if needed since a \"line\" of text can span multiple\n // rows\n let startRowOffset = 0;\n while (startRowOffset < offsets.length - 1 && resultIndex >= offsets[startRowOffset + 1]) {\n startRowOffset++;\n }\n let endRowOffset = startRowOffset;\n while (endRowOffset < offsets.length - 1 && resultIndex + term.length >= offsets[endRowOffset + 1]) {\n endRowOffset++;\n }\n const startColOffset = resultIndex - offsets[startRowOffset];\n const endColOffset = resultIndex + term.length - offsets[endRowOffset];\n const startColIndex = this._stringLengthToBufferSize(row + startRowOffset, startColOffset);\n const endColIndex = this._stringLengthToBufferSize(row + endRowOffset, endColOffset);\n const size = endColIndex - startColIndex + this._terminal.cols * (endRowOffset - startRowOffset);\n\n return {\n term,\n col: startColIndex,\n row: row + startRowOffset,\n size\n };\n }\n }\n\n private _stringLengthToBufferSize(row: number, offset: number): number {\n const line = this._terminal.buffer.active.getLine(row);\n if (!line) {\n return 0;\n }\n for (let i = 0; i < offset; i++) {\n const cell = line.getCell(i);\n if (!cell) {\n break;\n }\n // Adjust the searchIndex to normalize emoji into single chars\n const char = cell.getChars();\n if (char.length > 1) {\n offset -= char.length - 1;\n }\n // Adjust the searchIndex for empty characters following wide unicode\n // chars (eg. CJK)\n const nextCell = line.getCell(i + 1);\n if (nextCell && nextCell.getWidth() === 0) {\n offset++;\n }\n }\n return offset;\n }\n\n private _bufferColsToStringOffset(startRow: number, cols: number): number {\n let lineIndex = startRow;\n let offset = 0;\n let line = this._terminal.buffer.active.getLine(lineIndex);\n while (cols > 0 && line) {\n for (let i = 0; i < cols && i < this._terminal.cols; i++) {\n const cell = line.getCell(i);\n if (!cell) {\n break;\n }\n if (cell.getWidth()) {\n // Treat null characters as whitespace to align with the translateToString API\n offset += cell.getCode() === 0 ? 1 : cell.getChars().length;\n }\n }\n lineIndex++;\n line = this._terminal.buffer.active.getLine(lineIndex);\n if (line && !line.isWrapped) {\n break;\n }\n cols -= this._terminal.cols;\n }\n return offset;\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport type { Terminal } from '@xterm/xterm';\nimport { combinedDisposable, Disposable, MutableDisposable, toDisposable } from 'common/Lifecycle';\nimport { disposableTimeout } from 'common/Async';\n\nexport type LineCacheEntry = [\n /**\n * The string representation of a line (as opposed to the buffer cell representation).\n */\n lineAsString: string,\n /**\n * The offsets where each line starts when the entry describes a wrapped line.\n */\n lineOffsets: number[]\n];\n\n/**\n * Configuration constants for the search line cache functionality.\n */\nconst enum Constants {\n /**\n * Time-to-live for cached search results in milliseconds. After this duration, cached search\n * results will be invalidated to ensure they remain consistent with terminal content changes.\n */\n LINES_CACHE_TIME_TO_LIVE = 15000\n}\n\nexport class SearchLineCache extends Disposable {\n /**\n * translateBufferLineToStringWithWrap is a fairly expensive call.\n * We memoize the calls into an array that has a time based ttl.\n * _linesCache is also invalidated when the terminal cursor moves.\n */\n private _linesCache: LineCacheEntry[] | undefined;\n private _linesCacheTimeout = this._register(new MutableDisposable());\n private _linesCacheDisposables = this._register(new MutableDisposable());\n // Track access to avoid recreating a timeout on every init call which occurs once per search\n // result (findNext/findPrevious -> _highlightAllMatches -> find loop).\n private _lastAccessTimestamp = 0;\n\n constructor(private readonly _terminal: Terminal) {\n super();\n this._register(toDisposable(() => this._destroyLinesCache()));\n }\n\n /**\n * Sets up a line cache with a ttl\n */\n public initLinesCache(): void {\n if (!this._linesCache) {\n this._linesCache = new Array(this._terminal.buffer.active.length);\n this._linesCacheDisposables.value = combinedDisposable(\n this._terminal.onLineFeed(() => this._destroyLinesCache()),\n this._terminal.onCursorMove(() => this._destroyLinesCache()),\n this._terminal.onResize(() => this._destroyLinesCache())\n );\n }\n\n this._lastAccessTimestamp = Date.now();\n if (!this._linesCacheTimeout.value) {\n this._scheduleLinesCacheTimeout(Constants.LINES_CACHE_TIME_TO_LIVE);\n }\n }\n\n private _destroyLinesCache(): void {\n this._linesCache = undefined;\n this._lastAccessTimestamp = 0;\n this._linesCacheDisposables.clear();\n this._linesCacheTimeout.clear();\n }\n\n private _scheduleLinesCacheTimeout(delay: number): void {\n this._linesCacheTimeout.value = disposableTimeout(() => {\n if (!this._linesCache) {\n return;\n }\n const now = Date.now();\n const elapsed = now - this._lastAccessTimestamp;\n if (elapsed >= Constants.LINES_CACHE_TIME_TO_LIVE) {\n this._destroyLinesCache();\n return;\n }\n this._scheduleLinesCacheTimeout(Constants.LINES_CACHE_TIME_TO_LIVE - elapsed);\n }, delay);\n }\n\n public getLineFromCache(row: number): LineCacheEntry | undefined {\n return this._linesCache?.[row];\n }\n\n public setLineInCache(row: number, entry: LineCacheEntry): void {\n if (this._linesCache) {\n this._linesCache[row] = entry;\n }\n }\n\n /**\n * Translates a buffer line to a string, including subsequent lines if they are wraps.\n * Wide characters will count as two columns in the resulting string. This\n * function is useful for getting the actual text underneath the raw selection\n * position.\n * @param lineIndex The index of the line being translated.\n * @param trimRight Whether to trim whitespace to the right.\n */\n public translateBufferLineToStringWithWrap(lineIndex: number, trimRight: boolean): LineCacheEntry {\n const strings = [];\n const lineOffsets = [0];\n let line = this._terminal.buffer.active.getLine(lineIndex);\n while (line) {\n const nextLine = this._terminal.buffer.active.getLine(lineIndex + 1);\n const lineWrapsToNext = nextLine ? nextLine.isWrapped : false;\n let string = line.translateToString(!lineWrapsToNext && trimRight);\n if (lineWrapsToNext && nextLine) {\n const lastCell = line.getCell(line.length - 1);\n const lastCellIsNull = lastCell && lastCell.getCode() === 0 && lastCell.getWidth() === 1;\n // a wide character wrapped to the next line\n if (lastCellIsNull && nextLine.getCell(0)?.getWidth() === 2) {\n string = string.slice(0, -1);\n }\n }\n strings.push(string);\n if (lineWrapsToNext) {\n lineOffsets.push(lineOffsets[lineOffsets.length - 1] + string.length);\n } else {\n break;\n }\n lineIndex++;\n line = nextLine;\n }\n return [strings.join(''), lineOffsets];\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport type { ISearchResultChangeEvent } from '@xterm/addon-search';\nimport type { IDisposable } from '@xterm/xterm';\nimport { Emitter, type IEvent } from 'common/Event';\nimport { Disposable } from 'common/Lifecycle';\nimport type { ISearchResult } from './SearchEngine';\n\n/**\n * Interface for managing a currently selected decoration.\n */\ninterface ISelectedDecoration extends IDisposable {\n match: ISearchResult;\n}\n\n/**\n * Tracks search results, manages result indexing, and fires events when results change.\n * This class provides centralized management of search result state and notifications.\n */\nexport class SearchResultTracker extends Disposable {\n private _searchResults: ISearchResult[] = [];\n private _selectedDecoration: ISelectedDecoration | undefined;\n\n private readonly _onDidChangeResults = this._register(new Emitter());\n public get onDidChangeResults(): IEvent { return this._onDidChangeResults.event; }\n\n /**\n * Gets the current search results.\n */\n public get searchResults(): ReadonlyArray {\n return this._searchResults;\n }\n\n /**\n * Gets the currently selected decoration.\n */\n public get selectedDecoration(): ISelectedDecoration | undefined {\n return this._selectedDecoration;\n }\n\n /**\n * Sets the currently selected decoration.\n */\n public set selectedDecoration(decoration: ISelectedDecoration | undefined) {\n this._selectedDecoration = decoration;\n }\n\n /**\n * Updates the search results with a new set of results.\n * @param results The new search results.\n * @param maxResults The maximum number of results to track.\n */\n public updateResults(results: ISearchResult[], maxResults: number): void {\n this._searchResults = results.slice(0, maxResults);\n }\n\n /**\n * Clears all search results.\n */\n public clearResults(): void {\n this._searchResults = [];\n }\n\n /**\n * Clears the selected decoration.\n */\n public clearSelectedDecoration(): void {\n if (this._selectedDecoration) {\n this._selectedDecoration.dispose();\n this._selectedDecoration = undefined;\n }\n }\n\n /**\n * Finds the index of a result in the current results array.\n * @param result The result to find.\n * @returns The index of the result, or -1 if not found.\n */\n public findResultIndex(result: ISearchResult): number {\n for (let i = 0; i < this._searchResults.length; i++) {\n const match = this._searchResults[i];\n if (match.row === result.row && match.col === result.col && match.size === result.size) {\n return i;\n }\n }\n return -1;\n }\n\n /**\n * Fires a result change event with the current state.\n * @param hasDecorations Whether decorations are enabled.\n */\n public fireResultsChanged(hasDecorations: boolean): void {\n if (!hasDecorations) {\n return;\n }\n\n let resultIndex = -1;\n if (this._selectedDecoration) {\n resultIndex = this.findResultIndex(this._selectedDecoration.match);\n }\n\n this._onDidChangeResults.fire({\n resultIndex,\n resultCount: this._searchResults.length\n });\n }\n\n /**\n * Resets all state.\n */\n public reset(): void {\n this.clearSelectedDecoration();\n this.clearResults();\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport type { ISearchOptions } from '@xterm/addon-search';\n\n/**\n * Manages search state including cached search terms, options tracking, and validation.\n * This class provides a centralized way to handle search state consistency and option changes.\n */\nexport class SearchState {\n private _cachedSearchTerm: string | undefined;\n private _lastSearchOptions: ISearchOptions | undefined;\n\n /**\n * Gets the currently cached search term.\n */\n public get cachedSearchTerm(): string | undefined {\n return this._cachedSearchTerm;\n }\n\n /**\n * Sets the cached search term.\n */\n public set cachedSearchTerm(term: string | undefined) {\n this._cachedSearchTerm = term;\n }\n\n /**\n * Gets the last search options used.\n */\n public get lastSearchOptions(): ISearchOptions | undefined {\n return this._lastSearchOptions;\n }\n\n /**\n * Sets the last search options used.\n */\n public set lastSearchOptions(options: ISearchOptions | undefined) {\n this._lastSearchOptions = options;\n }\n\n /**\n * Validates a search term to ensure it's not empty or invalid.\n * @param term The search term to validate.\n * @returns true if the term is valid for searching.\n */\n public isValidSearchTerm(term: string): boolean {\n return !!(term && term.length > 0);\n }\n\n /**\n * Determines if search options have changed compared to the last search.\n * @param newOptions The new search options to compare.\n * @returns true if the options have changed.\n */\n public didOptionsChange(newOptions?: ISearchOptions): boolean {\n if (!this._lastSearchOptions) {\n return true;\n }\n if (!newOptions) {\n return false;\n }\n if (this._lastSearchOptions.caseSensitive !== newOptions.caseSensitive) {\n return true;\n }\n if (this._lastSearchOptions.regex !== newOptions.regex) {\n return true;\n }\n if (this._lastSearchOptions.wholeWord !== newOptions.wholeWord) {\n return true;\n }\n return false;\n }\n\n /**\n * Determines if a new search should trigger highlighting updates.\n * @param term The search term.\n * @param options The search options.\n * @returns true if highlighting should be updated.\n */\n public shouldUpdateHighlighting(term: string, options?: ISearchOptions): boolean {\n if (!options?.decorations) {\n return false;\n }\n return this._cachedSearchTerm === undefined ||\n term !== this._cachedSearchTerm ||\n this.didOptionsChange(options);\n }\n\n /**\n * Clears the cached search term.\n */\n public clearCachedTerm(): void {\n this._cachedSearchTerm = undefined;\n }\n\n /**\n * Resets all state.\n */\n public reset(): void {\n this._cachedSearchTerm = undefined;\n this._lastSearchOptions = undefined;\n }\n}\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport type { Terminal, IDisposable, ITerminalAddon } from '@xterm/xterm';\nimport type { SearchAddon as ISearchApi, ISearchOptions, ISearchAddonOptions, ISearchResultChangeEvent, ISearchDecorationOptions } from '@xterm/addon-search';\nimport { Emitter, type IEvent } from 'common/Event';\nimport { Disposable, MutableDisposable, toDisposable } from 'common/Lifecycle';\nimport { disposableTimeout } from 'common/Async';\nimport { SearchLineCache } from './SearchLineCache';\nimport { SearchState } from './SearchState';\nimport { SearchEngine, type ISearchResult } from './SearchEngine';\nimport { DecorationManager } from './DecorationManager';\nimport { SearchResultTracker } from './SearchResultTracker';\n\ninterface IInternalSearchOptions {\n noScroll: boolean;\n}\n\n/**\n * Configuration constants for the search addon functionality.\n */\nconst enum Constants {\n /**\n * Default maximum number of search results to highlight simultaneously. This limit prevents\n * performance degradation when searching for very common terms that would result in excessive\n * highlighting decorations.\n */\n DEFAULT_HIGHLIGHT_LIMIT = 1000\n}\n\nexport class SearchAddon extends Disposable implements ITerminalAddon, ISearchApi {\n private _terminal: Terminal | undefined;\n private _highlightLimit: number;\n private _highlightTimeout = this._register(new MutableDisposable());\n private _lineCache = this._register(new MutableDisposable());\n\n // Component instances\n private _state = new SearchState();\n private _engine: SearchEngine | undefined;\n private _decorationManager: DecorationManager | undefined;\n private _resultTracker = this._register(new SearchResultTracker());\n\n private readonly _onAfterSearch = this._register(new Emitter());\n public readonly onAfterSearch = this._onAfterSearch.event;\n private readonly _onBeforeSearch = this._register(new Emitter());\n public readonly onBeforeSearch = this._onBeforeSearch.event;\n\n public get onDidChangeResults(): IEvent {\n return this._resultTracker.onDidChangeResults;\n }\n\n constructor(options?: Partial) {\n super();\n\n this._highlightLimit = options?.highlightLimit ?? Constants.DEFAULT_HIGHLIGHT_LIMIT;\n }\n\n public activate(terminal: Terminal): void {\n this._terminal = terminal;\n this._lineCache.value = new SearchLineCache(terminal);\n this._engine = new SearchEngine(terminal, this._lineCache.value);\n this._decorationManager = new DecorationManager(terminal);\n this._register(this._terminal.onWriteParsed(() => this._updateMatches()));\n this._register(this._terminal.onResize(() => this._updateMatches()));\n this._register(toDisposable(() => this.clearDecorations()));\n }\n\n private _updateMatches(): void {\n this._highlightTimeout.clear();\n if (this._state.cachedSearchTerm && this._state.lastSearchOptions?.decorations) {\n this._highlightTimeout.value = disposableTimeout(() => {\n const term = this._state.cachedSearchTerm;\n this._state.clearCachedTerm();\n this.findPrevious(term!, { ...this._state.lastSearchOptions, incremental: true }, { noScroll: true });\n }, 200);\n }\n }\n\n public clearDecorations(retainCachedSearchTerm?: boolean): void {\n this._resultTracker.clearSelectedDecoration();\n this._decorationManager?.clearHighlightDecorations();\n this._resultTracker.clearResults();\n if (!retainCachedSearchTerm) {\n this._state.clearCachedTerm();\n }\n }\n\n public clearActiveDecoration(): void {\n this._resultTracker.clearSelectedDecoration();\n }\n\n /**\n * Find the next instance of the term, then scroll to and select it. If it\n * doesn't exist, do nothing.\n * @param term The search term.\n * @param searchOptions Search options.\n * @returns Whether a result was found.\n */\n public findNext(term: string, searchOptions?: ISearchOptions, internalSearchOptions?: IInternalSearchOptions): boolean {\n if (!this._terminal || !this._engine) {\n throw new Error('Cannot use addon until it has been loaded');\n }\n\n this._onBeforeSearch.fire();\n\n this._state.lastSearchOptions = searchOptions;\n\n if (this._state.shouldUpdateHighlighting(term, searchOptions)) {\n this._highlightAllMatches(term, searchOptions!);\n }\n\n const found = this._findNextAndSelect(term, searchOptions, internalSearchOptions);\n this._fireResults(searchOptions);\n this._state.cachedSearchTerm = term;\n\n this._onAfterSearch.fire();\n\n return found;\n }\n\n private _highlightAllMatches(term: string, searchOptions: ISearchOptions): void {\n if (!this._terminal || !this._engine || !this._decorationManager) {\n throw new Error('Cannot use addon until it has been loaded');\n }\n if (!this._state.isValidSearchTerm(term)) {\n this.clearDecorations();\n return;\n }\n\n // new search, clear out the old decorations\n this.clearDecorations(true);\n\n const results: ISearchResult[] = [];\n let prevResult: ISearchResult | undefined = undefined;\n let result = this._engine.find(term, 0, 0, searchOptions);\n\n while (result && (prevResult?.row !== result.row || prevResult?.col !== result.col)) {\n if (results.length >= this._highlightLimit) {\n break;\n }\n prevResult = result;\n results.push(prevResult);\n const cols = this._terminal.cols;\n let nextCol = prevResult.col + prevResult.size;\n let nextRow = prevResult.row;\n if (nextCol >= cols) {\n nextRow += Math.floor(nextCol / cols);\n nextCol = nextCol % cols;\n }\n result = this._engine.find(term, nextRow, nextCol, searchOptions);\n }\n\n this._resultTracker.updateResults(results, this._highlightLimit);\n if (searchOptions.decorations) {\n this._decorationManager.createHighlightDecorations(results, searchOptions.decorations);\n }\n }\n\n private _findNextAndSelect(term: string, searchOptions?: ISearchOptions, internalSearchOptions?: IInternalSearchOptions): boolean {\n if (!this._terminal || !this._engine) {\n return false;\n }\n if (!this._state.isValidSearchTerm(term)) {\n this._terminal.clearSelection();\n this.clearDecorations();\n return false;\n }\n\n const result = this._engine.findNextWithSelection(term, searchOptions, this._state.cachedSearchTerm);\n return this._selectResult(result, searchOptions?.decorations, internalSearchOptions?.noScroll);\n }\n\n /**\n * Find the previous instance of the term, then scroll to and select it. If it\n * doesn't exist, do nothing.\n * @param term The search term.\n * @param searchOptions Search options.\n * @returns Whether a result was found.\n */\n public findPrevious(term: string, searchOptions?: ISearchOptions, internalSearchOptions?: IInternalSearchOptions): boolean {\n if (!this._terminal || !this._engine) {\n throw new Error('Cannot use addon until it has been loaded');\n }\n\n this._onBeforeSearch.fire();\n\n this._state.lastSearchOptions = searchOptions;\n\n if (this._state.shouldUpdateHighlighting(term, searchOptions)) {\n this._highlightAllMatches(term, searchOptions!);\n }\n\n const found = this._findPreviousAndSelect(term, searchOptions, internalSearchOptions);\n this._fireResults(searchOptions);\n this._state.cachedSearchTerm = term;\n\n this._onAfterSearch.fire();\n\n return found;\n }\n\n private _fireResults(searchOptions?: ISearchOptions): void {\n this._resultTracker.fireResultsChanged(!!searchOptions?.decorations);\n }\n\n private _findPreviousAndSelect(term: string, searchOptions?: ISearchOptions, internalSearchOptions?: IInternalSearchOptions): boolean {\n if (!this._terminal || !this._engine) {\n return false;\n }\n if (!this._state.isValidSearchTerm(term)) {\n this._terminal.clearSelection();\n this.clearDecorations();\n return false;\n }\n\n const result = this._engine.findPreviousWithSelection(term, searchOptions, this._state.cachedSearchTerm);\n return this._selectResult(result, searchOptions?.decorations, internalSearchOptions?.noScroll);\n }\n\n /**\n * Selects and scrolls to a result.\n * @param result The result to select.\n * @returns Whether a result was selected.\n */\n private _selectResult(result: ISearchResult | undefined, options?: ISearchDecorationOptions, noScroll?: boolean): boolean {\n if (!this._terminal || !this._decorationManager) {\n return false;\n }\n\n this._resultTracker.clearSelectedDecoration();\n if (!result) {\n this._terminal.clearSelection();\n return false;\n }\n\n this._terminal.select(result.col, result.row, result.size);\n if (options) {\n const activeDecoration = this._decorationManager.createActiveDecoration(result, options);\n if (activeDecoration) {\n this._resultTracker.selectedDecoration = activeDecoration;\n }\n }\n\n if (!noScroll) {\n // If it is not in the viewport then we scroll else it just gets selected\n if (result.row >= (this._terminal.buffer.active.viewportY + this._terminal.rows) || result.row < this._terminal.buffer.active.viewportY) {\n let scroll = result.row - this._terminal.buffer.active.viewportY;\n scroll -= Math.floor(this._terminal.rows / 2);\n this._terminal.scrollLines(scroll);\n }\n }\n return true;\n }\n}\n"],"names":["root","factory","exports","module","define","amd","globalThis","millis","Promise","resolve","setTimeout","handler","timeout","store","timer","disposable","dispose","Lifecycle_1","toDisposable","clearTimeout","add","__webpack_require__","constructor","this","_token","_isDisposed","cancel","cancelAndSet","runner","Error","setIfNotSet","_isScheduled","set","queueMicrotask","_disposable","undefined","interval","context","handle","setInterval","clearInterval","EventUtils","_listeners","_disposed","event","_event","listener","thisArgs","disposables","entry","fn","slice","push","result","idx","indexOf","splice","Array","isArray","fire","length","call","listeners","i","len","forward","from","to","e","map","any","events","DisposableStore","runAndSubscribe","initial","arg","d","_disposables","Set","isDisposed","o","clear","Disposable","_store","_register","None","Object","freeze","value","_value","DecorationManager","_terminal","super","_highlightDecorations","_highlightedLines","clearHighlightDecorations","createHighlightDecorations","results","options","match","decorations","_createResultDecorations","decoration","_storeDecoration","createActiveDecoration","marker","line","_applyStyles","element","borderColor","isActiveResult","classList","contains","style","outline","decorationRanges","currentCol","col","remainingSize","size","markerOffset","buffer","active","baseY","cursorY","row","amountThisRow","Math","min","cols","range","registerMarker","registerDecoration","x","width","layer","backgroundColor","activeMatchBackground","matchBackground","overviewRulerOptions","has","color","activeMatchColorOverviewRuler","matchOverviewRuler","position","onRender","activeMatchBorder","matchBorder","onDispose","_lineCache","find","term","startRow","startCol","searchOptions","clearSelection","initLinesCache","searchPosition","_findInLine","y","rows","findNextWithSelection","cachedSearchTerm","prevSelectedPos","getSelectionPosition","end","start","findPreviousWithSelection","isReverseSearch","max","_isWholeWord","searchIndex","includes","firstLine","getLine","isWrapped","cache","getLineFromCache","translateBufferLineToStringWithWrap","setLineInCache","stringLine","offsets","offset","_bufferColsToStringOffset","searchTerm","searchStringLine","regex","caseSensitive","toLowerCase","resultIndex","searchRegex","RegExp","foundTerm","exec","lastIndex","lastIndexOf","wholeWord","startRowOffset","endRowOffset","startColOffset","endColOffset","startColIndex","_stringLengthToBufferSize","cell","getCell","char","getChars","nextCell","getWidth","lineIndex","getCode","Async_1","SearchLineCache","_linesCacheTimeout","MutableDisposable","_linesCacheDisposables","_lastAccessTimestamp","_destroyLinesCache","_linesCache","combinedDisposable","onLineFeed","onCursorMove","onResize","Date","now","_scheduleLinesCacheTimeout","delay","disposableTimeout","elapsed","trimRight","strings","lineOffsets","nextLine","lineWrapsToNext","string","translateToString","lastCell","join","Event_1","SearchResultTracker","_searchResults","_onDidChangeResults","Emitter","onDidChangeResults","searchResults","selectedDecoration","_selectedDecoration","updateResults","maxResults","clearResults","clearSelectedDecoration","findResultIndex","fireResultsChanged","hasDecorations","resultCount","reset","_cachedSearchTerm","lastSearchOptions","_lastSearchOptions","isValidSearchTerm","didOptionsChange","newOptions","shouldUpdateHighlighting","clearCachedTerm","__webpack_module_cache__","moduleId","cachedModule","__webpack_modules__","SearchLineCache_1","SearchState_1","SearchEngine_1","DecorationManager_1","SearchResultTracker_1","SearchAddon","_resultTracker","_highlightTimeout","_state","SearchState","_onAfterSearch","onAfterSearch","_onBeforeSearch","onBeforeSearch","_highlightLimit","highlightLimit","activate","terminal","_engine","SearchEngine","_decorationManager","onWriteParsed","_updateMatches","clearDecorations","findPrevious","incremental","noScroll","retainCachedSearchTerm","clearActiveDecoration","findNext","internalSearchOptions","_highlightAllMatches","found","_findNextAndSelect","_fireResults","prevResult","nextCol","nextRow","floor","_selectResult","_findPreviousAndSelect","select","activeDecoration","viewportY","scroll","scrollLines"],"sourceRoot":""} \ No newline at end of file -+{"version":3,"file":"addon-search.js","mappings":"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","sources":["webpack://SearchAddon/webpack/universalModuleDefinition","webpack://SearchAddon/../src/common/Async.ts","webpack://SearchAddon/../src/common/Event.ts","webpack://SearchAddon/../src/common/Lifecycle.ts","webpack://SearchAddon/./src/DecorationManager.ts","webpack://SearchAddon/./src/SearchEngine.ts","webpack://SearchAddon/./src/SearchLineCache.ts","webpack://SearchAddon/./src/SearchResultTracker.ts","webpack://SearchAddon/./src/SearchState.ts","webpack://SearchAddon/webpack/bootstrap","webpack://SearchAddon/./src/SearchAddon.ts"],"sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"SearchAddon\"] = factory();\n\telse\n\t\troot[\"SearchAddon\"] = factory();\n})(globalThis, () => {\nreturn ","/**\n * Copyright (c) 2026 The xterm.js authors. All rights reserved.\n * @license MIT\n *\n * Minimal async helpers for xterm.js core.\n */\n\nimport { DisposableStore, IDisposable, toDisposable } from './Lifecycle';\n\nexport function timeout(millis: number): Promise {\n return new Promise(resolve => setTimeout(resolve, millis));\n}\n\n/**\n * Creates a timeout that can be disposed using its returned value.\n * @param handler The timeout handler.\n * @param timeout An optional timeout in milliseconds.\n * @param store An optional {@link DisposableStore} that will have the timeout disposable managed\n * automatically.\n */\nexport function disposableTimeout(handler: () => void, timeout = 0, store?: DisposableStore): IDisposable {\n const timer = setTimeout(() => {\n handler();\n if (store) {\n disposable.dispose();\n }\n }, timeout);\n const disposable = toDisposable(() => {\n clearTimeout(timer);\n });\n store?.add(disposable);\n return disposable;\n}\n\nexport class TimeoutTimer implements IDisposable {\n private _token: any = -1;\n private _isDisposed = false;\n\n public dispose(): void {\n this.cancel();\n this._isDisposed = true;\n }\n\n public cancel(): void {\n if (this._token !== -1) {\n clearTimeout(this._token);\n this._token = -1;\n }\n }\n\n public cancelAndSet(runner: () => void, timeout: number): void {\n if (this._isDisposed) {\n throw new Error('Calling cancelAndSet on a disposed TimeoutTimer');\n }\n this.cancel();\n this._token = setTimeout(() => {\n this._token = -1;\n runner();\n }, timeout);\n }\n\n public setIfNotSet(runner: () => void, timeout: number): void {\n if (this._isDisposed) {\n throw new Error('Calling setIfNotSet on a disposed TimeoutTimer');\n }\n if (this._token !== -1) {\n return;\n }\n this._token = setTimeout(() => {\n this._token = -1;\n runner();\n }, timeout);\n }\n}\n\n/**\n * Schedules a single runner on the microtask queue. Unlike {@link TimeoutTimer}, a scheduled\n * microtask cannot be unqueued; {@link cancel} prevents the runner from executing if it has not\n * run yet.\n */\nexport class MicrotaskTimer implements IDisposable {\n private _isScheduled = false;\n private _isDisposed = false;\n\n public dispose(): void {\n this.cancel();\n this._isDisposed = true;\n }\n\n public cancel(): void {\n this._isScheduled = false;\n }\n\n public set(runner: () => void): void {\n if (this._isDisposed) {\n throw new Error('Calling set on a disposed MicrotaskTimer');\n }\n if (this._isScheduled) {\n return;\n }\n this._isScheduled = true;\n queueMicrotask(() => {\n if (!this._isScheduled) {\n return;\n }\n this._isScheduled = false;\n runner();\n });\n }\n}\n\nexport class IntervalTimer implements IDisposable {\n private _disposable: IDisposable | undefined;\n private _isDisposed = false;\n\n public cancel(): void {\n this._disposable?.dispose();\n this._disposable = undefined;\n }\n\n public cancelAndSet(runner: () => void, interval: number, context: Window | typeof globalThis = globalThis): void {\n if (this._isDisposed) {\n throw new Error('Calling cancelAndSet on a disposed IntervalTimer');\n }\n this.cancel();\n const handle = context.setInterval(() => {\n runner();\n }, interval);\n this._disposable = {\n dispose: () => {\n context.clearInterval(handle as any);\n this._disposable = undefined;\n }\n };\n }\n\n public dispose(): void {\n this.cancel();\n this._isDisposed = true;\n }\n}\n","/**\n * Copyright (c) 2024-2026 The xterm.js authors. All rights reserved.\n * @license MIT\n *\n * Minimal event utilities for xterm.js core.\n * Simplified from VS Code's event.ts - no leak detection/profiling.\n */\n\nimport { IDisposable, DisposableStore, toDisposable } from './Lifecycle';\n\nexport interface IEvent {\n (listener: (e: T) => any, thisArgs?: any, disposables?: IDisposable[] | DisposableStore): IDisposable;\n}\n\nexport class Emitter {\n private _listeners: { fn: (e: T) => any, thisArgs: any }[] = [];\n private _disposed = false;\n private _event: IEvent | undefined;\n\n public get event(): IEvent {\n if (this._event) {\n return this._event;\n }\n this._event = (listener: (e: T) => any, thisArgs?: any, disposables?: IDisposable[] | DisposableStore) => {\n if (this._disposed) {\n return toDisposable(() => {});\n }\n\n const entry = { fn: listener, thisArgs };\n this._listeners = this._listeners.slice();\n this._listeners.push(entry);\n\n const result = toDisposable(() => {\n const idx = this._listeners.indexOf(entry);\n if (idx !== -1) {\n this._listeners = this._listeners.slice();\n this._listeners.splice(idx, 1);\n }\n });\n\n if (disposables) {\n if (Array.isArray(disposables)) {\n disposables.push(result);\n } else {\n disposables.add(result);\n }\n }\n\n return result;\n };\n return this._event;\n }\n\n public fire(event: T): void {\n if (this._disposed || !this._listeners.length) {\n return;\n }\n if (this._listeners.length === 1) {\n this._listeners[0].fn.call(this._listeners[0].thisArgs, event);\n return;\n }\n const listeners = this._listeners;\n for (let i = 0, len = listeners.length; i < len; ++i) {\n listeners[i].fn.call(listeners[i].thisArgs, event);\n }\n }\n\n public dispose(): void {\n if (this._disposed) {\n return;\n }\n this._disposed = true;\n this._listeners.length = 0;\n }\n}\n\nexport namespace EventUtils {\n export function forward(from: IEvent, to: Emitter): IDisposable {\n return from(e => to.fire(e));\n }\n\n export function map(event: IEvent, map: (i: I) => O): IEvent {\n return (listener: (e: O) => any, thisArgs?: any, disposables?: IDisposable[] | DisposableStore) => {\n return event(i => listener.call(thisArgs, map(i)), undefined, disposables);\n };\n }\n\n export function any(...events: IEvent[]): IEvent;\n export function any(...events: IEvent[]): IEvent;\n export function any(...events: IEvent[]): IEvent {\n return (listener: (e: T) => any, thisArgs?: any, disposables?: IDisposable[] | DisposableStore) => {\n const store = new DisposableStore();\n for (const event of events) {\n store.add(event(e => listener.call(thisArgs, e)));\n }\n if (disposables) {\n if (Array.isArray(disposables)) {\n disposables.push(store);\n } else {\n disposables.add(store);\n }\n }\n return store;\n };\n }\n\n export function runAndSubscribe(event: IEvent, handler: (e: T) => void, initial: T): IDisposable;\n export function runAndSubscribe(event: IEvent, handler: (e: T | undefined) => void): IDisposable;\n export function runAndSubscribe(event: IEvent, handler: (e: T | undefined) => void, initial?: T): IDisposable {\n handler(initial);\n return event(e => handler(e));\n }\n}\n","/**\n * Copyright (c) 2024-2026 The xterm.js authors. All rights reserved.\n * @license MIT\n *\n * Minimal lifecycle utilities for xterm.js core.\n * Simplified from VS Code's lifecycle.ts - no tracking/leak detection.\n */\n\nexport interface IDisposable {\n dispose(): void;\n}\n\nexport function toDisposable(fn: () => void): IDisposable {\n return { dispose: fn };\n}\n\nexport function dispose(disposable: T): T;\nexport function dispose(disposable: T | undefined): T | undefined;\nexport function dispose(disposables: T[]): T[];\nexport function dispose(arg: T | T[] | undefined): T | T[] | undefined {\n if (!arg) {\n return arg;\n }\n if (Array.isArray(arg)) {\n for (const d of arg) {\n d.dispose();\n }\n return [];\n }\n arg.dispose();\n return arg;\n}\n\nexport function combinedDisposable(...disposables: IDisposable[]): IDisposable {\n return toDisposable(() => dispose(disposables));\n}\n\nexport class DisposableStore implements IDisposable {\n private readonly _disposables = new Set();\n private _isDisposed = false;\n\n public get isDisposed(): boolean {\n return this._isDisposed;\n }\n\n public add(o: T): T {\n if (this._isDisposed) {\n o.dispose();\n } else {\n this._disposables.add(o);\n }\n return o;\n }\n\n public dispose(): void {\n if (this._isDisposed) {\n return;\n }\n this._isDisposed = true;\n for (const d of this._disposables) {\n d.dispose();\n }\n this._disposables.clear();\n }\n\n public clear(): void {\n for (const d of this._disposables) {\n d.dispose();\n }\n this._disposables.clear();\n }\n}\n\nexport abstract class Disposable implements IDisposable {\n public static readonly None: IDisposable = Object.freeze({ dispose() { } });\n\n protected readonly _store = new DisposableStore();\n\n public dispose(): void {\n this._store.dispose();\n }\n\n protected _register(o: T): T {\n return this._store.add(o);\n }\n}\n\nexport class MutableDisposable implements IDisposable {\n private _value: T | undefined;\n private _isDisposed = false;\n\n public get value(): T | undefined {\n return this._isDisposed ? undefined : this._value;\n }\n\n public set value(value: T | undefined) {\n if (this._isDisposed || value === this._value) {\n return;\n }\n this._value?.dispose();\n this._value = value;\n }\n\n public clear(): void {\n this.value = undefined;\n }\n\n public dispose(): void {\n this._isDisposed = true;\n this._value?.dispose();\n this._value = undefined;\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport type { Terminal, IDisposable, IDecoration } from '@xterm/xterm';\nimport type { ISearchDecorationOptions } from '@xterm/addon-search';\nimport { dispose, Disposable, toDisposable } from 'common/Lifecycle';\nimport type { ISearchResult } from './SearchEngine';\n\n/**\n * Interface for managing a highlight decoration.\n */\ninterface IHighlight extends IDisposable {\n decoration: IDecoration;\n match: ISearchResult;\n}\n\n/**\n * Interface for managing multiple decorations for a single match.\n */\ninterface IMultiHighlight extends IDisposable {\n decorations: IDecoration[];\n match: ISearchResult;\n}\n\n/**\n * Manages visual decorations for search results including highlighting and active selection\n * indicators. This class handles the creation, styling, and disposal of search-related decorations.\n */\nexport class DecorationManager extends Disposable {\n private _highlightDecorations: IHighlight[] = [];\n private _highlightedLines: Set = new Set();\n\n constructor(private readonly _terminal: Terminal) {\n super();\n this._register(toDisposable(() => this.clearHighlightDecorations()));\n }\n\n /**\n * Creates decorations for all provided search results.\n * @param results The search results to create decorations for.\n * @param options The decoration options.\n */\n public createHighlightDecorations(results: ISearchResult[], options: ISearchDecorationOptions): void {\n this.clearHighlightDecorations();\n\n for (const match of results) {\n const decorations = this._createResultDecorations(match, options, false);\n if (decorations) {\n for (const decoration of decorations) {\n this._storeDecoration(decoration, match);\n }\n }\n }\n }\n\n /**\n * Creates decorations for the currently active search result.\n * @param result The active search result.\n * @param options The decoration options.\n * @returns The multi-highlight decoration or undefined if creation failed.\n */\n public createActiveDecoration(result: ISearchResult, options: ISearchDecorationOptions): IMultiHighlight | undefined {\n const decorations = this._createResultDecorations(result, options, true);\n if (decorations) {\n return { decorations, match: result, dispose() { dispose(decorations); } };\n }\n return undefined;\n }\n\n /**\n * Clears all highlight decorations.\n */\n public clearHighlightDecorations(): void {\n dispose(this._highlightDecorations);\n this._highlightDecorations = [];\n this._highlightedLines.clear();\n }\n\n /**\n * Stores a decoration and tracks it for management.\n * @param decoration The decoration to store.\n * @param match The search result this decoration represents.\n */\n private _storeDecoration(decoration: IDecoration, match: ISearchResult): void {\n this._highlightedLines.add(decoration.marker.line);\n this._highlightDecorations.push({ decoration, match, dispose() { decoration.dispose(); } });\n }\n\n /**\n * Applies styles to the decoration when it is rendered.\n * @param element The decoration's element.\n * @param borderColor The border color to apply.\n * @param isActiveResult Whether the element is part of the active search result.\n */\n private _applyStyles(element: HTMLElement, borderColor: string | undefined, isActiveResult: boolean): void {\n if (!element.classList.contains('xterm-find-result-decoration')) {\n element.classList.add('xterm-find-result-decoration');\n if (borderColor) {\n element.style.outline = `1px solid ${borderColor}`;\n }\n }\n if (isActiveResult) {\n element.classList.add('xterm-find-active-result-decoration');\n }\n }\n\n /**\n * Creates a decoration for the result and applies styles\n * @param result the search result for which to create the decoration\n * @param options the options for the decoration\n * @param isActiveResult whether this is the currently active result\n * @returns the decorations or undefined if the marker has already been disposed of\n */\n private _createResultDecorations(result: ISearchResult, options: ISearchDecorationOptions, isActiveResult: boolean): IDecoration[] | undefined {\n // Gather decoration ranges for this match as it could wrap\n const decorationRanges: [number, number, number][] = [];\n let currentCol = result.col;\n let remainingSize = result.size;\n let markerOffset = -this._terminal.buffer.active.baseY - this._terminal.buffer.active.cursorY + result.row;\n while (remainingSize > 0) {\n const amountThisRow = Math.min(this._terminal.cols - currentCol, remainingSize);\n decorationRanges.push([markerOffset, currentCol, amountThisRow]);\n currentCol = 0;\n remainingSize -= amountThisRow;\n markerOffset++;\n }\n\n // Create the decorations\n const decorations: IDecoration[] = [];\n for (const range of decorationRanges) {\n const marker = this._terminal.registerMarker(range[0]);\n const decoration = this._terminal.registerDecoration({\n marker,\n x: range[1],\n width: range[2],\n layer: isActiveResult ? 'top' : 'bottom',\n backgroundColor: isActiveResult ? options.activeMatchBackground : options.matchBackground,\n overviewRulerOptions: this._highlightedLines.has(marker.line) ? undefined : {\n color: isActiveResult ? options.activeMatchColorOverviewRuler : options.matchOverviewRuler,\n position: 'center'\n }\n });\n if (decoration) {\n const disposables: IDisposable[] = [];\n disposables.push(marker);\n disposables.push(decoration.onRender((e) => this._applyStyles(e, isActiveResult ? options.activeMatchBorder : options.matchBorder, false)));\n disposables.push(decoration.onDispose(() => dispose(disposables)));\n decorations.push(decoration);\n }\n }\n\n return decorations.length === 0 ? undefined : decorations;\n }\n}\n\n\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport type { Terminal } from '@xterm/xterm';\nimport type { ISearchOptions } from '@xterm/addon-search';\nimport type { SearchLineCache } from './SearchLineCache';\n\n/**\n * Represents the position to start a search from.\n */\ninterface ISearchPosition {\n startCol: number;\n startRow: number;\n}\n\n/**\n * Represents a search result with its position and content.\n */\nexport interface ISearchResult {\n term: string;\n col: number;\n row: number;\n size: number;\n}\n\n/**\n * Configuration constants for the search engine functionality.\n */\nconst enum Constants {\n /**\n * Characters that are considered non-word characters for search boundary detection. These\n * characters are used to determine word boundaries when performing whole-word searches. Includes\n * common punctuation, symbols, and whitespace characters.\n */\n NON_WORD_CHARACTERS = ' ~!@#$%^&*()+`-=[]{}|\\\\;:\"\\',./<>?'\n}\n\n/**\n * Core search engine that handles finding text within terminal content.\n * This class is responsible for the actual search algorithms and position calculations.\n */\nexport class SearchEngine {\n constructor(\n private readonly _terminal: Terminal,\n private readonly _lineCache: SearchLineCache\n ) {}\n\n /**\n * Find the first occurrence of a term starting from a specific position.\n * @param term The search term.\n * @param startRow The row to start searching from.\n * @param startCol The column to start searching from.\n * @param searchOptions Search options.\n * @returns The search result if found, undefined otherwise.\n */\n public find(term: string, startRow: number, startCol: number, searchOptions?: ISearchOptions): ISearchResult | undefined {\n if (!term || term.length === 0) {\n this._terminal.clearSelection();\n return undefined;\n }\n if (startCol >= this._terminal.cols) {\n throw new Error(`Invalid col: ${startCol} to search in terminal of ${this._terminal.cols} cols`);\n }\n\n this._lineCache.initLinesCache();\n\n const searchPosition: ISearchPosition = {\n startRow,\n startCol\n };\n\n // Search startRow\n let result = this._findInLine(term, searchPosition, searchOptions);\n // Search from startRow + 1 to end\n if (!result) {\n for (let y = startRow + 1; y < this._terminal.buffer.active.baseY + this._terminal.rows; y++) {\n searchPosition.startRow = y;\n searchPosition.startCol = 0;\n result = this._findInLine(term, searchPosition, searchOptions);\n if (result) {\n break;\n }\n }\n }\n return result;\n }\n\n /**\n * Find the next occurrence of a term with wrapping and selection management.\n * @param term The search term.\n * @param searchOptions Search options.\n * @param cachedSearchTerm The cached search term to determine incremental behavior.\n * @returns The search result if found, undefined otherwise.\n */\n public findNextWithSelection(term: string, searchOptions?: ISearchOptions, cachedSearchTerm?: string): ISearchResult | undefined {\n if (!term || term.length === 0) {\n this._terminal.clearSelection();\n return undefined;\n }\n\n const prevSelectedPos = this._terminal.getSelectionPosition();\n this._terminal.clearSelection();\n\n let startCol = 0;\n let startRow = 0;\n if (prevSelectedPos) {\n if (cachedSearchTerm === term) {\n startCol = prevSelectedPos.end.x;\n startRow = prevSelectedPos.end.y;\n } else {\n startCol = prevSelectedPos.start.x;\n startRow = prevSelectedPos.start.y;\n }\n }\n\n this._lineCache.initLinesCache();\n\n const searchPosition: ISearchPosition = {\n startRow,\n startCol\n };\n\n // Search startRow\n let result = this._findInLine(term, searchPosition, searchOptions);\n // Search from startRow + 1 to end\n if (!result) {\n for (let y = startRow + 1; y < this._terminal.buffer.active.baseY + this._terminal.rows; y++) {\n searchPosition.startRow = y;\n searchPosition.startCol = 0;\n result = this._findInLine(term, searchPosition, searchOptions);\n if (result) {\n break;\n }\n }\n }\n // If we hit the bottom and didn't search from the very top wrap back up\n if (!result && startRow !== 0) {\n for (let y = 0; y < startRow; y++) {\n searchPosition.startRow = y;\n searchPosition.startCol = 0;\n result = this._findInLine(term, searchPosition, searchOptions);\n if (result) {\n break;\n }\n }\n }\n\n // If there is only one result, wrap back and return selection if it exists.\n if (!result && prevSelectedPos) {\n searchPosition.startRow = prevSelectedPos.start.y;\n searchPosition.startCol = 0;\n result = this._findInLine(term, searchPosition, searchOptions);\n }\n\n return result;\n }\n\n /**\n * Find the previous occurrence of a term with wrapping and selection management.\n * @param term The search term.\n * @param searchOptions Search options.\n * @param cachedSearchTerm The cached search term to determine if expansion should occur.\n * @returns The search result if found, undefined otherwise.\n */\n public findPreviousWithSelection(term: string, searchOptions?: ISearchOptions, cachedSearchTerm?: string): ISearchResult | undefined {\n if (!term || term.length === 0) {\n this._terminal.clearSelection();\n return undefined;\n }\n\n const prevSelectedPos = this._terminal.getSelectionPosition();\n this._terminal.clearSelection();\n\n let startRow = this._terminal.buffer.active.baseY + this._terminal.rows - 1;\n const startCol = this._terminal.cols;\n const isReverseSearch = true;\n\n this._lineCache.initLinesCache();\n const searchPosition: ISearchPosition = {\n startRow,\n startCol\n };\n\n let result: ISearchResult | undefined;\n if (prevSelectedPos) {\n searchPosition.startRow = startRow = prevSelectedPos.start.y;\n searchPosition.startCol = prevSelectedPos.start.x;\n if (cachedSearchTerm !== term) {\n // Try to expand selection to right first.\n result = this._findInLine(term, searchPosition, searchOptions, false);\n if (!result) {\n // If selection was not able to be expanded to the right, then try reverse search\n searchPosition.startRow = startRow = prevSelectedPos.end.y;\n searchPosition.startCol = prevSelectedPos.end.x;\n }\n }\n }\n\n result ??= this._findInLine(term, searchPosition, searchOptions, isReverseSearch);\n\n // Search from startRow - 1 to top\n if (!result) {\n searchPosition.startCol = Math.max(searchPosition.startCol, this._terminal.cols);\n for (let y = startRow - 1; y >= 0; y--) {\n searchPosition.startRow = y;\n result = this._findInLine(term, searchPosition, searchOptions, isReverseSearch);\n if (result) {\n break;\n }\n }\n }\n // If we hit the top and didn't search from the very bottom wrap back down\n if (!result && startRow !== (this._terminal.buffer.active.baseY + this._terminal.rows - 1)) {\n for (let y = (this._terminal.buffer.active.baseY + this._terminal.rows - 1); y >= startRow; y--) {\n searchPosition.startRow = y;\n result = this._findInLine(term, searchPosition, searchOptions, isReverseSearch);\n if (result) {\n break;\n }\n }\n }\n\n return result;\n }\n\n /**\n * A found substring is a whole word if it doesn't have an alphanumeric character directly\n * adjacent to it.\n * @param searchIndex starting index of the potential whole word substring\n * @param line entire string in which the potential whole word was found\n * @param term the substring that starts at searchIndex\n */\n private _isWholeWord(searchIndex: number, line: string, term: string): boolean {\n return ((searchIndex === 0) || (Constants.NON_WORD_CHARACTERS.includes(line[searchIndex - 1]))) &&\n (((searchIndex + term.length) === line.length) || (Constants.NON_WORD_CHARACTERS.includes(line[searchIndex + term.length])));\n }\n\n /**\n * Searches a line for a search term. Takes the provided terminal line and searches the text line,\n * which may contain subsequent terminal lines if the text is wrapped. If the provided line number\n * is part of a wrapped text line that started on an earlier line then it is skipped since it will\n * be properly searched when the terminal line that the text starts on is searched.\n * @param term The search term.\n * @param searchPosition The position to start the search.\n * @param searchOptions Search options.\n * @param isReverseSearch Whether the search should start from the right side of the terminal and\n * search to the left.\n * @returns The search result if it was found.\n */\n private _findInLine(term: string, searchPosition: ISearchPosition, searchOptions: ISearchOptions = {}, isReverseSearch: boolean = false): ISearchResult | undefined {\n // Ignore wrapped lines, only consider on unwrapped line (first row of command string).\n // This walks back to the line start rather than recursing into it: one frame per wrapped\n // row overflows the stack on a line long enough to fill the scrollback.\n while (this._terminal.buffer.active.getLine(searchPosition.startRow)?.isWrapped) {\n searchPosition.startCol += this._terminal.cols;\n if (isReverseSearch) {\n return;\n }\n searchPosition.startRow--;\n }\n const row = searchPosition.startRow;\n const col = searchPosition.startCol;\n\n let cache = this._lineCache.getLineFromCache(row);\n if (!cache) {\n cache = this._lineCache.translateBufferLineToStringWithWrap(row, true);\n this._lineCache.setLineInCache(row, cache);\n }\n const [stringLine, offsets] = cache;\n\n const offset = this._bufferColsToStringOffset(row, col);\n let searchTerm = term;\n let searchStringLine = stringLine;\n if (!searchOptions.regex) {\n searchTerm = searchOptions.caseSensitive ? term : term.toLowerCase();\n searchStringLine = searchOptions.caseSensitive ? stringLine : stringLine.toLowerCase();\n }\n\n let resultIndex = -1;\n if (searchOptions.regex) {\n const searchRegex = RegExp(searchTerm, searchOptions.caseSensitive ? 'g' : 'gi');\n let foundTerm: RegExpExecArray | null;\n if (isReverseSearch) {\n // This loop will get the resultIndex of the _last_ regex match in the range 0..offset\n while (foundTerm = searchRegex.exec(searchStringLine.slice(0, offset))) {\n resultIndex = searchRegex.lastIndex - foundTerm[0].length;\n term = foundTerm[0];\n searchRegex.lastIndex -= (term.length - 1);\n }\n } else {\n foundTerm = searchRegex.exec(searchStringLine.slice(offset));\n if (foundTerm && foundTerm[0].length > 0) {\n resultIndex = offset + (searchRegex.lastIndex - foundTerm[0].length);\n term = foundTerm[0];\n }\n }\n } else {\n if (isReverseSearch) {\n if (offset - searchTerm.length >= 0) {\n resultIndex = searchStringLine.lastIndexOf(searchTerm, offset - searchTerm.length);\n }\n } else {\n resultIndex = searchStringLine.indexOf(searchTerm, offset);\n }\n }\n\n if (resultIndex >= 0) {\n if (searchOptions.wholeWord && !this._isWholeWord(resultIndex, searchStringLine, term)) {\n return;\n }\n\n // Adjust the row number and search index if needed since a \"line\" of text can span multiple\n // rows\n let startRowOffset = 0;\n while (startRowOffset < offsets.length - 1 && resultIndex >= offsets[startRowOffset + 1]) {\n startRowOffset++;\n }\n let endRowOffset = startRowOffset;\n while (endRowOffset < offsets.length - 1 && resultIndex + term.length >= offsets[endRowOffset + 1]) {\n endRowOffset++;\n }\n const startColOffset = resultIndex - offsets[startRowOffset];\n const endColOffset = resultIndex + term.length - offsets[endRowOffset];\n const startColIndex = this._stringLengthToBufferSize(row + startRowOffset, startColOffset);\n const endColIndex = this._stringLengthToBufferSize(row + endRowOffset, endColOffset);\n const size = endColIndex - startColIndex + this._terminal.cols * (endRowOffset - startRowOffset);\n\n return {\n term,\n col: startColIndex,\n row: row + startRowOffset,\n size\n };\n }\n }\n\n private _stringLengthToBufferSize(row: number, offset: number): number {\n const line = this._terminal.buffer.active.getLine(row);\n if (!line) {\n return 0;\n }\n for (let i = 0; i < offset; i++) {\n const cell = line.getCell(i);\n if (!cell) {\n break;\n }\n // Adjust the searchIndex to normalize emoji into single chars\n const char = cell.getChars();\n if (char.length > 1) {\n offset -= char.length - 1;\n }\n // Adjust the searchIndex for empty characters following wide unicode\n // chars (eg. CJK)\n const nextCell = line.getCell(i + 1);\n if (nextCell && nextCell.getWidth() === 0) {\n offset++;\n }\n }\n return offset;\n }\n\n private _bufferColsToStringOffset(startRow: number, cols: number): number {\n let lineIndex = startRow;\n let offset = 0;\n let line = this._terminal.buffer.active.getLine(lineIndex);\n while (cols > 0 && line) {\n for (let i = 0; i < cols && i < this._terminal.cols; i++) {\n const cell = line.getCell(i);\n if (!cell) {\n break;\n }\n if (cell.getWidth()) {\n // Treat null characters as whitespace to align with the translateToString API\n offset += cell.getCode() === 0 ? 1 : cell.getChars().length;\n }\n }\n lineIndex++;\n line = this._terminal.buffer.active.getLine(lineIndex);\n if (line && !line.isWrapped) {\n break;\n }\n cols -= this._terminal.cols;\n }\n return offset;\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport type { Terminal } from '@xterm/xterm';\nimport { combinedDisposable, Disposable, MutableDisposable, toDisposable } from 'common/Lifecycle';\nimport { disposableTimeout } from 'common/Async';\n\nexport type LineCacheEntry = [\n /**\n * The string representation of a line (as opposed to the buffer cell representation).\n */\n lineAsString: string,\n /**\n * The offsets where each line starts when the entry describes a wrapped line.\n */\n lineOffsets: number[]\n];\n\n/**\n * Configuration constants for the search line cache functionality.\n */\nconst enum Constants {\n /**\n * Time-to-live for cached search results in milliseconds. After this duration, cached search\n * results will be invalidated to ensure they remain consistent with terminal content changes.\n */\n LINES_CACHE_TIME_TO_LIVE = 15000\n}\n\nexport class SearchLineCache extends Disposable {\n /**\n * translateBufferLineToStringWithWrap is a fairly expensive call.\n * We memoize the calls into an array that has a time based ttl.\n * _linesCache is also invalidated when the terminal cursor moves.\n */\n private _linesCache: LineCacheEntry[] | undefined;\n private _linesCacheTimeout = this._register(new MutableDisposable());\n private _linesCacheDisposables = this._register(new MutableDisposable());\n // Track access to avoid recreating a timeout on every init call which occurs once per search\n // result (findNext/findPrevious -> _highlightAllMatches -> find loop).\n private _lastAccessTimestamp = 0;\n\n constructor(private readonly _terminal: Terminal) {\n super();\n this._register(toDisposable(() => this._destroyLinesCache()));\n }\n\n /**\n * Sets up a line cache with a ttl\n */\n public initLinesCache(): void {\n if (!this._linesCache) {\n this._linesCache = new Array(this._terminal.buffer.active.length);\n this._linesCacheDisposables.value = combinedDisposable(\n this._terminal.onLineFeed(() => this._destroyLinesCache()),\n this._terminal.onCursorMove(() => this._destroyLinesCache()),\n this._terminal.onResize(() => this._destroyLinesCache())\n );\n }\n\n this._lastAccessTimestamp = Date.now();\n if (!this._linesCacheTimeout.value) {\n this._scheduleLinesCacheTimeout(Constants.LINES_CACHE_TIME_TO_LIVE);\n }\n }\n\n private _destroyLinesCache(): void {\n this._linesCache = undefined;\n this._lastAccessTimestamp = 0;\n this._linesCacheDisposables.clear();\n this._linesCacheTimeout.clear();\n }\n\n private _scheduleLinesCacheTimeout(delay: number): void {\n this._linesCacheTimeout.value = disposableTimeout(() => {\n if (!this._linesCache) {\n return;\n }\n const now = Date.now();\n const elapsed = now - this._lastAccessTimestamp;\n if (elapsed >= Constants.LINES_CACHE_TIME_TO_LIVE) {\n this._destroyLinesCache();\n return;\n }\n this._scheduleLinesCacheTimeout(Constants.LINES_CACHE_TIME_TO_LIVE - elapsed);\n }, delay);\n }\n\n public getLineFromCache(row: number): LineCacheEntry | undefined {\n return this._linesCache?.[row];\n }\n\n public setLineInCache(row: number, entry: LineCacheEntry): void {\n if (this._linesCache) {\n this._linesCache[row] = entry;\n }\n }\n\n /**\n * Translates a buffer line to a string, including subsequent lines if they are wraps.\n * Wide characters will count as two columns in the resulting string. This\n * function is useful for getting the actual text underneath the raw selection\n * position.\n * @param lineIndex The index of the line being translated.\n * @param trimRight Whether to trim whitespace to the right.\n */\n public translateBufferLineToStringWithWrap(lineIndex: number, trimRight: boolean): LineCacheEntry {\n const strings = [];\n const lineOffsets = [0];\n let line = this._terminal.buffer.active.getLine(lineIndex);\n while (line) {\n const nextLine = this._terminal.buffer.active.getLine(lineIndex + 1);\n const lineWrapsToNext = nextLine ? nextLine.isWrapped : false;\n let string = line.translateToString(!lineWrapsToNext && trimRight);\n if (lineWrapsToNext && nextLine) {\n const lastCell = line.getCell(line.length - 1);\n const lastCellIsNull = lastCell && lastCell.getCode() === 0 && lastCell.getWidth() === 1;\n // a wide character wrapped to the next line\n if (lastCellIsNull && nextLine.getCell(0)?.getWidth() === 2) {\n string = string.slice(0, -1);\n }\n }\n strings.push(string);\n if (lineWrapsToNext) {\n lineOffsets.push(lineOffsets[lineOffsets.length - 1] + string.length);\n } else {\n break;\n }\n lineIndex++;\n line = nextLine;\n }\n return [strings.join(''), lineOffsets];\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport type { ISearchResultChangeEvent } from '@xterm/addon-search';\nimport type { IDisposable } from '@xterm/xterm';\nimport { Emitter, type IEvent } from 'common/Event';\nimport { Disposable } from 'common/Lifecycle';\nimport type { ISearchResult } from './SearchEngine';\n\n/**\n * Interface for managing a currently selected decoration.\n */\ninterface ISelectedDecoration extends IDisposable {\n match: ISearchResult;\n}\n\n/**\n * Tracks search results, manages result indexing, and fires events when results change.\n * This class provides centralized management of search result state and notifications.\n */\nexport class SearchResultTracker extends Disposable {\n private _searchResults: ISearchResult[] = [];\n private _selectedDecoration: ISelectedDecoration | undefined;\n\n private readonly _onDidChangeResults = this._register(new Emitter());\n public get onDidChangeResults(): IEvent { return this._onDidChangeResults.event; }\n\n /**\n * Gets the current search results.\n */\n public get searchResults(): ReadonlyArray {\n return this._searchResults;\n }\n\n /**\n * Gets the currently selected decoration.\n */\n public get selectedDecoration(): ISelectedDecoration | undefined {\n return this._selectedDecoration;\n }\n\n /**\n * Sets the currently selected decoration.\n */\n public set selectedDecoration(decoration: ISelectedDecoration | undefined) {\n this._selectedDecoration = decoration;\n }\n\n /**\n * Updates the search results with a new set of results.\n * @param results The new search results.\n * @param maxResults The maximum number of results to track.\n */\n public updateResults(results: ISearchResult[], maxResults: number): void {\n this._searchResults = results.slice(0, maxResults);\n }\n\n /**\n * Clears all search results.\n */\n public clearResults(): void {\n this._searchResults = [];\n }\n\n /**\n * Clears the selected decoration.\n */\n public clearSelectedDecoration(): void {\n if (this._selectedDecoration) {\n this._selectedDecoration.dispose();\n this._selectedDecoration = undefined;\n }\n }\n\n /**\n * Finds the index of a result in the current results array.\n * @param result The result to find.\n * @returns The index of the result, or -1 if not found.\n */\n public findResultIndex(result: ISearchResult): number {\n for (let i = 0; i < this._searchResults.length; i++) {\n const match = this._searchResults[i];\n if (match.row === result.row && match.col === result.col && match.size === result.size) {\n return i;\n }\n }\n return -1;\n }\n\n /**\n * Fires a result change event with the current state.\n * @param hasDecorations Whether decorations are enabled.\n */\n public fireResultsChanged(hasDecorations: boolean): void {\n if (!hasDecorations) {\n return;\n }\n\n let resultIndex = -1;\n if (this._selectedDecoration) {\n resultIndex = this.findResultIndex(this._selectedDecoration.match);\n }\n\n this._onDidChangeResults.fire({\n resultIndex,\n resultCount: this._searchResults.length\n });\n }\n\n /**\n * Resets all state.\n */\n public reset(): void {\n this.clearSelectedDecoration();\n this.clearResults();\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport type { ISearchOptions } from '@xterm/addon-search';\n\n/**\n * Manages search state including cached search terms, options tracking, and validation.\n * This class provides a centralized way to handle search state consistency and option changes.\n */\nexport class SearchState {\n private _cachedSearchTerm: string | undefined;\n private _lastSearchOptions: ISearchOptions | undefined;\n\n /**\n * Gets the currently cached search term.\n */\n public get cachedSearchTerm(): string | undefined {\n return this._cachedSearchTerm;\n }\n\n /**\n * Sets the cached search term.\n */\n public set cachedSearchTerm(term: string | undefined) {\n this._cachedSearchTerm = term;\n }\n\n /**\n * Gets the last search options used.\n */\n public get lastSearchOptions(): ISearchOptions | undefined {\n return this._lastSearchOptions;\n }\n\n /**\n * Sets the last search options used.\n */\n public set lastSearchOptions(options: ISearchOptions | undefined) {\n this._lastSearchOptions = options;\n }\n\n /**\n * Validates a search term to ensure it's not empty or invalid.\n * @param term The search term to validate.\n * @returns true if the term is valid for searching.\n */\n public isValidSearchTerm(term: string): boolean {\n return !!(term && term.length > 0);\n }\n\n /**\n * Determines if search options have changed compared to the last search.\n * @param newOptions The new search options to compare.\n * @returns true if the options have changed.\n */\n public didOptionsChange(newOptions?: ISearchOptions): boolean {\n if (!this._lastSearchOptions) {\n return true;\n }\n if (!newOptions) {\n return false;\n }\n if (this._lastSearchOptions.caseSensitive !== newOptions.caseSensitive) {\n return true;\n }\n if (this._lastSearchOptions.regex !== newOptions.regex) {\n return true;\n }\n if (this._lastSearchOptions.wholeWord !== newOptions.wholeWord) {\n return true;\n }\n return false;\n }\n\n /**\n * Determines if a new search should trigger highlighting updates.\n * @param term The search term.\n * @param options The search options.\n * @returns true if highlighting should be updated.\n */\n public shouldUpdateHighlighting(term: string, options?: ISearchOptions): boolean {\n if (!options?.decorations) {\n return false;\n }\n return this._cachedSearchTerm === undefined ||\n term !== this._cachedSearchTerm ||\n this.didOptionsChange(options);\n }\n\n /**\n * Clears the cached search term.\n */\n public clearCachedTerm(): void {\n this._cachedSearchTerm = undefined;\n }\n\n /**\n * Resets all state.\n */\n public reset(): void {\n this._cachedSearchTerm = undefined;\n this._lastSearchOptions = undefined;\n }\n}\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport type { Terminal, IDisposable, ITerminalAddon } from '@xterm/xterm';\nimport type { SearchAddon as ISearchApi, ISearchOptions, ISearchAddonOptions, ISearchResultChangeEvent, ISearchDecorationOptions } from '@xterm/addon-search';\nimport { Emitter, type IEvent } from 'common/Event';\nimport { Disposable, MutableDisposable, toDisposable } from 'common/Lifecycle';\nimport { disposableTimeout } from 'common/Async';\nimport { SearchLineCache } from './SearchLineCache';\nimport { SearchState } from './SearchState';\nimport { SearchEngine, type ISearchResult } from './SearchEngine';\nimport { DecorationManager } from './DecorationManager';\nimport { SearchResultTracker } from './SearchResultTracker';\n\ninterface IInternalSearchOptions {\n noScroll: boolean;\n}\n\n/**\n * Configuration constants for the search addon functionality.\n */\nconst enum Constants {\n /**\n * Default maximum number of search results to highlight simultaneously. This limit prevents\n * performance degradation when searching for very common terms that would result in excessive\n * highlighting decorations.\n */\n DEFAULT_HIGHLIGHT_LIMIT = 1000\n}\n\nexport class SearchAddon extends Disposable implements ITerminalAddon, ISearchApi {\n private _terminal: Terminal | undefined;\n private _highlightLimit: number;\n private _highlightTimeout = this._register(new MutableDisposable());\n private _lineCache = this._register(new MutableDisposable());\n\n // Component instances\n private _state = new SearchState();\n private _engine: SearchEngine | undefined;\n private _decorationManager: DecorationManager | undefined;\n private _resultTracker = this._register(new SearchResultTracker());\n\n private readonly _onAfterSearch = this._register(new Emitter());\n public readonly onAfterSearch = this._onAfterSearch.event;\n private readonly _onBeforeSearch = this._register(new Emitter());\n public readonly onBeforeSearch = this._onBeforeSearch.event;\n\n public get onDidChangeResults(): IEvent {\n return this._resultTracker.onDidChangeResults;\n }\n\n constructor(options?: Partial) {\n super();\n\n this._highlightLimit = options?.highlightLimit ?? Constants.DEFAULT_HIGHLIGHT_LIMIT;\n }\n\n public activate(terminal: Terminal): void {\n this._terminal = terminal;\n this._lineCache.value = new SearchLineCache(terminal);\n this._engine = new SearchEngine(terminal, this._lineCache.value);\n this._decorationManager = new DecorationManager(terminal);\n this._register(this._terminal.onWriteParsed(() => this._updateMatches()));\n this._register(this._terminal.onResize(() => this._updateMatches()));\n this._register(toDisposable(() => this.clearDecorations()));\n }\n\n private _updateMatches(): void {\n this._highlightTimeout.clear();\n if (this._state.cachedSearchTerm && this._state.lastSearchOptions?.decorations) {\n this._highlightTimeout.value = disposableTimeout(() => {\n const term = this._state.cachedSearchTerm;\n this._state.clearCachedTerm();\n this.findPrevious(term!, { ...this._state.lastSearchOptions, incremental: true }, { noScroll: true });\n }, 200);\n }\n }\n\n public clearDecorations(retainCachedSearchTerm?: boolean): void {\n this._resultTracker.clearSelectedDecoration();\n this._decorationManager?.clearHighlightDecorations();\n this._resultTracker.clearResults();\n if (!retainCachedSearchTerm) {\n this._state.clearCachedTerm();\n }\n }\n\n public clearActiveDecoration(): void {\n this._resultTracker.clearSelectedDecoration();\n }\n\n /**\n * Find the next instance of the term, then scroll to and select it. If it\n * doesn't exist, do nothing.\n * @param term The search term.\n * @param searchOptions Search options.\n * @returns Whether a result was found.\n */\n public findNext(term: string, searchOptions?: ISearchOptions, internalSearchOptions?: IInternalSearchOptions): boolean {\n if (!this._terminal || !this._engine) {\n throw new Error('Cannot use addon until it has been loaded');\n }\n\n this._onBeforeSearch.fire();\n\n this._state.lastSearchOptions = searchOptions;\n\n if (this._state.shouldUpdateHighlighting(term, searchOptions)) {\n this._highlightAllMatches(term, searchOptions!);\n }\n\n const found = this._findNextAndSelect(term, searchOptions, internalSearchOptions);\n this._fireResults(searchOptions);\n this._state.cachedSearchTerm = term;\n\n this._onAfterSearch.fire();\n\n return found;\n }\n\n private _highlightAllMatches(term: string, searchOptions: ISearchOptions): void {\n if (!this._terminal || !this._engine || !this._decorationManager) {\n throw new Error('Cannot use addon until it has been loaded');\n }\n if (!this._state.isValidSearchTerm(term)) {\n this.clearDecorations();\n return;\n }\n\n // new search, clear out the old decorations\n this.clearDecorations(true);\n\n const results: ISearchResult[] = [];\n let prevResult: ISearchResult | undefined = undefined;\n let result = this._engine.find(term, 0, 0, searchOptions);\n\n while (result && (prevResult?.row !== result.row || prevResult?.col !== result.col)) {\n if (results.length >= this._highlightLimit) {\n break;\n }\n prevResult = result;\n results.push(prevResult);\n const cols = this._terminal.cols;\n let nextCol = prevResult.col + prevResult.size;\n let nextRow = prevResult.row;\n if (nextCol >= cols) {\n nextRow += Math.floor(nextCol / cols);\n nextCol = nextCol % cols;\n }\n result = this._engine.find(term, nextRow, nextCol, searchOptions);\n }\n\n this._resultTracker.updateResults(results, this._highlightLimit);\n if (searchOptions.decorations) {\n this._decorationManager.createHighlightDecorations(results, searchOptions.decorations);\n }\n }\n\n private _findNextAndSelect(term: string, searchOptions?: ISearchOptions, internalSearchOptions?: IInternalSearchOptions): boolean {\n if (!this._terminal || !this._engine) {\n return false;\n }\n if (!this._state.isValidSearchTerm(term)) {\n this._terminal.clearSelection();\n this.clearDecorations();\n return false;\n }\n\n const result = this._engine.findNextWithSelection(term, searchOptions, this._state.cachedSearchTerm);\n return this._selectResult(result, searchOptions?.decorations, internalSearchOptions?.noScroll);\n }\n\n /**\n * Find the previous instance of the term, then scroll to and select it. If it\n * doesn't exist, do nothing.\n * @param term The search term.\n * @param searchOptions Search options.\n * @returns Whether a result was found.\n */\n public findPrevious(term: string, searchOptions?: ISearchOptions, internalSearchOptions?: IInternalSearchOptions): boolean {\n if (!this._terminal || !this._engine) {\n throw new Error('Cannot use addon until it has been loaded');\n }\n\n this._onBeforeSearch.fire();\n\n this._state.lastSearchOptions = searchOptions;\n\n if (this._state.shouldUpdateHighlighting(term, searchOptions)) {\n this._highlightAllMatches(term, searchOptions!);\n }\n\n const found = this._findPreviousAndSelect(term, searchOptions, internalSearchOptions);\n this._fireResults(searchOptions);\n this._state.cachedSearchTerm = term;\n\n this._onAfterSearch.fire();\n\n return found;\n }\n\n private _fireResults(searchOptions?: ISearchOptions): void {\n this._resultTracker.fireResultsChanged(!!searchOptions?.decorations);\n }\n\n private _findPreviousAndSelect(term: string, searchOptions?: ISearchOptions, internalSearchOptions?: IInternalSearchOptions): boolean {\n if (!this._terminal || !this._engine) {\n return false;\n }\n if (!this._state.isValidSearchTerm(term)) {\n this._terminal.clearSelection();\n this.clearDecorations();\n return false;\n }\n\n const result = this._engine.findPreviousWithSelection(term, searchOptions, this._state.cachedSearchTerm);\n return this._selectResult(result, searchOptions?.decorations, internalSearchOptions?.noScroll);\n }\n\n /**\n * Selects and scrolls to a result.\n * @param result The result to select.\n * @returns Whether a result was selected.\n */\n private _selectResult(result: ISearchResult | undefined, options?: ISearchDecorationOptions, noScroll?: boolean): boolean {\n if (!this._terminal || !this._decorationManager) {\n return false;\n }\n\n this._resultTracker.clearSelectedDecoration();\n if (!result) {\n this._terminal.clearSelection();\n return false;\n }\n\n this._terminal.select(result.col, result.row, result.size);\n if (options) {\n const activeDecoration = this._decorationManager.createActiveDecoration(result, options);\n if (activeDecoration) {\n this._resultTracker.selectedDecoration = activeDecoration;\n }\n }\n\n if (!noScroll) {\n // If it is not in the viewport then we scroll else it just gets selected\n if (result.row >= (this._terminal.buffer.active.viewportY + this._terminal.rows) || result.row < this._terminal.buffer.active.viewportY) {\n let scroll = result.row - this._terminal.buffer.active.viewportY;\n scroll -= Math.floor(this._terminal.rows / 2);\n this._terminal.scrollLines(scroll);\n }\n }\n return true;\n }\n}\n"],"names":["root","factory","exports","module","define","amd","globalThis","millis","Promise","resolve","setTimeout","handler","timeout","store","timer","disposable","dispose","Lifecycle_1","toDisposable","clearTimeout","add","__webpack_require__","constructor","this","_token","_isDisposed","cancel","cancelAndSet","runner","Error","setIfNotSet","_isScheduled","set","queueMicrotask","_disposable","undefined","interval","context","handle","setInterval","clearInterval","EventUtils","_listeners","_disposed","event","_event","listener","thisArgs","disposables","entry","fn","slice","push","result","idx","indexOf","splice","Array","isArray","fire","length","call","listeners","i","len","forward","from","to","e","map","any","events","DisposableStore","runAndSubscribe","initial","arg","d","_disposables","Set","isDisposed","o","clear","Disposable","_store","_register","None","Object","freeze","value","_value","DecorationManager","_terminal","super","_highlightDecorations","_highlightedLines","clearHighlightDecorations","createHighlightDecorations","results","options","match","decorations","_createResultDecorations","decoration","_storeDecoration","createActiveDecoration","marker","line","_applyStyles","element","borderColor","isActiveResult","classList","contains","style","outline","decorationRanges","currentCol","col","remainingSize","size","markerOffset","buffer","active","baseY","cursorY","row","amountThisRow","Math","min","cols","range","registerMarker","registerDecoration","x","width","layer","backgroundColor","activeMatchBackground","matchBackground","overviewRulerOptions","has","color","activeMatchColorOverviewRuler","matchOverviewRuler","position","onRender","activeMatchBorder","matchBorder","onDispose","_lineCache","find","term","startRow","startCol","searchOptions","clearSelection","initLinesCache","searchPosition","_findInLine","y","rows","findNextWithSelection","cachedSearchTerm","prevSelectedPos","getSelectionPosition","end","start","findPreviousWithSelection","isReverseSearch","max","_isWholeWord","searchIndex","includes","getLine","isWrapped","cache","getLineFromCache","translateBufferLineToStringWithWrap","setLineInCache","stringLine","offsets","offset","_bufferColsToStringOffset","searchTerm","searchStringLine","regex","caseSensitive","toLowerCase","resultIndex","searchRegex","RegExp","foundTerm","exec","lastIndex","lastIndexOf","wholeWord","startRowOffset","endRowOffset","startColOffset","endColOffset","startColIndex","_stringLengthToBufferSize","cell","getCell","char","getChars","nextCell","getWidth","lineIndex","getCode","Async_1","SearchLineCache","_linesCacheTimeout","MutableDisposable","_linesCacheDisposables","_lastAccessTimestamp","_destroyLinesCache","_linesCache","combinedDisposable","onLineFeed","onCursorMove","onResize","Date","now","_scheduleLinesCacheTimeout","delay","disposableTimeout","elapsed","trimRight","strings","lineOffsets","nextLine","lineWrapsToNext","string","translateToString","lastCell","join","Event_1","SearchResultTracker","_searchResults","_onDidChangeResults","Emitter","onDidChangeResults","searchResults","selectedDecoration","_selectedDecoration","updateResults","maxResults","clearResults","clearSelectedDecoration","findResultIndex","fireResultsChanged","hasDecorations","resultCount","reset","_cachedSearchTerm","lastSearchOptions","_lastSearchOptions","isValidSearchTerm","didOptionsChange","newOptions","shouldUpdateHighlighting","clearCachedTerm","__webpack_module_cache__","moduleId","cachedModule","__webpack_modules__","SearchLineCache_1","SearchState_1","SearchEngine_1","DecorationManager_1","SearchResultTracker_1","SearchAddon","_resultTracker","_highlightTimeout","_state","SearchState","_onAfterSearch","onAfterSearch","_onBeforeSearch","onBeforeSearch","_highlightLimit","highlightLimit","activate","terminal","_engine","SearchEngine","_decorationManager","onWriteParsed","_updateMatches","clearDecorations","findPrevious","incremental","noScroll","retainCachedSearchTerm","clearActiveDecoration","findNext","internalSearchOptions","_highlightAllMatches","found","_findNextAndSelect","_fireResults","prevResult","nextCol","nextRow","floor","_selectResult","_findPreviousAndSelect","select","activeDecoration","viewportY","scroll","scrollLines"],"sourceRoot":""} ++{"version":3,"file":"addon-search.js","mappings":"CAAA,SAAAA,EAAAC,GACA,iBAAAC,SAAA,iBAAAC,OACAA,OAAAD,QAAAD,IACA,mBAAAG,QAAAA,OAAAC,IACAD,OAAA,GAAAH,GACA,iBAAAC,QACAA,QAAA,YAAAD,IAEAD,EAAA,YAAAC,GACC,CATD,CASCK,WAAA,2JCAD,SAAwBC,GACtB,OAAO,IAAIC,QAAQC,GAAWC,WAAWD,EAASF,GACpD,sBASA,SAAkCI,EAAqBC,EAAU,EAAGC,GAClE,MAAMC,EAAQJ,WAAW,KACvBC,IACIE,GACFE,EAAWC,WAEZJ,GACGG,GAAa,EAAAE,EAAAC,cAAa,KAC9BC,aAAaL,KAGf,OADAD,GAAOO,IAAIL,GACJA,CACT,EAzBA,MAAAE,EAAAI,EAAA,oBA2BA,iBAAAC,GACUC,KAAAC,QAAe,EACfD,KAAAE,aAAc,CAqCxB,CAnCS,OAAAT,GACLO,KAAKG,SACLH,KAAKE,aAAc,CACrB,CAEO,MAAAC,IACgB,IAAjBH,KAAKC,SACPL,aAAaI,KAAKC,QAClBD,KAAKC,QAAU,EAEnB,CAEO,YAAAG,CAAaC,EAAoBhB,GACtC,GAAIW,KAAKE,YACP,MAAM,IAAII,MAAM,mDAElBN,KAAKG,SACLH,KAAKC,OAASd,WAAW,KACvBa,KAAKC,QAAU,EACfI,KACChB,EACL,CAEO,WAAAkB,CAAYF,EAAoBhB,GACrC,GAAIW,KAAKE,YACP,MAAM,IAAII,MAAM,mDAEG,IAAjBN,KAAKC,SAGTD,KAAKC,OAASd,WAAW,KACvBa,KAAKC,QAAU,EACfI,KACChB,GACL,oBAQF,iBAAAU,GACUC,KAAAQ,cAAe,EACfR,KAAAE,aAAc,CA2BxB,CAzBS,OAAAT,GACLO,KAAKG,SACLH,KAAKE,aAAc,CACrB,CAEO,MAAAC,GACLH,KAAKQ,cAAe,CACtB,CAEO,GAAAC,CAAIJ,GACT,GAAIL,KAAKE,YACP,MAAM,IAAII,MAAM,4CAEdN,KAAKQ,eAGTR,KAAKQ,cAAe,EACpBE,eAAe,KACRV,KAAKQ,eAGVR,KAAKQ,cAAe,EACpBH,OAEJ,mBAGF,iBAAAN,GAEUC,KAAAE,aAAc,CA2BxB,CAzBS,MAAAC,GACLH,KAAKW,aAAalB,UAClBO,KAAKW,iBAAcC,CACrB,CAEO,YAAAR,CAAaC,EAAoBQ,EAAkBC,EAAsC/B,YAC9F,GAAIiB,KAAKE,YACP,MAAM,IAAII,MAAM,oDAElBN,KAAKG,SACL,MAAMY,EAASD,EAAQE,YAAY,KACjCX,KACCQ,GACHb,KAAKW,YAAc,CACjBlB,QAAS,KACPqB,EAAQG,cAAcF,GACtBf,KAAKW,iBAAcC,GAGzB,CAEO,OAAAnB,GACLO,KAAKG,SACLH,KAAKE,aAAc,CACrB,8FCnIF,MAAAR,EAAAI,EAAA,KAoEA,IAAiBoB,YA9DjB,iBAAAnB,GACUC,KAAAmB,WAAqD,GACrDnB,KAAAoB,WAAY,CA0DtB,CAvDE,SAAWC,GACT,OAAIrB,KAAKsB,SAGTtB,KAAKsB,OAAS,CAACC,EAAyBC,EAAgBC,KACtD,GAAIzB,KAAKoB,UACP,OAAO,EAAA1B,EAAAC,cAAa,QAGtB,MAAM+B,EAAQ,CAAEC,GAAIJ,EAAUC,YAC9BxB,KAAKmB,WAAanB,KAAKmB,WAAWS,QAClC5B,KAAKmB,WAAWU,KAAKH,GAErB,MAAMI,GAAS,EAAApC,EAAAC,cAAa,KAC1B,MAAMoC,EAAM/B,KAAKmB,WAAWa,QAAQN,IACvB,IAATK,IACF/B,KAAKmB,WAAanB,KAAKmB,WAAWS,QAClC5B,KAAKmB,WAAWc,OAAOF,EAAK,MAYhC,OARIN,IACES,MAAMC,QAAQV,GAChBA,EAAYI,KAAKC,GAEjBL,EAAY5B,IAAIiC,IAIbA,IA3BA9B,KAAKsB,MA8BhB,CAEO,IAAAc,CAAKf,GACV,GAAIrB,KAAKoB,YAAcpB,KAAKmB,WAAWkB,OACrC,OAEF,GAA+B,IAA3BrC,KAAKmB,WAAWkB,OAElB,YADArC,KAAKmB,WAAW,GAAGQ,GAAGW,KAAKtC,KAAKmB,WAAW,GAAGK,SAAUH,GAG1D,MAAMkB,EAAYvC,KAAKmB,WACvB,IAAK,IAAIqB,EAAI,EAAGC,EAAMF,EAAUF,OAAQG,EAAIC,IAAOD,EACjDD,EAAUC,GAAGb,GAAGW,KAAKC,EAAUC,GAAGhB,SAAUH,EAEhD,CAEO,OAAA5B,GACDO,KAAKoB,YAGTpB,KAAKoB,WAAY,EACjBpB,KAAKmB,WAAWkB,OAAS,EAC3B,GAGF,SAAiBnB,GACCA,EAAAwB,QAAhB,SAA2BC,EAAiBC,GAC1C,OAAOD,EAAKE,GAAKD,EAAGR,KAAKS,GAC3B,EAEgB3B,EAAA4B,IAAhB,SAA0BzB,EAAkByB,GAC1C,MAAO,CAACvB,EAAyBC,EAAgBC,IACxCJ,EAAMmB,GAAKjB,EAASe,KAAKd,EAAUsB,EAAIN,SAAK5B,EAAWa,EAElE,EAIgBP,EAAA6B,IAAhB,YAA0BC,GACxB,MAAO,CAACzB,EAAyBC,EAAgBC,KAC/C,MAAMnC,EAAQ,IAAII,EAAAuD,gBAClB,IAAK,MAAM5B,KAAS2B,EAClB1D,EAAMO,IAAIwB,EAAMwB,GAAKtB,EAASe,KAAKd,EAAUqB,KAS/C,OAPIpB,IACES,MAAMC,QAAQV,GAChBA,EAAYI,KAAKvC,GAEjBmC,EAAY5B,IAAIP,IAGbA,EAEX,EAIgB4B,EAAAgC,gBAAhB,SAAmC7B,EAAkBjC,EAAqC+D,GAExF,OADA/D,EAAQ+D,GACD9B,EAAMwB,GAAKzD,EAAQyD,GAC5B,CACD,CApCD,CAAiB3B,IAAUvC,EAAAuC,WAAVA,EAAU,eChE3B,SAAAvB,EAA6BgC,GAC3B,MAAO,CAAElC,QAASkC,EACpB,CAKA,SAAAlC,EAA+C2D,GAC7C,IAAKA,EACH,OAAOA,EAET,GAAIlB,MAAMC,QAAQiB,GAAM,CACtB,IAAK,MAAMC,KAAKD,EACdC,EAAE5D,UAEJ,MAAO,EACT,CAEA,OADA2D,EAAI3D,UACG2D,CACT,8JAEA,YAAsC3B,GACpC,OAAO9B,EAAa,IAAMF,EAAQgC,GACpC,EAEA,MAAAwB,EAAA,WAAAlD,GACmBC,KAAAsD,aAAe,IAAIC,IAC5BvD,KAAAE,aAAc,CAgCxB,CA9BE,cAAWsD,GACT,OAAOxD,KAAKE,WACd,CAEO,GAAAL,CAA2B4D,GAMhC,OALIzD,KAAKE,YACPuD,EAAEhE,UAEFO,KAAKsD,aAAazD,IAAI4D,GAEjBA,CACT,CAEO,OAAAhE,GACL,IAAIO,KAAKE,YAAT,CAGAF,KAAKE,aAAc,EACnB,IAAK,MAAMmD,KAAKrD,KAAKsD,aACnBD,EAAE5D,UAEJO,KAAKsD,aAAaI,OALlB,CAMF,CAEO,KAAAA,GACL,IAAK,MAAML,KAAKrD,KAAKsD,aACnBD,EAAE5D,UAEJO,KAAKsD,aAAaI,OACpB,sBAGF,MAAAC,EAAA,WAAA5D,GAGqBC,KAAA4D,OAAS,IAAIX,CASlC,CAPS,OAAAxD,GACLO,KAAK4D,OAAOnE,SACd,CAEU,SAAAoE,CAAiCJ,GACzC,OAAOzD,KAAK4D,OAAO/D,IAAI4D,EACzB,iBAVuBE,EAAAG,KAAoBC,OAAOC,OAAO,CAAE,OAAAvE,GAAY,wBAazE,iBAAAM,GAEUC,KAAAE,aAAc,CAuBxB,CArBE,SAAW+D,GACT,OAAOjE,KAAKE,iBAAcU,EAAYZ,KAAKkE,MAC7C,CAEA,SAAWD,CAAMA,GACXjE,KAAKE,aAAe+D,IAAUjE,KAAKkE,SAGvClE,KAAKkE,QAAQzE,UACbO,KAAKkE,OAASD,EAChB,CAEO,KAAAP,GACL1D,KAAKiE,WAAQrD,CACf,CAEO,OAAAnB,GACLO,KAAKE,aAAc,EACnBF,KAAKkE,QAAQzE,UACbO,KAAKkE,YAAStD,CAChB,2FCxGF,MAAAlB,EAAAI,EAAA,KAuBA,MAAAqE,UAAuCzE,EAAAiE,WAIrC,WAAA5D,CAA6BqE,GAC3BC,QAD2BrE,KAAAoE,UAAAA,EAHrBpE,KAAAsE,sBAAsC,GACtCtE,KAAAuE,kBAAiC,IAAIhB,IAI3CvD,KAAK6D,WAAU,EAAAnE,EAAAC,cAAa,IAAMK,KAAKwE,6BACzC,CAOO,0BAAAC,CAA2BC,EAA0BC,GAC1D3E,KAAKwE,4BAEL,IAAK,MAAMI,KAASF,EAAS,CAC3B,MAAMG,EAAc7E,KAAK8E,yBAAyBF,EAAOD,GAAS,GAClE,GAAIE,EACF,IAAK,MAAME,KAAcF,EACvB7E,KAAKgF,iBAAiBD,EAAYH,EAGxC,CACF,CAQO,sBAAAK,CAAuBnD,EAAuB6C,GACnD,MAAME,EAAc7E,KAAK8E,yBAAyBhD,EAAQ6C,GAAS,GACnE,GAAIE,EACF,MAAO,CAAEA,cAAaD,MAAO9C,EAAQ,OAAArC,IAAY,EAAAC,EAAAD,SAAQoF,EAAc,EAG3E,CAKO,yBAAAL,IACL,EAAA9E,EAAAD,SAAQO,KAAKsE,uBACbtE,KAAKsE,sBAAwB,GAC7BtE,KAAKuE,kBAAkBb,OACzB,CAOQ,gBAAAsB,CAAiBD,EAAyBH,GAChD5E,KAAKuE,kBAAkB1E,IAAIkF,EAAWG,OAAOC,MAC7CnF,KAAKsE,sBAAsBzC,KAAK,CAAEkD,aAAYH,QAAO,OAAAnF,GAAYsF,EAAWtF,SAAW,GACzF,CAQQ,YAAA2F,CAAaC,EAAsBC,EAAiCC,GACrEF,EAAQG,UAAUC,SAAS,kCAC9BJ,EAAQG,UAAU3F,IAAI,gCAClByF,IACFD,EAAQK,MAAMC,QAAU,aAAaL,MAGrCC,GACFF,EAAQG,UAAU3F,IAAI,sCAE1B,CASQ,wBAAAiF,CAAyBhD,EAAuB6C,EAAmCY,GAEzF,MAAMK,EAA+C,GACrD,IAAIC,EAAa/D,EAAOgE,IACpBC,EAAgBjE,EAAOkE,KACvBC,GAAgBjG,KAAKoE,UAAU8B,OAAOC,OAAOC,MAAQpG,KAAKoE,UAAU8B,OAAOC,OAAOE,QAAUvE,EAAOwE,IACvG,KAAOP,EAAgB,GAAG,CACxB,MAAMQ,EAAgBC,KAAKC,IAAIzG,KAAKoE,UAAUsC,KAAOb,EAAYE,GACjEH,EAAiB/D,KAAK,CAACoE,EAAcJ,EAAYU,IACjDV,EAAa,EACbE,GAAiBQ,EACjBN,GACF,CAGA,MAAMpB,EAA6B,GACnC,IAAK,MAAM8B,KAASf,EAAkB,CACpC,MAAMV,EAASlF,KAAKoE,UAAUwC,eAAeD,EAAM,IAC7C5B,EAAa/E,KAAKoE,UAAUyC,mBAAmB,CACnD3B,SACA4B,EAAGH,EAAM,GACTI,MAAOJ,EAAM,GACbK,MAAOzB,EAAiB,MAAQ,SAChC0B,gBAAiB1B,EAAiBZ,EAAQuC,sBAAwBvC,EAAQwC,gBAC1EC,qBAAsBpH,KAAKuE,kBAAkB8C,IAAInC,EAAOC,WAAQvE,EAAY,CAC1E0G,MAAO/B,EAAiBZ,EAAQ4C,8BAAgC5C,EAAQ6C,mBACxEC,SAAU,YAGd,GAAI1C,EAAY,CACd,MAAMtD,EAA6B,GACnCA,EAAYI,KAAKqD,GACjBzD,EAAYI,KAAKkD,EAAW2C,SAAU7E,GAAM7C,KAAKoF,aAAavC,EAAG0C,EAAiBZ,EAAQgD,kBAAoBhD,EAAQiD,aAAa,KACnInG,EAAYI,KAAKkD,EAAW8C,UAAU,KAAM,EAAAnI,EAAAD,SAAQgC,KACpDoD,EAAYhD,KAAKkD,EACnB,CACF,CAEA,OAA8B,IAAvBF,EAAYxC,YAAezB,EAAYiE,CAChD,wHC/GF,MACE,WAAA9E,CACmBqE,EACA0D,kBADA1D,kBACA0D,CAChB,CAUI,IAAAC,CAAKC,EAAcC,EAAkBC,EAAkBC,GAC5D,IAAKH,GAAwB,IAAhBA,EAAK3F,OAEhB,YADArC,KAAKoE,UAAUgE,iBAGjB,GAAIF,GAAYlI,KAAKoE,UAAUsC,KAC7B,MAAM,IAAIpG,MAAM,gBAAgB4H,8BAAqClI,KAAKoE,UAAUsC,aAGtF1G,KAAK8H,WAAWO,iBAEhB,MAAMC,EAAkC,CACtCL,WACAC,YAIF,IAAIpG,EAAS9B,KAAKuI,YAAYP,EAAMM,EAAgBH,GAEpD,IAAKrG,EACH,IAAK,IAAI0G,EAAIP,EAAW,EAAGO,EAAIxI,KAAKoE,UAAU8B,OAAOC,OAAOC,MAAQpG,KAAKoE,UAAUqE,OAC7EzI,KAAK0I,yBAAyBF,EAAGL,KAGrCG,EAAeL,SAAWO,EAC1BF,EAAeJ,SAAW,EAC1BpG,EAAS9B,KAAKuI,YAAYP,EAAMM,EAAgBH,IAC5CrG,IAPmF0G,KAY3F,OAAO1G,CACT,CASO,qBAAA6G,CAAsBX,EAAcG,EAAgCS,GACzE,IAAKZ,GAAwB,IAAhBA,EAAK3F,OAEhB,YADArC,KAAKoE,UAAUgE,iBAIjB,MAAMS,EAAkB7I,KAAKoE,UAAU0E,uBACvC9I,KAAKoE,UAAUgE,iBAEf,IAAIF,EAAW,EACXD,EAAW,EACXY,IACED,IAAqBZ,GACvBE,EAAWW,EAAgBE,IAAIjC,EAC/BmB,EAAWY,EAAgBE,IAAIP,IAE/BN,EAAWW,EAAgBG,MAAMlC,EACjCmB,EAAWY,EAAgBG,MAAMR,IAIrCxI,KAAK8H,WAAWO,iBAEhB,MAAMC,EAAkC,CACtCL,WACAC,YAIF,IAAIpG,EAAS9B,KAAKuI,YAAYP,EAAMM,EAAgBH,GAEpD,IAAKrG,EACH,IAAK,IAAI0G,EAAIP,EAAW,EAAGO,EAAIxI,KAAKoE,UAAU8B,OAAOC,OAAOC,MAAQpG,KAAKoE,UAAUqE,OAC7EzI,KAAK0I,yBAAyBF,EAAGL,KAGrCG,EAAeL,SAAWO,EAC1BF,EAAeJ,SAAW,EAC1BpG,EAAS9B,KAAKuI,YAAYP,EAAMM,EAAgBH,IAC5CrG,IAPmF0G,KAa3F,IAAK1G,GAAuB,IAAbmG,EACb,IAAK,IAAIO,EAAI,EAAGA,EAAIP,IACdjI,KAAK0I,yBAAyBF,EAAGL,KAGrCG,EAAeL,SAAWO,EAC1BF,EAAeJ,SAAW,EAC1BpG,EAAS9B,KAAKuI,YAAYP,EAAMM,EAAgBH,IAC5CrG,IAPwB0G,KAoBhC,OANK1G,GAAU+G,IACbP,EAAeL,SAAWY,EAAgBG,MAAMR,EAChDF,EAAeJ,SAAW,EAC1BpG,EAAS9B,KAAKuI,YAAYP,EAAMM,EAAgBH,IAG3CrG,CACT,CASO,yBAAAmH,CAA0BjB,EAAcG,EAAgCS,GAC7E,IAAKZ,GAAwB,IAAhBA,EAAK3F,OAEhB,YADArC,KAAKoE,UAAUgE,iBAIjB,MAAMS,EAAkB7I,KAAKoE,UAAU0E,uBACvC9I,KAAKoE,UAAUgE,iBAEf,IAAIH,EAAWjI,KAAKoE,UAAU8B,OAAOC,OAAOC,MAAQpG,KAAKoE,UAAUqE,KAAO,EAC1E,MAAMP,EAAWlI,KAAKoE,UAAUsC,KAC1BwC,GAAkB,EAExBlJ,KAAK8H,WAAWO,iBAChB,MAAMC,EAAkC,CACtCL,WACAC,YAGF,IAAIpG,EAkBJ,GAjBI+G,IACFP,EAAeL,SAAWA,EAAWY,EAAgBG,MAAMR,EAC3DF,EAAeJ,SAAWW,EAAgBG,MAAMlC,EAC5C8B,IAAqBZ,IAEvBlG,EAAS9B,KAAKuI,YAAYP,EAAMM,EAAgBH,GAAe,GAC1DrG,IAEHwG,EAAeL,SAAWA,EAAWY,EAAgBE,IAAIP,EACzDF,EAAeJ,SAAWW,EAAgBE,IAAIjC,KAKpDhF,IAAW9B,KAAKuI,YAAYP,EAAMM,EAAgBH,EAAee,IAG5DpH,EAAQ,CACXwG,EAAeJ,SAAW1B,KAAK2C,IAAIb,EAAeJ,SAAUlI,KAAKoE,UAAUsC,MAC3E,IAAK,IAAI8B,EAAIP,EAAW,EAAGO,GAAK,IAC9BF,EAAeL,SAAWO,EAC1B1G,EAAS9B,KAAKuI,YAAYP,EAAMM,EAAgBH,EAAee,IAC3DpH,GAH6B0G,KAOrC,CAEA,IAAK1G,GAAUmG,IAAcjI,KAAKoE,UAAU8B,OAAOC,OAAOC,MAAQpG,KAAKoE,UAAUqE,KAAO,EACtF,IAAK,IAAID,EAAKxI,KAAKoE,UAAU8B,OAAOC,OAAOC,MAAQpG,KAAKoE,UAAUqE,KAAO,EAAID,GAAKP,IAChFK,EAAeL,SAAWO,EAC1B1G,EAAS9B,KAAKuI,YAAYP,EAAMM,EAAgBH,EAAee,IAC3DpH,GAHsF0G,KAS9F,OAAO1G,CACT,CASQ,YAAAsH,CAAaC,EAAqBlE,EAAc6C,GACtD,OAAyB,IAAhBqB,GAAuB,qCAA8BC,SAASnE,EAAKkE,EAAc,OACrFA,EAAcrB,EAAK3F,SAAY8C,EAAK9C,QAAY,qCAA8BiH,SAASnE,EAAKkE,EAAcrB,EAAK3F,SACtH,CAQQ,wBAAAqG,CAAyBpC,EAAa6B,GAC5C,OAAIA,GAAeoB,QAASpB,GAAeqB,YAGqB,IAAzDxJ,KAAKoE,UAAU8B,OAAOC,OAAOsD,QAAQnD,IAAMoD,SACpD,CAcQ,WAAAnB,CAAYP,EAAcM,EAAiCH,EAAgC,GAAIe,GAA2B,GAIhI,KAAOlJ,KAAKoE,UAAU8B,OAAOC,OAAOsD,QAAQnB,EAAeL,WAAWyB,WAAW,CAE/E,GADApB,EAAeJ,UAAYlI,KAAKoE,UAAUsC,KACtCwC,EACF,OAEFZ,EAAeL,UACjB,CACA,MAAM3B,EAAMgC,EAAeL,SACrBnC,EAAMwC,EAAeJ,SAE3B,IAAIyB,EAAQ3J,KAAK8H,WAAW8B,iBAAiBtD,GACxCqD,IACHA,EAAQ3J,KAAK8H,WAAW+B,oCAAoCvD,GAAK,GACjEtG,KAAK8H,WAAWgC,eAAexD,EAAKqD,IAEtC,MAAOI,EAAYC,GAAWL,EAExBM,EAASjK,KAAKkK,0BAA0B5D,EAAKR,GACnD,IAAIqE,EAAanC,EACboC,EAAmBL,EAClB5B,EAAcoB,QACjBY,EAAahC,EAAckC,cAAgBrC,EAAOA,EAAKsC,cACvDF,EAAmBjC,EAAckC,cAAgBN,EAAaA,EAAWO,eAG3E,IAAIC,GAAe,EACnB,GAAIpC,EAAcoB,MAAO,CACvB,MAAMiB,EAAcC,OAAON,EAAYhC,EAAckC,cAAgB,IAAM,MAC3E,IAAIK,EACJ,GAAIxB,EAEF,KAAOwB,EAAYF,EAAYG,KAAKP,EAAiBxI,MAAM,EAAGqI,KAC5DM,EAAcC,EAAYI,UAAYF,EAAU,GAAGrI,OACnD2F,EAAO0C,EAAU,GACjBF,EAAYI,WAAc5C,EAAK3F,OAAS,OAG1CqI,EAAYF,EAAYG,KAAKP,EAAiBxI,MAAMqI,IAChDS,GAAaA,EAAU,GAAGrI,OAAS,IACrCkI,EAAcN,GAAUO,EAAYI,UAAYF,EAAU,GAAGrI,QAC7D2F,EAAO0C,EAAU,GAGvB,MACMxB,EACEe,EAASE,EAAW9H,QAAU,IAChCkI,EAAcH,EAAiBS,YAAYV,EAAYF,EAASE,EAAW9H,SAG7EkI,EAAcH,EAAiBpI,QAAQmI,EAAYF,GAIvD,GAAIM,GAAe,EAAG,CACpB,GAAIpC,EAAcqB,YAAcxJ,KAAKoJ,aAAamB,EAAaH,EAAkBpC,GAC/E,OAKF,IAAI8C,EAAiB,EACrB,KAAOA,EAAiBd,EAAQ3H,OAAS,GAAKkI,GAAeP,EAAQc,EAAiB,IACpFA,IAEF,IAAIC,EAAeD,EACnB,KAAOC,EAAef,EAAQ3H,OAAS,GAAKkI,EAAcvC,EAAK3F,QAAU2H,EAAQe,EAAe,IAC9FA,IAEF,MAAMC,EAAiBT,EAAcP,EAAQc,GACvCG,EAAeV,EAAcvC,EAAK3F,OAAS2H,EAAQe,GACnDG,EAAgBlL,KAAKmL,0BAA0B7E,EAAMwE,EAAgBE,GAI3E,MAAO,CACLhD,OACAlC,IAAKoF,EACL5E,IAAKA,EAAMwE,EACX9E,KAPkBhG,KAAKmL,0BAA0B7E,EAAMyE,EAAcE,GAC5CC,EAAgBlL,KAAKoE,UAAUsC,MAAQqE,EAAeD,GAQnF,CACF,CAEQ,yBAAAK,CAA0B7E,EAAa2D,GAC7C,MAAM9E,EAAOnF,KAAKoE,UAAU8B,OAAOC,OAAOsD,QAAQnD,GAClD,IAAKnB,EACH,OAAO,EAET,IAAK,IAAI3C,EAAI,EAAGA,EAAIyH,EAAQzH,IAAK,CAC/B,MAAM4I,EAAOjG,EAAKkG,QAAQ7I,GAC1B,IAAK4I,EACH,MAGF,MAAME,EAAOF,EAAKG,WACdD,EAAKjJ,OAAS,IAChB4H,GAAUqB,EAAKjJ,OAAS,GAI1B,MAAMmJ,EAAWrG,EAAKkG,QAAQ7I,EAAI,GAC9BgJ,GAAoC,IAAxBA,EAASC,YACvBxB,GAEJ,CACA,OAAOA,CACT,CAEQ,yBAAAC,CAA0BjC,EAAkBvB,GAClD,IAAIgF,EAAYzD,EACZgC,EAAS,EACT9E,EAAOnF,KAAKoE,UAAU8B,OAAOC,OAAOsD,QAAQiC,GAChD,KAAOhF,EAAO,GAAKvB,GAAM,CACvB,IAAK,IAAI3C,EAAI,EAAGA,EAAIkE,GAAQlE,EAAIxC,KAAKoE,UAAUsC,KAAMlE,IAAK,CACxD,MAAM4I,EAAOjG,EAAKkG,QAAQ7I,GAC1B,IAAK4I,EACH,MAEEA,EAAKK,aAEPxB,GAA6B,IAAnBmB,EAAKO,UAAkB,EAAIP,EAAKG,WAAWlJ,OAEzD,CAGA,GAFAqJ,IACAvG,EAAOnF,KAAKoE,UAAU8B,OAAOC,OAAOsD,QAAQiC,GACxCvG,IAASA,EAAKuE,UAChB,MAEFhD,GAAQ1G,KAAKoE,UAAUsC,IACzB,CACA,OAAOuD,CACT,yFClZF,MAAAvK,EAAAI,EAAA,KACA8L,EAAA9L,EAAA,KAwBA,MAAA+L,UAAqCnM,EAAAiE,WAanC,WAAA5D,CAA6BqE,GAC3BC,QAD2BrE,KAAAoE,UAAAA,EANrBpE,KAAA8L,mBAAqB9L,KAAK6D,UAAU,IAAInE,EAAAqM,mBACxC/L,KAAAgM,uBAAyBhM,KAAK6D,UAAU,IAAInE,EAAAqM,mBAG5C/L,KAAAiM,qBAAuB,EAI7BjM,KAAK6D,WAAU,EAAAnE,EAAAC,cAAa,IAAMK,KAAKkM,sBACzC,CAKO,cAAA7D,GACArI,KAAKmM,cACRnM,KAAKmM,YAAc,IAAIjK,MAAMlC,KAAKoE,UAAU8B,OAAOC,OAAO9D,QAC1DrC,KAAKgM,uBAAuB/H,OAAQ,EAAAvE,EAAA0M,oBAClCpM,KAAKoE,UAAUiI,WAAW,IAAMrM,KAAKkM,sBACrClM,KAAKoE,UAAUkI,aAAa,IAAMtM,KAAKkM,sBACvClM,KAAKoE,UAAUmI,SAAS,IAAMvM,KAAKkM,wBAIvClM,KAAKiM,qBAAuBO,KAAKC,MAC5BzM,KAAK8L,mBAAmB7H,OAC3BjE,KAAK0M,2BAA0B,KAEnC,CAEQ,kBAAAR,GACNlM,KAAKmM,iBAAcvL,EACnBZ,KAAKiM,qBAAuB,EAC5BjM,KAAKgM,uBAAuBtI,QAC5B1D,KAAK8L,mBAAmBpI,OAC1B,CAEQ,0BAAAgJ,CAA2BC,GACjC3M,KAAK8L,mBAAmB7H,OAAQ,EAAA2H,EAAAgB,mBAAkB,KAChD,IAAK5M,KAAKmM,YACR,OAEF,MACMU,EADML,KAAKC,MACKzM,KAAKiM,qBACvBY,GAAO,KACT7M,KAAKkM,qBAGPlM,KAAK0M,2BAA2B,KAAqCG,IACpEF,EACL,CAEO,gBAAA/C,CAAiBtD,GACtB,OAAOtG,KAAKmM,cAAc7F,EAC5B,CAEO,cAAAwD,CAAexD,EAAa5E,GAC7B1B,KAAKmM,cACPnM,KAAKmM,YAAY7F,GAAO5E,EAE5B,CAUO,mCAAAmI,CAAoC6B,EAAmBoB,GAC5D,MAAMC,EAAU,GACVC,EAAc,CAAC,GACrB,IAAI7H,EAAOnF,KAAKoE,UAAU8B,OAAOC,OAAOsD,QAAQiC,GAChD,KAAOvG,GAAM,CACX,MAAM8H,EAAWjN,KAAKoE,UAAU8B,OAAOC,OAAOsD,QAAQiC,EAAY,GAC5DwB,IAAkBD,GAAWA,EAASvD,UAC5C,IAAIyD,EAAShI,EAAKiI,mBAAmBF,GAAmBJ,GACxD,GAAII,GAAmBD,EAAU,CAC/B,MAAMI,EAAWlI,EAAKkG,QAAQlG,EAAK9C,OAAS,GACrBgL,GAAmC,IAAvBA,EAAS1B,WAA2C,IAAxB0B,EAAS5B,YAEd,IAApCwB,EAAS5B,QAAQ,IAAII,aACzC0B,EAASA,EAAOvL,MAAM,GAAI,GAE9B,CAEA,GADAmL,EAAQlL,KAAKsL,IACTD,EAGF,MAFAF,EAAYnL,KAAKmL,EAAYA,EAAY3K,OAAS,GAAK8K,EAAO9K,QAIhEqJ,IACAvG,EAAO8H,CACT,CACA,MAAO,CAACF,EAAQO,KAAK,IAAKN,EAC5B,gHC/HF,MAAAO,EAAAzN,EAAA,KACAJ,EAAAI,EAAA,KAcA,MAAA0N,UAAyC9N,EAAAiE,WAAzC,WAAA5D,uBACUC,KAAAyN,eAAkC,GAGzBzN,KAAA0N,oBAAsB1N,KAAK6D,UAAU,IAAI0J,EAAAI,QA4F5D,CA3FE,sBAAWC,GAAyD,OAAO5N,KAAK0N,oBAAoBrM,KAAO,CAK3G,iBAAWwM,GACT,OAAO7N,KAAKyN,cACd,CAKA,sBAAWK,GACT,OAAO9N,KAAK+N,mBACd,CAKA,sBAAWD,CAAmB/I,GAC5B/E,KAAK+N,oBAAsBhJ,CAC7B,CAOO,aAAAiJ,CAActJ,EAA0BuJ,GAC7CjO,KAAKyN,eAAiB/I,EAAQ9C,MAAM,EAAGqM,EACzC,CAKO,YAAAC,GACLlO,KAAKyN,eAAiB,EACxB,CAKO,uBAAAU,GACDnO,KAAK+N,sBACP/N,KAAK+N,oBAAoBtO,UACzBO,KAAK+N,yBAAsBnN,EAE/B,CAOO,eAAAwN,CAAgBtM,GACrB,IAAK,IAAIU,EAAI,EAAGA,EAAIxC,KAAKyN,eAAepL,OAAQG,IAAK,CACnD,MAAMoC,EAAQ5E,KAAKyN,eAAejL,GAClC,GAAIoC,EAAM0B,MAAQxE,EAAOwE,KAAO1B,EAAMkB,MAAQhE,EAAOgE,KAAOlB,EAAMoB,OAASlE,EAAOkE,KAChF,OAAOxD,CAEX,CACA,OAAQ,CACV,CAMO,kBAAA6L,CAAmBC,GACxB,IAAKA,EACH,OAGF,IAAI/D,GAAe,EACfvK,KAAK+N,sBACPxD,EAAcvK,KAAKoO,gBAAgBpO,KAAK+N,oBAAoBnJ,QAG9D5E,KAAK0N,oBAAoBtL,KAAK,CAC5BmI,cACAgE,YAAavO,KAAKyN,eAAepL,QAErC,CAKO,KAAAmM,GACLxO,KAAKmO,0BACLnO,KAAKkO,cACP,wHC1GF,MAOE,oBAAWtF,GACT,OAAO5I,KAAKyO,iBACd,CAKA,oBAAW7F,CAAiBZ,GAC1BhI,KAAKyO,kBAAoBzG,CAC3B,CAKA,qBAAW0G,GACT,OAAO1O,KAAK2O,kBACd,CAKA,qBAAWD,CAAkB/J,GAC3B3E,KAAK2O,mBAAqBhK,CAC5B,CAOO,iBAAAiK,CAAkB5G,GACvB,SAAUA,GAAQA,EAAK3F,OAAS,EAClC,CAOO,gBAAAwM,CAAiBC,GACtB,OAAK9O,KAAK2O,sBAGLG,IAGD9O,KAAK2O,mBAAmBtE,gBAAkByE,EAAWzE,eAGrDrK,KAAK2O,mBAAmBpF,QAAUuF,EAAWvF,OAG7CvJ,KAAK2O,mBAAmBnF,YAAcsF,EAAWtF,UAIvD,CAQO,wBAAAuF,CAAyB/G,EAAcrD,GAC5C,QAAKA,GAASE,mBAGoBjE,IAA3BZ,KAAKyO,mBACLzG,IAAShI,KAAKyO,mBACdzO,KAAK6O,iBAAiBlK,GAC/B,CAKO,eAAAqK,GACLhP,KAAKyO,uBAAoB7N,CAC3B,CAKO,KAAA4N,GACLxO,KAAKyO,uBAAoB7N,EACzBZ,KAAK2O,wBAAqB/N,CAC5B,KCvGFqO,EAAA,GAGA,SAAAnP,EAAAoP,GAEA,IAAAC,EAAAF,EAAAC,GACA,QAAAtO,IAAAuO,EACA,OAAAA,EAAAxQ,QAGA,IAAAC,EAAAqQ,EAAAC,GAAA,CAGAvQ,QAAA,IAOA,OAHAyQ,EAAAF,GAAAtQ,EAAAA,EAAAD,QAAAmB,GAGAlB,EAAAD,OACA,oGCfA,MAAA4O,EAAAzN,EAAA,KACAJ,EAAAI,EAAA,KACA8L,EAAA9L,EAAA,KACAuP,EAAAvP,EAAA,KACAwP,EAAAxP,EAAA,KACAyP,EAAAzP,EAAA,KACA0P,EAAA1P,EAAA,KACA2P,EAAA3P,EAAA,KAkBA,MAAA4P,UAAiChQ,EAAAiE,WAiB/B,sBAAWiK,GACT,OAAO5N,KAAK2P,eAAe/B,kBAC7B,CAEA,WAAA7N,CAAY4E,GACVN,QAnBMrE,KAAA4P,kBAAoB5P,KAAK6D,UAAU,IAAInE,EAAAqM,mBACvC/L,KAAA8H,WAAa9H,KAAK6D,UAAU,IAAInE,EAAAqM,mBAGhC/L,KAAA6P,OAAS,IAAIP,EAAAQ,YAGb9P,KAAA2P,eAAiB3P,KAAK6D,UAAU,IAAI4L,EAAAjC,qBAE3BxN,KAAA+P,eAAiB/P,KAAK6D,UAAU,IAAI0J,EAAAI,SACrC3N,KAAAgQ,cAAgBhQ,KAAK+P,eAAe1O,MACnCrB,KAAAiQ,gBAAkBjQ,KAAK6D,UAAU,IAAI0J,EAAAI,SACtC3N,KAAAkQ,eAAiBlQ,KAAKiQ,gBAAgB5O,MASpDrB,KAAKmQ,gBAAkBxL,GAASyL,gBAAc,GAChD,CAEO,QAAAC,CAASC,GACdtQ,KAAKoE,UAAYkM,EACjBtQ,KAAK8H,WAAW7D,MAAQ,IAAIoL,EAAAxD,gBAAgByE,GAC5CtQ,KAAKuQ,QAAU,IAAIhB,EAAAiB,aAAaF,EAAUtQ,KAAK8H,WAAW7D,OAC1DjE,KAAKyQ,mBAAqB,IAAIjB,EAAArL,kBAAkBmM,GAChDtQ,KAAK6D,UAAU7D,KAAKoE,UAAUsM,cAAc,IAAM1Q,KAAK2Q,mBACvD3Q,KAAK6D,UAAU7D,KAAKoE,UAAUmI,SAAS,IAAMvM,KAAK2Q,mBAClD3Q,KAAK6D,WAAU,EAAAnE,EAAAC,cAAa,IAAMK,KAAK4Q,oBACzC,CAEQ,cAAAD,GACN3Q,KAAK4P,kBAAkBlM,QACnB1D,KAAK6P,OAAOjH,kBAAoB5I,KAAK6P,OAAOnB,mBAAmB7J,cACjE7E,KAAK4P,kBAAkB3L,OAAQ,EAAA2H,EAAAgB,mBAAkB,KAC/C,MAAM5E,EAAOhI,KAAK6P,OAAOjH,iBACzB5I,KAAK6P,OAAOb,kBACZhP,KAAK6Q,aAAa7I,EAAO,IAAKhI,KAAK6P,OAAOnB,kBAAmBoC,aAAa,GAAQ,CAAEC,UAAU,KAC7F,KAEP,CAEO,gBAAAH,CAAiBI,GACtBhR,KAAK2P,eAAexB,0BACpBnO,KAAKyQ,oBAAoBjM,4BACzBxE,KAAK2P,eAAezB,eACf8C,GACHhR,KAAK6P,OAAOb,iBAEhB,CAEO,qBAAAiC,GACLjR,KAAK2P,eAAexB,yBACtB,CASO,QAAA+C,CAASlJ,EAAcG,EAAgCgJ,GAC5D,IAAKnR,KAAKoE,YAAcpE,KAAKuQ,QAC3B,MAAM,IAAIjQ,MAAM,6CAGlBN,KAAKiQ,gBAAgB7N,OAErBpC,KAAK6P,OAAOnB,kBAAoBvG,EAE5BnI,KAAK6P,OAAOd,yBAAyB/G,EAAMG,IAC7CnI,KAAKoR,qBAAqBpJ,EAAMG,GAGlC,MAAMkJ,EAAQrR,KAAKsR,mBAAmBtJ,EAAMG,EAAegJ,GAM3D,OALAnR,KAAKuR,aAAapJ,GAClBnI,KAAK6P,OAAOjH,iBAAmBZ,EAE/BhI,KAAK+P,eAAe3N,OAEbiP,CACT,CAEQ,oBAAAD,CAAqBpJ,EAAcG,GACzC,IAAKnI,KAAKoE,YAAcpE,KAAKuQ,UAAYvQ,KAAKyQ,mBAC5C,MAAM,IAAInQ,MAAM,6CAElB,IAAKN,KAAK6P,OAAOjB,kBAAkB5G,GAEjC,YADAhI,KAAK4Q,mBAKP5Q,KAAK4Q,kBAAiB,GAEtB,MAAMlM,EAA2B,GACjC,IAAI8M,EACA1P,EAAS9B,KAAKuQ,QAAQxI,KAAKC,EAAM,EAAG,EAAGG,GAE3C,KAAOrG,IAAW0P,GAAYlL,MAAQxE,EAAOwE,KAAOkL,GAAY1L,MAAQhE,EAAOgE,QACzEpB,EAAQrC,QAAUrC,KAAKmQ,kBADwD,CAInFqB,EAAa1P,EACb4C,EAAQ7C,KAAK2P,GACb,MAAM9K,EAAO1G,KAAKoE,UAAUsC,KAC5B,IAAI+K,EAAUD,EAAW1L,IAAM0L,EAAWxL,KACtC0L,EAAUF,EAAWlL,IACrBmL,GAAW/K,IACbgL,GAAWlL,KAAKmL,MAAMF,EAAU/K,GAChC+K,GAAoB/K,GAEtB5E,EAAS9B,KAAKuQ,QAAQxI,KAAKC,EAAM0J,EAASD,EAAStJ,EACrD,CAEAnI,KAAK2P,eAAe3B,cAActJ,EAAS1E,KAAKmQ,iBAC5ChI,EAActD,aAChB7E,KAAKyQ,mBAAmBhM,2BAA2BC,EAASyD,EAActD,YAE9E,CAEQ,kBAAAyM,CAAmBtJ,EAAcG,EAAgCgJ,GACvE,IAAKnR,KAAKoE,YAAcpE,KAAKuQ,QAC3B,OAAO,EAET,IAAKvQ,KAAK6P,OAAOjB,kBAAkB5G,GAGjC,OAFAhI,KAAKoE,UAAUgE,iBACfpI,KAAK4Q,oBACE,EAGT,MAAM9O,EAAS9B,KAAKuQ,QAAQ5H,sBAAsBX,EAAMG,EAAenI,KAAK6P,OAAOjH,kBACnF,OAAO5I,KAAK4R,cAAc9P,EAAQqG,GAAetD,YAAasM,GAAuBJ,SACvF,CASO,YAAAF,CAAa7I,EAAcG,EAAgCgJ,GAChE,IAAKnR,KAAKoE,YAAcpE,KAAKuQ,QAC3B,MAAM,IAAIjQ,MAAM,6CAGlBN,KAAKiQ,gBAAgB7N,OAErBpC,KAAK6P,OAAOnB,kBAAoBvG,EAE5BnI,KAAK6P,OAAOd,yBAAyB/G,EAAMG,IAC7CnI,KAAKoR,qBAAqBpJ,EAAMG,GAGlC,MAAMkJ,EAAQrR,KAAK6R,uBAAuB7J,EAAMG,EAAegJ,GAM/D,OALAnR,KAAKuR,aAAapJ,GAClBnI,KAAK6P,OAAOjH,iBAAmBZ,EAE/BhI,KAAK+P,eAAe3N,OAEbiP,CACT,CAEQ,YAAAE,CAAapJ,GACnBnI,KAAK2P,eAAetB,qBAAqBlG,GAAetD,YAC1D,CAEQ,sBAAAgN,CAAuB7J,EAAcG,EAAgCgJ,GAC3E,IAAKnR,KAAKoE,YAAcpE,KAAKuQ,QAC3B,OAAO,EAET,IAAKvQ,KAAK6P,OAAOjB,kBAAkB5G,GAGjC,OAFAhI,KAAKoE,UAAUgE,iBACfpI,KAAK4Q,oBACE,EAGT,MAAM9O,EAAS9B,KAAKuQ,QAAQtH,0BAA0BjB,EAAMG,EAAenI,KAAK6P,OAAOjH,kBACvF,OAAO5I,KAAK4R,cAAc9P,EAAQqG,GAAetD,YAAasM,GAAuBJ,SACvF,CAOQ,aAAAa,CAAc9P,EAAmC6C,EAAoCoM,GAC3F,IAAK/Q,KAAKoE,YAAcpE,KAAKyQ,mBAC3B,OAAO,EAIT,GADAzQ,KAAK2P,eAAexB,2BACfrM,EAEH,OADA9B,KAAKoE,UAAUgE,kBACR,EAIT,GADApI,KAAKoE,UAAU0N,OAAOhQ,EAAOgE,IAAKhE,EAAOwE,IAAKxE,EAAOkE,MACjDrB,EAAS,CACX,MAAMoN,EAAmB/R,KAAKyQ,mBAAmBxL,uBAAuBnD,EAAQ6C,GAC5EoN,IACF/R,KAAK2P,eAAe7B,mBAAqBiE,EAE7C,CAEA,IAAKhB,IAECjP,EAAOwE,KAAQtG,KAAKoE,UAAU8B,OAAOC,OAAO6L,UAAYhS,KAAKoE,UAAUqE,MAAS3G,EAAOwE,IAAMtG,KAAKoE,UAAU8B,OAAOC,OAAO6L,WAAW,CACvI,IAAIC,EAASnQ,EAAOwE,IAAMtG,KAAKoE,UAAU8B,OAAOC,OAAO6L,UACvDC,GAAUzL,KAAKmL,MAAM3R,KAAKoE,UAAUqE,KAAO,GAC3CzI,KAAKoE,UAAU8N,YAAYD,EAC7B,CAEF,OAAO,CACT","sources":["webpack://SearchAddon/webpack/universalModuleDefinition","webpack://SearchAddon/../src/common/Async.ts","webpack://SearchAddon/../src/common/Event.ts","webpack://SearchAddon/../src/common/Lifecycle.ts","webpack://SearchAddon/./src/DecorationManager.ts","webpack://SearchAddon/./src/SearchEngine.ts","webpack://SearchAddon/./src/SearchLineCache.ts","webpack://SearchAddon/./src/SearchResultTracker.ts","webpack://SearchAddon/./src/SearchState.ts","webpack://SearchAddon/webpack/bootstrap","webpack://SearchAddon/./src/SearchAddon.ts"],"sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"SearchAddon\"] = factory();\n\telse\n\t\troot[\"SearchAddon\"] = factory();\n})(globalThis, () => {\nreturn ","/**\n * Copyright (c) 2026 The xterm.js authors. All rights reserved.\n * @license MIT\n *\n * Minimal async helpers for xterm.js core.\n */\n\nimport { DisposableStore, IDisposable, toDisposable } from './Lifecycle';\n\nexport function timeout(millis: number): Promise {\n return new Promise(resolve => setTimeout(resolve, millis));\n}\n\n/**\n * Creates a timeout that can be disposed using its returned value.\n * @param handler The timeout handler.\n * @param timeout An optional timeout in milliseconds.\n * @param store An optional {@link DisposableStore} that will have the timeout disposable managed\n * automatically.\n */\nexport function disposableTimeout(handler: () => void, timeout = 0, store?: DisposableStore): IDisposable {\n const timer = setTimeout(() => {\n handler();\n if (store) {\n disposable.dispose();\n }\n }, timeout);\n const disposable = toDisposable(() => {\n clearTimeout(timer);\n });\n store?.add(disposable);\n return disposable;\n}\n\nexport class TimeoutTimer implements IDisposable {\n private _token: any = -1;\n private _isDisposed = false;\n\n public dispose(): void {\n this.cancel();\n this._isDisposed = true;\n }\n\n public cancel(): void {\n if (this._token !== -1) {\n clearTimeout(this._token);\n this._token = -1;\n }\n }\n\n public cancelAndSet(runner: () => void, timeout: number): void {\n if (this._isDisposed) {\n throw new Error('Calling cancelAndSet on a disposed TimeoutTimer');\n }\n this.cancel();\n this._token = setTimeout(() => {\n this._token = -1;\n runner();\n }, timeout);\n }\n\n public setIfNotSet(runner: () => void, timeout: number): void {\n if (this._isDisposed) {\n throw new Error('Calling setIfNotSet on a disposed TimeoutTimer');\n }\n if (this._token !== -1) {\n return;\n }\n this._token = setTimeout(() => {\n this._token = -1;\n runner();\n }, timeout);\n }\n}\n\n/**\n * Schedules a single runner on the microtask queue. Unlike {@link TimeoutTimer}, a scheduled\n * microtask cannot be unqueued; {@link cancel} prevents the runner from executing if it has not\n * run yet.\n */\nexport class MicrotaskTimer implements IDisposable {\n private _isScheduled = false;\n private _isDisposed = false;\n\n public dispose(): void {\n this.cancel();\n this._isDisposed = true;\n }\n\n public cancel(): void {\n this._isScheduled = false;\n }\n\n public set(runner: () => void): void {\n if (this._isDisposed) {\n throw new Error('Calling set on a disposed MicrotaskTimer');\n }\n if (this._isScheduled) {\n return;\n }\n this._isScheduled = true;\n queueMicrotask(() => {\n if (!this._isScheduled) {\n return;\n }\n this._isScheduled = false;\n runner();\n });\n }\n}\n\nexport class IntervalTimer implements IDisposable {\n private _disposable: IDisposable | undefined;\n private _isDisposed = false;\n\n public cancel(): void {\n this._disposable?.dispose();\n this._disposable = undefined;\n }\n\n public cancelAndSet(runner: () => void, interval: number, context: Window | typeof globalThis = globalThis): void {\n if (this._isDisposed) {\n throw new Error('Calling cancelAndSet on a disposed IntervalTimer');\n }\n this.cancel();\n const handle = context.setInterval(() => {\n runner();\n }, interval);\n this._disposable = {\n dispose: () => {\n context.clearInterval(handle as any);\n this._disposable = undefined;\n }\n };\n }\n\n public dispose(): void {\n this.cancel();\n this._isDisposed = true;\n }\n}\n","/**\n * Copyright (c) 2024-2026 The xterm.js authors. All rights reserved.\n * @license MIT\n *\n * Minimal event utilities for xterm.js core.\n * Simplified from VS Code's event.ts - no leak detection/profiling.\n */\n\nimport { IDisposable, DisposableStore, toDisposable } from './Lifecycle';\n\nexport interface IEvent {\n (listener: (e: T) => any, thisArgs?: any, disposables?: IDisposable[] | DisposableStore): IDisposable;\n}\n\nexport class Emitter {\n private _listeners: { fn: (e: T) => any, thisArgs: any }[] = [];\n private _disposed = false;\n private _event: IEvent | undefined;\n\n public get event(): IEvent {\n if (this._event) {\n return this._event;\n }\n this._event = (listener: (e: T) => any, thisArgs?: any, disposables?: IDisposable[] | DisposableStore) => {\n if (this._disposed) {\n return toDisposable(() => {});\n }\n\n const entry = { fn: listener, thisArgs };\n this._listeners = this._listeners.slice();\n this._listeners.push(entry);\n\n const result = toDisposable(() => {\n const idx = this._listeners.indexOf(entry);\n if (idx !== -1) {\n this._listeners = this._listeners.slice();\n this._listeners.splice(idx, 1);\n }\n });\n\n if (disposables) {\n if (Array.isArray(disposables)) {\n disposables.push(result);\n } else {\n disposables.add(result);\n }\n }\n\n return result;\n };\n return this._event;\n }\n\n public fire(event: T): void {\n if (this._disposed || !this._listeners.length) {\n return;\n }\n if (this._listeners.length === 1) {\n this._listeners[0].fn.call(this._listeners[0].thisArgs, event);\n return;\n }\n const listeners = this._listeners;\n for (let i = 0, len = listeners.length; i < len; ++i) {\n listeners[i].fn.call(listeners[i].thisArgs, event);\n }\n }\n\n public dispose(): void {\n if (this._disposed) {\n return;\n }\n this._disposed = true;\n this._listeners.length = 0;\n }\n}\n\nexport namespace EventUtils {\n export function forward(from: IEvent, to: Emitter): IDisposable {\n return from(e => to.fire(e));\n }\n\n export function map(event: IEvent, map: (i: I) => O): IEvent {\n return (listener: (e: O) => any, thisArgs?: any, disposables?: IDisposable[] | DisposableStore) => {\n return event(i => listener.call(thisArgs, map(i)), undefined, disposables);\n };\n }\n\n export function any(...events: IEvent[]): IEvent;\n export function any(...events: IEvent[]): IEvent;\n export function any(...events: IEvent[]): IEvent {\n return (listener: (e: T) => any, thisArgs?: any, disposables?: IDisposable[] | DisposableStore) => {\n const store = new DisposableStore();\n for (const event of events) {\n store.add(event(e => listener.call(thisArgs, e)));\n }\n if (disposables) {\n if (Array.isArray(disposables)) {\n disposables.push(store);\n } else {\n disposables.add(store);\n }\n }\n return store;\n };\n }\n\n export function runAndSubscribe(event: IEvent, handler: (e: T) => void, initial: T): IDisposable;\n export function runAndSubscribe(event: IEvent, handler: (e: T | undefined) => void): IDisposable;\n export function runAndSubscribe(event: IEvent, handler: (e: T | undefined) => void, initial?: T): IDisposable {\n handler(initial);\n return event(e => handler(e));\n }\n}\n","/**\n * Copyright (c) 2024-2026 The xterm.js authors. All rights reserved.\n * @license MIT\n *\n * Minimal lifecycle utilities for xterm.js core.\n * Simplified from VS Code's lifecycle.ts - no tracking/leak detection.\n */\n\nexport interface IDisposable {\n dispose(): void;\n}\n\nexport function toDisposable(fn: () => void): IDisposable {\n return { dispose: fn };\n}\n\nexport function dispose(disposable: T): T;\nexport function dispose(disposable: T | undefined): T | undefined;\nexport function dispose(disposables: T[]): T[];\nexport function dispose(arg: T | T[] | undefined): T | T[] | undefined {\n if (!arg) {\n return arg;\n }\n if (Array.isArray(arg)) {\n for (const d of arg) {\n d.dispose();\n }\n return [];\n }\n arg.dispose();\n return arg;\n}\n\nexport function combinedDisposable(...disposables: IDisposable[]): IDisposable {\n return toDisposable(() => dispose(disposables));\n}\n\nexport class DisposableStore implements IDisposable {\n private readonly _disposables = new Set();\n private _isDisposed = false;\n\n public get isDisposed(): boolean {\n return this._isDisposed;\n }\n\n public add(o: T): T {\n if (this._isDisposed) {\n o.dispose();\n } else {\n this._disposables.add(o);\n }\n return o;\n }\n\n public dispose(): void {\n if (this._isDisposed) {\n return;\n }\n this._isDisposed = true;\n for (const d of this._disposables) {\n d.dispose();\n }\n this._disposables.clear();\n }\n\n public clear(): void {\n for (const d of this._disposables) {\n d.dispose();\n }\n this._disposables.clear();\n }\n}\n\nexport abstract class Disposable implements IDisposable {\n public static readonly None: IDisposable = Object.freeze({ dispose() { } });\n\n protected readonly _store = new DisposableStore();\n\n public dispose(): void {\n this._store.dispose();\n }\n\n protected _register(o: T): T {\n return this._store.add(o);\n }\n}\n\nexport class MutableDisposable implements IDisposable {\n private _value: T | undefined;\n private _isDisposed = false;\n\n public get value(): T | undefined {\n return this._isDisposed ? undefined : this._value;\n }\n\n public set value(value: T | undefined) {\n if (this._isDisposed || value === this._value) {\n return;\n }\n this._value?.dispose();\n this._value = value;\n }\n\n public clear(): void {\n this.value = undefined;\n }\n\n public dispose(): void {\n this._isDisposed = true;\n this._value?.dispose();\n this._value = undefined;\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport type { Terminal, IDisposable, IDecoration } from '@xterm/xterm';\nimport type { ISearchDecorationOptions } from '@xterm/addon-search';\nimport { dispose, Disposable, toDisposable } from 'common/Lifecycle';\nimport type { ISearchResult } from './SearchEngine';\n\n/**\n * Interface for managing a highlight decoration.\n */\ninterface IHighlight extends IDisposable {\n decoration: IDecoration;\n match: ISearchResult;\n}\n\n/**\n * Interface for managing multiple decorations for a single match.\n */\ninterface IMultiHighlight extends IDisposable {\n decorations: IDecoration[];\n match: ISearchResult;\n}\n\n/**\n * Manages visual decorations for search results including highlighting and active selection\n * indicators. This class handles the creation, styling, and disposal of search-related decorations.\n */\nexport class DecorationManager extends Disposable {\n private _highlightDecorations: IHighlight[] = [];\n private _highlightedLines: Set = new Set();\n\n constructor(private readonly _terminal: Terminal) {\n super();\n this._register(toDisposable(() => this.clearHighlightDecorations()));\n }\n\n /**\n * Creates decorations for all provided search results.\n * @param results The search results to create decorations for.\n * @param options The decoration options.\n */\n public createHighlightDecorations(results: ISearchResult[], options: ISearchDecorationOptions): void {\n this.clearHighlightDecorations();\n\n for (const match of results) {\n const decorations = this._createResultDecorations(match, options, false);\n if (decorations) {\n for (const decoration of decorations) {\n this._storeDecoration(decoration, match);\n }\n }\n }\n }\n\n /**\n * Creates decorations for the currently active search result.\n * @param result The active search result.\n * @param options The decoration options.\n * @returns The multi-highlight decoration or undefined if creation failed.\n */\n public createActiveDecoration(result: ISearchResult, options: ISearchDecorationOptions): IMultiHighlight | undefined {\n const decorations = this._createResultDecorations(result, options, true);\n if (decorations) {\n return { decorations, match: result, dispose() { dispose(decorations); } };\n }\n return undefined;\n }\n\n /**\n * Clears all highlight decorations.\n */\n public clearHighlightDecorations(): void {\n dispose(this._highlightDecorations);\n this._highlightDecorations = [];\n this._highlightedLines.clear();\n }\n\n /**\n * Stores a decoration and tracks it for management.\n * @param decoration The decoration to store.\n * @param match The search result this decoration represents.\n */\n private _storeDecoration(decoration: IDecoration, match: ISearchResult): void {\n this._highlightedLines.add(decoration.marker.line);\n this._highlightDecorations.push({ decoration, match, dispose() { decoration.dispose(); } });\n }\n\n /**\n * Applies styles to the decoration when it is rendered.\n * @param element The decoration's element.\n * @param borderColor The border color to apply.\n * @param isActiveResult Whether the element is part of the active search result.\n */\n private _applyStyles(element: HTMLElement, borderColor: string | undefined, isActiveResult: boolean): void {\n if (!element.classList.contains('xterm-find-result-decoration')) {\n element.classList.add('xterm-find-result-decoration');\n if (borderColor) {\n element.style.outline = `1px solid ${borderColor}`;\n }\n }\n if (isActiveResult) {\n element.classList.add('xterm-find-active-result-decoration');\n }\n }\n\n /**\n * Creates a decoration for the result and applies styles\n * @param result the search result for which to create the decoration\n * @param options the options for the decoration\n * @param isActiveResult whether this is the currently active result\n * @returns the decorations or undefined if the marker has already been disposed of\n */\n private _createResultDecorations(result: ISearchResult, options: ISearchDecorationOptions, isActiveResult: boolean): IDecoration[] | undefined {\n // Gather decoration ranges for this match as it could wrap\n const decorationRanges: [number, number, number][] = [];\n let currentCol = result.col;\n let remainingSize = result.size;\n let markerOffset = -this._terminal.buffer.active.baseY - this._terminal.buffer.active.cursorY + result.row;\n while (remainingSize > 0) {\n const amountThisRow = Math.min(this._terminal.cols - currentCol, remainingSize);\n decorationRanges.push([markerOffset, currentCol, amountThisRow]);\n currentCol = 0;\n remainingSize -= amountThisRow;\n markerOffset++;\n }\n\n // Create the decorations\n const decorations: IDecoration[] = [];\n for (const range of decorationRanges) {\n const marker = this._terminal.registerMarker(range[0]);\n const decoration = this._terminal.registerDecoration({\n marker,\n x: range[1],\n width: range[2],\n layer: isActiveResult ? 'top' : 'bottom',\n backgroundColor: isActiveResult ? options.activeMatchBackground : options.matchBackground,\n overviewRulerOptions: this._highlightedLines.has(marker.line) ? undefined : {\n color: isActiveResult ? options.activeMatchColorOverviewRuler : options.matchOverviewRuler,\n position: 'center'\n }\n });\n if (decoration) {\n const disposables: IDisposable[] = [];\n disposables.push(marker);\n disposables.push(decoration.onRender((e) => this._applyStyles(e, isActiveResult ? options.activeMatchBorder : options.matchBorder, false)));\n disposables.push(decoration.onDispose(() => dispose(disposables)));\n decorations.push(decoration);\n }\n }\n\n return decorations.length === 0 ? undefined : decorations;\n }\n}\n\n\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport type { Terminal } from '@xterm/xterm';\nimport type { ISearchOptions } from '@xterm/addon-search';\nimport type { SearchLineCache } from './SearchLineCache';\n\n/**\n * Represents the position to start a search from.\n */\ninterface ISearchPosition {\n startCol: number;\n startRow: number;\n}\n\n/**\n * Represents a search result with its position and content.\n */\nexport interface ISearchResult {\n term: string;\n col: number;\n row: number;\n size: number;\n}\n\n/**\n * Configuration constants for the search engine functionality.\n */\nconst enum Constants {\n /**\n * Characters that are considered non-word characters for search boundary detection. These\n * characters are used to determine word boundaries when performing whole-word searches. Includes\n * common punctuation, symbols, and whitespace characters.\n */\n NON_WORD_CHARACTERS = ' ~!@#$%^&*()+`-=[]{}|\\\\;:\"\\',./<>?'\n}\n\n/**\n * Core search engine that handles finding text within terminal content.\n * This class is responsible for the actual search algorithms and position calculations.\n */\nexport class SearchEngine {\n constructor(\n private readonly _terminal: Terminal,\n private readonly _lineCache: SearchLineCache\n ) {}\n\n /**\n * Find the first occurrence of a term starting from a specific position.\n * @param term The search term.\n * @param startRow The row to start searching from.\n * @param startCol The column to start searching from.\n * @param searchOptions Search options.\n * @returns The search result if found, undefined otherwise.\n */\n public find(term: string, startRow: number, startCol: number, searchOptions?: ISearchOptions): ISearchResult | undefined {\n if (!term || term.length === 0) {\n this._terminal.clearSelection();\n return undefined;\n }\n if (startCol >= this._terminal.cols) {\n throw new Error(`Invalid col: ${startCol} to search in terminal of ${this._terminal.cols} cols`);\n }\n\n this._lineCache.initLinesCache();\n\n const searchPosition: ISearchPosition = {\n startRow,\n startCol\n };\n\n // Search startRow\n let result = this._findInLine(term, searchPosition, searchOptions);\n // Search from startRow + 1 to end\n if (!result) {\n for (let y = startRow + 1; y < this._terminal.buffer.active.baseY + this._terminal.rows; y++) {\n if (this._isRowCoveredByLineStart(y, searchOptions)) {\n continue;\n }\n searchPosition.startRow = y;\n searchPosition.startCol = 0;\n result = this._findInLine(term, searchPosition, searchOptions);\n if (result) {\n break;\n }\n }\n }\n return result;\n }\n\n /**\n * Find the next occurrence of a term with wrapping and selection management.\n * @param term The search term.\n * @param searchOptions Search options.\n * @param cachedSearchTerm The cached search term to determine incremental behavior.\n * @returns The search result if found, undefined otherwise.\n */\n public findNextWithSelection(term: string, searchOptions?: ISearchOptions, cachedSearchTerm?: string): ISearchResult | undefined {\n if (!term || term.length === 0) {\n this._terminal.clearSelection();\n return undefined;\n }\n\n const prevSelectedPos = this._terminal.getSelectionPosition();\n this._terminal.clearSelection();\n\n let startCol = 0;\n let startRow = 0;\n if (prevSelectedPos) {\n if (cachedSearchTerm === term) {\n startCol = prevSelectedPos.end.x;\n startRow = prevSelectedPos.end.y;\n } else {\n startCol = prevSelectedPos.start.x;\n startRow = prevSelectedPos.start.y;\n }\n }\n\n this._lineCache.initLinesCache();\n\n const searchPosition: ISearchPosition = {\n startRow,\n startCol\n };\n\n // Search startRow\n let result = this._findInLine(term, searchPosition, searchOptions);\n // Search from startRow + 1 to end\n if (!result) {\n for (let y = startRow + 1; y < this._terminal.buffer.active.baseY + this._terminal.rows; y++) {\n if (this._isRowCoveredByLineStart(y, searchOptions)) {\n continue;\n }\n searchPosition.startRow = y;\n searchPosition.startCol = 0;\n result = this._findInLine(term, searchPosition, searchOptions);\n if (result) {\n break;\n }\n }\n }\n // If we hit the bottom and didn't search from the very top wrap back up\n if (!result && startRow !== 0) {\n for (let y = 0; y < startRow; y++) {\n if (this._isRowCoveredByLineStart(y, searchOptions)) {\n continue;\n }\n searchPosition.startRow = y;\n searchPosition.startCol = 0;\n result = this._findInLine(term, searchPosition, searchOptions);\n if (result) {\n break;\n }\n }\n }\n\n // If there is only one result, wrap back and return selection if it exists.\n if (!result && prevSelectedPos) {\n searchPosition.startRow = prevSelectedPos.start.y;\n searchPosition.startCol = 0;\n result = this._findInLine(term, searchPosition, searchOptions);\n }\n\n return result;\n }\n\n /**\n * Find the previous occurrence of a term with wrapping and selection management.\n * @param term The search term.\n * @param searchOptions Search options.\n * @param cachedSearchTerm The cached search term to determine if expansion should occur.\n * @returns The search result if found, undefined otherwise.\n */\n public findPreviousWithSelection(term: string, searchOptions?: ISearchOptions, cachedSearchTerm?: string): ISearchResult | undefined {\n if (!term || term.length === 0) {\n this._terminal.clearSelection();\n return undefined;\n }\n\n const prevSelectedPos = this._terminal.getSelectionPosition();\n this._terminal.clearSelection();\n\n let startRow = this._terminal.buffer.active.baseY + this._terminal.rows - 1;\n const startCol = this._terminal.cols;\n const isReverseSearch = true;\n\n this._lineCache.initLinesCache();\n const searchPosition: ISearchPosition = {\n startRow,\n startCol\n };\n\n let result: ISearchResult | undefined;\n if (prevSelectedPos) {\n searchPosition.startRow = startRow = prevSelectedPos.start.y;\n searchPosition.startCol = prevSelectedPos.start.x;\n if (cachedSearchTerm !== term) {\n // Try to expand selection to right first.\n result = this._findInLine(term, searchPosition, searchOptions, false);\n if (!result) {\n // If selection was not able to be expanded to the right, then try reverse search\n searchPosition.startRow = startRow = prevSelectedPos.end.y;\n searchPosition.startCol = prevSelectedPos.end.x;\n }\n }\n }\n\n result ??= this._findInLine(term, searchPosition, searchOptions, isReverseSearch);\n\n // Search from startRow - 1 to top\n if (!result) {\n searchPosition.startCol = Math.max(searchPosition.startCol, this._terminal.cols);\n for (let y = startRow - 1; y >= 0; y--) {\n searchPosition.startRow = y;\n result = this._findInLine(term, searchPosition, searchOptions, isReverseSearch);\n if (result) {\n break;\n }\n }\n }\n // If we hit the top and didn't search from the very bottom wrap back down\n if (!result && startRow !== (this._terminal.buffer.active.baseY + this._terminal.rows - 1)) {\n for (let y = (this._terminal.buffer.active.baseY + this._terminal.rows - 1); y >= startRow; y--) {\n searchPosition.startRow = y;\n result = this._findInLine(term, searchPosition, searchOptions, isReverseSearch);\n if (result) {\n break;\n }\n }\n }\n\n return result;\n }\n\n /**\n * A found substring is a whole word if it doesn't have an alphanumeric character directly\n * adjacent to it.\n * @param searchIndex starting index of the potential whole word substring\n * @param line entire string in which the potential whole word was found\n * @param term the substring that starts at searchIndex\n */\n private _isWholeWord(searchIndex: number, line: string, term: string): boolean {\n return ((searchIndex === 0) || (Constants.NON_WORD_CHARACTERS.includes(line[searchIndex - 1]))) &&\n (((searchIndex + term.length) === line.length) || (Constants.NON_WORD_CHARACTERS.includes(line[searchIndex + term.length])));\n }\n\n /**\n * A wrapped row's text was already searched in full when the first row of its line was, so a\n * full-buffer scan that visits every row does O(rows^2) work over one long line. Skipping is\n * only sound for a plain search: wholeWord and regex can both reject at one offset and match at\n * a later one within the same line.\n */\n private _isRowCoveredByLineStart(row: number, searchOptions?: ISearchOptions): boolean {\n if (searchOptions?.regex || searchOptions?.wholeWord) {\n return false;\n }\n return this._terminal.buffer.active.getLine(row)?.isWrapped === true;\n }\n\n /**\n * Searches a line for a search term. Takes the provided terminal line and searches the text line,\n * which may contain subsequent terminal lines if the text is wrapped. If the provided line number\n * is part of a wrapped text line that started on an earlier line then it is skipped since it will\n * be properly searched when the terminal line that the text starts on is searched.\n * @param term The search term.\n * @param searchPosition The position to start the search.\n * @param searchOptions Search options.\n * @param isReverseSearch Whether the search should start from the right side of the terminal and\n * search to the left.\n * @returns The search result if it was found.\n */\n private _findInLine(term: string, searchPosition: ISearchPosition, searchOptions: ISearchOptions = {}, isReverseSearch: boolean = false): ISearchResult | undefined {\n // Ignore wrapped lines, only consider on unwrapped line (first row of command string).\n // This walks back to the line start rather than recursing into it: one frame per wrapped\n // row overflows the stack on a line long enough to fill the scrollback.\n while (this._terminal.buffer.active.getLine(searchPosition.startRow)?.isWrapped) {\n searchPosition.startCol += this._terminal.cols;\n if (isReverseSearch) {\n return;\n }\n searchPosition.startRow--;\n }\n const row = searchPosition.startRow;\n const col = searchPosition.startCol;\n\n let cache = this._lineCache.getLineFromCache(row);\n if (!cache) {\n cache = this._lineCache.translateBufferLineToStringWithWrap(row, true);\n this._lineCache.setLineInCache(row, cache);\n }\n const [stringLine, offsets] = cache;\n\n const offset = this._bufferColsToStringOffset(row, col);\n let searchTerm = term;\n let searchStringLine = stringLine;\n if (!searchOptions.regex) {\n searchTerm = searchOptions.caseSensitive ? term : term.toLowerCase();\n searchStringLine = searchOptions.caseSensitive ? stringLine : stringLine.toLowerCase();\n }\n\n let resultIndex = -1;\n if (searchOptions.regex) {\n const searchRegex = RegExp(searchTerm, searchOptions.caseSensitive ? 'g' : 'gi');\n let foundTerm: RegExpExecArray | null;\n if (isReverseSearch) {\n // This loop will get the resultIndex of the _last_ regex match in the range 0..offset\n while (foundTerm = searchRegex.exec(searchStringLine.slice(0, offset))) {\n resultIndex = searchRegex.lastIndex - foundTerm[0].length;\n term = foundTerm[0];\n searchRegex.lastIndex -= (term.length - 1);\n }\n } else {\n foundTerm = searchRegex.exec(searchStringLine.slice(offset));\n if (foundTerm && foundTerm[0].length > 0) {\n resultIndex = offset + (searchRegex.lastIndex - foundTerm[0].length);\n term = foundTerm[0];\n }\n }\n } else {\n if (isReverseSearch) {\n if (offset - searchTerm.length >= 0) {\n resultIndex = searchStringLine.lastIndexOf(searchTerm, offset - searchTerm.length);\n }\n } else {\n resultIndex = searchStringLine.indexOf(searchTerm, offset);\n }\n }\n\n if (resultIndex >= 0) {\n if (searchOptions.wholeWord && !this._isWholeWord(resultIndex, searchStringLine, term)) {\n return;\n }\n\n // Adjust the row number and search index if needed since a \"line\" of text can span multiple\n // rows\n let startRowOffset = 0;\n while (startRowOffset < offsets.length - 1 && resultIndex >= offsets[startRowOffset + 1]) {\n startRowOffset++;\n }\n let endRowOffset = startRowOffset;\n while (endRowOffset < offsets.length - 1 && resultIndex + term.length >= offsets[endRowOffset + 1]) {\n endRowOffset++;\n }\n const startColOffset = resultIndex - offsets[startRowOffset];\n const endColOffset = resultIndex + term.length - offsets[endRowOffset];\n const startColIndex = this._stringLengthToBufferSize(row + startRowOffset, startColOffset);\n const endColIndex = this._stringLengthToBufferSize(row + endRowOffset, endColOffset);\n const size = endColIndex - startColIndex + this._terminal.cols * (endRowOffset - startRowOffset);\n\n return {\n term,\n col: startColIndex,\n row: row + startRowOffset,\n size\n };\n }\n }\n\n private _stringLengthToBufferSize(row: number, offset: number): number {\n const line = this._terminal.buffer.active.getLine(row);\n if (!line) {\n return 0;\n }\n for (let i = 0; i < offset; i++) {\n const cell = line.getCell(i);\n if (!cell) {\n break;\n }\n // Adjust the searchIndex to normalize emoji into single chars\n const char = cell.getChars();\n if (char.length > 1) {\n offset -= char.length - 1;\n }\n // Adjust the searchIndex for empty characters following wide unicode\n // chars (eg. CJK)\n const nextCell = line.getCell(i + 1);\n if (nextCell && nextCell.getWidth() === 0) {\n offset++;\n }\n }\n return offset;\n }\n\n private _bufferColsToStringOffset(startRow: number, cols: number): number {\n let lineIndex = startRow;\n let offset = 0;\n let line = this._terminal.buffer.active.getLine(lineIndex);\n while (cols > 0 && line) {\n for (let i = 0; i < cols && i < this._terminal.cols; i++) {\n const cell = line.getCell(i);\n if (!cell) {\n break;\n }\n if (cell.getWidth()) {\n // Treat null characters as whitespace to align with the translateToString API\n offset += cell.getCode() === 0 ? 1 : cell.getChars().length;\n }\n }\n lineIndex++;\n line = this._terminal.buffer.active.getLine(lineIndex);\n if (line && !line.isWrapped) {\n break;\n }\n cols -= this._terminal.cols;\n }\n return offset;\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport type { Terminal } from '@xterm/xterm';\nimport { combinedDisposable, Disposable, MutableDisposable, toDisposable } from 'common/Lifecycle';\nimport { disposableTimeout } from 'common/Async';\n\nexport type LineCacheEntry = [\n /**\n * The string representation of a line (as opposed to the buffer cell representation).\n */\n lineAsString: string,\n /**\n * The offsets where each line starts when the entry describes a wrapped line.\n */\n lineOffsets: number[]\n];\n\n/**\n * Configuration constants for the search line cache functionality.\n */\nconst enum Constants {\n /**\n * Time-to-live for cached search results in milliseconds. After this duration, cached search\n * results will be invalidated to ensure they remain consistent with terminal content changes.\n */\n LINES_CACHE_TIME_TO_LIVE = 15000\n}\n\nexport class SearchLineCache extends Disposable {\n /**\n * translateBufferLineToStringWithWrap is a fairly expensive call.\n * We memoize the calls into an array that has a time based ttl.\n * _linesCache is also invalidated when the terminal cursor moves.\n */\n private _linesCache: LineCacheEntry[] | undefined;\n private _linesCacheTimeout = this._register(new MutableDisposable());\n private _linesCacheDisposables = this._register(new MutableDisposable());\n // Track access to avoid recreating a timeout on every init call which occurs once per search\n // result (findNext/findPrevious -> _highlightAllMatches -> find loop).\n private _lastAccessTimestamp = 0;\n\n constructor(private readonly _terminal: Terminal) {\n super();\n this._register(toDisposable(() => this._destroyLinesCache()));\n }\n\n /**\n * Sets up a line cache with a ttl\n */\n public initLinesCache(): void {\n if (!this._linesCache) {\n this._linesCache = new Array(this._terminal.buffer.active.length);\n this._linesCacheDisposables.value = combinedDisposable(\n this._terminal.onLineFeed(() => this._destroyLinesCache()),\n this._terminal.onCursorMove(() => this._destroyLinesCache()),\n this._terminal.onResize(() => this._destroyLinesCache())\n );\n }\n\n this._lastAccessTimestamp = Date.now();\n if (!this._linesCacheTimeout.value) {\n this._scheduleLinesCacheTimeout(Constants.LINES_CACHE_TIME_TO_LIVE);\n }\n }\n\n private _destroyLinesCache(): void {\n this._linesCache = undefined;\n this._lastAccessTimestamp = 0;\n this._linesCacheDisposables.clear();\n this._linesCacheTimeout.clear();\n }\n\n private _scheduleLinesCacheTimeout(delay: number): void {\n this._linesCacheTimeout.value = disposableTimeout(() => {\n if (!this._linesCache) {\n return;\n }\n const now = Date.now();\n const elapsed = now - this._lastAccessTimestamp;\n if (elapsed >= Constants.LINES_CACHE_TIME_TO_LIVE) {\n this._destroyLinesCache();\n return;\n }\n this._scheduleLinesCacheTimeout(Constants.LINES_CACHE_TIME_TO_LIVE - elapsed);\n }, delay);\n }\n\n public getLineFromCache(row: number): LineCacheEntry | undefined {\n return this._linesCache?.[row];\n }\n\n public setLineInCache(row: number, entry: LineCacheEntry): void {\n if (this._linesCache) {\n this._linesCache[row] = entry;\n }\n }\n\n /**\n * Translates a buffer line to a string, including subsequent lines if they are wraps.\n * Wide characters will count as two columns in the resulting string. This\n * function is useful for getting the actual text underneath the raw selection\n * position.\n * @param lineIndex The index of the line being translated.\n * @param trimRight Whether to trim whitespace to the right.\n */\n public translateBufferLineToStringWithWrap(lineIndex: number, trimRight: boolean): LineCacheEntry {\n const strings = [];\n const lineOffsets = [0];\n let line = this._terminal.buffer.active.getLine(lineIndex);\n while (line) {\n const nextLine = this._terminal.buffer.active.getLine(lineIndex + 1);\n const lineWrapsToNext = nextLine ? nextLine.isWrapped : false;\n let string = line.translateToString(!lineWrapsToNext && trimRight);\n if (lineWrapsToNext && nextLine) {\n const lastCell = line.getCell(line.length - 1);\n const lastCellIsNull = lastCell && lastCell.getCode() === 0 && lastCell.getWidth() === 1;\n // a wide character wrapped to the next line\n if (lastCellIsNull && nextLine.getCell(0)?.getWidth() === 2) {\n string = string.slice(0, -1);\n }\n }\n strings.push(string);\n if (lineWrapsToNext) {\n lineOffsets.push(lineOffsets[lineOffsets.length - 1] + string.length);\n } else {\n break;\n }\n lineIndex++;\n line = nextLine;\n }\n return [strings.join(''), lineOffsets];\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport type { ISearchResultChangeEvent } from '@xterm/addon-search';\nimport type { IDisposable } from '@xterm/xterm';\nimport { Emitter, type IEvent } from 'common/Event';\nimport { Disposable } from 'common/Lifecycle';\nimport type { ISearchResult } from './SearchEngine';\n\n/**\n * Interface for managing a currently selected decoration.\n */\ninterface ISelectedDecoration extends IDisposable {\n match: ISearchResult;\n}\n\n/**\n * Tracks search results, manages result indexing, and fires events when results change.\n * This class provides centralized management of search result state and notifications.\n */\nexport class SearchResultTracker extends Disposable {\n private _searchResults: ISearchResult[] = [];\n private _selectedDecoration: ISelectedDecoration | undefined;\n\n private readonly _onDidChangeResults = this._register(new Emitter());\n public get onDidChangeResults(): IEvent { return this._onDidChangeResults.event; }\n\n /**\n * Gets the current search results.\n */\n public get searchResults(): ReadonlyArray {\n return this._searchResults;\n }\n\n /**\n * Gets the currently selected decoration.\n */\n public get selectedDecoration(): ISelectedDecoration | undefined {\n return this._selectedDecoration;\n }\n\n /**\n * Sets the currently selected decoration.\n */\n public set selectedDecoration(decoration: ISelectedDecoration | undefined) {\n this._selectedDecoration = decoration;\n }\n\n /**\n * Updates the search results with a new set of results.\n * @param results The new search results.\n * @param maxResults The maximum number of results to track.\n */\n public updateResults(results: ISearchResult[], maxResults: number): void {\n this._searchResults = results.slice(0, maxResults);\n }\n\n /**\n * Clears all search results.\n */\n public clearResults(): void {\n this._searchResults = [];\n }\n\n /**\n * Clears the selected decoration.\n */\n public clearSelectedDecoration(): void {\n if (this._selectedDecoration) {\n this._selectedDecoration.dispose();\n this._selectedDecoration = undefined;\n }\n }\n\n /**\n * Finds the index of a result in the current results array.\n * @param result The result to find.\n * @returns The index of the result, or -1 if not found.\n */\n public findResultIndex(result: ISearchResult): number {\n for (let i = 0; i < this._searchResults.length; i++) {\n const match = this._searchResults[i];\n if (match.row === result.row && match.col === result.col && match.size === result.size) {\n return i;\n }\n }\n return -1;\n }\n\n /**\n * Fires a result change event with the current state.\n * @param hasDecorations Whether decorations are enabled.\n */\n public fireResultsChanged(hasDecorations: boolean): void {\n if (!hasDecorations) {\n return;\n }\n\n let resultIndex = -1;\n if (this._selectedDecoration) {\n resultIndex = this.findResultIndex(this._selectedDecoration.match);\n }\n\n this._onDidChangeResults.fire({\n resultIndex,\n resultCount: this._searchResults.length\n });\n }\n\n /**\n * Resets all state.\n */\n public reset(): void {\n this.clearSelectedDecoration();\n this.clearResults();\n }\n}\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport type { ISearchOptions } from '@xterm/addon-search';\n\n/**\n * Manages search state including cached search terms, options tracking, and validation.\n * This class provides a centralized way to handle search state consistency and option changes.\n */\nexport class SearchState {\n private _cachedSearchTerm: string | undefined;\n private _lastSearchOptions: ISearchOptions | undefined;\n\n /**\n * Gets the currently cached search term.\n */\n public get cachedSearchTerm(): string | undefined {\n return this._cachedSearchTerm;\n }\n\n /**\n * Sets the cached search term.\n */\n public set cachedSearchTerm(term: string | undefined) {\n this._cachedSearchTerm = term;\n }\n\n /**\n * Gets the last search options used.\n */\n public get lastSearchOptions(): ISearchOptions | undefined {\n return this._lastSearchOptions;\n }\n\n /**\n * Sets the last search options used.\n */\n public set lastSearchOptions(options: ISearchOptions | undefined) {\n this._lastSearchOptions = options;\n }\n\n /**\n * Validates a search term to ensure it's not empty or invalid.\n * @param term The search term to validate.\n * @returns true if the term is valid for searching.\n */\n public isValidSearchTerm(term: string): boolean {\n return !!(term && term.length > 0);\n }\n\n /**\n * Determines if search options have changed compared to the last search.\n * @param newOptions The new search options to compare.\n * @returns true if the options have changed.\n */\n public didOptionsChange(newOptions?: ISearchOptions): boolean {\n if (!this._lastSearchOptions) {\n return true;\n }\n if (!newOptions) {\n return false;\n }\n if (this._lastSearchOptions.caseSensitive !== newOptions.caseSensitive) {\n return true;\n }\n if (this._lastSearchOptions.regex !== newOptions.regex) {\n return true;\n }\n if (this._lastSearchOptions.wholeWord !== newOptions.wholeWord) {\n return true;\n }\n return false;\n }\n\n /**\n * Determines if a new search should trigger highlighting updates.\n * @param term The search term.\n * @param options The search options.\n * @returns true if highlighting should be updated.\n */\n public shouldUpdateHighlighting(term: string, options?: ISearchOptions): boolean {\n if (!options?.decorations) {\n return false;\n }\n return this._cachedSearchTerm === undefined ||\n term !== this._cachedSearchTerm ||\n this.didOptionsChange(options);\n }\n\n /**\n * Clears the cached search term.\n */\n public clearCachedTerm(): void {\n this._cachedSearchTerm = undefined;\n }\n\n /**\n * Resets all state.\n */\n public reset(): void {\n this._cachedSearchTerm = undefined;\n this._lastSearchOptions = undefined;\n }\n}\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport type { Terminal, IDisposable, ITerminalAddon } from '@xterm/xterm';\nimport type { SearchAddon as ISearchApi, ISearchOptions, ISearchAddonOptions, ISearchResultChangeEvent, ISearchDecorationOptions } from '@xterm/addon-search';\nimport { Emitter, type IEvent } from 'common/Event';\nimport { Disposable, MutableDisposable, toDisposable } from 'common/Lifecycle';\nimport { disposableTimeout } from 'common/Async';\nimport { SearchLineCache } from './SearchLineCache';\nimport { SearchState } from './SearchState';\nimport { SearchEngine, type ISearchResult } from './SearchEngine';\nimport { DecorationManager } from './DecorationManager';\nimport { SearchResultTracker } from './SearchResultTracker';\n\ninterface IInternalSearchOptions {\n noScroll: boolean;\n}\n\n/**\n * Configuration constants for the search addon functionality.\n */\nconst enum Constants {\n /**\n * Default maximum number of search results to highlight simultaneously. This limit prevents\n * performance degradation when searching for very common terms that would result in excessive\n * highlighting decorations.\n */\n DEFAULT_HIGHLIGHT_LIMIT = 1000\n}\n\nexport class SearchAddon extends Disposable implements ITerminalAddon, ISearchApi {\n private _terminal: Terminal | undefined;\n private _highlightLimit: number;\n private _highlightTimeout = this._register(new MutableDisposable());\n private _lineCache = this._register(new MutableDisposable());\n\n // Component instances\n private _state = new SearchState();\n private _engine: SearchEngine | undefined;\n private _decorationManager: DecorationManager | undefined;\n private _resultTracker = this._register(new SearchResultTracker());\n\n private readonly _onAfterSearch = this._register(new Emitter());\n public readonly onAfterSearch = this._onAfterSearch.event;\n private readonly _onBeforeSearch = this._register(new Emitter());\n public readonly onBeforeSearch = this._onBeforeSearch.event;\n\n public get onDidChangeResults(): IEvent {\n return this._resultTracker.onDidChangeResults;\n }\n\n constructor(options?: Partial) {\n super();\n\n this._highlightLimit = options?.highlightLimit ?? Constants.DEFAULT_HIGHLIGHT_LIMIT;\n }\n\n public activate(terminal: Terminal): void {\n this._terminal = terminal;\n this._lineCache.value = new SearchLineCache(terminal);\n this._engine = new SearchEngine(terminal, this._lineCache.value);\n this._decorationManager = new DecorationManager(terminal);\n this._register(this._terminal.onWriteParsed(() => this._updateMatches()));\n this._register(this._terminal.onResize(() => this._updateMatches()));\n this._register(toDisposable(() => this.clearDecorations()));\n }\n\n private _updateMatches(): void {\n this._highlightTimeout.clear();\n if (this._state.cachedSearchTerm && this._state.lastSearchOptions?.decorations) {\n this._highlightTimeout.value = disposableTimeout(() => {\n const term = this._state.cachedSearchTerm;\n this._state.clearCachedTerm();\n this.findPrevious(term!, { ...this._state.lastSearchOptions, incremental: true }, { noScroll: true });\n }, 200);\n }\n }\n\n public clearDecorations(retainCachedSearchTerm?: boolean): void {\n this._resultTracker.clearSelectedDecoration();\n this._decorationManager?.clearHighlightDecorations();\n this._resultTracker.clearResults();\n if (!retainCachedSearchTerm) {\n this._state.clearCachedTerm();\n }\n }\n\n public clearActiveDecoration(): void {\n this._resultTracker.clearSelectedDecoration();\n }\n\n /**\n * Find the next instance of the term, then scroll to and select it. If it\n * doesn't exist, do nothing.\n * @param term The search term.\n * @param searchOptions Search options.\n * @returns Whether a result was found.\n */\n public findNext(term: string, searchOptions?: ISearchOptions, internalSearchOptions?: IInternalSearchOptions): boolean {\n if (!this._terminal || !this._engine) {\n throw new Error('Cannot use addon until it has been loaded');\n }\n\n this._onBeforeSearch.fire();\n\n this._state.lastSearchOptions = searchOptions;\n\n if (this._state.shouldUpdateHighlighting(term, searchOptions)) {\n this._highlightAllMatches(term, searchOptions!);\n }\n\n const found = this._findNextAndSelect(term, searchOptions, internalSearchOptions);\n this._fireResults(searchOptions);\n this._state.cachedSearchTerm = term;\n\n this._onAfterSearch.fire();\n\n return found;\n }\n\n private _highlightAllMatches(term: string, searchOptions: ISearchOptions): void {\n if (!this._terminal || !this._engine || !this._decorationManager) {\n throw new Error('Cannot use addon until it has been loaded');\n }\n if (!this._state.isValidSearchTerm(term)) {\n this.clearDecorations();\n return;\n }\n\n // new search, clear out the old decorations\n this.clearDecorations(true);\n\n const results: ISearchResult[] = [];\n let prevResult: ISearchResult | undefined = undefined;\n let result = this._engine.find(term, 0, 0, searchOptions);\n\n while (result && (prevResult?.row !== result.row || prevResult?.col !== result.col)) {\n if (results.length >= this._highlightLimit) {\n break;\n }\n prevResult = result;\n results.push(prevResult);\n const cols = this._terminal.cols;\n let nextCol = prevResult.col + prevResult.size;\n let nextRow = prevResult.row;\n if (nextCol >= cols) {\n nextRow += Math.floor(nextCol / cols);\n nextCol = nextCol % cols;\n }\n result = this._engine.find(term, nextRow, nextCol, searchOptions);\n }\n\n this._resultTracker.updateResults(results, this._highlightLimit);\n if (searchOptions.decorations) {\n this._decorationManager.createHighlightDecorations(results, searchOptions.decorations);\n }\n }\n\n private _findNextAndSelect(term: string, searchOptions?: ISearchOptions, internalSearchOptions?: IInternalSearchOptions): boolean {\n if (!this._terminal || !this._engine) {\n return false;\n }\n if (!this._state.isValidSearchTerm(term)) {\n this._terminal.clearSelection();\n this.clearDecorations();\n return false;\n }\n\n const result = this._engine.findNextWithSelection(term, searchOptions, this._state.cachedSearchTerm);\n return this._selectResult(result, searchOptions?.decorations, internalSearchOptions?.noScroll);\n }\n\n /**\n * Find the previous instance of the term, then scroll to and select it. If it\n * doesn't exist, do nothing.\n * @param term The search term.\n * @param searchOptions Search options.\n * @returns Whether a result was found.\n */\n public findPrevious(term: string, searchOptions?: ISearchOptions, internalSearchOptions?: IInternalSearchOptions): boolean {\n if (!this._terminal || !this._engine) {\n throw new Error('Cannot use addon until it has been loaded');\n }\n\n this._onBeforeSearch.fire();\n\n this._state.lastSearchOptions = searchOptions;\n\n if (this._state.shouldUpdateHighlighting(term, searchOptions)) {\n this._highlightAllMatches(term, searchOptions!);\n }\n\n const found = this._findPreviousAndSelect(term, searchOptions, internalSearchOptions);\n this._fireResults(searchOptions);\n this._state.cachedSearchTerm = term;\n\n this._onAfterSearch.fire();\n\n return found;\n }\n\n private _fireResults(searchOptions?: ISearchOptions): void {\n this._resultTracker.fireResultsChanged(!!searchOptions?.decorations);\n }\n\n private _findPreviousAndSelect(term: string, searchOptions?: ISearchOptions, internalSearchOptions?: IInternalSearchOptions): boolean {\n if (!this._terminal || !this._engine) {\n return false;\n }\n if (!this._state.isValidSearchTerm(term)) {\n this._terminal.clearSelection();\n this.clearDecorations();\n return false;\n }\n\n const result = this._engine.findPreviousWithSelection(term, searchOptions, this._state.cachedSearchTerm);\n return this._selectResult(result, searchOptions?.decorations, internalSearchOptions?.noScroll);\n }\n\n /**\n * Selects and scrolls to a result.\n * @param result The result to select.\n * @returns Whether a result was selected.\n */\n private _selectResult(result: ISearchResult | undefined, options?: ISearchDecorationOptions, noScroll?: boolean): boolean {\n if (!this._terminal || !this._decorationManager) {\n return false;\n }\n\n this._resultTracker.clearSelectedDecoration();\n if (!result) {\n this._terminal.clearSelection();\n return false;\n }\n\n this._terminal.select(result.col, result.row, result.size);\n if (options) {\n const activeDecoration = this._decorationManager.createActiveDecoration(result, options);\n if (activeDecoration) {\n this._resultTracker.selectedDecoration = activeDecoration;\n }\n }\n\n if (!noScroll) {\n // If it is not in the viewport then we scroll else it just gets selected\n if (result.row >= (this._terminal.buffer.active.viewportY + this._terminal.rows) || result.row < this._terminal.buffer.active.viewportY) {\n let scroll = result.row - this._terminal.buffer.active.viewportY;\n scroll -= Math.floor(this._terminal.rows / 2);\n this._terminal.scrollLines(scroll);\n }\n }\n return true;\n }\n}\n"],"names":["root","factory","exports","module","define","amd","globalThis","millis","Promise","resolve","setTimeout","handler","timeout","store","timer","disposable","dispose","Lifecycle_1","toDisposable","clearTimeout","add","__webpack_require__","constructor","this","_token","_isDisposed","cancel","cancelAndSet","runner","Error","setIfNotSet","_isScheduled","set","queueMicrotask","_disposable","undefined","interval","context","handle","setInterval","clearInterval","EventUtils","_listeners","_disposed","event","_event","listener","thisArgs","disposables","entry","fn","slice","push","result","idx","indexOf","splice","Array","isArray","fire","length","call","listeners","i","len","forward","from","to","e","map","any","events","DisposableStore","runAndSubscribe","initial","arg","d","_disposables","Set","isDisposed","o","clear","Disposable","_store","_register","None","Object","freeze","value","_value","DecorationManager","_terminal","super","_highlightDecorations","_highlightedLines","clearHighlightDecorations","createHighlightDecorations","results","options","match","decorations","_createResultDecorations","decoration","_storeDecoration","createActiveDecoration","marker","line","_applyStyles","element","borderColor","isActiveResult","classList","contains","style","outline","decorationRanges","currentCol","col","remainingSize","size","markerOffset","buffer","active","baseY","cursorY","row","amountThisRow","Math","min","cols","range","registerMarker","registerDecoration","x","width","layer","backgroundColor","activeMatchBackground","matchBackground","overviewRulerOptions","has","color","activeMatchColorOverviewRuler","matchOverviewRuler","position","onRender","activeMatchBorder","matchBorder","onDispose","_lineCache","find","term","startRow","startCol","searchOptions","clearSelection","initLinesCache","searchPosition","_findInLine","y","rows","_isRowCoveredByLineStart","findNextWithSelection","cachedSearchTerm","prevSelectedPos","getSelectionPosition","end","start","findPreviousWithSelection","isReverseSearch","max","_isWholeWord","searchIndex","includes","regex","wholeWord","getLine","isWrapped","cache","getLineFromCache","translateBufferLineToStringWithWrap","setLineInCache","stringLine","offsets","offset","_bufferColsToStringOffset","searchTerm","searchStringLine","caseSensitive","toLowerCase","resultIndex","searchRegex","RegExp","foundTerm","exec","lastIndex","lastIndexOf","startRowOffset","endRowOffset","startColOffset","endColOffset","startColIndex","_stringLengthToBufferSize","cell","getCell","char","getChars","nextCell","getWidth","lineIndex","getCode","Async_1","SearchLineCache","_linesCacheTimeout","MutableDisposable","_linesCacheDisposables","_lastAccessTimestamp","_destroyLinesCache","_linesCache","combinedDisposable","onLineFeed","onCursorMove","onResize","Date","now","_scheduleLinesCacheTimeout","delay","disposableTimeout","elapsed","trimRight","strings","lineOffsets","nextLine","lineWrapsToNext","string","translateToString","lastCell","join","Event_1","SearchResultTracker","_searchResults","_onDidChangeResults","Emitter","onDidChangeResults","searchResults","selectedDecoration","_selectedDecoration","updateResults","maxResults","clearResults","clearSelectedDecoration","findResultIndex","fireResultsChanged","hasDecorations","resultCount","reset","_cachedSearchTerm","lastSearchOptions","_lastSearchOptions","isValidSearchTerm","didOptionsChange","newOptions","shouldUpdateHighlighting","clearCachedTerm","__webpack_module_cache__","moduleId","cachedModule","__webpack_modules__","SearchLineCache_1","SearchState_1","SearchEngine_1","DecorationManager_1","SearchResultTracker_1","SearchAddon","_resultTracker","_highlightTimeout","_state","SearchState","_onAfterSearch","onAfterSearch","_onBeforeSearch","onBeforeSearch","_highlightLimit","highlightLimit","activate","terminal","_engine","SearchEngine","_decorationManager","onWriteParsed","_updateMatches","clearDecorations","findPrevious","incremental","noScroll","retainCachedSearchTerm","clearActiveDecoration","findNext","internalSearchOptions","_highlightAllMatches","found","_findNextAndSelect","_fireResults","prevResult","nextCol","nextRow","floor","_selectResult","_findPreviousAndSelect","select","activeDecoration","viewportY","scroll","scrollLines"],"sourceRoot":""} \ No newline at end of file diff --git a/lib/addon-search.mjs b/lib/addon-search.mjs -index 5cf231a96b56284705711faebe6b0c492f133546..c62f09af02e07980289fe39f59da418eb7729a26 100644 +index 5cf231a96b56284705711faebe6b0c492f133546..6fc158e5b19ab89e296057a1464fb4179b7145f7 100644 --- a/lib/addon-search.mjs +++ b/lib/addon-search.mjs @@ -14,5 +14,5 @@ @@ -25,10 +25,10 @@ index 5cf231a96b56284705711faebe6b0c492f133546..c62f09af02e07980289fe39f59da418e * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -function _(c){return{dispose:c}}function D(c){if(!c)return c;if(Array.isArray(c)){for(let i of c)i.dispose();return[]}return c.dispose(),c}function E(...c){return _(()=>D(c))}var S=class{constructor(){this._disposables=new Set;this._isDisposed=!1}get isDisposed(){return this._isDisposed}add(i){return this._isDisposed?i.dispose():this._disposables.add(i),i}dispose(){if(!this._isDisposed){this._isDisposed=!0;for(let i of this._disposables)i.dispose();this._disposables.clear()}}clear(){for(let i of this._disposables)i.dispose();this._disposables.clear()}},b=class{constructor(){this._store=new S}dispose(){this._store.dispose()}_register(i){return this._store.add(i)}};b.None=Object.freeze({dispose(){}});var v=class{constructor(){this._isDisposed=!1}get value(){return this._isDisposed?void 0:this._value}set value(i){this._isDisposed||i===this._value||(this._value?.dispose(),this._value=i)}clear(){this.value=void 0}dispose(){this._isDisposed=!0,this._value?.dispose(),this._value=void 0}};var I=class{constructor(){this._listeners=[];this._disposed=!1}get event(){return this._event?this._event:(this._event=(i,e,t)=>{if(this._disposed)return _(()=>{});let r={fn:i,thisArgs:e};this._listeners=this._listeners.slice(),this._listeners.push(r);let s=_(()=>{let n=this._listeners.indexOf(r);n!==-1&&(this._listeners=this._listeners.slice(),this._listeners.splice(n,1))});return t&&(Array.isArray(t)?t.push(s):t.add(s)),s},this._event)}fire(i){if(this._disposed||!this._listeners.length)return;if(this._listeners.length===1){this._listeners[0].fn.call(this._listeners[0].thisArgs,i);return}let e=this._listeners;for(let t=0,r=e.length;t{function c(s,n){return s(a=>n.fire(a))}r.forward=c;function i(s,n){return(a,o,l)=>s(h=>a.call(o,n(h)),void 0,l)}r.map=i;function e(...s){return(n,a,o)=>{let l=new S;for(let h of s)l.add(h(p=>n.call(a,p)));return o&&(Array.isArray(o)?o.push(l):o.add(l)),l}}r.any=e;function t(s,n,a){return n(a),s(o=>n(o))}r.runAndSubscribe=t})(W||={});function T(c,i=0,e){let t=setTimeout(()=>{c(),e&&r.dispose()},i),r=_(()=>{clearTimeout(t)});return e?.add(r),r}var C=class extends b{constructor(e){super();this._terminal=e;this._linesCacheTimeout=this._register(new v);this._linesCacheDisposables=this._register(new v);this._lastAccessTimestamp=0;this._register(_(()=>this._destroyLinesCache()))}initLinesCache(){this._linesCache||(this._linesCache=new Array(this._terminal.buffer.active.length),this._linesCacheDisposables.value=E(this._terminal.onLineFeed(()=>this._destroyLinesCache()),this._terminal.onCursorMove(()=>this._destroyLinesCache()),this._terminal.onResize(()=>this._destroyLinesCache()))),this._lastAccessTimestamp=Date.now(),this._linesCacheTimeout.value||this._scheduleLinesCacheTimeout(15e3)}_destroyLinesCache(){this._linesCache=void 0,this._lastAccessTimestamp=0,this._linesCacheDisposables.clear(),this._linesCacheTimeout.clear()}_scheduleLinesCacheTimeout(e){this._linesCacheTimeout.value=T(()=>{if(!this._linesCache)return;let r=Date.now()-this._lastAccessTimestamp;if(r>=15e3){this._destroyLinesCache();return}this._scheduleLinesCacheTimeout(15e3-r)},e)}getLineFromCache(e){return this._linesCache?.[e]}setLineInCache(e,t){this._linesCache&&(this._linesCache[e]=t)}translateBufferLineToStringWithWrap(e,t){let r=[],s=[0],n=this._terminal.buffer.active.getLine(e);for(;n;){let a=this._terminal.buffer.active.getLine(e+1),o=a?a.isWrapped:!1,l=n.translateToString(!o&&t);if(o&&a){let h=n.getCell(n.length-1);h&&h.getCode()===0&&h.getWidth()===1&&a.getCell(0)?.getWidth()===2&&(l=l.slice(0,-1))}if(r.push(l),o)s.push(s[s.length-1]+l.length);else break;e++,n=a}return[r.join(""),s]}};var x=class{get cachedSearchTerm(){return this._cachedSearchTerm}set cachedSearchTerm(i){this._cachedSearchTerm=i}get lastSearchOptions(){return this._lastSearchOptions}set lastSearchOptions(i){this._lastSearchOptions=i}isValidSearchTerm(i){return!!(i&&i.length>0)}didOptionsChange(i){return this._lastSearchOptions?i?this._lastSearchOptions.caseSensitive!==i.caseSensitive||this._lastSearchOptions.regex!==i.regex||this._lastSearchOptions.wholeWord!==i.wholeWord:!1:!0}shouldUpdateHighlighting(i,e){return e?.decorations?this._cachedSearchTerm===void 0||i!==this._cachedSearchTerm||this.didOptionsChange(e):!1}clearCachedTerm(){this._cachedSearchTerm=void 0}reset(){this._cachedSearchTerm=void 0,this._lastSearchOptions=void 0}};var R=class{constructor(i,e){this._terminal=i;this._lineCache=e}find(i,e,t,r){if(!i||i.length===0){this._terminal.clearSelection();return}if(t>=this._terminal.cols)throw new Error(`Invalid col: ${t} to search in terminal of ${this._terminal.cols} cols`);this._lineCache.initLinesCache();let s={startRow:e,startCol:t},n=this._findInLine(i,s,r);if(!n)for(let a=e+1;a=0&&(o.startRow=h,l=this._findInLine(i,o,e,a),!l);h--);}if(!l&&s!==this._terminal.buffer.active.baseY+this._terminal.rows-1)for(let h=this._terminal.buffer.active.baseY+this._terminal.rows-1;h>=s&&(o.startRow=h,l=this._findInLine(i,o,e,a),!l);h--);return l}_isWholeWord(i,e,t){return(i===0||" ~!@#$%^&*()+`-=[]{}|\\;:\"',./<>?".includes(e[i-1]))&&(i+t.length===e.length||" ~!@#$%^&*()+`-=[]{}|\\;:\"',./<>?".includes(e[i+t.length]))}_findInLine(i,e,t={},r=!1){let s=e.startRow,n=e.startCol;if(this._terminal.buffer.active.getLine(s)?.isWrapped){if(r){e.startCol+=this._terminal.cols;return}return e.startRow--,e.startCol+=this._terminal.cols,this._findInLine(i,e,t)}let o=this._lineCache.getLineFromCache(s);o||(o=this._lineCache.translateBufferLineToStringWithWrap(s,!0),this._lineCache.setLineInCache(s,o));let[l,h]=o,p=this._bufferColsToStringOffset(s,n),m=i,g=l;t.regex||(m=t.caseSensitive?i:i.toLowerCase(),g=t.caseSensitive?l:l.toLowerCase());let f=-1;if(t.regex){let u=RegExp(m,t.caseSensitive?"g":"gi"),d;if(r)for(;d=u.exec(g.slice(0,p));)f=u.lastIndex-d[0].length,i=d[0],u.lastIndex-=i.length-1;else d=u.exec(g.slice(p)),d&&d[0].length>0&&(f=p+(u.lastIndex-d[0].length),i=d[0])}else r?p-m.length>=0&&(f=g.lastIndexOf(m,p-m.length)):f=g.indexOf(m,p);if(f>=0){if(t.wholeWord&&!this._isWholeWord(f,g,i))return;let u=0;for(;u=h[u+1];)u++;let d=u;for(;d=h[d+1];)d++;let O=f-h[u],k=f+i.length-h[d],y=this._stringLengthToBufferSize(s+u,O),M=this._stringLengthToBufferSize(s+d,k)-y+this._terminal.cols*(d-u);return{term:i,col:y,row:s+u,size:M}}}_stringLengthToBufferSize(i,e){let t=this._terminal.buffer.active.getLine(i);if(!t)return 0;for(let r=0;r1&&(e-=n.length-1);let a=t.getCell(r+1);a&&a.getWidth()===0&&e++}return e}_bufferColsToStringOffset(i,e){let t=i,r=0,s=this._terminal.buffer.active.getLine(t);for(;e>0&&s;){for(let n=0;nthis.clearHighlightDecorations()))}createHighlightDecorations(e,t){this.clearHighlightDecorations();for(let r of e){let s=this._createResultDecorations(r,t,!1);if(s)for(let n of s)this._storeDecoration(n,r)}}createActiveDecoration(e,t){let r=this._createResultDecorations(e,t,!0);if(r)return{decorations:r,match:e,dispose(){D(r)}}}clearHighlightDecorations(){D(this._highlightDecorations),this._highlightDecorations=[],this._highlightedLines.clear()}_storeDecoration(e,t){this._highlightedLines.add(e.marker.line),this._highlightDecorations.push({decoration:e,match:t,dispose(){e.dispose()}})}_applyStyles(e,t,r){e.classList.contains("xterm-find-result-decoration")||(e.classList.add("xterm-find-result-decoration"),t&&(e.style.outline=`1px solid ${t}`)),r&&e.classList.add("xterm-find-active-result-decoration")}_createResultDecorations(e,t,r){let s=[],n=e.col,a=e.size,o=-this._terminal.buffer.active.baseY-this._terminal.buffer.active.cursorY+e.row;for(;a>0;){let h=Math.min(this._terminal.cols-n,a);s.push([o,n,h]),n=0,a-=h,o++}let l=[];for(let h of s){let p=this._terminal.registerMarker(h[0]),m=this._terminal.registerDecoration({marker:p,x:h[1],width:h[2],layer:r?"top":"bottom",backgroundColor:r?t.activeMatchBackground:t.matchBackground,overviewRulerOptions:this._highlightedLines.has(p.line)?void 0:{color:r?t.activeMatchColorOverviewRuler:t.matchOverviewRuler,position:"center"}});if(m){let g=[];g.push(p),g.push(m.onRender(f=>this._applyStyles(f,r?t.activeMatchBorder:t.matchBorder,!1))),g.push(m.onDispose(()=>D(g))),l.push(m)}}return l.length===0?void 0:l}};var L=class extends b{constructor(){super(...arguments);this._searchResults=[];this._onDidChangeResults=this._register(new I)}get onDidChangeResults(){return this._onDidChangeResults.event}get searchResults(){return this._searchResults}get selectedDecoration(){return this._selectedDecoration}set selectedDecoration(e){this._selectedDecoration=e}updateResults(e,t){this._searchResults=e.slice(0,t)}clearResults(){this._searchResults=[]}clearSelectedDecoration(){this._selectedDecoration&&(this._selectedDecoration.dispose(),this._selectedDecoration=void 0)}findResultIndex(e){for(let t=0;tthis._updateMatches())),this._register(this._terminal.onResize(()=>this._updateMatches())),this._register(_(()=>this.clearDecorations()))}_updateMatches(){this._highlightTimeout.clear(),this._state.cachedSearchTerm&&this._state.lastSearchOptions?.decorations&&(this._highlightTimeout.value=T(()=>{let e=this._state.cachedSearchTerm;this._state.clearCachedTerm(),this.findPrevious(e,{...this._state.lastSearchOptions,incremental:!0},{noScroll:!0})},200))}clearDecorations(e){this._resultTracker.clearSelectedDecoration(),this._decorationManager?.clearHighlightDecorations(),this._resultTracker.clearResults(),e||this._state.clearCachedTerm()}clearActiveDecoration(){this._resultTracker.clearSelectedDecoration()}findNext(e,t,r){if(!this._terminal||!this._engine)throw new Error("Cannot use addon until it has been loaded");this._onBeforeSearch.fire(),this._state.lastSearchOptions=t,this._state.shouldUpdateHighlighting(e,t)&&this._highlightAllMatches(e,t);let s=this._findNextAndSelect(e,t,r);return this._fireResults(t),this._state.cachedSearchTerm=e,this._onAfterSearch.fire(),s}_highlightAllMatches(e,t){if(!this._terminal||!this._engine||!this._decorationManager)throw new Error("Cannot use addon until it has been loaded");if(!this._state.isValidSearchTerm(e)){this.clearDecorations();return}this.clearDecorations(!0);let r=[],s,n=this._engine.find(e,0,0,t);for(;n&&(s?.row!==n.row||s?.col!==n.col)&&!(r.length>=this._highlightLimit);){s=n,r.push(s);let a=this._terminal.cols,o=s.col+s.size,l=s.row;o>=a&&(l+=Math.floor(o/a),o=o%a),n=this._engine.find(e,l,o,t)}this._resultTracker.updateResults(r,this._highlightLimit),t.decorations&&this._decorationManager.createHighlightDecorations(r,t.decorations)}_findNextAndSelect(e,t,r){if(!this._terminal||!this._engine)return!1;if(!this._state.isValidSearchTerm(e))return this._terminal.clearSelection(),this.clearDecorations(),!1;let s=this._engine.findNextWithSelection(e,t,this._state.cachedSearchTerm);return this._selectResult(s,t?.decorations,r?.noScroll)}findPrevious(e,t,r){if(!this._terminal||!this._engine)throw new Error("Cannot use addon until it has been loaded");this._onBeforeSearch.fire(),this._state.lastSearchOptions=t,this._state.shouldUpdateHighlighting(e,t)&&this._highlightAllMatches(e,t);let s=this._findPreviousAndSelect(e,t,r);return this._fireResults(t),this._state.cachedSearchTerm=e,this._onAfterSearch.fire(),s}_fireResults(e){this._resultTracker.fireResultsChanged(!!e?.decorations)}_findPreviousAndSelect(e,t,r){if(!this._terminal||!this._engine)return!1;if(!this._state.isValidSearchTerm(e))return this._terminal.clearSelection(),this.clearDecorations(),!1;let s=this._engine.findPreviousWithSelection(e,t,this._state.cachedSearchTerm);return this._selectResult(s,t?.decorations,r?.noScroll)}_selectResult(e,t,r){if(!this._terminal||!this._decorationManager)return!1;if(this._resultTracker.clearSelectedDecoration(),!e)return this._terminal.clearSelection(),!1;if(this._terminal.select(e.col,e.row,e.size),t){let s=this._decorationManager.createActiveDecoration(e,t);s&&(this._resultTracker.selectedDecoration=s)}if(!r&&(e.row>=this._terminal.buffer.active.viewportY+this._terminal.rows||e.rowI(c))}var S=class{constructor(){this._disposables=new Set;this._isDisposed=!1}get isDisposed(){return this._isDisposed}add(i){return this._isDisposed?i.dispose():this._disposables.add(i),i}dispose(){if(!this._isDisposed){this._isDisposed=!0;for(let i of this._disposables)i.dispose();this._disposables.clear()}}clear(){for(let i of this._disposables)i.dispose();this._disposables.clear()}},g=class{constructor(){this._store=new S}dispose(){this._store.dispose()}_register(i){return this._store.add(i)}};g.None=Object.freeze({dispose(){}});var b=class{constructor(){this._isDisposed=!1}get value(){return this._isDisposed?void 0:this._value}set value(i){this._isDisposed||i===this._value||(this._value?.dispose(),this._value=i)}clear(){this.value=void 0}dispose(){this._isDisposed=!0,this._value?.dispose(),this._value=void 0}};var v=class{constructor(){this._listeners=[];this._disposed=!1}get event(){return this._event?this._event:(this._event=(i,e,t)=>{if(this._disposed)return _(()=>{});let s={fn:i,thisArgs:e};this._listeners=this._listeners.slice(),this._listeners.push(s);let r=_(()=>{let n=this._listeners.indexOf(s);n!==-1&&(this._listeners=this._listeners.slice(),this._listeners.splice(n,1))});return t&&(Array.isArray(t)?t.push(r):t.add(r)),r},this._event)}fire(i){if(this._disposed||!this._listeners.length)return;if(this._listeners.length===1){this._listeners[0].fn.call(this._listeners[0].thisArgs,i);return}let e=this._listeners;for(let t=0,s=e.length;t{function c(r,n){return r(a=>n.fire(a))}s.forward=c;function i(r,n){return(a,o,l)=>r(h=>a.call(o,n(h)),void 0,l)}s.map=i;function e(...r){return(n,a,o)=>{let l=new S;for(let h of r)l.add(h(f=>n.call(a,f)));return o&&(Array.isArray(o)?o.push(l):o.add(l)),l}}s.any=e;function t(r,n,a){return n(a),r(o=>n(o))}s.runAndSubscribe=t})(M||={});function D(c,i=0,e){let t=setTimeout(()=>{c(),e&&s.dispose()},i),s=_(()=>{clearTimeout(t)});return e?.add(s),s}var T=class extends g{constructor(e){super();this._terminal=e;this._linesCacheTimeout=this._register(new b);this._linesCacheDisposables=this._register(new b);this._lastAccessTimestamp=0;this._register(_(()=>this._destroyLinesCache()))}initLinesCache(){this._linesCache||(this._linesCache=new Array(this._terminal.buffer.active.length),this._linesCacheDisposables.value=L(this._terminal.onLineFeed(()=>this._destroyLinesCache()),this._terminal.onCursorMove(()=>this._destroyLinesCache()),this._terminal.onResize(()=>this._destroyLinesCache()))),this._lastAccessTimestamp=Date.now(),this._linesCacheTimeout.value||this._scheduleLinesCacheTimeout(15e3)}_destroyLinesCache(){this._linesCache=void 0,this._lastAccessTimestamp=0,this._linesCacheDisposables.clear(),this._linesCacheTimeout.clear()}_scheduleLinesCacheTimeout(e){this._linesCacheTimeout.value=D(()=>{if(!this._linesCache)return;let s=Date.now()-this._lastAccessTimestamp;if(s>=15e3){this._destroyLinesCache();return}this._scheduleLinesCacheTimeout(15e3-s)},e)}getLineFromCache(e){return this._linesCache?.[e]}setLineInCache(e,t){this._linesCache&&(this._linesCache[e]=t)}translateBufferLineToStringWithWrap(e,t){let s=[],r=[0],n=this._terminal.buffer.active.getLine(e);for(;n;){let a=this._terminal.buffer.active.getLine(e+1),o=a?a.isWrapped:!1,l=n.translateToString(!o&&t);if(o&&a){let h=n.getCell(n.length-1);h&&h.getCode()===0&&h.getWidth()===1&&a.getCell(0)?.getWidth()===2&&(l=l.slice(0,-1))}if(s.push(l),o)r.push(r[r.length-1]+l.length);else break;e++,n=a}return[s.join(""),r]}};var C=class{get cachedSearchTerm(){return this._cachedSearchTerm}set cachedSearchTerm(i){this._cachedSearchTerm=i}get lastSearchOptions(){return this._lastSearchOptions}set lastSearchOptions(i){this._lastSearchOptions=i}isValidSearchTerm(i){return!!(i&&i.length>0)}didOptionsChange(i){return this._lastSearchOptions?i?this._lastSearchOptions.caseSensitive!==i.caseSensitive||this._lastSearchOptions.regex!==i.regex||this._lastSearchOptions.wholeWord!==i.wholeWord:!1:!0}shouldUpdateHighlighting(i,e){return e?.decorations?this._cachedSearchTerm===void 0||i!==this._cachedSearchTerm||this.didOptionsChange(e):!1}clearCachedTerm(){this._cachedSearchTerm=void 0}reset(){this._cachedSearchTerm=void 0,this._lastSearchOptions=void 0}};var x=class{constructor(i,e){this._terminal=i;this._lineCache=e}find(i,e,t,s){if(!i||i.length===0){this._terminal.clearSelection();return}if(t>=this._terminal.cols)throw new Error(`Invalid col: ${t} to search in terminal of ${this._terminal.cols} cols`);this._lineCache.initLinesCache();let r={startRow:e,startCol:t},n=this._findInLine(i,r,s);if(!n)for(let a=e+1;a=0&&(o.startRow=h,l=this._findInLine(i,o,e,a),!l);h--);}if(!l&&r!==this._terminal.buffer.active.baseY+this._terminal.rows-1)for(let h=this._terminal.buffer.active.baseY+this._terminal.rows-1;h>=r&&(o.startRow=h,l=this._findInLine(i,o,e,a),!l);h--);return l}_isWholeWord(i,e,t){return(i===0||" ~!@#$%^&*()+`-=[]{}|\\;:\"',./<>?".includes(e[i-1]))&&(i+t.length===e.length||" ~!@#$%^&*()+`-=[]{}|\\;:\"',./<>?".includes(e[i+t.length]))}_findInLine(i,e,t={},s=!1){for(;this._terminal.buffer.active.getLine(e.startRow)?.isWrapped;){if(e.startCol+=this._terminal.cols,s)return;e.startRow--}let r=e.startRow,n=e.startCol,a=this._lineCache.getLineFromCache(r);a||(a=this._lineCache.translateBufferLineToStringWithWrap(r,!0),this._lineCache.setLineInCache(r,a));let[o,l]=a,h=this._bufferColsToStringOffset(r,n),f=i,m=o;t.regex||(f=t.caseSensitive?i:i.toLowerCase(),m=t.caseSensitive?o:o.toLowerCase());let u=-1;if(t.regex){let d=RegExp(f,t.caseSensitive?"g":"gi"),p;if(s)for(;p=d.exec(m.slice(0,h));)u=d.lastIndex-p[0].length,i=p[0],d.lastIndex-=i.length-1;else p=d.exec(m.slice(h)),p&&p[0].length>0&&(u=h+(d.lastIndex-p[0].length),i=p[0])}else s?h-f.length>=0&&(u=m.lastIndexOf(f,h-f.length)):u=m.indexOf(f,h);if(u>=0){if(t.wholeWord&&!this._isWholeWord(u,m,i))return;let d=0;for(;d=l[d+1];)d++;let p=d;for(;p=l[p+1];)p++;let A=u-l[d],O=u+i.length-l[p],y=this._stringLengthToBufferSize(r+d,A),k=this._stringLengthToBufferSize(r+p,O)-y+this._terminal.cols*(p-d);return{term:i,col:y,row:r+d,size:k}}}_stringLengthToBufferSize(i,e){let t=this._terminal.buffer.active.getLine(i);if(!t)return 0;for(let s=0;s1&&(e-=n.length-1);let a=t.getCell(s+1);a&&a.getWidth()===0&&e++}return e}_bufferColsToStringOffset(i,e){let t=i,s=0,r=this._terminal.buffer.active.getLine(t);for(;e>0&&r;){for(let n=0;nthis.clearHighlightDecorations()))}createHighlightDecorations(e,t){this.clearHighlightDecorations();for(let s of e){let r=this._createResultDecorations(s,t,!1);if(r)for(let n of r)this._storeDecoration(n,s)}}createActiveDecoration(e,t){let s=this._createResultDecorations(e,t,!0);if(s)return{decorations:s,match:e,dispose(){I(s)}}}clearHighlightDecorations(){I(this._highlightDecorations),this._highlightDecorations=[],this._highlightedLines.clear()}_storeDecoration(e,t){this._highlightedLines.add(e.marker.line),this._highlightDecorations.push({decoration:e,match:t,dispose(){e.dispose()}})}_applyStyles(e,t,s){e.classList.contains("xterm-find-result-decoration")||(e.classList.add("xterm-find-result-decoration"),t&&(e.style.outline=`1px solid ${t}`)),s&&e.classList.add("xterm-find-active-result-decoration")}_createResultDecorations(e,t,s){let r=[],n=e.col,a=e.size,o=-this._terminal.buffer.active.baseY-this._terminal.buffer.active.cursorY+e.row;for(;a>0;){let h=Math.min(this._terminal.cols-n,a);r.push([o,n,h]),n=0,a-=h,o++}let l=[];for(let h of r){let f=this._terminal.registerMarker(h[0]),m=this._terminal.registerDecoration({marker:f,x:h[1],width:h[2],layer:s?"top":"bottom",backgroundColor:s?t.activeMatchBackground:t.matchBackground,overviewRulerOptions:this._highlightedLines.has(f.line)?void 0:{color:s?t.activeMatchColorOverviewRuler:t.matchOverviewRuler,position:"center"}});if(m){let u=[];u.push(f),u.push(m.onRender(d=>this._applyStyles(d,s?t.activeMatchBorder:t.matchBorder,!1))),u.push(m.onDispose(()=>I(u))),l.push(m)}}return l.length===0?void 0:l}};var R=class extends g{constructor(){super(...arguments);this._searchResults=[];this._onDidChangeResults=this._register(new v)}get onDidChangeResults(){return this._onDidChangeResults.event}get searchResults(){return this._searchResults}get selectedDecoration(){return this._selectedDecoration}set selectedDecoration(e){this._selectedDecoration=e}updateResults(e,t){this._searchResults=e.slice(0,t)}clearResults(){this._searchResults=[]}clearSelectedDecoration(){this._selectedDecoration&&(this._selectedDecoration.dispose(),this._selectedDecoration=void 0)}findResultIndex(e){for(let t=0;tthis._updateMatches())),this._register(this._terminal.onResize(()=>this._updateMatches())),this._register(_(()=>this.clearDecorations()))}_updateMatches(){this._highlightTimeout.clear(),this._state.cachedSearchTerm&&this._state.lastSearchOptions?.decorations&&(this._highlightTimeout.value=D(()=>{let e=this._state.cachedSearchTerm;this._state.clearCachedTerm(),this.findPrevious(e,{...this._state.lastSearchOptions,incremental:!0},{noScroll:!0})},200))}clearDecorations(e){this._resultTracker.clearSelectedDecoration(),this._decorationManager?.clearHighlightDecorations(),this._resultTracker.clearResults(),e||this._state.clearCachedTerm()}clearActiveDecoration(){this._resultTracker.clearSelectedDecoration()}findNext(e,t,s){if(!this._terminal||!this._engine)throw new Error("Cannot use addon until it has been loaded");this._onBeforeSearch.fire(),this._state.lastSearchOptions=t,this._state.shouldUpdateHighlighting(e,t)&&this._highlightAllMatches(e,t);let r=this._findNextAndSelect(e,t,s);return this._fireResults(t),this._state.cachedSearchTerm=e,this._onAfterSearch.fire(),r}_highlightAllMatches(e,t){if(!this._terminal||!this._engine||!this._decorationManager)throw new Error("Cannot use addon until it has been loaded");if(!this._state.isValidSearchTerm(e)){this.clearDecorations();return}this.clearDecorations(!0);let s=[],r,n=this._engine.find(e,0,0,t);for(;n&&(r?.row!==n.row||r?.col!==n.col)&&!(s.length>=this._highlightLimit);){r=n,s.push(r);let a=this._terminal.cols,o=r.col+r.size,l=r.row;o>=a&&(l+=Math.floor(o/a),o=o%a),n=this._engine.find(e,l,o,t)}this._resultTracker.updateResults(s,this._highlightLimit),t.decorations&&this._decorationManager.createHighlightDecorations(s,t.decorations)}_findNextAndSelect(e,t,s){if(!this._terminal||!this._engine)return!1;if(!this._state.isValidSearchTerm(e))return this._terminal.clearSelection(),this.clearDecorations(),!1;let r=this._engine.findNextWithSelection(e,t,this._state.cachedSearchTerm);return this._selectResult(r,t?.decorations,s?.noScroll)}findPrevious(e,t,s){if(!this._terminal||!this._engine)throw new Error("Cannot use addon until it has been loaded");this._onBeforeSearch.fire(),this._state.lastSearchOptions=t,this._state.shouldUpdateHighlighting(e,t)&&this._highlightAllMatches(e,t);let r=this._findPreviousAndSelect(e,t,s);return this._fireResults(t),this._state.cachedSearchTerm=e,this._onAfterSearch.fire(),r}_fireResults(e){this._resultTracker.fireResultsChanged(!!e?.decorations)}_findPreviousAndSelect(e,t,s){if(!this._terminal||!this._engine)return!1;if(!this._state.isValidSearchTerm(e))return this._terminal.clearSelection(),this.clearDecorations(),!1;let r=this._engine.findPreviousWithSelection(e,t,this._state.cachedSearchTerm);return this._selectResult(r,t?.decorations,s?.noScroll)}_selectResult(e,t,s){if(!this._terminal||!this._decorationManager)return!1;if(this._resultTracker.clearSelectedDecoration(),!e)return this._terminal.clearSelection(),!1;if(this._terminal.select(e.col,e.row,e.size),t){let r=this._decorationManager.createActiveDecoration(e,t);r&&(this._resultTracker.selectedDecoration=r)}if(!s&&(e.row>=this._terminal.buffer.active.viewportY+this._terminal.rows||e.rowI(c))}var S=class{constructor(){this._disposables=new Set;this._isDisposed=!1}get isDisposed(){return this._isDisposed}add(i){return this._isDisposed?i.dispose():this._disposables.add(i),i}dispose(){if(!this._isDisposed){this._isDisposed=!0;for(let i of this._disposables)i.dispose();this._disposables.clear()}}clear(){for(let i of this._disposables)i.dispose();this._disposables.clear()}},g=class{constructor(){this._store=new S}dispose(){this._store.dispose()}_register(i){return this._store.add(i)}};g.None=Object.freeze({dispose(){}});var b=class{constructor(){this._isDisposed=!1}get value(){return this._isDisposed?void 0:this._value}set value(i){this._isDisposed||i===this._value||(this._value?.dispose(),this._value=i)}clear(){this.value=void 0}dispose(){this._isDisposed=!0,this._value?.dispose(),this._value=void 0}};var v=class{constructor(){this._listeners=[];this._disposed=!1}get event(){return this._event?this._event:(this._event=(i,e,t)=>{if(this._disposed)return _(()=>{});let s={fn:i,thisArgs:e};this._listeners=this._listeners.slice(),this._listeners.push(s);let r=_(()=>{let o=this._listeners.indexOf(s);o!==-1&&(this._listeners=this._listeners.slice(),this._listeners.splice(o,1))});return t&&(Array.isArray(t)?t.push(r):t.add(r)),r},this._event)}fire(i){if(this._disposed||!this._listeners.length)return;if(this._listeners.length===1){this._listeners[0].fn.call(this._listeners[0].thisArgs,i);return}let e=this._listeners;for(let t=0,s=e.length;t{function c(r,o){return r(n=>o.fire(n))}s.forward=c;function i(r,o){return(n,a,l)=>r(h=>n.call(a,o(h)),void 0,l)}s.map=i;function e(...r){return(o,n,a)=>{let l=new S;for(let h of r)l.add(h(f=>o.call(n,f)));return a&&(Array.isArray(a)?a.push(l):a.add(l)),l}}s.any=e;function t(r,o,n){return o(n),r(a=>o(a))}s.runAndSubscribe=t})(M||={});function D(c,i=0,e){let t=setTimeout(()=>{c(),e&&s.dispose()},i),s=_(()=>{clearTimeout(t)});return e?.add(s),s}var T=class extends g{constructor(e){super();this._terminal=e;this._linesCacheTimeout=this._register(new b);this._linesCacheDisposables=this._register(new b);this._lastAccessTimestamp=0;this._register(_(()=>this._destroyLinesCache()))}initLinesCache(){this._linesCache||(this._linesCache=new Array(this._terminal.buffer.active.length),this._linesCacheDisposables.value=L(this._terminal.onLineFeed(()=>this._destroyLinesCache()),this._terminal.onCursorMove(()=>this._destroyLinesCache()),this._terminal.onResize(()=>this._destroyLinesCache()))),this._lastAccessTimestamp=Date.now(),this._linesCacheTimeout.value||this._scheduleLinesCacheTimeout(15e3)}_destroyLinesCache(){this._linesCache=void 0,this._lastAccessTimestamp=0,this._linesCacheDisposables.clear(),this._linesCacheTimeout.clear()}_scheduleLinesCacheTimeout(e){this._linesCacheTimeout.value=D(()=>{if(!this._linesCache)return;let s=Date.now()-this._lastAccessTimestamp;if(s>=15e3){this._destroyLinesCache();return}this._scheduleLinesCacheTimeout(15e3-s)},e)}getLineFromCache(e){return this._linesCache?.[e]}setLineInCache(e,t){this._linesCache&&(this._linesCache[e]=t)}translateBufferLineToStringWithWrap(e,t){let s=[],r=[0],o=this._terminal.buffer.active.getLine(e);for(;o;){let n=this._terminal.buffer.active.getLine(e+1),a=n?n.isWrapped:!1,l=o.translateToString(!a&&t);if(a&&n){let h=o.getCell(o.length-1);h&&h.getCode()===0&&h.getWidth()===1&&n.getCell(0)?.getWidth()===2&&(l=l.slice(0,-1))}if(s.push(l),a)r.push(r[r.length-1]+l.length);else break;e++,o=n}return[s.join(""),r]}};var C=class{get cachedSearchTerm(){return this._cachedSearchTerm}set cachedSearchTerm(i){this._cachedSearchTerm=i}get lastSearchOptions(){return this._lastSearchOptions}set lastSearchOptions(i){this._lastSearchOptions=i}isValidSearchTerm(i){return!!(i&&i.length>0)}didOptionsChange(i){return this._lastSearchOptions?i?this._lastSearchOptions.caseSensitive!==i.caseSensitive||this._lastSearchOptions.regex!==i.regex||this._lastSearchOptions.wholeWord!==i.wholeWord:!1:!0}shouldUpdateHighlighting(i,e){return e?.decorations?this._cachedSearchTerm===void 0||i!==this._cachedSearchTerm||this.didOptionsChange(e):!1}clearCachedTerm(){this._cachedSearchTerm=void 0}reset(){this._cachedSearchTerm=void 0,this._lastSearchOptions=void 0}};var x=class{constructor(i,e){this._terminal=i;this._lineCache=e}find(i,e,t,s){if(!i||i.length===0){this._terminal.clearSelection();return}if(t>=this._terminal.cols)throw new Error(`Invalid col: ${t} to search in terminal of ${this._terminal.cols} cols`);this._lineCache.initLinesCache();let r={startRow:e,startCol:t},o=this._findInLine(i,r,s);if(!o)for(let n=e+1;n=0&&(a.startRow=h,l=this._findInLine(i,a,e,n),!l);h--);}if(!l&&r!==this._terminal.buffer.active.baseY+this._terminal.rows-1)for(let h=this._terminal.buffer.active.baseY+this._terminal.rows-1;h>=r&&(a.startRow=h,l=this._findInLine(i,a,e,n),!l);h--);return l}_isWholeWord(i,e,t){return(i===0||" ~!@#$%^&*()+`-=[]{}|\\;:\"',./<>?".includes(e[i-1]))&&(i+t.length===e.length||" ~!@#$%^&*()+`-=[]{}|\\;:\"',./<>?".includes(e[i+t.length]))}_isRowCoveredByLineStart(i,e){return e?.regex||e?.wholeWord?!1:this._terminal.buffer.active.getLine(i)?.isWrapped===!0}_findInLine(i,e,t={},s=!1){for(;this._terminal.buffer.active.getLine(e.startRow)?.isWrapped;){if(e.startCol+=this._terminal.cols,s)return;e.startRow--}let r=e.startRow,o=e.startCol,n=this._lineCache.getLineFromCache(r);n||(n=this._lineCache.translateBufferLineToStringWithWrap(r,!0),this._lineCache.setLineInCache(r,n));let[a,l]=n,h=this._bufferColsToStringOffset(r,o),f=i,m=a;t.regex||(f=t.caseSensitive?i:i.toLowerCase(),m=t.caseSensitive?a:a.toLowerCase());let u=-1;if(t.regex){let d=RegExp(f,t.caseSensitive?"g":"gi"),p;if(s)for(;p=d.exec(m.slice(0,h));)u=d.lastIndex-p[0].length,i=p[0],d.lastIndex-=i.length-1;else p=d.exec(m.slice(h)),p&&p[0].length>0&&(u=h+(d.lastIndex-p[0].length),i=p[0])}else s?h-f.length>=0&&(u=m.lastIndexOf(f,h-f.length)):u=m.indexOf(f,h);if(u>=0){if(t.wholeWord&&!this._isWholeWord(u,m,i))return;let d=0;for(;d=l[d+1];)d++;let p=d;for(;p=l[p+1];)p++;let A=u-l[d],O=u+i.length-l[p],y=this._stringLengthToBufferSize(r+d,A),k=this._stringLengthToBufferSize(r+p,O)-y+this._terminal.cols*(p-d);return{term:i,col:y,row:r+d,size:k}}}_stringLengthToBufferSize(i,e){let t=this._terminal.buffer.active.getLine(i);if(!t)return 0;for(let s=0;s1&&(e-=o.length-1);let n=t.getCell(s+1);n&&n.getWidth()===0&&e++}return e}_bufferColsToStringOffset(i,e){let t=i,s=0,r=this._terminal.buffer.active.getLine(t);for(;e>0&&r;){for(let o=0;othis.clearHighlightDecorations()))}createHighlightDecorations(e,t){this.clearHighlightDecorations();for(let s of e){let r=this._createResultDecorations(s,t,!1);if(r)for(let o of r)this._storeDecoration(o,s)}}createActiveDecoration(e,t){let s=this._createResultDecorations(e,t,!0);if(s)return{decorations:s,match:e,dispose(){I(s)}}}clearHighlightDecorations(){I(this._highlightDecorations),this._highlightDecorations=[],this._highlightedLines.clear()}_storeDecoration(e,t){this._highlightedLines.add(e.marker.line),this._highlightDecorations.push({decoration:e,match:t,dispose(){e.dispose()}})}_applyStyles(e,t,s){e.classList.contains("xterm-find-result-decoration")||(e.classList.add("xterm-find-result-decoration"),t&&(e.style.outline=`1px solid ${t}`)),s&&e.classList.add("xterm-find-active-result-decoration")}_createResultDecorations(e,t,s){let r=[],o=e.col,n=e.size,a=-this._terminal.buffer.active.baseY-this._terminal.buffer.active.cursorY+e.row;for(;n>0;){let h=Math.min(this._terminal.cols-o,n);r.push([a,o,h]),o=0,n-=h,a++}let l=[];for(let h of r){let f=this._terminal.registerMarker(h[0]),m=this._terminal.registerDecoration({marker:f,x:h[1],width:h[2],layer:s?"top":"bottom",backgroundColor:s?t.activeMatchBackground:t.matchBackground,overviewRulerOptions:this._highlightedLines.has(f.line)?void 0:{color:s?t.activeMatchColorOverviewRuler:t.matchOverviewRuler,position:"center"}});if(m){let u=[];u.push(f),u.push(m.onRender(d=>this._applyStyles(d,s?t.activeMatchBorder:t.matchBorder,!1))),u.push(m.onDispose(()=>I(u))),l.push(m)}}return l.length===0?void 0:l}};var R=class extends g{constructor(){super(...arguments);this._searchResults=[];this._onDidChangeResults=this._register(new v)}get onDidChangeResults(){return this._onDidChangeResults.event}get searchResults(){return this._searchResults}get selectedDecoration(){return this._selectedDecoration}set selectedDecoration(e){this._selectedDecoration=e}updateResults(e,t){this._searchResults=e.slice(0,t)}clearResults(){this._searchResults=[]}clearSelectedDecoration(){this._selectedDecoration&&(this._selectedDecoration.dispose(),this._selectedDecoration=void 0)}findResultIndex(e){for(let t=0;tthis._updateMatches())),this._register(this._terminal.onResize(()=>this._updateMatches())),this._register(_(()=>this.clearDecorations()))}_updateMatches(){this._highlightTimeout.clear(),this._state.cachedSearchTerm&&this._state.lastSearchOptions?.decorations&&(this._highlightTimeout.value=D(()=>{let e=this._state.cachedSearchTerm;this._state.clearCachedTerm(),this.findPrevious(e,{...this._state.lastSearchOptions,incremental:!0},{noScroll:!0})},200))}clearDecorations(e){this._resultTracker.clearSelectedDecoration(),this._decorationManager?.clearHighlightDecorations(),this._resultTracker.clearResults(),e||this._state.clearCachedTerm()}clearActiveDecoration(){this._resultTracker.clearSelectedDecoration()}findNext(e,t,s){if(!this._terminal||!this._engine)throw new Error("Cannot use addon until it has been loaded");this._onBeforeSearch.fire(),this._state.lastSearchOptions=t,this._state.shouldUpdateHighlighting(e,t)&&this._highlightAllMatches(e,t);let r=this._findNextAndSelect(e,t,s);return this._fireResults(t),this._state.cachedSearchTerm=e,this._onAfterSearch.fire(),r}_highlightAllMatches(e,t){if(!this._terminal||!this._engine||!this._decorationManager)throw new Error("Cannot use addon until it has been loaded");if(!this._state.isValidSearchTerm(e)){this.clearDecorations();return}this.clearDecorations(!0);let s=[],r,o=this._engine.find(e,0,0,t);for(;o&&(r?.row!==o.row||r?.col!==o.col)&&!(s.length>=this._highlightLimit);){r=o,s.push(r);let n=this._terminal.cols,a=r.col+r.size,l=r.row;a>=n&&(l+=Math.floor(a/n),a=a%n),o=this._engine.find(e,l,a,t)}this._resultTracker.updateResults(s,this._highlightLimit),t.decorations&&this._decorationManager.createHighlightDecorations(s,t.decorations)}_findNextAndSelect(e,t,s){if(!this._terminal||!this._engine)return!1;if(!this._state.isValidSearchTerm(e))return this._terminal.clearSelection(),this.clearDecorations(),!1;let r=this._engine.findNextWithSelection(e,t,this._state.cachedSearchTerm);return this._selectResult(r,t?.decorations,s?.noScroll)}findPrevious(e,t,s){if(!this._terminal||!this._engine)throw new Error("Cannot use addon until it has been loaded");this._onBeforeSearch.fire(),this._state.lastSearchOptions=t,this._state.shouldUpdateHighlighting(e,t)&&this._highlightAllMatches(e,t);let r=this._findPreviousAndSelect(e,t,s);return this._fireResults(t),this._state.cachedSearchTerm=e,this._onAfterSearch.fire(),r}_fireResults(e){this._resultTracker.fireResultsChanged(!!e?.decorations)}_findPreviousAndSelect(e,t,s){if(!this._terminal||!this._engine)return!1;if(!this._state.isValidSearchTerm(e))return this._terminal.clearSelection(),this.clearDecorations(),!1;let r=this._engine.findPreviousWithSelection(e,t,this._state.cachedSearchTerm);return this._selectResult(r,t?.decorations,s?.noScroll)}_selectResult(e,t,s){if(!this._terminal||!this._decorationManager)return!1;if(this._resultTracker.clearSelectedDecoration(),!e)return this._terminal.clearSelection(),!1;if(this._terminal.select(e.col,e.row,e.size),t){let r=this._decorationManager.createActiveDecoration(e,t);r&&(this._resultTracker.selectedDecoration=r)}if(!s&&(e.row>=this._terminal.buffer.active.viewportY+this._terminal.rows||e.row void): IDisposable {\n return { dispose: fn };\n}\n\nexport function dispose(disposable: T): T;\nexport function dispose(disposable: T | undefined): T | undefined;\nexport function dispose(disposables: T[]): T[];\nexport function dispose(arg: T | T[] | undefined): T | T[] | undefined {\n if (!arg) {\n return arg;\n }\n if (Array.isArray(arg)) {\n for (const d of arg) {\n d.dispose();\n }\n return [];\n }\n arg.dispose();\n return arg;\n}\n\nexport function combinedDisposable(...disposables: IDisposable[]): IDisposable {\n return toDisposable(() => dispose(disposables));\n}\n\nexport class DisposableStore implements IDisposable {\n private readonly _disposables = new Set();\n private _isDisposed = false;\n\n public get isDisposed(): boolean {\n return this._isDisposed;\n }\n\n public add(o: T): T {\n if (this._isDisposed) {\n o.dispose();\n } else {\n this._disposables.add(o);\n }\n return o;\n }\n\n public dispose(): void {\n if (this._isDisposed) {\n return;\n }\n this._isDisposed = true;\n for (const d of this._disposables) {\n d.dispose();\n }\n this._disposables.clear();\n }\n\n public clear(): void {\n for (const d of this._disposables) {\n d.dispose();\n }\n this._disposables.clear();\n }\n}\n\nexport abstract class Disposable implements IDisposable {\n public static readonly None: IDisposable = Object.freeze({ dispose() { } });\n\n protected readonly _store = new DisposableStore();\n\n public dispose(): void {\n this._store.dispose();\n }\n\n protected _register(o: T): T {\n return this._store.add(o);\n }\n}\n\nexport class MutableDisposable implements IDisposable {\n private _value: T | undefined;\n private _isDisposed = false;\n\n public get value(): T | undefined {\n return this._isDisposed ? undefined : this._value;\n }\n\n public set value(value: T | undefined) {\n if (this._isDisposed || value === this._value) {\n return;\n }\n this._value?.dispose();\n this._value = value;\n }\n\n public clear(): void {\n this.value = undefined;\n }\n\n public dispose(): void {\n this._isDisposed = true;\n this._value?.dispose();\n this._value = undefined;\n }\n}\n", "/**\n * Copyright (c) 2024-2026 The xterm.js authors. All rights reserved.\n * @license MIT\n *\n * Minimal event utilities for xterm.js core.\n * Simplified from VS Code's event.ts - no leak detection/profiling.\n */\n\nimport { IDisposable, DisposableStore, toDisposable } from './Lifecycle';\n\nexport interface IEvent {\n (listener: (e: T) => any, thisArgs?: any, disposables?: IDisposable[] | DisposableStore): IDisposable;\n}\n\nexport class Emitter {\n private _listeners: { fn: (e: T) => any, thisArgs: any }[] = [];\n private _disposed = false;\n private _event: IEvent | undefined;\n\n public get event(): IEvent {\n if (this._event) {\n return this._event;\n }\n this._event = (listener: (e: T) => any, thisArgs?: any, disposables?: IDisposable[] | DisposableStore) => {\n if (this._disposed) {\n return toDisposable(() => {});\n }\n\n const entry = { fn: listener, thisArgs };\n this._listeners = this._listeners.slice();\n this._listeners.push(entry);\n\n const result = toDisposable(() => {\n const idx = this._listeners.indexOf(entry);\n if (idx !== -1) {\n this._listeners = this._listeners.slice();\n this._listeners.splice(idx, 1);\n }\n });\n\n if (disposables) {\n if (Array.isArray(disposables)) {\n disposables.push(result);\n } else {\n disposables.add(result);\n }\n }\n\n return result;\n };\n return this._event;\n }\n\n public fire(event: T): void {\n if (this._disposed || !this._listeners.length) {\n return;\n }\n if (this._listeners.length === 1) {\n this._listeners[0].fn.call(this._listeners[0].thisArgs, event);\n return;\n }\n const listeners = this._listeners;\n for (let i = 0, len = listeners.length; i < len; ++i) {\n listeners[i].fn.call(listeners[i].thisArgs, event);\n }\n }\n\n public dispose(): void {\n if (this._disposed) {\n return;\n }\n this._disposed = true;\n this._listeners.length = 0;\n }\n}\n\nexport namespace EventUtils {\n export function forward(from: IEvent, to: Emitter): IDisposable {\n return from(e => to.fire(e));\n }\n\n export function map(event: IEvent, map: (i: I) => O): IEvent {\n return (listener: (e: O) => any, thisArgs?: any, disposables?: IDisposable[] | DisposableStore) => {\n return event(i => listener.call(thisArgs, map(i)), undefined, disposables);\n };\n }\n\n export function any(...events: IEvent[]): IEvent;\n export function any(...events: IEvent[]): IEvent;\n export function any(...events: IEvent[]): IEvent {\n return (listener: (e: T) => any, thisArgs?: any, disposables?: IDisposable[] | DisposableStore) => {\n const store = new DisposableStore();\n for (const event of events) {\n store.add(event(e => listener.call(thisArgs, e)));\n }\n if (disposables) {\n if (Array.isArray(disposables)) {\n disposables.push(store);\n } else {\n disposables.add(store);\n }\n }\n return store;\n };\n }\n\n export function runAndSubscribe(event: IEvent, handler: (e: T) => void, initial: T): IDisposable;\n export function runAndSubscribe(event: IEvent, handler: (e: T | undefined) => void): IDisposable;\n export function runAndSubscribe(event: IEvent, handler: (e: T | undefined) => void, initial?: T): IDisposable {\n handler(initial);\n return event(e => handler(e));\n }\n}\n", "/**\n * Copyright (c) 2026 The xterm.js authors. All rights reserved.\n * @license MIT\n *\n * Minimal async helpers for xterm.js core.\n */\n\nimport { DisposableStore, IDisposable, toDisposable } from './Lifecycle';\n\nexport function timeout(millis: number): Promise {\n return new Promise(resolve => setTimeout(resolve, millis));\n}\n\n/**\n * Creates a timeout that can be disposed using its returned value.\n * @param handler The timeout handler.\n * @param timeout An optional timeout in milliseconds.\n * @param store An optional {@link DisposableStore} that will have the timeout disposable managed\n * automatically.\n */\nexport function disposableTimeout(handler: () => void, timeout = 0, store?: DisposableStore): IDisposable {\n const timer = setTimeout(() => {\n handler();\n if (store) {\n disposable.dispose();\n }\n }, timeout);\n const disposable = toDisposable(() => {\n clearTimeout(timer);\n });\n store?.add(disposable);\n return disposable;\n}\n\nexport class TimeoutTimer implements IDisposable {\n private _token: any = -1;\n private _isDisposed = false;\n\n public dispose(): void {\n this.cancel();\n this._isDisposed = true;\n }\n\n public cancel(): void {\n if (this._token !== -1) {\n clearTimeout(this._token);\n this._token = -1;\n }\n }\n\n public cancelAndSet(runner: () => void, timeout: number): void {\n if (this._isDisposed) {\n throw new Error('Calling cancelAndSet on a disposed TimeoutTimer');\n }\n this.cancel();\n this._token = setTimeout(() => {\n this._token = -1;\n runner();\n }, timeout);\n }\n\n public setIfNotSet(runner: () => void, timeout: number): void {\n if (this._isDisposed) {\n throw new Error('Calling setIfNotSet on a disposed TimeoutTimer');\n }\n if (this._token !== -1) {\n return;\n }\n this._token = setTimeout(() => {\n this._token = -1;\n runner();\n }, timeout);\n }\n}\n\n/**\n * Schedules a single runner on the microtask queue. Unlike {@link TimeoutTimer}, a scheduled\n * microtask cannot be unqueued; {@link cancel} prevents the runner from executing if it has not\n * run yet.\n */\nexport class MicrotaskTimer implements IDisposable {\n private _isScheduled = false;\n private _isDisposed = false;\n\n public dispose(): void {\n this.cancel();\n this._isDisposed = true;\n }\n\n public cancel(): void {\n this._isScheduled = false;\n }\n\n public set(runner: () => void): void {\n if (this._isDisposed) {\n throw new Error('Calling set on a disposed MicrotaskTimer');\n }\n if (this._isScheduled) {\n return;\n }\n this._isScheduled = true;\n queueMicrotask(() => {\n if (!this._isScheduled) {\n return;\n }\n this._isScheduled = false;\n runner();\n });\n }\n}\n\nexport class IntervalTimer implements IDisposable {\n private _disposable: IDisposable | undefined;\n private _isDisposed = false;\n\n public cancel(): void {\n this._disposable?.dispose();\n this._disposable = undefined;\n }\n\n public cancelAndSet(runner: () => void, interval: number, context: Window | typeof globalThis = globalThis): void {\n if (this._isDisposed) {\n throw new Error('Calling cancelAndSet on a disposed IntervalTimer');\n }\n this.cancel();\n const handle = context.setInterval(() => {\n runner();\n }, interval);\n this._disposable = {\n dispose: () => {\n context.clearInterval(handle as any);\n this._disposable = undefined;\n }\n };\n }\n\n public dispose(): void {\n this.cancel();\n this._isDisposed = true;\n }\n}\n", "/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport type { Terminal } from '@xterm/xterm';\nimport { combinedDisposable, Disposable, MutableDisposable, toDisposable } from 'common/Lifecycle';\nimport { disposableTimeout } from 'common/Async';\n\nexport type LineCacheEntry = [\n /**\n * The string representation of a line (as opposed to the buffer cell representation).\n */\n lineAsString: string,\n /**\n * The offsets where each line starts when the entry describes a wrapped line.\n */\n lineOffsets: number[]\n];\n\n/**\n * Configuration constants for the search line cache functionality.\n */\nconst enum Constants {\n /**\n * Time-to-live for cached search results in milliseconds. After this duration, cached search\n * results will be invalidated to ensure they remain consistent with terminal content changes.\n */\n LINES_CACHE_TIME_TO_LIVE = 15000\n}\n\nexport class SearchLineCache extends Disposable {\n /**\n * translateBufferLineToStringWithWrap is a fairly expensive call.\n * We memoize the calls into an array that has a time based ttl.\n * _linesCache is also invalidated when the terminal cursor moves.\n */\n private _linesCache: LineCacheEntry[] | undefined;\n private _linesCacheTimeout = this._register(new MutableDisposable());\n private _linesCacheDisposables = this._register(new MutableDisposable());\n // Track access to avoid recreating a timeout on every init call which occurs once per search\n // result (findNext/findPrevious -> _highlightAllMatches -> find loop).\n private _lastAccessTimestamp = 0;\n\n constructor(private readonly _terminal: Terminal) {\n super();\n this._register(toDisposable(() => this._destroyLinesCache()));\n }\n\n /**\n * Sets up a line cache with a ttl\n */\n public initLinesCache(): void {\n if (!this._linesCache) {\n this._linesCache = new Array(this._terminal.buffer.active.length);\n this._linesCacheDisposables.value = combinedDisposable(\n this._terminal.onLineFeed(() => this._destroyLinesCache()),\n this._terminal.onCursorMove(() => this._destroyLinesCache()),\n this._terminal.onResize(() => this._destroyLinesCache())\n );\n }\n\n this._lastAccessTimestamp = Date.now();\n if (!this._linesCacheTimeout.value) {\n this._scheduleLinesCacheTimeout(Constants.LINES_CACHE_TIME_TO_LIVE);\n }\n }\n\n private _destroyLinesCache(): void {\n this._linesCache = undefined;\n this._lastAccessTimestamp = 0;\n this._linesCacheDisposables.clear();\n this._linesCacheTimeout.clear();\n }\n\n private _scheduleLinesCacheTimeout(delay: number): void {\n this._linesCacheTimeout.value = disposableTimeout(() => {\n if (!this._linesCache) {\n return;\n }\n const now = Date.now();\n const elapsed = now - this._lastAccessTimestamp;\n if (elapsed >= Constants.LINES_CACHE_TIME_TO_LIVE) {\n this._destroyLinesCache();\n return;\n }\n this._scheduleLinesCacheTimeout(Constants.LINES_CACHE_TIME_TO_LIVE - elapsed);\n }, delay);\n }\n\n public getLineFromCache(row: number): LineCacheEntry | undefined {\n return this._linesCache?.[row];\n }\n\n public setLineInCache(row: number, entry: LineCacheEntry): void {\n if (this._linesCache) {\n this._linesCache[row] = entry;\n }\n }\n\n /**\n * Translates a buffer line to a string, including subsequent lines if they are wraps.\n * Wide characters will count as two columns in the resulting string. This\n * function is useful for getting the actual text underneath the raw selection\n * position.\n * @param lineIndex The index of the line being translated.\n * @param trimRight Whether to trim whitespace to the right.\n */\n public translateBufferLineToStringWithWrap(lineIndex: number, trimRight: boolean): LineCacheEntry {\n const strings = [];\n const lineOffsets = [0];\n let line = this._terminal.buffer.active.getLine(lineIndex);\n while (line) {\n const nextLine = this._terminal.buffer.active.getLine(lineIndex + 1);\n const lineWrapsToNext = nextLine ? nextLine.isWrapped : false;\n let string = line.translateToString(!lineWrapsToNext && trimRight);\n if (lineWrapsToNext && nextLine) {\n const lastCell = line.getCell(line.length - 1);\n const lastCellIsNull = lastCell && lastCell.getCode() === 0 && lastCell.getWidth() === 1;\n // a wide character wrapped to the next line\n if (lastCellIsNull && nextLine.getCell(0)?.getWidth() === 2) {\n string = string.slice(0, -1);\n }\n }\n strings.push(string);\n if (lineWrapsToNext) {\n lineOffsets.push(lineOffsets[lineOffsets.length - 1] + string.length);\n } else {\n break;\n }\n lineIndex++;\n line = nextLine;\n }\n return [strings.join(''), lineOffsets];\n }\n}\n", "/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport type { ISearchOptions } from '@xterm/addon-search';\n\n/**\n * Manages search state including cached search terms, options tracking, and validation.\n * This class provides a centralized way to handle search state consistency and option changes.\n */\nexport class SearchState {\n private _cachedSearchTerm: string | undefined;\n private _lastSearchOptions: ISearchOptions | undefined;\n\n /**\n * Gets the currently cached search term.\n */\n public get cachedSearchTerm(): string | undefined {\n return this._cachedSearchTerm;\n }\n\n /**\n * Sets the cached search term.\n */\n public set cachedSearchTerm(term: string | undefined) {\n this._cachedSearchTerm = term;\n }\n\n /**\n * Gets the last search options used.\n */\n public get lastSearchOptions(): ISearchOptions | undefined {\n return this._lastSearchOptions;\n }\n\n /**\n * Sets the last search options used.\n */\n public set lastSearchOptions(options: ISearchOptions | undefined) {\n this._lastSearchOptions = options;\n }\n\n /**\n * Validates a search term to ensure it's not empty or invalid.\n * @param term The search term to validate.\n * @returns true if the term is valid for searching.\n */\n public isValidSearchTerm(term: string): boolean {\n return !!(term && term.length > 0);\n }\n\n /**\n * Determines if search options have changed compared to the last search.\n * @param newOptions The new search options to compare.\n * @returns true if the options have changed.\n */\n public didOptionsChange(newOptions?: ISearchOptions): boolean {\n if (!this._lastSearchOptions) {\n return true;\n }\n if (!newOptions) {\n return false;\n }\n if (this._lastSearchOptions.caseSensitive !== newOptions.caseSensitive) {\n return true;\n }\n if (this._lastSearchOptions.regex !== newOptions.regex) {\n return true;\n }\n if (this._lastSearchOptions.wholeWord !== newOptions.wholeWord) {\n return true;\n }\n return false;\n }\n\n /**\n * Determines if a new search should trigger highlighting updates.\n * @param term The search term.\n * @param options The search options.\n * @returns true if highlighting should be updated.\n */\n public shouldUpdateHighlighting(term: string, options?: ISearchOptions): boolean {\n if (!options?.decorations) {\n return false;\n }\n return this._cachedSearchTerm === undefined ||\n term !== this._cachedSearchTerm ||\n this.didOptionsChange(options);\n }\n\n /**\n * Clears the cached search term.\n */\n public clearCachedTerm(): void {\n this._cachedSearchTerm = undefined;\n }\n\n /**\n * Resets all state.\n */\n public reset(): void {\n this._cachedSearchTerm = undefined;\n this._lastSearchOptions = undefined;\n }\n}\n", "/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport type { Terminal } from '@xterm/xterm';\nimport type { ISearchOptions } from '@xterm/addon-search';\nimport type { SearchLineCache } from './SearchLineCache';\n\n/**\n * Represents the position to start a search from.\n */\ninterface ISearchPosition {\n startCol: number;\n startRow: number;\n}\n\n/**\n * Represents a search result with its position and content.\n */\nexport interface ISearchResult {\n term: string;\n col: number;\n row: number;\n size: number;\n}\n\n/**\n * Configuration constants for the search engine functionality.\n */\nconst enum Constants {\n /**\n * Characters that are considered non-word characters for search boundary detection. These\n * characters are used to determine word boundaries when performing whole-word searches. Includes\n * common punctuation, symbols, and whitespace characters.\n */\n NON_WORD_CHARACTERS = ' ~!@#$%^&*()+`-=[]{}|\\\\;:\"\\',./<>?'\n}\n\n/**\n * Core search engine that handles finding text within terminal content.\n * This class is responsible for the actual search algorithms and position calculations.\n */\nexport class SearchEngine {\n constructor(\n private readonly _terminal: Terminal,\n private readonly _lineCache: SearchLineCache\n ) {}\n\n /**\n * Find the first occurrence of a term starting from a specific position.\n * @param term The search term.\n * @param startRow The row to start searching from.\n * @param startCol The column to start searching from.\n * @param searchOptions Search options.\n * @returns The search result if found, undefined otherwise.\n */\n public find(term: string, startRow: number, startCol: number, searchOptions?: ISearchOptions): ISearchResult | undefined {\n if (!term || term.length === 0) {\n this._terminal.clearSelection();\n return undefined;\n }\n if (startCol >= this._terminal.cols) {\n throw new Error(`Invalid col: ${startCol} to search in terminal of ${this._terminal.cols} cols`);\n }\n\n this._lineCache.initLinesCache();\n\n const searchPosition: ISearchPosition = {\n startRow,\n startCol\n };\n\n // Search startRow\n let result = this._findInLine(term, searchPosition, searchOptions);\n // Search from startRow + 1 to end\n if (!result) {\n for (let y = startRow + 1; y < this._terminal.buffer.active.baseY + this._terminal.rows; y++) {\n searchPosition.startRow = y;\n searchPosition.startCol = 0;\n result = this._findInLine(term, searchPosition, searchOptions);\n if (result) {\n break;\n }\n }\n }\n return result;\n }\n\n /**\n * Find the next occurrence of a term with wrapping and selection management.\n * @param term The search term.\n * @param searchOptions Search options.\n * @param cachedSearchTerm The cached search term to determine incremental behavior.\n * @returns The search result if found, undefined otherwise.\n */\n public findNextWithSelection(term: string, searchOptions?: ISearchOptions, cachedSearchTerm?: string): ISearchResult | undefined {\n if (!term || term.length === 0) {\n this._terminal.clearSelection();\n return undefined;\n }\n\n const prevSelectedPos = this._terminal.getSelectionPosition();\n this._terminal.clearSelection();\n\n let startCol = 0;\n let startRow = 0;\n if (prevSelectedPos) {\n if (cachedSearchTerm === term) {\n startCol = prevSelectedPos.end.x;\n startRow = prevSelectedPos.end.y;\n } else {\n startCol = prevSelectedPos.start.x;\n startRow = prevSelectedPos.start.y;\n }\n }\n\n this._lineCache.initLinesCache();\n\n const searchPosition: ISearchPosition = {\n startRow,\n startCol\n };\n\n // Search startRow\n let result = this._findInLine(term, searchPosition, searchOptions);\n // Search from startRow + 1 to end\n if (!result) {\n for (let y = startRow + 1; y < this._terminal.buffer.active.baseY + this._terminal.rows; y++) {\n searchPosition.startRow = y;\n searchPosition.startCol = 0;\n result = this._findInLine(term, searchPosition, searchOptions);\n if (result) {\n break;\n }\n }\n }\n // If we hit the bottom and didn't search from the very top wrap back up\n if (!result && startRow !== 0) {\n for (let y = 0; y < startRow; y++) {\n searchPosition.startRow = y;\n searchPosition.startCol = 0;\n result = this._findInLine(term, searchPosition, searchOptions);\n if (result) {\n break;\n }\n }\n }\n\n // If there is only one result, wrap back and return selection if it exists.\n if (!result && prevSelectedPos) {\n searchPosition.startRow = prevSelectedPos.start.y;\n searchPosition.startCol = 0;\n result = this._findInLine(term, searchPosition, searchOptions);\n }\n\n return result;\n }\n\n /**\n * Find the previous occurrence of a term with wrapping and selection management.\n * @param term The search term.\n * @param searchOptions Search options.\n * @param cachedSearchTerm The cached search term to determine if expansion should occur.\n * @returns The search result if found, undefined otherwise.\n */\n public findPreviousWithSelection(term: string, searchOptions?: ISearchOptions, cachedSearchTerm?: string): ISearchResult | undefined {\n if (!term || term.length === 0) {\n this._terminal.clearSelection();\n return undefined;\n }\n\n const prevSelectedPos = this._terminal.getSelectionPosition();\n this._terminal.clearSelection();\n\n let startRow = this._terminal.buffer.active.baseY + this._terminal.rows - 1;\n const startCol = this._terminal.cols;\n const isReverseSearch = true;\n\n this._lineCache.initLinesCache();\n const searchPosition: ISearchPosition = {\n startRow,\n startCol\n };\n\n let result: ISearchResult | undefined;\n if (prevSelectedPos) {\n searchPosition.startRow = startRow = prevSelectedPos.start.y;\n searchPosition.startCol = prevSelectedPos.start.x;\n if (cachedSearchTerm !== term) {\n // Try to expand selection to right first.\n result = this._findInLine(term, searchPosition, searchOptions, false);\n if (!result) {\n // If selection was not able to be expanded to the right, then try reverse search\n searchPosition.startRow = startRow = prevSelectedPos.end.y;\n searchPosition.startCol = prevSelectedPos.end.x;\n }\n }\n }\n\n result ??= this._findInLine(term, searchPosition, searchOptions, isReverseSearch);\n\n // Search from startRow - 1 to top\n if (!result) {\n searchPosition.startCol = Math.max(searchPosition.startCol, this._terminal.cols);\n for (let y = startRow - 1; y >= 0; y--) {\n searchPosition.startRow = y;\n result = this._findInLine(term, searchPosition, searchOptions, isReverseSearch);\n if (result) {\n break;\n }\n }\n }\n // If we hit the top and didn't search from the very bottom wrap back down\n if (!result && startRow !== (this._terminal.buffer.active.baseY + this._terminal.rows - 1)) {\n for (let y = (this._terminal.buffer.active.baseY + this._terminal.rows - 1); y >= startRow; y--) {\n searchPosition.startRow = y;\n result = this._findInLine(term, searchPosition, searchOptions, isReverseSearch);\n if (result) {\n break;\n }\n }\n }\n\n return result;\n }\n\n /**\n * A found substring is a whole word if it doesn't have an alphanumeric character directly\n * adjacent to it.\n * @param searchIndex starting index of the potential whole word substring\n * @param line entire string in which the potential whole word was found\n * @param term the substring that starts at searchIndex\n */\n private _isWholeWord(searchIndex: number, line: string, term: string): boolean {\n return ((searchIndex === 0) || (Constants.NON_WORD_CHARACTERS.includes(line[searchIndex - 1]))) &&\n (((searchIndex + term.length) === line.length) || (Constants.NON_WORD_CHARACTERS.includes(line[searchIndex + term.length])));\n }\n\n /**\n * Searches a line for a search term. Takes the provided terminal line and searches the text line,\n * which may contain subsequent terminal lines if the text is wrapped. If the provided line number\n * is part of a wrapped text line that started on an earlier line then it is skipped since it will\n * be properly searched when the terminal line that the text starts on is searched.\n * @param term The search term.\n * @param searchPosition The position to start the search.\n * @param searchOptions Search options.\n * @param isReverseSearch Whether the search should start from the right side of the terminal and\n * search to the left.\n * @returns The search result if it was found.\n */\n private _findInLine(term: string, searchPosition: ISearchPosition, searchOptions: ISearchOptions = {}, isReverseSearch: boolean = false): ISearchResult | undefined {\n const row = searchPosition.startRow;\n const col = searchPosition.startCol;\n\n // Ignore wrapped lines, only consider on unwrapped line (first row of command string).\n const firstLine = this._terminal.buffer.active.getLine(row);\n if (firstLine?.isWrapped) {\n if (isReverseSearch) {\n searchPosition.startCol += this._terminal.cols;\n return;\n }\n\n // This will iterate until we find the line start.\n // When we find it, we will search using the calculated start column.\n searchPosition.startRow--;\n searchPosition.startCol += this._terminal.cols;\n return this._findInLine(term, searchPosition, searchOptions);\n }\n let cache = this._lineCache.getLineFromCache(row);\n if (!cache) {\n cache = this._lineCache.translateBufferLineToStringWithWrap(row, true);\n this._lineCache.setLineInCache(row, cache);\n }\n const [stringLine, offsets] = cache;\n\n const offset = this._bufferColsToStringOffset(row, col);\n let searchTerm = term;\n let searchStringLine = stringLine;\n if (!searchOptions.regex) {\n searchTerm = searchOptions.caseSensitive ? term : term.toLowerCase();\n searchStringLine = searchOptions.caseSensitive ? stringLine : stringLine.toLowerCase();\n }\n\n let resultIndex = -1;\n if (searchOptions.regex) {\n const searchRegex = RegExp(searchTerm, searchOptions.caseSensitive ? 'g' : 'gi');\n let foundTerm: RegExpExecArray | null;\n if (isReverseSearch) {\n // This loop will get the resultIndex of the _last_ regex match in the range 0..offset\n while (foundTerm = searchRegex.exec(searchStringLine.slice(0, offset))) {\n resultIndex = searchRegex.lastIndex - foundTerm[0].length;\n term = foundTerm[0];\n searchRegex.lastIndex -= (term.length - 1);\n }\n } else {\n foundTerm = searchRegex.exec(searchStringLine.slice(offset));\n if (foundTerm && foundTerm[0].length > 0) {\n resultIndex = offset + (searchRegex.lastIndex - foundTerm[0].length);\n term = foundTerm[0];\n }\n }\n } else {\n if (isReverseSearch) {\n if (offset - searchTerm.length >= 0) {\n resultIndex = searchStringLine.lastIndexOf(searchTerm, offset - searchTerm.length);\n }\n } else {\n resultIndex = searchStringLine.indexOf(searchTerm, offset);\n }\n }\n\n if (resultIndex >= 0) {\n if (searchOptions.wholeWord && !this._isWholeWord(resultIndex, searchStringLine, term)) {\n return;\n }\n\n // Adjust the row number and search index if needed since a \"line\" of text can span multiple\n // rows\n let startRowOffset = 0;\n while (startRowOffset < offsets.length - 1 && resultIndex >= offsets[startRowOffset + 1]) {\n startRowOffset++;\n }\n let endRowOffset = startRowOffset;\n while (endRowOffset < offsets.length - 1 && resultIndex + term.length >= offsets[endRowOffset + 1]) {\n endRowOffset++;\n }\n const startColOffset = resultIndex - offsets[startRowOffset];\n const endColOffset = resultIndex + term.length - offsets[endRowOffset];\n const startColIndex = this._stringLengthToBufferSize(row + startRowOffset, startColOffset);\n const endColIndex = this._stringLengthToBufferSize(row + endRowOffset, endColOffset);\n const size = endColIndex - startColIndex + this._terminal.cols * (endRowOffset - startRowOffset);\n\n return {\n term,\n col: startColIndex,\n row: row + startRowOffset,\n size\n };\n }\n }\n\n private _stringLengthToBufferSize(row: number, offset: number): number {\n const line = this._terminal.buffer.active.getLine(row);\n if (!line) {\n return 0;\n }\n for (let i = 0; i < offset; i++) {\n const cell = line.getCell(i);\n if (!cell) {\n break;\n }\n // Adjust the searchIndex to normalize emoji into single chars\n const char = cell.getChars();\n if (char.length > 1) {\n offset -= char.length - 1;\n }\n // Adjust the searchIndex for empty characters following wide unicode\n // chars (eg. CJK)\n const nextCell = line.getCell(i + 1);\n if (nextCell && nextCell.getWidth() === 0) {\n offset++;\n }\n }\n return offset;\n }\n\n private _bufferColsToStringOffset(startRow: number, cols: number): number {\n let lineIndex = startRow;\n let offset = 0;\n let line = this._terminal.buffer.active.getLine(lineIndex);\n while (cols > 0 && line) {\n for (let i = 0; i < cols && i < this._terminal.cols; i++) {\n const cell = line.getCell(i);\n if (!cell) {\n break;\n }\n if (cell.getWidth()) {\n // Treat null characters as whitespace to align with the translateToString API\n offset += cell.getCode() === 0 ? 1 : cell.getChars().length;\n }\n }\n lineIndex++;\n line = this._terminal.buffer.active.getLine(lineIndex);\n if (line && !line.isWrapped) {\n break;\n }\n cols -= this._terminal.cols;\n }\n return offset;\n }\n}\n", "/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport type { Terminal, IDisposable, IDecoration } from '@xterm/xterm';\nimport type { ISearchDecorationOptions } from '@xterm/addon-search';\nimport { dispose, Disposable, toDisposable } from 'common/Lifecycle';\nimport type { ISearchResult } from './SearchEngine';\n\n/**\n * Interface for managing a highlight decoration.\n */\ninterface IHighlight extends IDisposable {\n decoration: IDecoration;\n match: ISearchResult;\n}\n\n/**\n * Interface for managing multiple decorations for a single match.\n */\ninterface IMultiHighlight extends IDisposable {\n decorations: IDecoration[];\n match: ISearchResult;\n}\n\n/**\n * Manages visual decorations for search results including highlighting and active selection\n * indicators. This class handles the creation, styling, and disposal of search-related decorations.\n */\nexport class DecorationManager extends Disposable {\n private _highlightDecorations: IHighlight[] = [];\n private _highlightedLines: Set = new Set();\n\n constructor(private readonly _terminal: Terminal) {\n super();\n this._register(toDisposable(() => this.clearHighlightDecorations()));\n }\n\n /**\n * Creates decorations for all provided search results.\n * @param results The search results to create decorations for.\n * @param options The decoration options.\n */\n public createHighlightDecorations(results: ISearchResult[], options: ISearchDecorationOptions): void {\n this.clearHighlightDecorations();\n\n for (const match of results) {\n const decorations = this._createResultDecorations(match, options, false);\n if (decorations) {\n for (const decoration of decorations) {\n this._storeDecoration(decoration, match);\n }\n }\n }\n }\n\n /**\n * Creates decorations for the currently active search result.\n * @param result The active search result.\n * @param options The decoration options.\n * @returns The multi-highlight decoration or undefined if creation failed.\n */\n public createActiveDecoration(result: ISearchResult, options: ISearchDecorationOptions): IMultiHighlight | undefined {\n const decorations = this._createResultDecorations(result, options, true);\n if (decorations) {\n return { decorations, match: result, dispose() { dispose(decorations); } };\n }\n return undefined;\n }\n\n /**\n * Clears all highlight decorations.\n */\n public clearHighlightDecorations(): void {\n dispose(this._highlightDecorations);\n this._highlightDecorations = [];\n this._highlightedLines.clear();\n }\n\n /**\n * Stores a decoration and tracks it for management.\n * @param decoration The decoration to store.\n * @param match The search result this decoration represents.\n */\n private _storeDecoration(decoration: IDecoration, match: ISearchResult): void {\n this._highlightedLines.add(decoration.marker.line);\n this._highlightDecorations.push({ decoration, match, dispose() { decoration.dispose(); } });\n }\n\n /**\n * Applies styles to the decoration when it is rendered.\n * @param element The decoration's element.\n * @param borderColor The border color to apply.\n * @param isActiveResult Whether the element is part of the active search result.\n */\n private _applyStyles(element: HTMLElement, borderColor: string | undefined, isActiveResult: boolean): void {\n if (!element.classList.contains('xterm-find-result-decoration')) {\n element.classList.add('xterm-find-result-decoration');\n if (borderColor) {\n element.style.outline = `1px solid ${borderColor}`;\n }\n }\n if (isActiveResult) {\n element.classList.add('xterm-find-active-result-decoration');\n }\n }\n\n /**\n * Creates a decoration for the result and applies styles\n * @param result the search result for which to create the decoration\n * @param options the options for the decoration\n * @param isActiveResult whether this is the currently active result\n * @returns the decorations or undefined if the marker has already been disposed of\n */\n private _createResultDecorations(result: ISearchResult, options: ISearchDecorationOptions, isActiveResult: boolean): IDecoration[] | undefined {\n // Gather decoration ranges for this match as it could wrap\n const decorationRanges: [number, number, number][] = [];\n let currentCol = result.col;\n let remainingSize = result.size;\n let markerOffset = -this._terminal.buffer.active.baseY - this._terminal.buffer.active.cursorY + result.row;\n while (remainingSize > 0) {\n const amountThisRow = Math.min(this._terminal.cols - currentCol, remainingSize);\n decorationRanges.push([markerOffset, currentCol, amountThisRow]);\n currentCol = 0;\n remainingSize -= amountThisRow;\n markerOffset++;\n }\n\n // Create the decorations\n const decorations: IDecoration[] = [];\n for (const range of decorationRanges) {\n const marker = this._terminal.registerMarker(range[0]);\n const decoration = this._terminal.registerDecoration({\n marker,\n x: range[1],\n width: range[2],\n layer: isActiveResult ? 'top' : 'bottom',\n backgroundColor: isActiveResult ? options.activeMatchBackground : options.matchBackground,\n overviewRulerOptions: this._highlightedLines.has(marker.line) ? undefined : {\n color: isActiveResult ? options.activeMatchColorOverviewRuler : options.matchOverviewRuler,\n position: 'center'\n }\n });\n if (decoration) {\n const disposables: IDisposable[] = [];\n disposables.push(marker);\n disposables.push(decoration.onRender((e) => this._applyStyles(e, isActiveResult ? options.activeMatchBorder : options.matchBorder, false)));\n disposables.push(decoration.onDispose(() => dispose(disposables)));\n decorations.push(decoration);\n }\n }\n\n return decorations.length === 0 ? undefined : decorations;\n }\n}\n\n\n", "/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport type { ISearchResultChangeEvent } from '@xterm/addon-search';\nimport type { IDisposable } from '@xterm/xterm';\nimport { Emitter, type IEvent } from 'common/Event';\nimport { Disposable } from 'common/Lifecycle';\nimport type { ISearchResult } from './SearchEngine';\n\n/**\n * Interface for managing a currently selected decoration.\n */\ninterface ISelectedDecoration extends IDisposable {\n match: ISearchResult;\n}\n\n/**\n * Tracks search results, manages result indexing, and fires events when results change.\n * This class provides centralized management of search result state and notifications.\n */\nexport class SearchResultTracker extends Disposable {\n private _searchResults: ISearchResult[] = [];\n private _selectedDecoration: ISelectedDecoration | undefined;\n\n private readonly _onDidChangeResults = this._register(new Emitter());\n public get onDidChangeResults(): IEvent { return this._onDidChangeResults.event; }\n\n /**\n * Gets the current search results.\n */\n public get searchResults(): ReadonlyArray {\n return this._searchResults;\n }\n\n /**\n * Gets the currently selected decoration.\n */\n public get selectedDecoration(): ISelectedDecoration | undefined {\n return this._selectedDecoration;\n }\n\n /**\n * Sets the currently selected decoration.\n */\n public set selectedDecoration(decoration: ISelectedDecoration | undefined) {\n this._selectedDecoration = decoration;\n }\n\n /**\n * Updates the search results with a new set of results.\n * @param results The new search results.\n * @param maxResults The maximum number of results to track.\n */\n public updateResults(results: ISearchResult[], maxResults: number): void {\n this._searchResults = results.slice(0, maxResults);\n }\n\n /**\n * Clears all search results.\n */\n public clearResults(): void {\n this._searchResults = [];\n }\n\n /**\n * Clears the selected decoration.\n */\n public clearSelectedDecoration(): void {\n if (this._selectedDecoration) {\n this._selectedDecoration.dispose();\n this._selectedDecoration = undefined;\n }\n }\n\n /**\n * Finds the index of a result in the current results array.\n * @param result The result to find.\n * @returns The index of the result, or -1 if not found.\n */\n public findResultIndex(result: ISearchResult): number {\n for (let i = 0; i < this._searchResults.length; i++) {\n const match = this._searchResults[i];\n if (match.row === result.row && match.col === result.col && match.size === result.size) {\n return i;\n }\n }\n return -1;\n }\n\n /**\n * Fires a result change event with the current state.\n * @param hasDecorations Whether decorations are enabled.\n */\n public fireResultsChanged(hasDecorations: boolean): void {\n if (!hasDecorations) {\n return;\n }\n\n let resultIndex = -1;\n if (this._selectedDecoration) {\n resultIndex = this.findResultIndex(this._selectedDecoration.match);\n }\n\n this._onDidChangeResults.fire({\n resultIndex,\n resultCount: this._searchResults.length\n });\n }\n\n /**\n * Resets all state.\n */\n public reset(): void {\n this.clearSelectedDecoration();\n this.clearResults();\n }\n}\n", "/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport type { Terminal, IDisposable, ITerminalAddon } from '@xterm/xterm';\nimport type { SearchAddon as ISearchApi, ISearchOptions, ISearchAddonOptions, ISearchResultChangeEvent, ISearchDecorationOptions } from '@xterm/addon-search';\nimport { Emitter, type IEvent } from 'common/Event';\nimport { Disposable, MutableDisposable, toDisposable } from 'common/Lifecycle';\nimport { disposableTimeout } from 'common/Async';\nimport { SearchLineCache } from './SearchLineCache';\nimport { SearchState } from './SearchState';\nimport { SearchEngine, type ISearchResult } from './SearchEngine';\nimport { DecorationManager } from './DecorationManager';\nimport { SearchResultTracker } from './SearchResultTracker';\n\ninterface IInternalSearchOptions {\n noScroll: boolean;\n}\n\n/**\n * Configuration constants for the search addon functionality.\n */\nconst enum Constants {\n /**\n * Default maximum number of search results to highlight simultaneously. This limit prevents\n * performance degradation when searching for very common terms that would result in excessive\n * highlighting decorations.\n */\n DEFAULT_HIGHLIGHT_LIMIT = 1000\n}\n\nexport class SearchAddon extends Disposable implements ITerminalAddon, ISearchApi {\n private _terminal: Terminal | undefined;\n private _highlightLimit: number;\n private _highlightTimeout = this._register(new MutableDisposable());\n private _lineCache = this._register(new MutableDisposable());\n\n // Component instances\n private _state = new SearchState();\n private _engine: SearchEngine | undefined;\n private _decorationManager: DecorationManager | undefined;\n private _resultTracker = this._register(new SearchResultTracker());\n\n private readonly _onAfterSearch = this._register(new Emitter());\n public readonly onAfterSearch = this._onAfterSearch.event;\n private readonly _onBeforeSearch = this._register(new Emitter());\n public readonly onBeforeSearch = this._onBeforeSearch.event;\n\n public get onDidChangeResults(): IEvent {\n return this._resultTracker.onDidChangeResults;\n }\n\n constructor(options?: Partial) {\n super();\n\n this._highlightLimit = options?.highlightLimit ?? Constants.DEFAULT_HIGHLIGHT_LIMIT;\n }\n\n public activate(terminal: Terminal): void {\n this._terminal = terminal;\n this._lineCache.value = new SearchLineCache(terminal);\n this._engine = new SearchEngine(terminal, this._lineCache.value);\n this._decorationManager = new DecorationManager(terminal);\n this._register(this._terminal.onWriteParsed(() => this._updateMatches()));\n this._register(this._terminal.onResize(() => this._updateMatches()));\n this._register(toDisposable(() => this.clearDecorations()));\n }\n\n private _updateMatches(): void {\n this._highlightTimeout.clear();\n if (this._state.cachedSearchTerm && this._state.lastSearchOptions?.decorations) {\n this._highlightTimeout.value = disposableTimeout(() => {\n const term = this._state.cachedSearchTerm;\n this._state.clearCachedTerm();\n this.findPrevious(term!, { ...this._state.lastSearchOptions, incremental: true }, { noScroll: true });\n }, 200);\n }\n }\n\n public clearDecorations(retainCachedSearchTerm?: boolean): void {\n this._resultTracker.clearSelectedDecoration();\n this._decorationManager?.clearHighlightDecorations();\n this._resultTracker.clearResults();\n if (!retainCachedSearchTerm) {\n this._state.clearCachedTerm();\n }\n }\n\n public clearActiveDecoration(): void {\n this._resultTracker.clearSelectedDecoration();\n }\n\n /**\n * Find the next instance of the term, then scroll to and select it. If it\n * doesn't exist, do nothing.\n * @param term The search term.\n * @param searchOptions Search options.\n * @returns Whether a result was found.\n */\n public findNext(term: string, searchOptions?: ISearchOptions, internalSearchOptions?: IInternalSearchOptions): boolean {\n if (!this._terminal || !this._engine) {\n throw new Error('Cannot use addon until it has been loaded');\n }\n\n this._onBeforeSearch.fire();\n\n this._state.lastSearchOptions = searchOptions;\n\n if (this._state.shouldUpdateHighlighting(term, searchOptions)) {\n this._highlightAllMatches(term, searchOptions!);\n }\n\n const found = this._findNextAndSelect(term, searchOptions, internalSearchOptions);\n this._fireResults(searchOptions);\n this._state.cachedSearchTerm = term;\n\n this._onAfterSearch.fire();\n\n return found;\n }\n\n private _highlightAllMatches(term: string, searchOptions: ISearchOptions): void {\n if (!this._terminal || !this._engine || !this._decorationManager) {\n throw new Error('Cannot use addon until it has been loaded');\n }\n if (!this._state.isValidSearchTerm(term)) {\n this.clearDecorations();\n return;\n }\n\n // new search, clear out the old decorations\n this.clearDecorations(true);\n\n const results: ISearchResult[] = [];\n let prevResult: ISearchResult | undefined = undefined;\n let result = this._engine.find(term, 0, 0, searchOptions);\n\n while (result && (prevResult?.row !== result.row || prevResult?.col !== result.col)) {\n if (results.length >= this._highlightLimit) {\n break;\n }\n prevResult = result;\n results.push(prevResult);\n const cols = this._terminal.cols;\n let nextCol = prevResult.col + prevResult.size;\n let nextRow = prevResult.row;\n if (nextCol >= cols) {\n nextRow += Math.floor(nextCol / cols);\n nextCol = nextCol % cols;\n }\n result = this._engine.find(term, nextRow, nextCol, searchOptions);\n }\n\n this._resultTracker.updateResults(results, this._highlightLimit);\n if (searchOptions.decorations) {\n this._decorationManager.createHighlightDecorations(results, searchOptions.decorations);\n }\n }\n\n private _findNextAndSelect(term: string, searchOptions?: ISearchOptions, internalSearchOptions?: IInternalSearchOptions): boolean {\n if (!this._terminal || !this._engine) {\n return false;\n }\n if (!this._state.isValidSearchTerm(term)) {\n this._terminal.clearSelection();\n this.clearDecorations();\n return false;\n }\n\n const result = this._engine.findNextWithSelection(term, searchOptions, this._state.cachedSearchTerm);\n return this._selectResult(result, searchOptions?.decorations, internalSearchOptions?.noScroll);\n }\n\n /**\n * Find the previous instance of the term, then scroll to and select it. If it\n * doesn't exist, do nothing.\n * @param term The search term.\n * @param searchOptions Search options.\n * @returns Whether a result was found.\n */\n public findPrevious(term: string, searchOptions?: ISearchOptions, internalSearchOptions?: IInternalSearchOptions): boolean {\n if (!this._terminal || !this._engine) {\n throw new Error('Cannot use addon until it has been loaded');\n }\n\n this._onBeforeSearch.fire();\n\n this._state.lastSearchOptions = searchOptions;\n\n if (this._state.shouldUpdateHighlighting(term, searchOptions)) {\n this._highlightAllMatches(term, searchOptions!);\n }\n\n const found = this._findPreviousAndSelect(term, searchOptions, internalSearchOptions);\n this._fireResults(searchOptions);\n this._state.cachedSearchTerm = term;\n\n this._onAfterSearch.fire();\n\n return found;\n }\n\n private _fireResults(searchOptions?: ISearchOptions): void {\n this._resultTracker.fireResultsChanged(!!searchOptions?.decorations);\n }\n\n private _findPreviousAndSelect(term: string, searchOptions?: ISearchOptions, internalSearchOptions?: IInternalSearchOptions): boolean {\n if (!this._terminal || !this._engine) {\n return false;\n }\n if (!this._state.isValidSearchTerm(term)) {\n this._terminal.clearSelection();\n this.clearDecorations();\n return false;\n }\n\n const result = this._engine.findPreviousWithSelection(term, searchOptions, this._state.cachedSearchTerm);\n return this._selectResult(result, searchOptions?.decorations, internalSearchOptions?.noScroll);\n }\n\n /**\n * Selects and scrolls to a result.\n * @param result The result to select.\n * @returns Whether a result was selected.\n */\n private _selectResult(result: ISearchResult | undefined, options?: ISearchDecorationOptions, noScroll?: boolean): boolean {\n if (!this._terminal || !this._decorationManager) {\n return false;\n }\n\n this._resultTracker.clearSelectedDecoration();\n if (!result) {\n this._terminal.clearSelection();\n return false;\n }\n\n this._terminal.select(result.col, result.row, result.size);\n if (options) {\n const activeDecoration = this._decorationManager.createActiveDecoration(result, options);\n if (activeDecoration) {\n this._resultTracker.selectedDecoration = activeDecoration;\n }\n }\n\n if (!noScroll) {\n // If it is not in the viewport then we scroll else it just gets selected\n if (result.row >= (this._terminal.buffer.active.viewportY + this._terminal.rows) || result.row < this._terminal.buffer.active.viewportY) {\n let scroll = result.row - this._terminal.buffer.active.viewportY;\n scroll -= Math.floor(this._terminal.rows / 2);\n this._terminal.scrollLines(scroll);\n }\n }\n return true;\n }\n}\n"], - "mappings": "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", -+ "sourcesContent": ["/**\n * Copyright (c) 2024-2026 The xterm.js authors. All rights reserved.\n * @license MIT\n *\n * Minimal lifecycle utilities for xterm.js core.\n * Simplified from VS Code's lifecycle.ts - no tracking/leak detection.\n */\n\nexport interface IDisposable {\n dispose(): void;\n}\n\nexport function toDisposable(fn: () => void): IDisposable {\n return { dispose: fn };\n}\n\nexport function dispose(disposable: T): T;\nexport function dispose(disposable: T | undefined): T | undefined;\nexport function dispose(disposables: T[]): T[];\nexport function dispose(arg: T | T[] | undefined): T | T[] | undefined {\n if (!arg) {\n return arg;\n }\n if (Array.isArray(arg)) {\n for (const d of arg) {\n d.dispose();\n }\n return [];\n }\n arg.dispose();\n return arg;\n}\n\nexport function combinedDisposable(...disposables: IDisposable[]): IDisposable {\n return toDisposable(() => dispose(disposables));\n}\n\nexport class DisposableStore implements IDisposable {\n private readonly _disposables = new Set();\n private _isDisposed = false;\n\n public get isDisposed(): boolean {\n return this._isDisposed;\n }\n\n public add(o: T): T {\n if (this._isDisposed) {\n o.dispose();\n } else {\n this._disposables.add(o);\n }\n return o;\n }\n\n public dispose(): void {\n if (this._isDisposed) {\n return;\n }\n this._isDisposed = true;\n for (const d of this._disposables) {\n d.dispose();\n }\n this._disposables.clear();\n }\n\n public clear(): void {\n for (const d of this._disposables) {\n d.dispose();\n }\n this._disposables.clear();\n }\n}\n\nexport abstract class Disposable implements IDisposable {\n public static readonly None: IDisposable = Object.freeze({ dispose() { } });\n\n protected readonly _store = new DisposableStore();\n\n public dispose(): void {\n this._store.dispose();\n }\n\n protected _register(o: T): T {\n return this._store.add(o);\n }\n}\n\nexport class MutableDisposable implements IDisposable {\n private _value: T | undefined;\n private _isDisposed = false;\n\n public get value(): T | undefined {\n return this._isDisposed ? undefined : this._value;\n }\n\n public set value(value: T | undefined) {\n if (this._isDisposed || value === this._value) {\n return;\n }\n this._value?.dispose();\n this._value = value;\n }\n\n public clear(): void {\n this.value = undefined;\n }\n\n public dispose(): void {\n this._isDisposed = true;\n this._value?.dispose();\n this._value = undefined;\n }\n}\n", "/**\n * Copyright (c) 2024-2026 The xterm.js authors. All rights reserved.\n * @license MIT\n *\n * Minimal event utilities for xterm.js core.\n * Simplified from VS Code's event.ts - no leak detection/profiling.\n */\n\nimport { IDisposable, DisposableStore, toDisposable } from './Lifecycle';\n\nexport interface IEvent {\n (listener: (e: T) => any, thisArgs?: any, disposables?: IDisposable[] | DisposableStore): IDisposable;\n}\n\nexport class Emitter {\n private _listeners: { fn: (e: T) => any, thisArgs: any }[] = [];\n private _disposed = false;\n private _event: IEvent | undefined;\n\n public get event(): IEvent {\n if (this._event) {\n return this._event;\n }\n this._event = (listener: (e: T) => any, thisArgs?: any, disposables?: IDisposable[] | DisposableStore) => {\n if (this._disposed) {\n return toDisposable(() => {});\n }\n\n const entry = { fn: listener, thisArgs };\n this._listeners = this._listeners.slice();\n this._listeners.push(entry);\n\n const result = toDisposable(() => {\n const idx = this._listeners.indexOf(entry);\n if (idx !== -1) {\n this._listeners = this._listeners.slice();\n this._listeners.splice(idx, 1);\n }\n });\n\n if (disposables) {\n if (Array.isArray(disposables)) {\n disposables.push(result);\n } else {\n disposables.add(result);\n }\n }\n\n return result;\n };\n return this._event;\n }\n\n public fire(event: T): void {\n if (this._disposed || !this._listeners.length) {\n return;\n }\n if (this._listeners.length === 1) {\n this._listeners[0].fn.call(this._listeners[0].thisArgs, event);\n return;\n }\n const listeners = this._listeners;\n for (let i = 0, len = listeners.length; i < len; ++i) {\n listeners[i].fn.call(listeners[i].thisArgs, event);\n }\n }\n\n public dispose(): void {\n if (this._disposed) {\n return;\n }\n this._disposed = true;\n this._listeners.length = 0;\n }\n}\n\nexport namespace EventUtils {\n export function forward(from: IEvent, to: Emitter): IDisposable {\n return from(e => to.fire(e));\n }\n\n export function map(event: IEvent, map: (i: I) => O): IEvent {\n return (listener: (e: O) => any, thisArgs?: any, disposables?: IDisposable[] | DisposableStore) => {\n return event(i => listener.call(thisArgs, map(i)), undefined, disposables);\n };\n }\n\n export function any(...events: IEvent[]): IEvent;\n export function any(...events: IEvent[]): IEvent;\n export function any(...events: IEvent[]): IEvent {\n return (listener: (e: T) => any, thisArgs?: any, disposables?: IDisposable[] | DisposableStore) => {\n const store = new DisposableStore();\n for (const event of events) {\n store.add(event(e => listener.call(thisArgs, e)));\n }\n if (disposables) {\n if (Array.isArray(disposables)) {\n disposables.push(store);\n } else {\n disposables.add(store);\n }\n }\n return store;\n };\n }\n\n export function runAndSubscribe(event: IEvent, handler: (e: T) => void, initial: T): IDisposable;\n export function runAndSubscribe(event: IEvent, handler: (e: T | undefined) => void): IDisposable;\n export function runAndSubscribe(event: IEvent, handler: (e: T | undefined) => void, initial?: T): IDisposable {\n handler(initial);\n return event(e => handler(e));\n }\n}\n", "/**\n * Copyright (c) 2026 The xterm.js authors. All rights reserved.\n * @license MIT\n *\n * Minimal async helpers for xterm.js core.\n */\n\nimport { DisposableStore, IDisposable, toDisposable } from './Lifecycle';\n\nexport function timeout(millis: number): Promise {\n return new Promise(resolve => setTimeout(resolve, millis));\n}\n\n/**\n * Creates a timeout that can be disposed using its returned value.\n * @param handler The timeout handler.\n * @param timeout An optional timeout in milliseconds.\n * @param store An optional {@link DisposableStore} that will have the timeout disposable managed\n * automatically.\n */\nexport function disposableTimeout(handler: () => void, timeout = 0, store?: DisposableStore): IDisposable {\n const timer = setTimeout(() => {\n handler();\n if (store) {\n disposable.dispose();\n }\n }, timeout);\n const disposable = toDisposable(() => {\n clearTimeout(timer);\n });\n store?.add(disposable);\n return disposable;\n}\n\nexport class TimeoutTimer implements IDisposable {\n private _token: any = -1;\n private _isDisposed = false;\n\n public dispose(): void {\n this.cancel();\n this._isDisposed = true;\n }\n\n public cancel(): void {\n if (this._token !== -1) {\n clearTimeout(this._token);\n this._token = -1;\n }\n }\n\n public cancelAndSet(runner: () => void, timeout: number): void {\n if (this._isDisposed) {\n throw new Error('Calling cancelAndSet on a disposed TimeoutTimer');\n }\n this.cancel();\n this._token = setTimeout(() => {\n this._token = -1;\n runner();\n }, timeout);\n }\n\n public setIfNotSet(runner: () => void, timeout: number): void {\n if (this._isDisposed) {\n throw new Error('Calling setIfNotSet on a disposed TimeoutTimer');\n }\n if (this._token !== -1) {\n return;\n }\n this._token = setTimeout(() => {\n this._token = -1;\n runner();\n }, timeout);\n }\n}\n\n/**\n * Schedules a single runner on the microtask queue. Unlike {@link TimeoutTimer}, a scheduled\n * microtask cannot be unqueued; {@link cancel} prevents the runner from executing if it has not\n * run yet.\n */\nexport class MicrotaskTimer implements IDisposable {\n private _isScheduled = false;\n private _isDisposed = false;\n\n public dispose(): void {\n this.cancel();\n this._isDisposed = true;\n }\n\n public cancel(): void {\n this._isScheduled = false;\n }\n\n public set(runner: () => void): void {\n if (this._isDisposed) {\n throw new Error('Calling set on a disposed MicrotaskTimer');\n }\n if (this._isScheduled) {\n return;\n }\n this._isScheduled = true;\n queueMicrotask(() => {\n if (!this._isScheduled) {\n return;\n }\n this._isScheduled = false;\n runner();\n });\n }\n}\n\nexport class IntervalTimer implements IDisposable {\n private _disposable: IDisposable | undefined;\n private _isDisposed = false;\n\n public cancel(): void {\n this._disposable?.dispose();\n this._disposable = undefined;\n }\n\n public cancelAndSet(runner: () => void, interval: number, context: Window | typeof globalThis = globalThis): void {\n if (this._isDisposed) {\n throw new Error('Calling cancelAndSet on a disposed IntervalTimer');\n }\n this.cancel();\n const handle = context.setInterval(() => {\n runner();\n }, interval);\n this._disposable = {\n dispose: () => {\n context.clearInterval(handle as any);\n this._disposable = undefined;\n }\n };\n }\n\n public dispose(): void {\n this.cancel();\n this._isDisposed = true;\n }\n}\n", "/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport type { Terminal } from '@xterm/xterm';\nimport { combinedDisposable, Disposable, MutableDisposable, toDisposable } from 'common/Lifecycle';\nimport { disposableTimeout } from 'common/Async';\n\nexport type LineCacheEntry = [\n /**\n * The string representation of a line (as opposed to the buffer cell representation).\n */\n lineAsString: string,\n /**\n * The offsets where each line starts when the entry describes a wrapped line.\n */\n lineOffsets: number[]\n];\n\n/**\n * Configuration constants for the search line cache functionality.\n */\nconst enum Constants {\n /**\n * Time-to-live for cached search results in milliseconds. After this duration, cached search\n * results will be invalidated to ensure they remain consistent with terminal content changes.\n */\n LINES_CACHE_TIME_TO_LIVE = 15000\n}\n\nexport class SearchLineCache extends Disposable {\n /**\n * translateBufferLineToStringWithWrap is a fairly expensive call.\n * We memoize the calls into an array that has a time based ttl.\n * _linesCache is also invalidated when the terminal cursor moves.\n */\n private _linesCache: LineCacheEntry[] | undefined;\n private _linesCacheTimeout = this._register(new MutableDisposable());\n private _linesCacheDisposables = this._register(new MutableDisposable());\n // Track access to avoid recreating a timeout on every init call which occurs once per search\n // result (findNext/findPrevious -> _highlightAllMatches -> find loop).\n private _lastAccessTimestamp = 0;\n\n constructor(private readonly _terminal: Terminal) {\n super();\n this._register(toDisposable(() => this._destroyLinesCache()));\n }\n\n /**\n * Sets up a line cache with a ttl\n */\n public initLinesCache(): void {\n if (!this._linesCache) {\n this._linesCache = new Array(this._terminal.buffer.active.length);\n this._linesCacheDisposables.value = combinedDisposable(\n this._terminal.onLineFeed(() => this._destroyLinesCache()),\n this._terminal.onCursorMove(() => this._destroyLinesCache()),\n this._terminal.onResize(() => this._destroyLinesCache())\n );\n }\n\n this._lastAccessTimestamp = Date.now();\n if (!this._linesCacheTimeout.value) {\n this._scheduleLinesCacheTimeout(Constants.LINES_CACHE_TIME_TO_LIVE);\n }\n }\n\n private _destroyLinesCache(): void {\n this._linesCache = undefined;\n this._lastAccessTimestamp = 0;\n this._linesCacheDisposables.clear();\n this._linesCacheTimeout.clear();\n }\n\n private _scheduleLinesCacheTimeout(delay: number): void {\n this._linesCacheTimeout.value = disposableTimeout(() => {\n if (!this._linesCache) {\n return;\n }\n const now = Date.now();\n const elapsed = now - this._lastAccessTimestamp;\n if (elapsed >= Constants.LINES_CACHE_TIME_TO_LIVE) {\n this._destroyLinesCache();\n return;\n }\n this._scheduleLinesCacheTimeout(Constants.LINES_CACHE_TIME_TO_LIVE - elapsed);\n }, delay);\n }\n\n public getLineFromCache(row: number): LineCacheEntry | undefined {\n return this._linesCache?.[row];\n }\n\n public setLineInCache(row: number, entry: LineCacheEntry): void {\n if (this._linesCache) {\n this._linesCache[row] = entry;\n }\n }\n\n /**\n * Translates a buffer line to a string, including subsequent lines if they are wraps.\n * Wide characters will count as two columns in the resulting string. This\n * function is useful for getting the actual text underneath the raw selection\n * position.\n * @param lineIndex The index of the line being translated.\n * @param trimRight Whether to trim whitespace to the right.\n */\n public translateBufferLineToStringWithWrap(lineIndex: number, trimRight: boolean): LineCacheEntry {\n const strings = [];\n const lineOffsets = [0];\n let line = this._terminal.buffer.active.getLine(lineIndex);\n while (line) {\n const nextLine = this._terminal.buffer.active.getLine(lineIndex + 1);\n const lineWrapsToNext = nextLine ? nextLine.isWrapped : false;\n let string = line.translateToString(!lineWrapsToNext && trimRight);\n if (lineWrapsToNext && nextLine) {\n const lastCell = line.getCell(line.length - 1);\n const lastCellIsNull = lastCell && lastCell.getCode() === 0 && lastCell.getWidth() === 1;\n // a wide character wrapped to the next line\n if (lastCellIsNull && nextLine.getCell(0)?.getWidth() === 2) {\n string = string.slice(0, -1);\n }\n }\n strings.push(string);\n if (lineWrapsToNext) {\n lineOffsets.push(lineOffsets[lineOffsets.length - 1] + string.length);\n } else {\n break;\n }\n lineIndex++;\n line = nextLine;\n }\n return [strings.join(''), lineOffsets];\n }\n}\n", "/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport type { ISearchOptions } from '@xterm/addon-search';\n\n/**\n * Manages search state including cached search terms, options tracking, and validation.\n * This class provides a centralized way to handle search state consistency and option changes.\n */\nexport class SearchState {\n private _cachedSearchTerm: string | undefined;\n private _lastSearchOptions: ISearchOptions | undefined;\n\n /**\n * Gets the currently cached search term.\n */\n public get cachedSearchTerm(): string | undefined {\n return this._cachedSearchTerm;\n }\n\n /**\n * Sets the cached search term.\n */\n public set cachedSearchTerm(term: string | undefined) {\n this._cachedSearchTerm = term;\n }\n\n /**\n * Gets the last search options used.\n */\n public get lastSearchOptions(): ISearchOptions | undefined {\n return this._lastSearchOptions;\n }\n\n /**\n * Sets the last search options used.\n */\n public set lastSearchOptions(options: ISearchOptions | undefined) {\n this._lastSearchOptions = options;\n }\n\n /**\n * Validates a search term to ensure it's not empty or invalid.\n * @param term The search term to validate.\n * @returns true if the term is valid for searching.\n */\n public isValidSearchTerm(term: string): boolean {\n return !!(term && term.length > 0);\n }\n\n /**\n * Determines if search options have changed compared to the last search.\n * @param newOptions The new search options to compare.\n * @returns true if the options have changed.\n */\n public didOptionsChange(newOptions?: ISearchOptions): boolean {\n if (!this._lastSearchOptions) {\n return true;\n }\n if (!newOptions) {\n return false;\n }\n if (this._lastSearchOptions.caseSensitive !== newOptions.caseSensitive) {\n return true;\n }\n if (this._lastSearchOptions.regex !== newOptions.regex) {\n return true;\n }\n if (this._lastSearchOptions.wholeWord !== newOptions.wholeWord) {\n return true;\n }\n return false;\n }\n\n /**\n * Determines if a new search should trigger highlighting updates.\n * @param term The search term.\n * @param options The search options.\n * @returns true if highlighting should be updated.\n */\n public shouldUpdateHighlighting(term: string, options?: ISearchOptions): boolean {\n if (!options?.decorations) {\n return false;\n }\n return this._cachedSearchTerm === undefined ||\n term !== this._cachedSearchTerm ||\n this.didOptionsChange(options);\n }\n\n /**\n * Clears the cached search term.\n */\n public clearCachedTerm(): void {\n this._cachedSearchTerm = undefined;\n }\n\n /**\n * Resets all state.\n */\n public reset(): void {\n this._cachedSearchTerm = undefined;\n this._lastSearchOptions = undefined;\n }\n}\n", "/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport type { Terminal } from '@xterm/xterm';\nimport type { ISearchOptions } from '@xterm/addon-search';\nimport type { SearchLineCache } from './SearchLineCache';\n\n/**\n * Represents the position to start a search from.\n */\ninterface ISearchPosition {\n startCol: number;\n startRow: number;\n}\n\n/**\n * Represents a search result with its position and content.\n */\nexport interface ISearchResult {\n term: string;\n col: number;\n row: number;\n size: number;\n}\n\n/**\n * Configuration constants for the search engine functionality.\n */\nconst enum Constants {\n /**\n * Characters that are considered non-word characters for search boundary detection. These\n * characters are used to determine word boundaries when performing whole-word searches. Includes\n * common punctuation, symbols, and whitespace characters.\n */\n NON_WORD_CHARACTERS = ' ~!@#$%^&*()+`-=[]{}|\\\\;:\"\\',./<>?'\n}\n\n/**\n * Core search engine that handles finding text within terminal content.\n * This class is responsible for the actual search algorithms and position calculations.\n */\nexport class SearchEngine {\n constructor(\n private readonly _terminal: Terminal,\n private readonly _lineCache: SearchLineCache\n ) {}\n\n /**\n * Find the first occurrence of a term starting from a specific position.\n * @param term The search term.\n * @param startRow The row to start searching from.\n * @param startCol The column to start searching from.\n * @param searchOptions Search options.\n * @returns The search result if found, undefined otherwise.\n */\n public find(term: string, startRow: number, startCol: number, searchOptions?: ISearchOptions): ISearchResult | undefined {\n if (!term || term.length === 0) {\n this._terminal.clearSelection();\n return undefined;\n }\n if (startCol >= this._terminal.cols) {\n throw new Error(`Invalid col: ${startCol} to search in terminal of ${this._terminal.cols} cols`);\n }\n\n this._lineCache.initLinesCache();\n\n const searchPosition: ISearchPosition = {\n startRow,\n startCol\n };\n\n // Search startRow\n let result = this._findInLine(term, searchPosition, searchOptions);\n // Search from startRow + 1 to end\n if (!result) {\n for (let y = startRow + 1; y < this._terminal.buffer.active.baseY + this._terminal.rows; y++) {\n searchPosition.startRow = y;\n searchPosition.startCol = 0;\n result = this._findInLine(term, searchPosition, searchOptions);\n if (result) {\n break;\n }\n }\n }\n return result;\n }\n\n /**\n * Find the next occurrence of a term with wrapping and selection management.\n * @param term The search term.\n * @param searchOptions Search options.\n * @param cachedSearchTerm The cached search term to determine incremental behavior.\n * @returns The search result if found, undefined otherwise.\n */\n public findNextWithSelection(term: string, searchOptions?: ISearchOptions, cachedSearchTerm?: string): ISearchResult | undefined {\n if (!term || term.length === 0) {\n this._terminal.clearSelection();\n return undefined;\n }\n\n const prevSelectedPos = this._terminal.getSelectionPosition();\n this._terminal.clearSelection();\n\n let startCol = 0;\n let startRow = 0;\n if (prevSelectedPos) {\n if (cachedSearchTerm === term) {\n startCol = prevSelectedPos.end.x;\n startRow = prevSelectedPos.end.y;\n } else {\n startCol = prevSelectedPos.start.x;\n startRow = prevSelectedPos.start.y;\n }\n }\n\n this._lineCache.initLinesCache();\n\n const searchPosition: ISearchPosition = {\n startRow,\n startCol\n };\n\n // Search startRow\n let result = this._findInLine(term, searchPosition, searchOptions);\n // Search from startRow + 1 to end\n if (!result) {\n for (let y = startRow + 1; y < this._terminal.buffer.active.baseY + this._terminal.rows; y++) {\n searchPosition.startRow = y;\n searchPosition.startCol = 0;\n result = this._findInLine(term, searchPosition, searchOptions);\n if (result) {\n break;\n }\n }\n }\n // If we hit the bottom and didn't search from the very top wrap back up\n if (!result && startRow !== 0) {\n for (let y = 0; y < startRow; y++) {\n searchPosition.startRow = y;\n searchPosition.startCol = 0;\n result = this._findInLine(term, searchPosition, searchOptions);\n if (result) {\n break;\n }\n }\n }\n\n // If there is only one result, wrap back and return selection if it exists.\n if (!result && prevSelectedPos) {\n searchPosition.startRow = prevSelectedPos.start.y;\n searchPosition.startCol = 0;\n result = this._findInLine(term, searchPosition, searchOptions);\n }\n\n return result;\n }\n\n /**\n * Find the previous occurrence of a term with wrapping and selection management.\n * @param term The search term.\n * @param searchOptions Search options.\n * @param cachedSearchTerm The cached search term to determine if expansion should occur.\n * @returns The search result if found, undefined otherwise.\n */\n public findPreviousWithSelection(term: string, searchOptions?: ISearchOptions, cachedSearchTerm?: string): ISearchResult | undefined {\n if (!term || term.length === 0) {\n this._terminal.clearSelection();\n return undefined;\n }\n\n const prevSelectedPos = this._terminal.getSelectionPosition();\n this._terminal.clearSelection();\n\n let startRow = this._terminal.buffer.active.baseY + this._terminal.rows - 1;\n const startCol = this._terminal.cols;\n const isReverseSearch = true;\n\n this._lineCache.initLinesCache();\n const searchPosition: ISearchPosition = {\n startRow,\n startCol\n };\n\n let result: ISearchResult | undefined;\n if (prevSelectedPos) {\n searchPosition.startRow = startRow = prevSelectedPos.start.y;\n searchPosition.startCol = prevSelectedPos.start.x;\n if (cachedSearchTerm !== term) {\n // Try to expand selection to right first.\n result = this._findInLine(term, searchPosition, searchOptions, false);\n if (!result) {\n // If selection was not able to be expanded to the right, then try reverse search\n searchPosition.startRow = startRow = prevSelectedPos.end.y;\n searchPosition.startCol = prevSelectedPos.end.x;\n }\n }\n }\n\n result ??= this._findInLine(term, searchPosition, searchOptions, isReverseSearch);\n\n // Search from startRow - 1 to top\n if (!result) {\n searchPosition.startCol = Math.max(searchPosition.startCol, this._terminal.cols);\n for (let y = startRow - 1; y >= 0; y--) {\n searchPosition.startRow = y;\n result = this._findInLine(term, searchPosition, searchOptions, isReverseSearch);\n if (result) {\n break;\n }\n }\n }\n // If we hit the top and didn't search from the very bottom wrap back down\n if (!result && startRow !== (this._terminal.buffer.active.baseY + this._terminal.rows - 1)) {\n for (let y = (this._terminal.buffer.active.baseY + this._terminal.rows - 1); y >= startRow; y--) {\n searchPosition.startRow = y;\n result = this._findInLine(term, searchPosition, searchOptions, isReverseSearch);\n if (result) {\n break;\n }\n }\n }\n\n return result;\n }\n\n /**\n * A found substring is a whole word if it doesn't have an alphanumeric character directly\n * adjacent to it.\n * @param searchIndex starting index of the potential whole word substring\n * @param line entire string in which the potential whole word was found\n * @param term the substring that starts at searchIndex\n */\n private _isWholeWord(searchIndex: number, line: string, term: string): boolean {\n return ((searchIndex === 0) || (Constants.NON_WORD_CHARACTERS.includes(line[searchIndex - 1]))) &&\n (((searchIndex + term.length) === line.length) || (Constants.NON_WORD_CHARACTERS.includes(line[searchIndex + term.length])));\n }\n\n /**\n * Searches a line for a search term. Takes the provided terminal line and searches the text line,\n * which may contain subsequent terminal lines if the text is wrapped. If the provided line number\n * is part of a wrapped text line that started on an earlier line then it is skipped since it will\n * be properly searched when the terminal line that the text starts on is searched.\n * @param term The search term.\n * @param searchPosition The position to start the search.\n * @param searchOptions Search options.\n * @param isReverseSearch Whether the search should start from the right side of the terminal and\n * search to the left.\n * @returns The search result if it was found.\n */\n private _findInLine(term: string, searchPosition: ISearchPosition, searchOptions: ISearchOptions = {}, isReverseSearch: boolean = false): ISearchResult | undefined {\n // Ignore wrapped lines, only consider on unwrapped line (first row of command string).\n // This walks back to the line start rather than recursing into it: one frame per wrapped\n // row overflows the stack on a line long enough to fill the scrollback.\n while (this._terminal.buffer.active.getLine(searchPosition.startRow)?.isWrapped) {\n searchPosition.startCol += this._terminal.cols;\n if (isReverseSearch) {\n return;\n }\n searchPosition.startRow--;\n }\n const row = searchPosition.startRow;\n const col = searchPosition.startCol;\n\n let cache = this._lineCache.getLineFromCache(row);\n if (!cache) {\n cache = this._lineCache.translateBufferLineToStringWithWrap(row, true);\n this._lineCache.setLineInCache(row, cache);\n }\n const [stringLine, offsets] = cache;\n\n const offset = this._bufferColsToStringOffset(row, col);\n let searchTerm = term;\n let searchStringLine = stringLine;\n if (!searchOptions.regex) {\n searchTerm = searchOptions.caseSensitive ? term : term.toLowerCase();\n searchStringLine = searchOptions.caseSensitive ? stringLine : stringLine.toLowerCase();\n }\n\n let resultIndex = -1;\n if (searchOptions.regex) {\n const searchRegex = RegExp(searchTerm, searchOptions.caseSensitive ? 'g' : 'gi');\n let foundTerm: RegExpExecArray | null;\n if (isReverseSearch) {\n // This loop will get the resultIndex of the _last_ regex match in the range 0..offset\n while (foundTerm = searchRegex.exec(searchStringLine.slice(0, offset))) {\n resultIndex = searchRegex.lastIndex - foundTerm[0].length;\n term = foundTerm[0];\n searchRegex.lastIndex -= (term.length - 1);\n }\n } else {\n foundTerm = searchRegex.exec(searchStringLine.slice(offset));\n if (foundTerm && foundTerm[0].length > 0) {\n resultIndex = offset + (searchRegex.lastIndex - foundTerm[0].length);\n term = foundTerm[0];\n }\n }\n } else {\n if (isReverseSearch) {\n if (offset - searchTerm.length >= 0) {\n resultIndex = searchStringLine.lastIndexOf(searchTerm, offset - searchTerm.length);\n }\n } else {\n resultIndex = searchStringLine.indexOf(searchTerm, offset);\n }\n }\n\n if (resultIndex >= 0) {\n if (searchOptions.wholeWord && !this._isWholeWord(resultIndex, searchStringLine, term)) {\n return;\n }\n\n // Adjust the row number and search index if needed since a \"line\" of text can span multiple\n // rows\n let startRowOffset = 0;\n while (startRowOffset < offsets.length - 1 && resultIndex >= offsets[startRowOffset + 1]) {\n startRowOffset++;\n }\n let endRowOffset = startRowOffset;\n while (endRowOffset < offsets.length - 1 && resultIndex + term.length >= offsets[endRowOffset + 1]) {\n endRowOffset++;\n }\n const startColOffset = resultIndex - offsets[startRowOffset];\n const endColOffset = resultIndex + term.length - offsets[endRowOffset];\n const startColIndex = this._stringLengthToBufferSize(row + startRowOffset, startColOffset);\n const endColIndex = this._stringLengthToBufferSize(row + endRowOffset, endColOffset);\n const size = endColIndex - startColIndex + this._terminal.cols * (endRowOffset - startRowOffset);\n\n return {\n term,\n col: startColIndex,\n row: row + startRowOffset,\n size\n };\n }\n }\n\n private _stringLengthToBufferSize(row: number, offset: number): number {\n const line = this._terminal.buffer.active.getLine(row);\n if (!line) {\n return 0;\n }\n for (let i = 0; i < offset; i++) {\n const cell = line.getCell(i);\n if (!cell) {\n break;\n }\n // Adjust the searchIndex to normalize emoji into single chars\n const char = cell.getChars();\n if (char.length > 1) {\n offset -= char.length - 1;\n }\n // Adjust the searchIndex for empty characters following wide unicode\n // chars (eg. CJK)\n const nextCell = line.getCell(i + 1);\n if (nextCell && nextCell.getWidth() === 0) {\n offset++;\n }\n }\n return offset;\n }\n\n private _bufferColsToStringOffset(startRow: number, cols: number): number {\n let lineIndex = startRow;\n let offset = 0;\n let line = this._terminal.buffer.active.getLine(lineIndex);\n while (cols > 0 && line) {\n for (let i = 0; i < cols && i < this._terminal.cols; i++) {\n const cell = line.getCell(i);\n if (!cell) {\n break;\n }\n if (cell.getWidth()) {\n // Treat null characters as whitespace to align with the translateToString API\n offset += cell.getCode() === 0 ? 1 : cell.getChars().length;\n }\n }\n lineIndex++;\n line = this._terminal.buffer.active.getLine(lineIndex);\n if (line && !line.isWrapped) {\n break;\n }\n cols -= this._terminal.cols;\n }\n return offset;\n }\n}\n", "/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport type { Terminal, IDisposable, IDecoration } from '@xterm/xterm';\nimport type { ISearchDecorationOptions } from '@xterm/addon-search';\nimport { dispose, Disposable, toDisposable } from 'common/Lifecycle';\nimport type { ISearchResult } from './SearchEngine';\n\n/**\n * Interface for managing a highlight decoration.\n */\ninterface IHighlight extends IDisposable {\n decoration: IDecoration;\n match: ISearchResult;\n}\n\n/**\n * Interface for managing multiple decorations for a single match.\n */\ninterface IMultiHighlight extends IDisposable {\n decorations: IDecoration[];\n match: ISearchResult;\n}\n\n/**\n * Manages visual decorations for search results including highlighting and active selection\n * indicators. This class handles the creation, styling, and disposal of search-related decorations.\n */\nexport class DecorationManager extends Disposable {\n private _highlightDecorations: IHighlight[] = [];\n private _highlightedLines: Set = new Set();\n\n constructor(private readonly _terminal: Terminal) {\n super();\n this._register(toDisposable(() => this.clearHighlightDecorations()));\n }\n\n /**\n * Creates decorations for all provided search results.\n * @param results The search results to create decorations for.\n * @param options The decoration options.\n */\n public createHighlightDecorations(results: ISearchResult[], options: ISearchDecorationOptions): void {\n this.clearHighlightDecorations();\n\n for (const match of results) {\n const decorations = this._createResultDecorations(match, options, false);\n if (decorations) {\n for (const decoration of decorations) {\n this._storeDecoration(decoration, match);\n }\n }\n }\n }\n\n /**\n * Creates decorations for the currently active search result.\n * @param result The active search result.\n * @param options The decoration options.\n * @returns The multi-highlight decoration or undefined if creation failed.\n */\n public createActiveDecoration(result: ISearchResult, options: ISearchDecorationOptions): IMultiHighlight | undefined {\n const decorations = this._createResultDecorations(result, options, true);\n if (decorations) {\n return { decorations, match: result, dispose() { dispose(decorations); } };\n }\n return undefined;\n }\n\n /**\n * Clears all highlight decorations.\n */\n public clearHighlightDecorations(): void {\n dispose(this._highlightDecorations);\n this._highlightDecorations = [];\n this._highlightedLines.clear();\n }\n\n /**\n * Stores a decoration and tracks it for management.\n * @param decoration The decoration to store.\n * @param match The search result this decoration represents.\n */\n private _storeDecoration(decoration: IDecoration, match: ISearchResult): void {\n this._highlightedLines.add(decoration.marker.line);\n this._highlightDecorations.push({ decoration, match, dispose() { decoration.dispose(); } });\n }\n\n /**\n * Applies styles to the decoration when it is rendered.\n * @param element The decoration's element.\n * @param borderColor The border color to apply.\n * @param isActiveResult Whether the element is part of the active search result.\n */\n private _applyStyles(element: HTMLElement, borderColor: string | undefined, isActiveResult: boolean): void {\n if (!element.classList.contains('xterm-find-result-decoration')) {\n element.classList.add('xterm-find-result-decoration');\n if (borderColor) {\n element.style.outline = `1px solid ${borderColor}`;\n }\n }\n if (isActiveResult) {\n element.classList.add('xterm-find-active-result-decoration');\n }\n }\n\n /**\n * Creates a decoration for the result and applies styles\n * @param result the search result for which to create the decoration\n * @param options the options for the decoration\n * @param isActiveResult whether this is the currently active result\n * @returns the decorations or undefined if the marker has already been disposed of\n */\n private _createResultDecorations(result: ISearchResult, options: ISearchDecorationOptions, isActiveResult: boolean): IDecoration[] | undefined {\n // Gather decoration ranges for this match as it could wrap\n const decorationRanges: [number, number, number][] = [];\n let currentCol = result.col;\n let remainingSize = result.size;\n let markerOffset = -this._terminal.buffer.active.baseY - this._terminal.buffer.active.cursorY + result.row;\n while (remainingSize > 0) {\n const amountThisRow = Math.min(this._terminal.cols - currentCol, remainingSize);\n decorationRanges.push([markerOffset, currentCol, amountThisRow]);\n currentCol = 0;\n remainingSize -= amountThisRow;\n markerOffset++;\n }\n\n // Create the decorations\n const decorations: IDecoration[] = [];\n for (const range of decorationRanges) {\n const marker = this._terminal.registerMarker(range[0]);\n const decoration = this._terminal.registerDecoration({\n marker,\n x: range[1],\n width: range[2],\n layer: isActiveResult ? 'top' : 'bottom',\n backgroundColor: isActiveResult ? options.activeMatchBackground : options.matchBackground,\n overviewRulerOptions: this._highlightedLines.has(marker.line) ? undefined : {\n color: isActiveResult ? options.activeMatchColorOverviewRuler : options.matchOverviewRuler,\n position: 'center'\n }\n });\n if (decoration) {\n const disposables: IDisposable[] = [];\n disposables.push(marker);\n disposables.push(decoration.onRender((e) => this._applyStyles(e, isActiveResult ? options.activeMatchBorder : options.matchBorder, false)));\n disposables.push(decoration.onDispose(() => dispose(disposables)));\n decorations.push(decoration);\n }\n }\n\n return decorations.length === 0 ? undefined : decorations;\n }\n}\n\n\n", "/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport type { ISearchResultChangeEvent } from '@xterm/addon-search';\nimport type { IDisposable } from '@xterm/xterm';\nimport { Emitter, type IEvent } from 'common/Event';\nimport { Disposable } from 'common/Lifecycle';\nimport type { ISearchResult } from './SearchEngine';\n\n/**\n * Interface for managing a currently selected decoration.\n */\ninterface ISelectedDecoration extends IDisposable {\n match: ISearchResult;\n}\n\n/**\n * Tracks search results, manages result indexing, and fires events when results change.\n * This class provides centralized management of search result state and notifications.\n */\nexport class SearchResultTracker extends Disposable {\n private _searchResults: ISearchResult[] = [];\n private _selectedDecoration: ISelectedDecoration | undefined;\n\n private readonly _onDidChangeResults = this._register(new Emitter());\n public get onDidChangeResults(): IEvent { return this._onDidChangeResults.event; }\n\n /**\n * Gets the current search results.\n */\n public get searchResults(): ReadonlyArray {\n return this._searchResults;\n }\n\n /**\n * Gets the currently selected decoration.\n */\n public get selectedDecoration(): ISelectedDecoration | undefined {\n return this._selectedDecoration;\n }\n\n /**\n * Sets the currently selected decoration.\n */\n public set selectedDecoration(decoration: ISelectedDecoration | undefined) {\n this._selectedDecoration = decoration;\n }\n\n /**\n * Updates the search results with a new set of results.\n * @param results The new search results.\n * @param maxResults The maximum number of results to track.\n */\n public updateResults(results: ISearchResult[], maxResults: number): void {\n this._searchResults = results.slice(0, maxResults);\n }\n\n /**\n * Clears all search results.\n */\n public clearResults(): void {\n this._searchResults = [];\n }\n\n /**\n * Clears the selected decoration.\n */\n public clearSelectedDecoration(): void {\n if (this._selectedDecoration) {\n this._selectedDecoration.dispose();\n this._selectedDecoration = undefined;\n }\n }\n\n /**\n * Finds the index of a result in the current results array.\n * @param result The result to find.\n * @returns The index of the result, or -1 if not found.\n */\n public findResultIndex(result: ISearchResult): number {\n for (let i = 0; i < this._searchResults.length; i++) {\n const match = this._searchResults[i];\n if (match.row === result.row && match.col === result.col && match.size === result.size) {\n return i;\n }\n }\n return -1;\n }\n\n /**\n * Fires a result change event with the current state.\n * @param hasDecorations Whether decorations are enabled.\n */\n public fireResultsChanged(hasDecorations: boolean): void {\n if (!hasDecorations) {\n return;\n }\n\n let resultIndex = -1;\n if (this._selectedDecoration) {\n resultIndex = this.findResultIndex(this._selectedDecoration.match);\n }\n\n this._onDidChangeResults.fire({\n resultIndex,\n resultCount: this._searchResults.length\n });\n }\n\n /**\n * Resets all state.\n */\n public reset(): void {\n this.clearSelectedDecoration();\n this.clearResults();\n }\n}\n", "/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport type { Terminal, IDisposable, ITerminalAddon } from '@xterm/xterm';\nimport type { SearchAddon as ISearchApi, ISearchOptions, ISearchAddonOptions, ISearchResultChangeEvent, ISearchDecorationOptions } from '@xterm/addon-search';\nimport { Emitter, type IEvent } from 'common/Event';\nimport { Disposable, MutableDisposable, toDisposable } from 'common/Lifecycle';\nimport { disposableTimeout } from 'common/Async';\nimport { SearchLineCache } from './SearchLineCache';\nimport { SearchState } from './SearchState';\nimport { SearchEngine, type ISearchResult } from './SearchEngine';\nimport { DecorationManager } from './DecorationManager';\nimport { SearchResultTracker } from './SearchResultTracker';\n\ninterface IInternalSearchOptions {\n noScroll: boolean;\n}\n\n/**\n * Configuration constants for the search addon functionality.\n */\nconst enum Constants {\n /**\n * Default maximum number of search results to highlight simultaneously. This limit prevents\n * performance degradation when searching for very common terms that would result in excessive\n * highlighting decorations.\n */\n DEFAULT_HIGHLIGHT_LIMIT = 1000\n}\n\nexport class SearchAddon extends Disposable implements ITerminalAddon, ISearchApi {\n private _terminal: Terminal | undefined;\n private _highlightLimit: number;\n private _highlightTimeout = this._register(new MutableDisposable());\n private _lineCache = this._register(new MutableDisposable());\n\n // Component instances\n private _state = new SearchState();\n private _engine: SearchEngine | undefined;\n private _decorationManager: DecorationManager | undefined;\n private _resultTracker = this._register(new SearchResultTracker());\n\n private readonly _onAfterSearch = this._register(new Emitter());\n public readonly onAfterSearch = this._onAfterSearch.event;\n private readonly _onBeforeSearch = this._register(new Emitter());\n public readonly onBeforeSearch = this._onBeforeSearch.event;\n\n public get onDidChangeResults(): IEvent {\n return this._resultTracker.onDidChangeResults;\n }\n\n constructor(options?: Partial) {\n super();\n\n this._highlightLimit = options?.highlightLimit ?? Constants.DEFAULT_HIGHLIGHT_LIMIT;\n }\n\n public activate(terminal: Terminal): void {\n this._terminal = terminal;\n this._lineCache.value = new SearchLineCache(terminal);\n this._engine = new SearchEngine(terminal, this._lineCache.value);\n this._decorationManager = new DecorationManager(terminal);\n this._register(this._terminal.onWriteParsed(() => this._updateMatches()));\n this._register(this._terminal.onResize(() => this._updateMatches()));\n this._register(toDisposable(() => this.clearDecorations()));\n }\n\n private _updateMatches(): void {\n this._highlightTimeout.clear();\n if (this._state.cachedSearchTerm && this._state.lastSearchOptions?.decorations) {\n this._highlightTimeout.value = disposableTimeout(() => {\n const term = this._state.cachedSearchTerm;\n this._state.clearCachedTerm();\n this.findPrevious(term!, { ...this._state.lastSearchOptions, incremental: true }, { noScroll: true });\n }, 200);\n }\n }\n\n public clearDecorations(retainCachedSearchTerm?: boolean): void {\n this._resultTracker.clearSelectedDecoration();\n this._decorationManager?.clearHighlightDecorations();\n this._resultTracker.clearResults();\n if (!retainCachedSearchTerm) {\n this._state.clearCachedTerm();\n }\n }\n\n public clearActiveDecoration(): void {\n this._resultTracker.clearSelectedDecoration();\n }\n\n /**\n * Find the next instance of the term, then scroll to and select it. If it\n * doesn't exist, do nothing.\n * @param term The search term.\n * @param searchOptions Search options.\n * @returns Whether a result was found.\n */\n public findNext(term: string, searchOptions?: ISearchOptions, internalSearchOptions?: IInternalSearchOptions): boolean {\n if (!this._terminal || !this._engine) {\n throw new Error('Cannot use addon until it has been loaded');\n }\n\n this._onBeforeSearch.fire();\n\n this._state.lastSearchOptions = searchOptions;\n\n if (this._state.shouldUpdateHighlighting(term, searchOptions)) {\n this._highlightAllMatches(term, searchOptions!);\n }\n\n const found = this._findNextAndSelect(term, searchOptions, internalSearchOptions);\n this._fireResults(searchOptions);\n this._state.cachedSearchTerm = term;\n\n this._onAfterSearch.fire();\n\n return found;\n }\n\n private _highlightAllMatches(term: string, searchOptions: ISearchOptions): void {\n if (!this._terminal || !this._engine || !this._decorationManager) {\n throw new Error('Cannot use addon until it has been loaded');\n }\n if (!this._state.isValidSearchTerm(term)) {\n this.clearDecorations();\n return;\n }\n\n // new search, clear out the old decorations\n this.clearDecorations(true);\n\n const results: ISearchResult[] = [];\n let prevResult: ISearchResult | undefined = undefined;\n let result = this._engine.find(term, 0, 0, searchOptions);\n\n while (result && (prevResult?.row !== result.row || prevResult?.col !== result.col)) {\n if (results.length >= this._highlightLimit) {\n break;\n }\n prevResult = result;\n results.push(prevResult);\n const cols = this._terminal.cols;\n let nextCol = prevResult.col + prevResult.size;\n let nextRow = prevResult.row;\n if (nextCol >= cols) {\n nextRow += Math.floor(nextCol / cols);\n nextCol = nextCol % cols;\n }\n result = this._engine.find(term, nextRow, nextCol, searchOptions);\n }\n\n this._resultTracker.updateResults(results, this._highlightLimit);\n if (searchOptions.decorations) {\n this._decorationManager.createHighlightDecorations(results, searchOptions.decorations);\n }\n }\n\n private _findNextAndSelect(term: string, searchOptions?: ISearchOptions, internalSearchOptions?: IInternalSearchOptions): boolean {\n if (!this._terminal || !this._engine) {\n return false;\n }\n if (!this._state.isValidSearchTerm(term)) {\n this._terminal.clearSelection();\n this.clearDecorations();\n return false;\n }\n\n const result = this._engine.findNextWithSelection(term, searchOptions, this._state.cachedSearchTerm);\n return this._selectResult(result, searchOptions?.decorations, internalSearchOptions?.noScroll);\n }\n\n /**\n * Find the previous instance of the term, then scroll to and select it. If it\n * doesn't exist, do nothing.\n * @param term The search term.\n * @param searchOptions Search options.\n * @returns Whether a result was found.\n */\n public findPrevious(term: string, searchOptions?: ISearchOptions, internalSearchOptions?: IInternalSearchOptions): boolean {\n if (!this._terminal || !this._engine) {\n throw new Error('Cannot use addon until it has been loaded');\n }\n\n this._onBeforeSearch.fire();\n\n this._state.lastSearchOptions = searchOptions;\n\n if (this._state.shouldUpdateHighlighting(term, searchOptions)) {\n this._highlightAllMatches(term, searchOptions!);\n }\n\n const found = this._findPreviousAndSelect(term, searchOptions, internalSearchOptions);\n this._fireResults(searchOptions);\n this._state.cachedSearchTerm = term;\n\n this._onAfterSearch.fire();\n\n return found;\n }\n\n private _fireResults(searchOptions?: ISearchOptions): void {\n this._resultTracker.fireResultsChanged(!!searchOptions?.decorations);\n }\n\n private _findPreviousAndSelect(term: string, searchOptions?: ISearchOptions, internalSearchOptions?: IInternalSearchOptions): boolean {\n if (!this._terminal || !this._engine) {\n return false;\n }\n if (!this._state.isValidSearchTerm(term)) {\n this._terminal.clearSelection();\n this.clearDecorations();\n return false;\n }\n\n const result = this._engine.findPreviousWithSelection(term, searchOptions, this._state.cachedSearchTerm);\n return this._selectResult(result, searchOptions?.decorations, internalSearchOptions?.noScroll);\n }\n\n /**\n * Selects and scrolls to a result.\n * @param result The result to select.\n * @returns Whether a result was selected.\n */\n private _selectResult(result: ISearchResult | undefined, options?: ISearchDecorationOptions, noScroll?: boolean): boolean {\n if (!this._terminal || !this._decorationManager) {\n return false;\n }\n\n this._resultTracker.clearSelectedDecoration();\n if (!result) {\n this._terminal.clearSelection();\n return false;\n }\n\n this._terminal.select(result.col, result.row, result.size);\n if (options) {\n const activeDecoration = this._decorationManager.createActiveDecoration(result, options);\n if (activeDecoration) {\n this._resultTracker.selectedDecoration = activeDecoration;\n }\n }\n\n if (!noScroll) {\n // If it is not in the viewport then we scroll else it just gets selected\n if (result.row >= (this._terminal.buffer.active.viewportY + this._terminal.rows) || result.row < this._terminal.buffer.active.viewportY) {\n let scroll = result.row - this._terminal.buffer.active.viewportY;\n scroll -= Math.floor(this._terminal.rows / 2);\n this._terminal.scrollLines(scroll);\n }\n }\n return true;\n }\n}\n"], -+ "mappings": "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", ++ "sourcesContent": ["/**\n * Copyright (c) 2024-2026 The xterm.js authors. All rights reserved.\n * @license MIT\n *\n * Minimal lifecycle utilities for xterm.js core.\n * Simplified from VS Code's lifecycle.ts - no tracking/leak detection.\n */\n\nexport interface IDisposable {\n dispose(): void;\n}\n\nexport function toDisposable(fn: () => void): IDisposable {\n return { dispose: fn };\n}\n\nexport function dispose(disposable: T): T;\nexport function dispose(disposable: T | undefined): T | undefined;\nexport function dispose(disposables: T[]): T[];\nexport function dispose(arg: T | T[] | undefined): T | T[] | undefined {\n if (!arg) {\n return arg;\n }\n if (Array.isArray(arg)) {\n for (const d of arg) {\n d.dispose();\n }\n return [];\n }\n arg.dispose();\n return arg;\n}\n\nexport function combinedDisposable(...disposables: IDisposable[]): IDisposable {\n return toDisposable(() => dispose(disposables));\n}\n\nexport class DisposableStore implements IDisposable {\n private readonly _disposables = new Set();\n private _isDisposed = false;\n\n public get isDisposed(): boolean {\n return this._isDisposed;\n }\n\n public add(o: T): T {\n if (this._isDisposed) {\n o.dispose();\n } else {\n this._disposables.add(o);\n }\n return o;\n }\n\n public dispose(): void {\n if (this._isDisposed) {\n return;\n }\n this._isDisposed = true;\n for (const d of this._disposables) {\n d.dispose();\n }\n this._disposables.clear();\n }\n\n public clear(): void {\n for (const d of this._disposables) {\n d.dispose();\n }\n this._disposables.clear();\n }\n}\n\nexport abstract class Disposable implements IDisposable {\n public static readonly None: IDisposable = Object.freeze({ dispose() { } });\n\n protected readonly _store = new DisposableStore();\n\n public dispose(): void {\n this._store.dispose();\n }\n\n protected _register(o: T): T {\n return this._store.add(o);\n }\n}\n\nexport class MutableDisposable implements IDisposable {\n private _value: T | undefined;\n private _isDisposed = false;\n\n public get value(): T | undefined {\n return this._isDisposed ? undefined : this._value;\n }\n\n public set value(value: T | undefined) {\n if (this._isDisposed || value === this._value) {\n return;\n }\n this._value?.dispose();\n this._value = value;\n }\n\n public clear(): void {\n this.value = undefined;\n }\n\n public dispose(): void {\n this._isDisposed = true;\n this._value?.dispose();\n this._value = undefined;\n }\n}\n", "/**\n * Copyright (c) 2024-2026 The xterm.js authors. All rights reserved.\n * @license MIT\n *\n * Minimal event utilities for xterm.js core.\n * Simplified from VS Code's event.ts - no leak detection/profiling.\n */\n\nimport { IDisposable, DisposableStore, toDisposable } from './Lifecycle';\n\nexport interface IEvent {\n (listener: (e: T) => any, thisArgs?: any, disposables?: IDisposable[] | DisposableStore): IDisposable;\n}\n\nexport class Emitter {\n private _listeners: { fn: (e: T) => any, thisArgs: any }[] = [];\n private _disposed = false;\n private _event: IEvent | undefined;\n\n public get event(): IEvent {\n if (this._event) {\n return this._event;\n }\n this._event = (listener: (e: T) => any, thisArgs?: any, disposables?: IDisposable[] | DisposableStore) => {\n if (this._disposed) {\n return toDisposable(() => {});\n }\n\n const entry = { fn: listener, thisArgs };\n this._listeners = this._listeners.slice();\n this._listeners.push(entry);\n\n const result = toDisposable(() => {\n const idx = this._listeners.indexOf(entry);\n if (idx !== -1) {\n this._listeners = this._listeners.slice();\n this._listeners.splice(idx, 1);\n }\n });\n\n if (disposables) {\n if (Array.isArray(disposables)) {\n disposables.push(result);\n } else {\n disposables.add(result);\n }\n }\n\n return result;\n };\n return this._event;\n }\n\n public fire(event: T): void {\n if (this._disposed || !this._listeners.length) {\n return;\n }\n if (this._listeners.length === 1) {\n this._listeners[0].fn.call(this._listeners[0].thisArgs, event);\n return;\n }\n const listeners = this._listeners;\n for (let i = 0, len = listeners.length; i < len; ++i) {\n listeners[i].fn.call(listeners[i].thisArgs, event);\n }\n }\n\n public dispose(): void {\n if (this._disposed) {\n return;\n }\n this._disposed = true;\n this._listeners.length = 0;\n }\n}\n\nexport namespace EventUtils {\n export function forward(from: IEvent, to: Emitter): IDisposable {\n return from(e => to.fire(e));\n }\n\n export function map(event: IEvent, map: (i: I) => O): IEvent {\n return (listener: (e: O) => any, thisArgs?: any, disposables?: IDisposable[] | DisposableStore) => {\n return event(i => listener.call(thisArgs, map(i)), undefined, disposables);\n };\n }\n\n export function any(...events: IEvent[]): IEvent;\n export function any(...events: IEvent[]): IEvent;\n export function any(...events: IEvent[]): IEvent {\n return (listener: (e: T) => any, thisArgs?: any, disposables?: IDisposable[] | DisposableStore) => {\n const store = new DisposableStore();\n for (const event of events) {\n store.add(event(e => listener.call(thisArgs, e)));\n }\n if (disposables) {\n if (Array.isArray(disposables)) {\n disposables.push(store);\n } else {\n disposables.add(store);\n }\n }\n return store;\n };\n }\n\n export function runAndSubscribe(event: IEvent, handler: (e: T) => void, initial: T): IDisposable;\n export function runAndSubscribe(event: IEvent, handler: (e: T | undefined) => void): IDisposable;\n export function runAndSubscribe(event: IEvent, handler: (e: T | undefined) => void, initial?: T): IDisposable {\n handler(initial);\n return event(e => handler(e));\n }\n}\n", "/**\n * Copyright (c) 2026 The xterm.js authors. All rights reserved.\n * @license MIT\n *\n * Minimal async helpers for xterm.js core.\n */\n\nimport { DisposableStore, IDisposable, toDisposable } from './Lifecycle';\n\nexport function timeout(millis: number): Promise {\n return new Promise(resolve => setTimeout(resolve, millis));\n}\n\n/**\n * Creates a timeout that can be disposed using its returned value.\n * @param handler The timeout handler.\n * @param timeout An optional timeout in milliseconds.\n * @param store An optional {@link DisposableStore} that will have the timeout disposable managed\n * automatically.\n */\nexport function disposableTimeout(handler: () => void, timeout = 0, store?: DisposableStore): IDisposable {\n const timer = setTimeout(() => {\n handler();\n if (store) {\n disposable.dispose();\n }\n }, timeout);\n const disposable = toDisposable(() => {\n clearTimeout(timer);\n });\n store?.add(disposable);\n return disposable;\n}\n\nexport class TimeoutTimer implements IDisposable {\n private _token: any = -1;\n private _isDisposed = false;\n\n public dispose(): void {\n this.cancel();\n this._isDisposed = true;\n }\n\n public cancel(): void {\n if (this._token !== -1) {\n clearTimeout(this._token);\n this._token = -1;\n }\n }\n\n public cancelAndSet(runner: () => void, timeout: number): void {\n if (this._isDisposed) {\n throw new Error('Calling cancelAndSet on a disposed TimeoutTimer');\n }\n this.cancel();\n this._token = setTimeout(() => {\n this._token = -1;\n runner();\n }, timeout);\n }\n\n public setIfNotSet(runner: () => void, timeout: number): void {\n if (this._isDisposed) {\n throw new Error('Calling setIfNotSet on a disposed TimeoutTimer');\n }\n if (this._token !== -1) {\n return;\n }\n this._token = setTimeout(() => {\n this._token = -1;\n runner();\n }, timeout);\n }\n}\n\n/**\n * Schedules a single runner on the microtask queue. Unlike {@link TimeoutTimer}, a scheduled\n * microtask cannot be unqueued; {@link cancel} prevents the runner from executing if it has not\n * run yet.\n */\nexport class MicrotaskTimer implements IDisposable {\n private _isScheduled = false;\n private _isDisposed = false;\n\n public dispose(): void {\n this.cancel();\n this._isDisposed = true;\n }\n\n public cancel(): void {\n this._isScheduled = false;\n }\n\n public set(runner: () => void): void {\n if (this._isDisposed) {\n throw new Error('Calling set on a disposed MicrotaskTimer');\n }\n if (this._isScheduled) {\n return;\n }\n this._isScheduled = true;\n queueMicrotask(() => {\n if (!this._isScheduled) {\n return;\n }\n this._isScheduled = false;\n runner();\n });\n }\n}\n\nexport class IntervalTimer implements IDisposable {\n private _disposable: IDisposable | undefined;\n private _isDisposed = false;\n\n public cancel(): void {\n this._disposable?.dispose();\n this._disposable = undefined;\n }\n\n public cancelAndSet(runner: () => void, interval: number, context: Window | typeof globalThis = globalThis): void {\n if (this._isDisposed) {\n throw new Error('Calling cancelAndSet on a disposed IntervalTimer');\n }\n this.cancel();\n const handle = context.setInterval(() => {\n runner();\n }, interval);\n this._disposable = {\n dispose: () => {\n context.clearInterval(handle as any);\n this._disposable = undefined;\n }\n };\n }\n\n public dispose(): void {\n this.cancel();\n this._isDisposed = true;\n }\n}\n", "/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport type { Terminal } from '@xterm/xterm';\nimport { combinedDisposable, Disposable, MutableDisposable, toDisposable } from 'common/Lifecycle';\nimport { disposableTimeout } from 'common/Async';\n\nexport type LineCacheEntry = [\n /**\n * The string representation of a line (as opposed to the buffer cell representation).\n */\n lineAsString: string,\n /**\n * The offsets where each line starts when the entry describes a wrapped line.\n */\n lineOffsets: number[]\n];\n\n/**\n * Configuration constants for the search line cache functionality.\n */\nconst enum Constants {\n /**\n * Time-to-live for cached search results in milliseconds. After this duration, cached search\n * results will be invalidated to ensure they remain consistent with terminal content changes.\n */\n LINES_CACHE_TIME_TO_LIVE = 15000\n}\n\nexport class SearchLineCache extends Disposable {\n /**\n * translateBufferLineToStringWithWrap is a fairly expensive call.\n * We memoize the calls into an array that has a time based ttl.\n * _linesCache is also invalidated when the terminal cursor moves.\n */\n private _linesCache: LineCacheEntry[] | undefined;\n private _linesCacheTimeout = this._register(new MutableDisposable());\n private _linesCacheDisposables = this._register(new MutableDisposable());\n // Track access to avoid recreating a timeout on every init call which occurs once per search\n // result (findNext/findPrevious -> _highlightAllMatches -> find loop).\n private _lastAccessTimestamp = 0;\n\n constructor(private readonly _terminal: Terminal) {\n super();\n this._register(toDisposable(() => this._destroyLinesCache()));\n }\n\n /**\n * Sets up a line cache with a ttl\n */\n public initLinesCache(): void {\n if (!this._linesCache) {\n this._linesCache = new Array(this._terminal.buffer.active.length);\n this._linesCacheDisposables.value = combinedDisposable(\n this._terminal.onLineFeed(() => this._destroyLinesCache()),\n this._terminal.onCursorMove(() => this._destroyLinesCache()),\n this._terminal.onResize(() => this._destroyLinesCache())\n );\n }\n\n this._lastAccessTimestamp = Date.now();\n if (!this._linesCacheTimeout.value) {\n this._scheduleLinesCacheTimeout(Constants.LINES_CACHE_TIME_TO_LIVE);\n }\n }\n\n private _destroyLinesCache(): void {\n this._linesCache = undefined;\n this._lastAccessTimestamp = 0;\n this._linesCacheDisposables.clear();\n this._linesCacheTimeout.clear();\n }\n\n private _scheduleLinesCacheTimeout(delay: number): void {\n this._linesCacheTimeout.value = disposableTimeout(() => {\n if (!this._linesCache) {\n return;\n }\n const now = Date.now();\n const elapsed = now - this._lastAccessTimestamp;\n if (elapsed >= Constants.LINES_CACHE_TIME_TO_LIVE) {\n this._destroyLinesCache();\n return;\n }\n this._scheduleLinesCacheTimeout(Constants.LINES_CACHE_TIME_TO_LIVE - elapsed);\n }, delay);\n }\n\n public getLineFromCache(row: number): LineCacheEntry | undefined {\n return this._linesCache?.[row];\n }\n\n public setLineInCache(row: number, entry: LineCacheEntry): void {\n if (this._linesCache) {\n this._linesCache[row] = entry;\n }\n }\n\n /**\n * Translates a buffer line to a string, including subsequent lines if they are wraps.\n * Wide characters will count as two columns in the resulting string. This\n * function is useful for getting the actual text underneath the raw selection\n * position.\n * @param lineIndex The index of the line being translated.\n * @param trimRight Whether to trim whitespace to the right.\n */\n public translateBufferLineToStringWithWrap(lineIndex: number, trimRight: boolean): LineCacheEntry {\n const strings = [];\n const lineOffsets = [0];\n let line = this._terminal.buffer.active.getLine(lineIndex);\n while (line) {\n const nextLine = this._terminal.buffer.active.getLine(lineIndex + 1);\n const lineWrapsToNext = nextLine ? nextLine.isWrapped : false;\n let string = line.translateToString(!lineWrapsToNext && trimRight);\n if (lineWrapsToNext && nextLine) {\n const lastCell = line.getCell(line.length - 1);\n const lastCellIsNull = lastCell && lastCell.getCode() === 0 && lastCell.getWidth() === 1;\n // a wide character wrapped to the next line\n if (lastCellIsNull && nextLine.getCell(0)?.getWidth() === 2) {\n string = string.slice(0, -1);\n }\n }\n strings.push(string);\n if (lineWrapsToNext) {\n lineOffsets.push(lineOffsets[lineOffsets.length - 1] + string.length);\n } else {\n break;\n }\n lineIndex++;\n line = nextLine;\n }\n return [strings.join(''), lineOffsets];\n }\n}\n", "/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport type { ISearchOptions } from '@xterm/addon-search';\n\n/**\n * Manages search state including cached search terms, options tracking, and validation.\n * This class provides a centralized way to handle search state consistency and option changes.\n */\nexport class SearchState {\n private _cachedSearchTerm: string | undefined;\n private _lastSearchOptions: ISearchOptions | undefined;\n\n /**\n * Gets the currently cached search term.\n */\n public get cachedSearchTerm(): string | undefined {\n return this._cachedSearchTerm;\n }\n\n /**\n * Sets the cached search term.\n */\n public set cachedSearchTerm(term: string | undefined) {\n this._cachedSearchTerm = term;\n }\n\n /**\n * Gets the last search options used.\n */\n public get lastSearchOptions(): ISearchOptions | undefined {\n return this._lastSearchOptions;\n }\n\n /**\n * Sets the last search options used.\n */\n public set lastSearchOptions(options: ISearchOptions | undefined) {\n this._lastSearchOptions = options;\n }\n\n /**\n * Validates a search term to ensure it's not empty or invalid.\n * @param term The search term to validate.\n * @returns true if the term is valid for searching.\n */\n public isValidSearchTerm(term: string): boolean {\n return !!(term && term.length > 0);\n }\n\n /**\n * Determines if search options have changed compared to the last search.\n * @param newOptions The new search options to compare.\n * @returns true if the options have changed.\n */\n public didOptionsChange(newOptions?: ISearchOptions): boolean {\n if (!this._lastSearchOptions) {\n return true;\n }\n if (!newOptions) {\n return false;\n }\n if (this._lastSearchOptions.caseSensitive !== newOptions.caseSensitive) {\n return true;\n }\n if (this._lastSearchOptions.regex !== newOptions.regex) {\n return true;\n }\n if (this._lastSearchOptions.wholeWord !== newOptions.wholeWord) {\n return true;\n }\n return false;\n }\n\n /**\n * Determines if a new search should trigger highlighting updates.\n * @param term The search term.\n * @param options The search options.\n * @returns true if highlighting should be updated.\n */\n public shouldUpdateHighlighting(term: string, options?: ISearchOptions): boolean {\n if (!options?.decorations) {\n return false;\n }\n return this._cachedSearchTerm === undefined ||\n term !== this._cachedSearchTerm ||\n this.didOptionsChange(options);\n }\n\n /**\n * Clears the cached search term.\n */\n public clearCachedTerm(): void {\n this._cachedSearchTerm = undefined;\n }\n\n /**\n * Resets all state.\n */\n public reset(): void {\n this._cachedSearchTerm = undefined;\n this._lastSearchOptions = undefined;\n }\n}\n", "/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport type { Terminal } from '@xterm/xterm';\nimport type { ISearchOptions } from '@xterm/addon-search';\nimport type { SearchLineCache } from './SearchLineCache';\n\n/**\n * Represents the position to start a search from.\n */\ninterface ISearchPosition {\n startCol: number;\n startRow: number;\n}\n\n/**\n * Represents a search result with its position and content.\n */\nexport interface ISearchResult {\n term: string;\n col: number;\n row: number;\n size: number;\n}\n\n/**\n * Configuration constants for the search engine functionality.\n */\nconst enum Constants {\n /**\n * Characters that are considered non-word characters for search boundary detection. These\n * characters are used to determine word boundaries when performing whole-word searches. Includes\n * common punctuation, symbols, and whitespace characters.\n */\n NON_WORD_CHARACTERS = ' ~!@#$%^&*()+`-=[]{}|\\\\;:\"\\',./<>?'\n}\n\n/**\n * Core search engine that handles finding text within terminal content.\n * This class is responsible for the actual search algorithms and position calculations.\n */\nexport class SearchEngine {\n constructor(\n private readonly _terminal: Terminal,\n private readonly _lineCache: SearchLineCache\n ) {}\n\n /**\n * Find the first occurrence of a term starting from a specific position.\n * @param term The search term.\n * @param startRow The row to start searching from.\n * @param startCol The column to start searching from.\n * @param searchOptions Search options.\n * @returns The search result if found, undefined otherwise.\n */\n public find(term: string, startRow: number, startCol: number, searchOptions?: ISearchOptions): ISearchResult | undefined {\n if (!term || term.length === 0) {\n this._terminal.clearSelection();\n return undefined;\n }\n if (startCol >= this._terminal.cols) {\n throw new Error(`Invalid col: ${startCol} to search in terminal of ${this._terminal.cols} cols`);\n }\n\n this._lineCache.initLinesCache();\n\n const searchPosition: ISearchPosition = {\n startRow,\n startCol\n };\n\n // Search startRow\n let result = this._findInLine(term, searchPosition, searchOptions);\n // Search from startRow + 1 to end\n if (!result) {\n for (let y = startRow + 1; y < this._terminal.buffer.active.baseY + this._terminal.rows; y++) {\n if (this._isRowCoveredByLineStart(y, searchOptions)) {\n continue;\n }\n searchPosition.startRow = y;\n searchPosition.startCol = 0;\n result = this._findInLine(term, searchPosition, searchOptions);\n if (result) {\n break;\n }\n }\n }\n return result;\n }\n\n /**\n * Find the next occurrence of a term with wrapping and selection management.\n * @param term The search term.\n * @param searchOptions Search options.\n * @param cachedSearchTerm The cached search term to determine incremental behavior.\n * @returns The search result if found, undefined otherwise.\n */\n public findNextWithSelection(term: string, searchOptions?: ISearchOptions, cachedSearchTerm?: string): ISearchResult | undefined {\n if (!term || term.length === 0) {\n this._terminal.clearSelection();\n return undefined;\n }\n\n const prevSelectedPos = this._terminal.getSelectionPosition();\n this._terminal.clearSelection();\n\n let startCol = 0;\n let startRow = 0;\n if (prevSelectedPos) {\n if (cachedSearchTerm === term) {\n startCol = prevSelectedPos.end.x;\n startRow = prevSelectedPos.end.y;\n } else {\n startCol = prevSelectedPos.start.x;\n startRow = prevSelectedPos.start.y;\n }\n }\n\n this._lineCache.initLinesCache();\n\n const searchPosition: ISearchPosition = {\n startRow,\n startCol\n };\n\n // Search startRow\n let result = this._findInLine(term, searchPosition, searchOptions);\n // Search from startRow + 1 to end\n if (!result) {\n for (let y = startRow + 1; y < this._terminal.buffer.active.baseY + this._terminal.rows; y++) {\n if (this._isRowCoveredByLineStart(y, searchOptions)) {\n continue;\n }\n searchPosition.startRow = y;\n searchPosition.startCol = 0;\n result = this._findInLine(term, searchPosition, searchOptions);\n if (result) {\n break;\n }\n }\n }\n // If we hit the bottom and didn't search from the very top wrap back up\n if (!result && startRow !== 0) {\n for (let y = 0; y < startRow; y++) {\n if (this._isRowCoveredByLineStart(y, searchOptions)) {\n continue;\n }\n searchPosition.startRow = y;\n searchPosition.startCol = 0;\n result = this._findInLine(term, searchPosition, searchOptions);\n if (result) {\n break;\n }\n }\n }\n\n // If there is only one result, wrap back and return selection if it exists.\n if (!result && prevSelectedPos) {\n searchPosition.startRow = prevSelectedPos.start.y;\n searchPosition.startCol = 0;\n result = this._findInLine(term, searchPosition, searchOptions);\n }\n\n return result;\n }\n\n /**\n * Find the previous occurrence of a term with wrapping and selection management.\n * @param term The search term.\n * @param searchOptions Search options.\n * @param cachedSearchTerm The cached search term to determine if expansion should occur.\n * @returns The search result if found, undefined otherwise.\n */\n public findPreviousWithSelection(term: string, searchOptions?: ISearchOptions, cachedSearchTerm?: string): ISearchResult | undefined {\n if (!term || term.length === 0) {\n this._terminal.clearSelection();\n return undefined;\n }\n\n const prevSelectedPos = this._terminal.getSelectionPosition();\n this._terminal.clearSelection();\n\n let startRow = this._terminal.buffer.active.baseY + this._terminal.rows - 1;\n const startCol = this._terminal.cols;\n const isReverseSearch = true;\n\n this._lineCache.initLinesCache();\n const searchPosition: ISearchPosition = {\n startRow,\n startCol\n };\n\n let result: ISearchResult | undefined;\n if (prevSelectedPos) {\n searchPosition.startRow = startRow = prevSelectedPos.start.y;\n searchPosition.startCol = prevSelectedPos.start.x;\n if (cachedSearchTerm !== term) {\n // Try to expand selection to right first.\n result = this._findInLine(term, searchPosition, searchOptions, false);\n if (!result) {\n // If selection was not able to be expanded to the right, then try reverse search\n searchPosition.startRow = startRow = prevSelectedPos.end.y;\n searchPosition.startCol = prevSelectedPos.end.x;\n }\n }\n }\n\n result ??= this._findInLine(term, searchPosition, searchOptions, isReverseSearch);\n\n // Search from startRow - 1 to top\n if (!result) {\n searchPosition.startCol = Math.max(searchPosition.startCol, this._terminal.cols);\n for (let y = startRow - 1; y >= 0; y--) {\n searchPosition.startRow = y;\n result = this._findInLine(term, searchPosition, searchOptions, isReverseSearch);\n if (result) {\n break;\n }\n }\n }\n // If we hit the top and didn't search from the very bottom wrap back down\n if (!result && startRow !== (this._terminal.buffer.active.baseY + this._terminal.rows - 1)) {\n for (let y = (this._terminal.buffer.active.baseY + this._terminal.rows - 1); y >= startRow; y--) {\n searchPosition.startRow = y;\n result = this._findInLine(term, searchPosition, searchOptions, isReverseSearch);\n if (result) {\n break;\n }\n }\n }\n\n return result;\n }\n\n /**\n * A found substring is a whole word if it doesn't have an alphanumeric character directly\n * adjacent to it.\n * @param searchIndex starting index of the potential whole word substring\n * @param line entire string in which the potential whole word was found\n * @param term the substring that starts at searchIndex\n */\n private _isWholeWord(searchIndex: number, line: string, term: string): boolean {\n return ((searchIndex === 0) || (Constants.NON_WORD_CHARACTERS.includes(line[searchIndex - 1]))) &&\n (((searchIndex + term.length) === line.length) || (Constants.NON_WORD_CHARACTERS.includes(line[searchIndex + term.length])));\n }\n\n /**\n * A wrapped row's text was already searched in full when the first row of its line was, so a\n * full-buffer scan that visits every row does O(rows^2) work over one long line. Skipping is\n * only sound for a plain search: wholeWord and regex can both reject at one offset and match at\n * a later one within the same line.\n */\n private _isRowCoveredByLineStart(row: number, searchOptions?: ISearchOptions): boolean {\n if (searchOptions?.regex || searchOptions?.wholeWord) {\n return false;\n }\n return this._terminal.buffer.active.getLine(row)?.isWrapped === true;\n }\n\n /**\n * Searches a line for a search term. Takes the provided terminal line and searches the text line,\n * which may contain subsequent terminal lines if the text is wrapped. If the provided line number\n * is part of a wrapped text line that started on an earlier line then it is skipped since it will\n * be properly searched when the terminal line that the text starts on is searched.\n * @param term The search term.\n * @param searchPosition The position to start the search.\n * @param searchOptions Search options.\n * @param isReverseSearch Whether the search should start from the right side of the terminal and\n * search to the left.\n * @returns The search result if it was found.\n */\n private _findInLine(term: string, searchPosition: ISearchPosition, searchOptions: ISearchOptions = {}, isReverseSearch: boolean = false): ISearchResult | undefined {\n // Ignore wrapped lines, only consider on unwrapped line (first row of command string).\n // This walks back to the line start rather than recursing into it: one frame per wrapped\n // row overflows the stack on a line long enough to fill the scrollback.\n while (this._terminal.buffer.active.getLine(searchPosition.startRow)?.isWrapped) {\n searchPosition.startCol += this._terminal.cols;\n if (isReverseSearch) {\n return;\n }\n searchPosition.startRow--;\n }\n const row = searchPosition.startRow;\n const col = searchPosition.startCol;\n\n let cache = this._lineCache.getLineFromCache(row);\n if (!cache) {\n cache = this._lineCache.translateBufferLineToStringWithWrap(row, true);\n this._lineCache.setLineInCache(row, cache);\n }\n const [stringLine, offsets] = cache;\n\n const offset = this._bufferColsToStringOffset(row, col);\n let searchTerm = term;\n let searchStringLine = stringLine;\n if (!searchOptions.regex) {\n searchTerm = searchOptions.caseSensitive ? term : term.toLowerCase();\n searchStringLine = searchOptions.caseSensitive ? stringLine : stringLine.toLowerCase();\n }\n\n let resultIndex = -1;\n if (searchOptions.regex) {\n const searchRegex = RegExp(searchTerm, searchOptions.caseSensitive ? 'g' : 'gi');\n let foundTerm: RegExpExecArray | null;\n if (isReverseSearch) {\n // This loop will get the resultIndex of the _last_ regex match in the range 0..offset\n while (foundTerm = searchRegex.exec(searchStringLine.slice(0, offset))) {\n resultIndex = searchRegex.lastIndex - foundTerm[0].length;\n term = foundTerm[0];\n searchRegex.lastIndex -= (term.length - 1);\n }\n } else {\n foundTerm = searchRegex.exec(searchStringLine.slice(offset));\n if (foundTerm && foundTerm[0].length > 0) {\n resultIndex = offset + (searchRegex.lastIndex - foundTerm[0].length);\n term = foundTerm[0];\n }\n }\n } else {\n if (isReverseSearch) {\n if (offset - searchTerm.length >= 0) {\n resultIndex = searchStringLine.lastIndexOf(searchTerm, offset - searchTerm.length);\n }\n } else {\n resultIndex = searchStringLine.indexOf(searchTerm, offset);\n }\n }\n\n if (resultIndex >= 0) {\n if (searchOptions.wholeWord && !this._isWholeWord(resultIndex, searchStringLine, term)) {\n return;\n }\n\n // Adjust the row number and search index if needed since a \"line\" of text can span multiple\n // rows\n let startRowOffset = 0;\n while (startRowOffset < offsets.length - 1 && resultIndex >= offsets[startRowOffset + 1]) {\n startRowOffset++;\n }\n let endRowOffset = startRowOffset;\n while (endRowOffset < offsets.length - 1 && resultIndex + term.length >= offsets[endRowOffset + 1]) {\n endRowOffset++;\n }\n const startColOffset = resultIndex - offsets[startRowOffset];\n const endColOffset = resultIndex + term.length - offsets[endRowOffset];\n const startColIndex = this._stringLengthToBufferSize(row + startRowOffset, startColOffset);\n const endColIndex = this._stringLengthToBufferSize(row + endRowOffset, endColOffset);\n const size = endColIndex - startColIndex + this._terminal.cols * (endRowOffset - startRowOffset);\n\n return {\n term,\n col: startColIndex,\n row: row + startRowOffset,\n size\n };\n }\n }\n\n private _stringLengthToBufferSize(row: number, offset: number): number {\n const line = this._terminal.buffer.active.getLine(row);\n if (!line) {\n return 0;\n }\n for (let i = 0; i < offset; i++) {\n const cell = line.getCell(i);\n if (!cell) {\n break;\n }\n // Adjust the searchIndex to normalize emoji into single chars\n const char = cell.getChars();\n if (char.length > 1) {\n offset -= char.length - 1;\n }\n // Adjust the searchIndex for empty characters following wide unicode\n // chars (eg. CJK)\n const nextCell = line.getCell(i + 1);\n if (nextCell && nextCell.getWidth() === 0) {\n offset++;\n }\n }\n return offset;\n }\n\n private _bufferColsToStringOffset(startRow: number, cols: number): number {\n let lineIndex = startRow;\n let offset = 0;\n let line = this._terminal.buffer.active.getLine(lineIndex);\n while (cols > 0 && line) {\n for (let i = 0; i < cols && i < this._terminal.cols; i++) {\n const cell = line.getCell(i);\n if (!cell) {\n break;\n }\n if (cell.getWidth()) {\n // Treat null characters as whitespace to align with the translateToString API\n offset += cell.getCode() === 0 ? 1 : cell.getChars().length;\n }\n }\n lineIndex++;\n line = this._terminal.buffer.active.getLine(lineIndex);\n if (line && !line.isWrapped) {\n break;\n }\n cols -= this._terminal.cols;\n }\n return offset;\n }\n}\n", "/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport type { Terminal, IDisposable, IDecoration } from '@xterm/xterm';\nimport type { ISearchDecorationOptions } from '@xterm/addon-search';\nimport { dispose, Disposable, toDisposable } from 'common/Lifecycle';\nimport type { ISearchResult } from './SearchEngine';\n\n/**\n * Interface for managing a highlight decoration.\n */\ninterface IHighlight extends IDisposable {\n decoration: IDecoration;\n match: ISearchResult;\n}\n\n/**\n * Interface for managing multiple decorations for a single match.\n */\ninterface IMultiHighlight extends IDisposable {\n decorations: IDecoration[];\n match: ISearchResult;\n}\n\n/**\n * Manages visual decorations for search results including highlighting and active selection\n * indicators. This class handles the creation, styling, and disposal of search-related decorations.\n */\nexport class DecorationManager extends Disposable {\n private _highlightDecorations: IHighlight[] = [];\n private _highlightedLines: Set = new Set();\n\n constructor(private readonly _terminal: Terminal) {\n super();\n this._register(toDisposable(() => this.clearHighlightDecorations()));\n }\n\n /**\n * Creates decorations for all provided search results.\n * @param results The search results to create decorations for.\n * @param options The decoration options.\n */\n public createHighlightDecorations(results: ISearchResult[], options: ISearchDecorationOptions): void {\n this.clearHighlightDecorations();\n\n for (const match of results) {\n const decorations = this._createResultDecorations(match, options, false);\n if (decorations) {\n for (const decoration of decorations) {\n this._storeDecoration(decoration, match);\n }\n }\n }\n }\n\n /**\n * Creates decorations for the currently active search result.\n * @param result The active search result.\n * @param options The decoration options.\n * @returns The multi-highlight decoration or undefined if creation failed.\n */\n public createActiveDecoration(result: ISearchResult, options: ISearchDecorationOptions): IMultiHighlight | undefined {\n const decorations = this._createResultDecorations(result, options, true);\n if (decorations) {\n return { decorations, match: result, dispose() { dispose(decorations); } };\n }\n return undefined;\n }\n\n /**\n * Clears all highlight decorations.\n */\n public clearHighlightDecorations(): void {\n dispose(this._highlightDecorations);\n this._highlightDecorations = [];\n this._highlightedLines.clear();\n }\n\n /**\n * Stores a decoration and tracks it for management.\n * @param decoration The decoration to store.\n * @param match The search result this decoration represents.\n */\n private _storeDecoration(decoration: IDecoration, match: ISearchResult): void {\n this._highlightedLines.add(decoration.marker.line);\n this._highlightDecorations.push({ decoration, match, dispose() { decoration.dispose(); } });\n }\n\n /**\n * Applies styles to the decoration when it is rendered.\n * @param element The decoration's element.\n * @param borderColor The border color to apply.\n * @param isActiveResult Whether the element is part of the active search result.\n */\n private _applyStyles(element: HTMLElement, borderColor: string | undefined, isActiveResult: boolean): void {\n if (!element.classList.contains('xterm-find-result-decoration')) {\n element.classList.add('xterm-find-result-decoration');\n if (borderColor) {\n element.style.outline = `1px solid ${borderColor}`;\n }\n }\n if (isActiveResult) {\n element.classList.add('xterm-find-active-result-decoration');\n }\n }\n\n /**\n * Creates a decoration for the result and applies styles\n * @param result the search result for which to create the decoration\n * @param options the options for the decoration\n * @param isActiveResult whether this is the currently active result\n * @returns the decorations or undefined if the marker has already been disposed of\n */\n private _createResultDecorations(result: ISearchResult, options: ISearchDecorationOptions, isActiveResult: boolean): IDecoration[] | undefined {\n // Gather decoration ranges for this match as it could wrap\n const decorationRanges: [number, number, number][] = [];\n let currentCol = result.col;\n let remainingSize = result.size;\n let markerOffset = -this._terminal.buffer.active.baseY - this._terminal.buffer.active.cursorY + result.row;\n while (remainingSize > 0) {\n const amountThisRow = Math.min(this._terminal.cols - currentCol, remainingSize);\n decorationRanges.push([markerOffset, currentCol, amountThisRow]);\n currentCol = 0;\n remainingSize -= amountThisRow;\n markerOffset++;\n }\n\n // Create the decorations\n const decorations: IDecoration[] = [];\n for (const range of decorationRanges) {\n const marker = this._terminal.registerMarker(range[0]);\n const decoration = this._terminal.registerDecoration({\n marker,\n x: range[1],\n width: range[2],\n layer: isActiveResult ? 'top' : 'bottom',\n backgroundColor: isActiveResult ? options.activeMatchBackground : options.matchBackground,\n overviewRulerOptions: this._highlightedLines.has(marker.line) ? undefined : {\n color: isActiveResult ? options.activeMatchColorOverviewRuler : options.matchOverviewRuler,\n position: 'center'\n }\n });\n if (decoration) {\n const disposables: IDisposable[] = [];\n disposables.push(marker);\n disposables.push(decoration.onRender((e) => this._applyStyles(e, isActiveResult ? options.activeMatchBorder : options.matchBorder, false)));\n disposables.push(decoration.onDispose(() => dispose(disposables)));\n decorations.push(decoration);\n }\n }\n\n return decorations.length === 0 ? undefined : decorations;\n }\n}\n\n\n", "/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport type { ISearchResultChangeEvent } from '@xterm/addon-search';\nimport type { IDisposable } from '@xterm/xterm';\nimport { Emitter, type IEvent } from 'common/Event';\nimport { Disposable } from 'common/Lifecycle';\nimport type { ISearchResult } from './SearchEngine';\n\n/**\n * Interface for managing a currently selected decoration.\n */\ninterface ISelectedDecoration extends IDisposable {\n match: ISearchResult;\n}\n\n/**\n * Tracks search results, manages result indexing, and fires events when results change.\n * This class provides centralized management of search result state and notifications.\n */\nexport class SearchResultTracker extends Disposable {\n private _searchResults: ISearchResult[] = [];\n private _selectedDecoration: ISelectedDecoration | undefined;\n\n private readonly _onDidChangeResults = this._register(new Emitter());\n public get onDidChangeResults(): IEvent { return this._onDidChangeResults.event; }\n\n /**\n * Gets the current search results.\n */\n public get searchResults(): ReadonlyArray {\n return this._searchResults;\n }\n\n /**\n * Gets the currently selected decoration.\n */\n public get selectedDecoration(): ISelectedDecoration | undefined {\n return this._selectedDecoration;\n }\n\n /**\n * Sets the currently selected decoration.\n */\n public set selectedDecoration(decoration: ISelectedDecoration | undefined) {\n this._selectedDecoration = decoration;\n }\n\n /**\n * Updates the search results with a new set of results.\n * @param results The new search results.\n * @param maxResults The maximum number of results to track.\n */\n public updateResults(results: ISearchResult[], maxResults: number): void {\n this._searchResults = results.slice(0, maxResults);\n }\n\n /**\n * Clears all search results.\n */\n public clearResults(): void {\n this._searchResults = [];\n }\n\n /**\n * Clears the selected decoration.\n */\n public clearSelectedDecoration(): void {\n if (this._selectedDecoration) {\n this._selectedDecoration.dispose();\n this._selectedDecoration = undefined;\n }\n }\n\n /**\n * Finds the index of a result in the current results array.\n * @param result The result to find.\n * @returns The index of the result, or -1 if not found.\n */\n public findResultIndex(result: ISearchResult): number {\n for (let i = 0; i < this._searchResults.length; i++) {\n const match = this._searchResults[i];\n if (match.row === result.row && match.col === result.col && match.size === result.size) {\n return i;\n }\n }\n return -1;\n }\n\n /**\n * Fires a result change event with the current state.\n * @param hasDecorations Whether decorations are enabled.\n */\n public fireResultsChanged(hasDecorations: boolean): void {\n if (!hasDecorations) {\n return;\n }\n\n let resultIndex = -1;\n if (this._selectedDecoration) {\n resultIndex = this.findResultIndex(this._selectedDecoration.match);\n }\n\n this._onDidChangeResults.fire({\n resultIndex,\n resultCount: this._searchResults.length\n });\n }\n\n /**\n * Resets all state.\n */\n public reset(): void {\n this.clearSelectedDecoration();\n this.clearResults();\n }\n}\n", "/**\n * Copyright (c) 2017 The xterm.js authors. All rights reserved.\n * @license MIT\n */\n\nimport type { Terminal, IDisposable, ITerminalAddon } from '@xterm/xterm';\nimport type { SearchAddon as ISearchApi, ISearchOptions, ISearchAddonOptions, ISearchResultChangeEvent, ISearchDecorationOptions } from '@xterm/addon-search';\nimport { Emitter, type IEvent } from 'common/Event';\nimport { Disposable, MutableDisposable, toDisposable } from 'common/Lifecycle';\nimport { disposableTimeout } from 'common/Async';\nimport { SearchLineCache } from './SearchLineCache';\nimport { SearchState } from './SearchState';\nimport { SearchEngine, type ISearchResult } from './SearchEngine';\nimport { DecorationManager } from './DecorationManager';\nimport { SearchResultTracker } from './SearchResultTracker';\n\ninterface IInternalSearchOptions {\n noScroll: boolean;\n}\n\n/**\n * Configuration constants for the search addon functionality.\n */\nconst enum Constants {\n /**\n * Default maximum number of search results to highlight simultaneously. This limit prevents\n * performance degradation when searching for very common terms that would result in excessive\n * highlighting decorations.\n */\n DEFAULT_HIGHLIGHT_LIMIT = 1000\n}\n\nexport class SearchAddon extends Disposable implements ITerminalAddon, ISearchApi {\n private _terminal: Terminal | undefined;\n private _highlightLimit: number;\n private _highlightTimeout = this._register(new MutableDisposable());\n private _lineCache = this._register(new MutableDisposable());\n\n // Component instances\n private _state = new SearchState();\n private _engine: SearchEngine | undefined;\n private _decorationManager: DecorationManager | undefined;\n private _resultTracker = this._register(new SearchResultTracker());\n\n private readonly _onAfterSearch = this._register(new Emitter());\n public readonly onAfterSearch = this._onAfterSearch.event;\n private readonly _onBeforeSearch = this._register(new Emitter());\n public readonly onBeforeSearch = this._onBeforeSearch.event;\n\n public get onDidChangeResults(): IEvent {\n return this._resultTracker.onDidChangeResults;\n }\n\n constructor(options?: Partial) {\n super();\n\n this._highlightLimit = options?.highlightLimit ?? Constants.DEFAULT_HIGHLIGHT_LIMIT;\n }\n\n public activate(terminal: Terminal): void {\n this._terminal = terminal;\n this._lineCache.value = new SearchLineCache(terminal);\n this._engine = new SearchEngine(terminal, this._lineCache.value);\n this._decorationManager = new DecorationManager(terminal);\n this._register(this._terminal.onWriteParsed(() => this._updateMatches()));\n this._register(this._terminal.onResize(() => this._updateMatches()));\n this._register(toDisposable(() => this.clearDecorations()));\n }\n\n private _updateMatches(): void {\n this._highlightTimeout.clear();\n if (this._state.cachedSearchTerm && this._state.lastSearchOptions?.decorations) {\n this._highlightTimeout.value = disposableTimeout(() => {\n const term = this._state.cachedSearchTerm;\n this._state.clearCachedTerm();\n this.findPrevious(term!, { ...this._state.lastSearchOptions, incremental: true }, { noScroll: true });\n }, 200);\n }\n }\n\n public clearDecorations(retainCachedSearchTerm?: boolean): void {\n this._resultTracker.clearSelectedDecoration();\n this._decorationManager?.clearHighlightDecorations();\n this._resultTracker.clearResults();\n if (!retainCachedSearchTerm) {\n this._state.clearCachedTerm();\n }\n }\n\n public clearActiveDecoration(): void {\n this._resultTracker.clearSelectedDecoration();\n }\n\n /**\n * Find the next instance of the term, then scroll to and select it. If it\n * doesn't exist, do nothing.\n * @param term The search term.\n * @param searchOptions Search options.\n * @returns Whether a result was found.\n */\n public findNext(term: string, searchOptions?: ISearchOptions, internalSearchOptions?: IInternalSearchOptions): boolean {\n if (!this._terminal || !this._engine) {\n throw new Error('Cannot use addon until it has been loaded');\n }\n\n this._onBeforeSearch.fire();\n\n this._state.lastSearchOptions = searchOptions;\n\n if (this._state.shouldUpdateHighlighting(term, searchOptions)) {\n this._highlightAllMatches(term, searchOptions!);\n }\n\n const found = this._findNextAndSelect(term, searchOptions, internalSearchOptions);\n this._fireResults(searchOptions);\n this._state.cachedSearchTerm = term;\n\n this._onAfterSearch.fire();\n\n return found;\n }\n\n private _highlightAllMatches(term: string, searchOptions: ISearchOptions): void {\n if (!this._terminal || !this._engine || !this._decorationManager) {\n throw new Error('Cannot use addon until it has been loaded');\n }\n if (!this._state.isValidSearchTerm(term)) {\n this.clearDecorations();\n return;\n }\n\n // new search, clear out the old decorations\n this.clearDecorations(true);\n\n const results: ISearchResult[] = [];\n let prevResult: ISearchResult | undefined = undefined;\n let result = this._engine.find(term, 0, 0, searchOptions);\n\n while (result && (prevResult?.row !== result.row || prevResult?.col !== result.col)) {\n if (results.length >= this._highlightLimit) {\n break;\n }\n prevResult = result;\n results.push(prevResult);\n const cols = this._terminal.cols;\n let nextCol = prevResult.col + prevResult.size;\n let nextRow = prevResult.row;\n if (nextCol >= cols) {\n nextRow += Math.floor(nextCol / cols);\n nextCol = nextCol % cols;\n }\n result = this._engine.find(term, nextRow, nextCol, searchOptions);\n }\n\n this._resultTracker.updateResults(results, this._highlightLimit);\n if (searchOptions.decorations) {\n this._decorationManager.createHighlightDecorations(results, searchOptions.decorations);\n }\n }\n\n private _findNextAndSelect(term: string, searchOptions?: ISearchOptions, internalSearchOptions?: IInternalSearchOptions): boolean {\n if (!this._terminal || !this._engine) {\n return false;\n }\n if (!this._state.isValidSearchTerm(term)) {\n this._terminal.clearSelection();\n this.clearDecorations();\n return false;\n }\n\n const result = this._engine.findNextWithSelection(term, searchOptions, this._state.cachedSearchTerm);\n return this._selectResult(result, searchOptions?.decorations, internalSearchOptions?.noScroll);\n }\n\n /**\n * Find the previous instance of the term, then scroll to and select it. If it\n * doesn't exist, do nothing.\n * @param term The search term.\n * @param searchOptions Search options.\n * @returns Whether a result was found.\n */\n public findPrevious(term: string, searchOptions?: ISearchOptions, internalSearchOptions?: IInternalSearchOptions): boolean {\n if (!this._terminal || !this._engine) {\n throw new Error('Cannot use addon until it has been loaded');\n }\n\n this._onBeforeSearch.fire();\n\n this._state.lastSearchOptions = searchOptions;\n\n if (this._state.shouldUpdateHighlighting(term, searchOptions)) {\n this._highlightAllMatches(term, searchOptions!);\n }\n\n const found = this._findPreviousAndSelect(term, searchOptions, internalSearchOptions);\n this._fireResults(searchOptions);\n this._state.cachedSearchTerm = term;\n\n this._onAfterSearch.fire();\n\n return found;\n }\n\n private _fireResults(searchOptions?: ISearchOptions): void {\n this._resultTracker.fireResultsChanged(!!searchOptions?.decorations);\n }\n\n private _findPreviousAndSelect(term: string, searchOptions?: ISearchOptions, internalSearchOptions?: IInternalSearchOptions): boolean {\n if (!this._terminal || !this._engine) {\n return false;\n }\n if (!this._state.isValidSearchTerm(term)) {\n this._terminal.clearSelection();\n this.clearDecorations();\n return false;\n }\n\n const result = this._engine.findPreviousWithSelection(term, searchOptions, this._state.cachedSearchTerm);\n return this._selectResult(result, searchOptions?.decorations, internalSearchOptions?.noScroll);\n }\n\n /**\n * Selects and scrolls to a result.\n * @param result The result to select.\n * @returns Whether a result was selected.\n */\n private _selectResult(result: ISearchResult | undefined, options?: ISearchDecorationOptions, noScroll?: boolean): boolean {\n if (!this._terminal || !this._decorationManager) {\n return false;\n }\n\n this._resultTracker.clearSelectedDecoration();\n if (!result) {\n this._terminal.clearSelection();\n return false;\n }\n\n this._terminal.select(result.col, result.row, result.size);\n if (options) {\n const activeDecoration = this._decorationManager.createActiveDecoration(result, options);\n if (activeDecoration) {\n this._resultTracker.selectedDecoration = activeDecoration;\n }\n }\n\n if (!noScroll) {\n // If it is not in the viewport then we scroll else it just gets selected\n if (result.row >= (this._terminal.buffer.active.viewportY + this._terminal.rows) || result.row < this._terminal.buffer.active.viewportY) {\n let scroll = result.row - this._terminal.buffer.active.viewportY;\n scroll -= Math.floor(this._terminal.rows / 2);\n this._terminal.scrollLines(scroll);\n }\n }\n return true;\n }\n}\n"], ++ "mappings": ";;;;;;;;;;;;;;;;AAYO,SAASA,EAAaC,EAA6B,CACxD,MAAO,CAAE,QAASA,CAAG,CACvB,CAKO,SAASC,EAA+BC,EAA+C,CAC5F,GAAI,CAACA,EACH,OAAOA,EAET,GAAI,MAAM,QAAQA,CAAG,EAAG,CACtB,QAAWC,KAAKD,EACdC,EAAE,QAAQ,EAEZ,MAAO,CAAC,CACV,CACA,OAAAD,EAAI,QAAQ,EACLA,CACT,CAEO,SAASE,KAAsBC,EAAyC,CAC7E,OAAON,EAAa,IAAME,EAAQI,CAAW,CAAC,CAChD,CAEO,IAAMC,EAAN,KAA6C,CAA7C,cACL,KAAiB,aAAe,IAAI,IACpC,KAAQ,YAAc,GAEtB,IAAW,YAAsB,CAC/B,OAAO,KAAK,WACd,CAEO,IAA2BC,EAAS,CACzC,OAAI,KAAK,YACPA,EAAE,QAAQ,EAEV,KAAK,aAAa,IAAIA,CAAC,EAElBA,CACT,CAEO,SAAgB,CACrB,GAAI,MAAK,YAGT,MAAK,YAAc,GACnB,QAAWJ,KAAK,KAAK,aACnBA,EAAE,QAAQ,EAEZ,KAAK,aAAa,MAAM,EAC1B,CAEO,OAAc,CACnB,QAAWA,KAAK,KAAK,aACnBA,EAAE,QAAQ,EAEZ,KAAK,aAAa,MAAM,CAC1B,CACF,EAEsBK,EAAf,KAAiD,CAAjD,cAGL,KAAmB,OAAS,IAAIF,EAEzB,SAAgB,CACrB,KAAK,OAAO,QAAQ,CACtB,CAEU,UAAiCC,EAAS,CAClD,OAAO,KAAK,OAAO,IAAIA,CAAC,CAC1B,CACF,EAZsBC,EACG,KAAoB,OAAO,OAAO,CAAE,SAAU,CAAE,CAAE,CAAC,EAarE,IAAMC,EAAN,KAAsE,CAAtE,cAEL,KAAQ,YAAc,GAEtB,IAAW,OAAuB,CAChC,OAAO,KAAK,YAAc,OAAY,KAAK,MAC7C,CAEA,IAAW,MAAMC,EAAsB,CACjC,KAAK,aAAeA,IAAU,KAAK,SAGvC,KAAK,QAAQ,QAAQ,EACrB,KAAK,OAASA,EAChB,CAEO,OAAc,CACnB,KAAK,MAAQ,MACf,CAEO,SAAgB,CACrB,KAAK,YAAc,GACnB,KAAK,QAAQ,QAAQ,EACrB,KAAK,OAAS,MAChB,CACF,EClGO,IAAMC,EAAN,KAAiB,CAAjB,cACL,KAAQ,WAAqD,CAAC,EAC9D,KAAQ,UAAY,GAGpB,IAAW,OAAmB,CAC5B,OAAI,KAAK,OACA,KAAK,QAEd,KAAK,OAAS,CAACC,EAAyBC,EAAgBC,IAAkD,CACxG,GAAI,KAAK,UACP,OAAOC,EAAa,IAAM,CAAC,CAAC,EAG9B,IAAMC,EAAQ,CAAE,GAAIJ,EAAU,SAAAC,CAAS,EACvC,KAAK,WAAa,KAAK,WAAW,MAAM,EACxC,KAAK,WAAW,KAAKG,CAAK,EAE1B,IAAMC,EAASF,EAAa,IAAM,CAChC,IAAMG,EAAM,KAAK,WAAW,QAAQF,CAAK,EACrCE,IAAQ,KACV,KAAK,WAAa,KAAK,WAAW,MAAM,EACxC,KAAK,WAAW,OAAOA,EAAK,CAAC,EAEjC,CAAC,EAED,OAAIJ,IACE,MAAM,QAAQA,CAAW,EAC3BA,EAAY,KAAKG,CAAM,EAEvBH,EAAY,IAAIG,CAAM,GAInBA,CACT,EACO,KAAK,OACd,CAEO,KAAKE,EAAgB,CAC1B,GAAI,KAAK,WAAa,CAAC,KAAK,WAAW,OACrC,OAEF,GAAI,KAAK,WAAW,SAAW,EAAG,CAChC,KAAK,WAAW,CAAC,EAAE,GAAG,KAAK,KAAK,WAAW,CAAC,EAAE,SAAUA,CAAK,EAC7D,MACF,CACA,IAAMC,EAAY,KAAK,WACvB,QAASC,EAAI,EAAGC,EAAMF,EAAU,OAAQC,EAAIC,EAAK,EAAED,EACjDD,EAAUC,CAAC,EAAE,GAAG,KAAKD,EAAUC,CAAC,EAAE,SAAUF,CAAK,CAErD,CAEO,SAAgB,CACjB,KAAK,YAGT,KAAK,UAAY,GACjB,KAAK,WAAW,OAAS,EAC3B,CACF,EAEiBI,MAAV,CACE,SAASC,EAAWC,EAAiBC,EAA6B,CACvE,OAAOD,EAAKE,GAAKD,EAAG,KAAKC,CAAC,CAAC,CAC7B,CAFOJ,EAAS,QAAAC,EAIT,SAASI,EAAUT,EAAkBS,EAA6B,CACvE,MAAO,CAAChB,EAAyBC,EAAgBC,IACxCK,EAAME,GAAKT,EAAS,KAAKC,EAAUe,EAAIP,CAAC,CAAC,EAAG,OAAWP,CAAW,CAE7E,CAJOS,EAAS,IAAAK,EAQT,SAASC,KAAUC,EAAgC,CACxD,MAAO,CAAClB,EAAyBC,EAAgBC,IAAkD,CACjG,IAAMiB,EAAQ,IAAIC,EAClB,QAAWb,KAASW,EAClBC,EAAM,IAAIZ,EAAMQ,GAAKf,EAAS,KAAKC,EAAUc,CAAC,CAAC,CAAC,EAElD,OAAIb,IACE,MAAM,QAAQA,CAAW,EAC3BA,EAAY,KAAKiB,CAAK,EAEtBjB,EAAY,IAAIiB,CAAK,GAGlBA,CACT,CACF,CAfOR,EAAS,IAAAM,EAmBT,SAASI,EAAmBd,EAAkBe,EAAqCC,EAA0B,CAClH,OAAAD,EAAQC,CAAO,EACRhB,EAAMQ,GAAKO,EAAQP,CAAC,CAAC,CAC9B,CAHOJ,EAAS,gBAAAU,IAhCDV,IAAA,ICxDV,SAASa,EAAkBC,EAAqBC,EAAU,EAAGC,EAAsC,CACxG,IAAMC,EAAQ,WAAW,IAAM,CAC7BH,EAAQ,EACJE,GACFE,EAAW,QAAQ,CAEvB,EAAGH,CAAO,EACJG,EAAaC,EAAa,IAAM,CACpC,aAAaF,CAAK,CACpB,CAAC,EACD,OAAAD,GAAO,IAAIE,CAAU,EACdA,CACT,CCDO,IAAME,EAAN,cAA8BC,CAAW,CAa9C,YAA6BC,EAAqB,CAChD,MAAM,EADqB,eAAAA,EAN7B,KAAQ,mBAAqB,KAAK,UAAU,IAAIC,CAAmB,EACnE,KAAQ,uBAAyB,KAAK,UAAU,IAAIA,CAAmB,EAGvE,KAAQ,qBAAuB,EAI7B,KAAK,UAAUC,EAAa,IAAM,KAAK,mBAAmB,CAAC,CAAC,CAC9D,CAKO,gBAAuB,CACvB,KAAK,cACR,KAAK,YAAc,IAAI,MAAM,KAAK,UAAU,OAAO,OAAO,MAAM,EAChE,KAAK,uBAAuB,MAAQC,EAClC,KAAK,UAAU,WAAW,IAAM,KAAK,mBAAmB,CAAC,EACzD,KAAK,UAAU,aAAa,IAAM,KAAK,mBAAmB,CAAC,EAC3D,KAAK,UAAU,SAAS,IAAM,KAAK,mBAAmB,CAAC,CACzD,GAGF,KAAK,qBAAuB,KAAK,IAAI,EAChC,KAAK,mBAAmB,OAC3B,KAAK,2BAA2B,IAAkC,CAEtE,CAEQ,oBAA2B,CACjC,KAAK,YAAc,OACnB,KAAK,qBAAuB,EAC5B,KAAK,uBAAuB,MAAM,EAClC,KAAK,mBAAmB,MAAM,CAChC,CAEQ,2BAA2BC,EAAqB,CACtD,KAAK,mBAAmB,MAAQC,EAAkB,IAAM,CACtD,GAAI,CAAC,KAAK,YACR,OAGF,IAAMC,EADM,KAAK,IAAI,EACC,KAAK,qBAC3B,GAAIA,GAAW,KAAoC,CACjD,KAAK,mBAAmB,EACxB,MACF,CACA,KAAK,2BAA2B,KAAqCA,CAAO,CAC9E,EAAGF,CAAK,CACV,CAEO,iBAAiBG,EAAyC,CAC/D,OAAO,KAAK,cAAcA,CAAG,CAC/B,CAEO,eAAeA,EAAaC,EAA6B,CAC1D,KAAK,cACP,KAAK,YAAYD,CAAG,EAAIC,EAE5B,CAUO,oCAAoCC,EAAmBC,EAAoC,CAChG,IAAMC,EAAU,CAAC,EACXC,EAAc,CAAC,CAAC,EAClBC,EAAO,KAAK,UAAU,OAAO,OAAO,QAAQJ,CAAS,EACzD,KAAOI,GAAM,CACX,IAAMC,EAAW,KAAK,UAAU,OAAO,OAAO,QAAQL,EAAY,CAAC,EAC7DM,EAAkBD,EAAWA,EAAS,UAAY,GACpDE,EAASH,EAAK,kBAAkB,CAACE,GAAmBL,CAAS,EACjE,GAAIK,GAAmBD,EAAU,CAC/B,IAAMG,EAAWJ,EAAK,QAAQA,EAAK,OAAS,CAAC,EACtBI,GAAYA,EAAS,QAAQ,IAAM,GAAKA,EAAS,SAAS,IAAM,GAEjEH,EAAS,QAAQ,CAAC,GAAG,SAAS,IAAM,IACxDE,EAASA,EAAO,MAAM,EAAG,EAAE,EAE/B,CAEA,GADAL,EAAQ,KAAKK,CAAM,EACfD,EACFH,EAAY,KAAKA,EAAYA,EAAY,OAAS,CAAC,EAAII,EAAO,MAAM,MAEpE,OAEFP,IACAI,EAAOC,CACT,CACA,MAAO,CAACH,EAAQ,KAAK,EAAE,EAAGC,CAAW,CACvC,CACF,EC5HO,IAAMM,EAAN,KAAkB,CAOvB,IAAW,kBAAuC,CAChD,OAAO,KAAK,iBACd,CAKA,IAAW,iBAAiBC,EAA0B,CACpD,KAAK,kBAAoBA,CAC3B,CAKA,IAAW,mBAAgD,CACzD,OAAO,KAAK,kBACd,CAKA,IAAW,kBAAkBC,EAAqC,CAChE,KAAK,mBAAqBA,CAC5B,CAOO,kBAAkBD,EAAuB,CAC9C,MAAO,CAAC,EAAEA,GAAQA,EAAK,OAAS,EAClC,CAOO,iBAAiBE,EAAsC,CAC5D,OAAK,KAAK,mBAGLA,EAGD,KAAK,mBAAmB,gBAAkBA,EAAW,eAGrD,KAAK,mBAAmB,QAAUA,EAAW,OAG7C,KAAK,mBAAmB,YAAcA,EAAW,UAR5C,GAHA,EAeX,CAQO,yBAAyBF,EAAcC,EAAmC,CAC/E,OAAKA,GAAS,YAGP,KAAK,oBAAsB,QAC3BD,IAAS,KAAK,mBACd,KAAK,iBAAiBC,CAAO,EAJ3B,EAKX,CAKO,iBAAwB,CAC7B,KAAK,kBAAoB,MAC3B,CAKO,OAAc,CACnB,KAAK,kBAAoB,OACzB,KAAK,mBAAqB,MAC5B,CACF,EC9DO,IAAME,EAAN,KAAmB,CACxB,YACmBC,EACAC,EACjB,CAFiB,eAAAD,EACA,gBAAAC,CAChB,CAUI,KAAKC,EAAcC,EAAkBC,EAAkBC,EAA2D,CACvH,GAAI,CAACH,GAAQA,EAAK,SAAW,EAAG,CAC9B,KAAK,UAAU,eAAe,EAC9B,MACF,CACA,GAAIE,GAAY,KAAK,UAAU,KAC7B,MAAM,IAAI,MAAM,gBAAgBA,CAAQ,6BAA6B,KAAK,UAAU,IAAI,OAAO,EAGjG,KAAK,WAAW,eAAe,EAE/B,IAAME,EAAkC,CACtC,SAAAH,EACA,SAAAC,CACF,EAGIG,EAAS,KAAK,YAAYL,EAAMI,EAAgBD,CAAa,EAEjE,GAAI,CAACE,EACH,QAASC,EAAIL,EAAW,EAAGK,EAAI,KAAK,UAAU,OAAO,OAAO,MAAQ,KAAK,UAAU,MAC7E,QAAK,yBAAyBA,EAAGH,CAAa,IAGlDC,EAAe,SAAWE,EAC1BF,EAAe,SAAW,EAC1BC,EAAS,KAAK,YAAYL,EAAMI,EAAgBD,CAAa,EACzDE,IAPmFC,IACvF,CAWJ,OAAOD,CACT,CASO,sBAAsBL,EAAcG,EAAgCI,EAAsD,CAC/H,GAAI,CAACP,GAAQA,EAAK,SAAW,EAAG,CAC9B,KAAK,UAAU,eAAe,EAC9B,MACF,CAEA,IAAMQ,EAAkB,KAAK,UAAU,qBAAqB,EAC5D,KAAK,UAAU,eAAe,EAE9B,IAAIN,EAAW,EACXD,EAAW,EACXO,IACED,IAAqBP,GACvBE,EAAWM,EAAgB,IAAI,EAC/BP,EAAWO,EAAgB,IAAI,IAE/BN,EAAWM,EAAgB,MAAM,EACjCP,EAAWO,EAAgB,MAAM,IAIrC,KAAK,WAAW,eAAe,EAE/B,IAAMJ,EAAkC,CACtC,SAAAH,EACA,SAAAC,CACF,EAGIG,EAAS,KAAK,YAAYL,EAAMI,EAAgBD,CAAa,EAEjE,GAAI,CAACE,EACH,QAASC,EAAIL,EAAW,EAAGK,EAAI,KAAK,UAAU,OAAO,OAAO,MAAQ,KAAK,UAAU,MAC7E,QAAK,yBAAyBA,EAAGH,CAAa,IAGlDC,EAAe,SAAWE,EAC1BF,EAAe,SAAW,EAC1BC,EAAS,KAAK,YAAYL,EAAMI,EAAgBD,CAAa,EACzDE,IAPmFC,IACvF,CAYJ,GAAI,CAACD,GAAUJ,IAAa,EAC1B,QAASK,EAAI,EAAGA,EAAIL,GACd,QAAK,yBAAyBK,EAAGH,CAAa,IAGlDC,EAAe,SAAWE,EAC1BF,EAAe,SAAW,EAC1BC,EAAS,KAAK,YAAYL,EAAMI,EAAgBD,CAAa,EACzDE,IAPwBC,IAC5B,CAaJ,MAAI,CAACD,GAAUG,IACbJ,EAAe,SAAWI,EAAgB,MAAM,EAChDJ,EAAe,SAAW,EAC1BC,EAAS,KAAK,YAAYL,EAAMI,EAAgBD,CAAa,GAGxDE,CACT,CASO,0BAA0BL,EAAcG,EAAgCI,EAAsD,CACnI,GAAI,CAACP,GAAQA,EAAK,SAAW,EAAG,CAC9B,KAAK,UAAU,eAAe,EAC9B,MACF,CAEA,IAAMQ,EAAkB,KAAK,UAAU,qBAAqB,EAC5D,KAAK,UAAU,eAAe,EAE9B,IAAIP,EAAW,KAAK,UAAU,OAAO,OAAO,MAAQ,KAAK,UAAU,KAAO,EACpEC,EAAW,KAAK,UAAU,KAC1BO,EAAkB,GAExB,KAAK,WAAW,eAAe,EAC/B,IAAML,EAAkC,CACtC,SAAAH,EACA,SAAAC,CACF,EAEIG,EAkBJ,GAjBIG,IACFJ,EAAe,SAAWH,EAAWO,EAAgB,MAAM,EAC3DJ,EAAe,SAAWI,EAAgB,MAAM,EAC5CD,IAAqBP,IAEvBK,EAAS,KAAK,YAAYL,EAAMI,EAAgBD,EAAe,EAAK,EAC/DE,IAEHD,EAAe,SAAWH,EAAWO,EAAgB,IAAI,EACzDJ,EAAe,SAAWI,EAAgB,IAAI,KAKpDH,IAAW,KAAK,YAAYL,EAAMI,EAAgBD,EAAeM,CAAe,EAG5E,CAACJ,EAAQ,CACXD,EAAe,SAAW,KAAK,IAAIA,EAAe,SAAU,KAAK,UAAU,IAAI,EAC/E,QAASE,EAAIL,EAAW,EAAGK,GAAK,IAC9BF,EAAe,SAAWE,EAC1BD,EAAS,KAAK,YAAYL,EAAMI,EAAgBD,EAAeM,CAAe,EAC1E,CAAAJ,GAH6BC,IAGjC,CAIJ,CAEA,GAAI,CAACD,GAAUJ,IAAc,KAAK,UAAU,OAAO,OAAO,MAAQ,KAAK,UAAU,KAAO,EACtF,QAASK,EAAK,KAAK,UAAU,OAAO,OAAO,MAAQ,KAAK,UAAU,KAAO,EAAIA,GAAKL,IAChFG,EAAe,SAAWE,EAC1BD,EAAS,KAAK,YAAYL,EAAMI,EAAgBD,EAAeM,CAAe,EAC1E,CAAAJ,GAHsFC,IAG1F,CAMJ,OAAOD,CACT,CASQ,aAAaK,EAAqBC,EAAcX,EAAuB,CAC7E,OAASU,IAAgB,GAAO,qCAA8B,SAASC,EAAKD,EAAc,CAAC,CAAC,KACvFA,EAAcV,EAAK,SAAYW,EAAK,QAAY,qCAA8B,SAASA,EAAKD,EAAcV,EAAK,MAAM,CAAC,EAC7H,CAQQ,yBAAyBY,EAAaT,EAAyC,CACrF,OAAIA,GAAe,OAASA,GAAe,UAClC,GAEF,KAAK,UAAU,OAAO,OAAO,QAAQS,CAAG,GAAG,YAAc,EAClE,CAcQ,YAAYZ,EAAcI,EAAiCD,EAAgC,CAAC,EAAGM,EAA2B,GAAkC,CAIlK,KAAO,KAAK,UAAU,OAAO,OAAO,QAAQL,EAAe,QAAQ,GAAG,WAAW,CAE/E,GADAA,EAAe,UAAY,KAAK,UAAU,KACtCK,EACF,OAEFL,EAAe,UACjB,CACA,IAAMQ,EAAMR,EAAe,SACrBS,EAAMT,EAAe,SAEvBU,EAAQ,KAAK,WAAW,iBAAiBF,CAAG,EAC3CE,IACHA,EAAQ,KAAK,WAAW,oCAAoCF,EAAK,EAAI,EACrE,KAAK,WAAW,eAAeA,EAAKE,CAAK,GAE3C,GAAM,CAACC,EAAYC,CAAO,EAAIF,EAExBG,EAAS,KAAK,0BAA0BL,EAAKC,CAAG,EAClDK,EAAalB,EACbmB,EAAmBJ,EAClBZ,EAAc,QACjBe,EAAaf,EAAc,cAAgBH,EAAOA,EAAK,YAAY,EACnEmB,EAAmBhB,EAAc,cAAgBY,EAAaA,EAAW,YAAY,GAGvF,IAAIK,EAAc,GAClB,GAAIjB,EAAc,MAAO,CACvB,IAAMkB,EAAc,OAAOH,EAAYf,EAAc,cAAgB,IAAM,IAAI,EAC3EmB,EACJ,GAAIb,EAEF,KAAOa,EAAYD,EAAY,KAAKF,EAAiB,MAAM,EAAGF,CAAM,CAAC,GACnEG,EAAcC,EAAY,UAAYC,EAAU,CAAC,EAAE,OACnDtB,EAAOsB,EAAU,CAAC,EAClBD,EAAY,WAAcrB,EAAK,OAAS,OAG1CsB,EAAYD,EAAY,KAAKF,EAAiB,MAAMF,CAAM,CAAC,EACvDK,GAAaA,EAAU,CAAC,EAAE,OAAS,IACrCF,EAAcH,GAAUI,EAAY,UAAYC,EAAU,CAAC,EAAE,QAC7DtB,EAAOsB,EAAU,CAAC,EAGxB,MACMb,EACEQ,EAASC,EAAW,QAAU,IAChCE,EAAcD,EAAiB,YAAYD,EAAYD,EAASC,EAAW,MAAM,GAGnFE,EAAcD,EAAiB,QAAQD,EAAYD,CAAM,EAI7D,GAAIG,GAAe,EAAG,CACpB,GAAIjB,EAAc,WAAa,CAAC,KAAK,aAAaiB,EAAaD,EAAkBnB,CAAI,EACnF,OAKF,IAAIuB,EAAiB,EACrB,KAAOA,EAAiBP,EAAQ,OAAS,GAAKI,GAAeJ,EAAQO,EAAiB,CAAC,GACrFA,IAEF,IAAIC,EAAeD,EACnB,KAAOC,EAAeR,EAAQ,OAAS,GAAKI,EAAcpB,EAAK,QAAUgB,EAAQQ,EAAe,CAAC,GAC/FA,IAEF,IAAMC,EAAiBL,EAAcJ,EAAQO,CAAc,EACrDG,EAAeN,EAAcpB,EAAK,OAASgB,EAAQQ,CAAY,EAC/DG,EAAgB,KAAK,0BAA0Bf,EAAMW,EAAgBE,CAAc,EAEnFG,EADc,KAAK,0BAA0BhB,EAAMY,EAAcE,CAAY,EACxDC,EAAgB,KAAK,UAAU,MAAQH,EAAeD,GAEjF,MAAO,CACL,KAAAvB,EACA,IAAK2B,EACL,IAAKf,EAAMW,EACX,KAAAK,CACF,CACF,CACF,CAEQ,0BAA0BhB,EAAaK,EAAwB,CACrE,IAAMN,EAAO,KAAK,UAAU,OAAO,OAAO,QAAQC,CAAG,EACrD,GAAI,CAACD,EACH,MAAO,GAET,QAASkB,EAAI,EAAGA,EAAIZ,EAAQY,IAAK,CAC/B,IAAMC,EAAOnB,EAAK,QAAQkB,CAAC,EAC3B,GAAI,CAACC,EACH,MAGF,IAAMC,EAAOD,EAAK,SAAS,EACvBC,EAAK,OAAS,IAChBd,GAAUc,EAAK,OAAS,GAI1B,IAAMC,EAAWrB,EAAK,QAAQkB,EAAI,CAAC,EAC/BG,GAAYA,EAAS,SAAS,IAAM,GACtCf,GAEJ,CACA,OAAOA,CACT,CAEQ,0BAA0BhB,EAAkBgC,EAAsB,CACxE,IAAIC,EAAYjC,EACZgB,EAAS,EACTN,EAAO,KAAK,UAAU,OAAO,OAAO,QAAQuB,CAAS,EACzD,KAAOD,EAAO,GAAKtB,GAAM,CACvB,QAASkB,EAAI,EAAGA,EAAII,GAAQJ,EAAI,KAAK,UAAU,KAAMA,IAAK,CACxD,IAAMC,EAAOnB,EAAK,QAAQkB,CAAC,EAC3B,GAAI,CAACC,EACH,MAEEA,EAAK,SAAS,IAEhBb,GAAUa,EAAK,QAAQ,IAAM,EAAI,EAAIA,EAAK,SAAS,EAAE,OAEzD,CAGA,GAFAI,IACAvB,EAAO,KAAK,UAAU,OAAO,OAAO,QAAQuB,CAAS,EACjDvB,GAAQ,CAACA,EAAK,UAChB,MAEFsB,GAAQ,KAAK,UAAU,IACzB,CACA,OAAOhB,CACT,CACF,EC3XO,IAAMkB,EAAN,cAAgCC,CAAW,CAIhD,YAA6BC,EAAqB,CAChD,MAAM,EADqB,eAAAA,EAH7B,KAAQ,sBAAsC,CAAC,EAC/C,KAAQ,kBAAiC,IAAI,IAI3C,KAAK,UAAUC,EAAa,IAAM,KAAK,0BAA0B,CAAC,CAAC,CACrE,CAOO,2BAA2BC,EAA0BC,EAAyC,CACnG,KAAK,0BAA0B,EAE/B,QAAWC,KAASF,EAAS,CAC3B,IAAMG,EAAc,KAAK,yBAAyBD,EAAOD,EAAS,EAAK,EACvE,GAAIE,EACF,QAAWC,KAAcD,EACvB,KAAK,iBAAiBC,EAAYF,CAAK,CAG7C,CACF,CAQO,uBAAuBG,EAAuBJ,EAAgE,CACnH,IAAME,EAAc,KAAK,yBAAyBE,EAAQJ,EAAS,EAAI,EACvE,GAAIE,EACF,MAAO,CAAE,YAAAA,EAAa,MAAOE,EAAQ,SAAU,CAAEC,EAAQH,CAAW,CAAG,CAAE,CAG7E,CAKO,2BAAkC,CACvCG,EAAQ,KAAK,qBAAqB,EAClC,KAAK,sBAAwB,CAAC,EAC9B,KAAK,kBAAkB,MAAM,CAC/B,CAOQ,iBAAiBF,EAAyBF,EAA4B,CAC5E,KAAK,kBAAkB,IAAIE,EAAW,OAAO,IAAI,EACjD,KAAK,sBAAsB,KAAK,CAAE,WAAAA,EAAY,MAAAF,EAAO,SAAU,CAAEE,EAAW,QAAQ,CAAG,CAAE,CAAC,CAC5F,CAQQ,aAAaG,EAAsBC,EAAiCC,EAA+B,CACpGF,EAAQ,UAAU,SAAS,8BAA8B,IAC5DA,EAAQ,UAAU,IAAI,8BAA8B,EAChDC,IACFD,EAAQ,MAAM,QAAU,aAAaC,CAAW,KAGhDC,GACFF,EAAQ,UAAU,IAAI,qCAAqC,CAE/D,CASQ,yBAAyBF,EAAuBJ,EAAmCQ,EAAoD,CAE7I,IAAMC,EAA+C,CAAC,EAClDC,EAAaN,EAAO,IACpBO,EAAgBP,EAAO,KACvBQ,EAAe,CAAC,KAAK,UAAU,OAAO,OAAO,MAAQ,KAAK,UAAU,OAAO,OAAO,QAAUR,EAAO,IACvG,KAAOO,EAAgB,GAAG,CACxB,IAAME,EAAgB,KAAK,IAAI,KAAK,UAAU,KAAOH,EAAYC,CAAa,EAC9EF,EAAiB,KAAK,CAACG,EAAcF,EAAYG,CAAa,CAAC,EAC/DH,EAAa,EACbC,GAAiBE,EACjBD,GACF,CAGA,IAAMV,EAA6B,CAAC,EACpC,QAAWY,KAASL,EAAkB,CACpC,IAAMM,EAAS,KAAK,UAAU,eAAeD,EAAM,CAAC,CAAC,EAC/CX,EAAa,KAAK,UAAU,mBAAmB,CACnD,OAAAY,EACA,EAAGD,EAAM,CAAC,EACV,MAAOA,EAAM,CAAC,EACd,MAAON,EAAiB,MAAQ,SAChC,gBAAiBA,EAAiBR,EAAQ,sBAAwBA,EAAQ,gBAC1E,qBAAsB,KAAK,kBAAkB,IAAIe,EAAO,IAAI,EAAI,OAAY,CAC1E,MAAOP,EAAiBR,EAAQ,8BAAgCA,EAAQ,mBACxE,SAAU,QACZ,CACF,CAAC,EACD,GAAIG,EAAY,CACd,IAAMa,EAA6B,CAAC,EACpCA,EAAY,KAAKD,CAAM,EACvBC,EAAY,KAAKb,EAAW,SAAUc,GAAM,KAAK,aAAaA,EAAGT,EAAiBR,EAAQ,kBAAoBA,EAAQ,YAAa,EAAK,CAAC,CAAC,EAC1IgB,EAAY,KAAKb,EAAW,UAAU,IAAME,EAAQW,CAAW,CAAC,CAAC,EACjEd,EAAY,KAAKC,CAAU,CAC7B,CACF,CAEA,OAAOD,EAAY,SAAW,EAAI,OAAYA,CAChD,CACF,ECrIO,IAAMgB,EAAN,cAAkCC,CAAW,CAA7C,kCACL,KAAQ,eAAkC,CAAC,EAG3C,KAAiB,oBAAsB,KAAK,UAAU,IAAIC,CAAmC,EAC7F,IAAW,oBAAuD,CAAE,OAAO,KAAK,oBAAoB,KAAO,CAK3G,IAAW,eAA8C,CACvD,OAAO,KAAK,cACd,CAKA,IAAW,oBAAsD,CAC/D,OAAO,KAAK,mBACd,CAKA,IAAW,mBAAmBC,EAA6C,CACzE,KAAK,oBAAsBA,CAC7B,CAOO,cAAcC,EAA0BC,EAA0B,CACvE,KAAK,eAAiBD,EAAQ,MAAM,EAAGC,CAAU,CACnD,CAKO,cAAqB,CAC1B,KAAK,eAAiB,CAAC,CACzB,CAKO,yBAAgC,CACjC,KAAK,sBACP,KAAK,oBAAoB,QAAQ,EACjC,KAAK,oBAAsB,OAE/B,CAOO,gBAAgBC,EAA+B,CACpD,QAASC,EAAI,EAAGA,EAAI,KAAK,eAAe,OAAQA,IAAK,CACnD,IAAMC,EAAQ,KAAK,eAAeD,CAAC,EACnC,GAAIC,EAAM,MAAQF,EAAO,KAAOE,EAAM,MAAQF,EAAO,KAAOE,EAAM,OAASF,EAAO,KAChF,OAAOC,CAEX,CACA,MAAO,EACT,CAMO,mBAAmBE,EAA+B,CACvD,GAAI,CAACA,EACH,OAGF,IAAIC,EAAc,GACd,KAAK,sBACPA,EAAc,KAAK,gBAAgB,KAAK,oBAAoB,KAAK,GAGnE,KAAK,oBAAoB,KAAK,CAC5B,YAAAA,EACA,YAAa,KAAK,eAAe,MACnC,CAAC,CACH,CAKO,OAAc,CACnB,KAAK,wBAAwB,EAC7B,KAAK,aAAa,CACpB,CACF,ECtFO,IAAMC,EAAN,cAA0BC,CAAiD,CAqBhF,YAAYC,EAAwC,CAClD,MAAM,EAnBR,KAAQ,kBAAoB,KAAK,UAAU,IAAIC,CAAgC,EAC/E,KAAQ,WAAa,KAAK,UAAU,IAAIA,CAAoC,EAG5E,KAAQ,OAAS,IAAIC,EAGrB,KAAQ,eAAiB,KAAK,UAAU,IAAIC,CAAqB,EAEjE,KAAiB,eAAiB,KAAK,UAAU,IAAIC,CAAe,EACpE,KAAgB,cAAgB,KAAK,eAAe,MACpD,KAAiB,gBAAkB,KAAK,UAAU,IAAIA,CAAe,EACrE,KAAgB,eAAiB,KAAK,gBAAgB,MASpD,KAAK,gBAAkBJ,GAAS,gBAAkB,GACpD,CARA,IAAW,oBAAuD,CAChE,OAAO,KAAK,eAAe,kBAC7B,CAQO,SAASK,EAA0B,CACxC,KAAK,UAAYA,EACjB,KAAK,WAAW,MAAQ,IAAIC,EAAgBD,CAAQ,EACpD,KAAK,QAAU,IAAIE,EAAaF,EAAU,KAAK,WAAW,KAAK,EAC/D,KAAK,mBAAqB,IAAIG,EAAkBH,CAAQ,EACxD,KAAK,UAAU,KAAK,UAAU,cAAc,IAAM,KAAK,eAAe,CAAC,CAAC,EACxE,KAAK,UAAU,KAAK,UAAU,SAAS,IAAM,KAAK,eAAe,CAAC,CAAC,EACnE,KAAK,UAAUI,EAAa,IAAM,KAAK,iBAAiB,CAAC,CAAC,CAC5D,CAEQ,gBAAuB,CAC7B,KAAK,kBAAkB,MAAM,EACzB,KAAK,OAAO,kBAAoB,KAAK,OAAO,mBAAmB,cACjE,KAAK,kBAAkB,MAAQC,EAAkB,IAAM,CACrD,IAAMC,EAAO,KAAK,OAAO,iBACzB,KAAK,OAAO,gBAAgB,EAC5B,KAAK,aAAaA,EAAO,CAAE,GAAG,KAAK,OAAO,kBAAmB,YAAa,EAAK,EAAG,CAAE,SAAU,EAAK,CAAC,CACtG,EAAG,GAAG,EAEV,CAEO,iBAAiBC,EAAwC,CAC9D,KAAK,eAAe,wBAAwB,EAC5C,KAAK,oBAAoB,0BAA0B,EACnD,KAAK,eAAe,aAAa,EAC5BA,GACH,KAAK,OAAO,gBAAgB,CAEhC,CAEO,uBAA8B,CACnC,KAAK,eAAe,wBAAwB,CAC9C,CASO,SAASD,EAAcE,EAAgCC,EAAyD,CACrH,GAAI,CAAC,KAAK,WAAa,CAAC,KAAK,QAC3B,MAAM,IAAI,MAAM,2CAA2C,EAG7D,KAAK,gBAAgB,KAAK,EAE1B,KAAK,OAAO,kBAAoBD,EAE5B,KAAK,OAAO,yBAAyBF,EAAME,CAAa,GAC1D,KAAK,qBAAqBF,EAAME,CAAc,EAGhD,IAAME,EAAQ,KAAK,mBAAmBJ,EAAME,EAAeC,CAAqB,EAChF,YAAK,aAAaD,CAAa,EAC/B,KAAK,OAAO,iBAAmBF,EAE/B,KAAK,eAAe,KAAK,EAElBI,CACT,CAEQ,qBAAqBJ,EAAcE,EAAqC,CAC9E,GAAI,CAAC,KAAK,WAAa,CAAC,KAAK,SAAW,CAAC,KAAK,mBAC5C,MAAM,IAAI,MAAM,2CAA2C,EAE7D,GAAI,CAAC,KAAK,OAAO,kBAAkBF,CAAI,EAAG,CACxC,KAAK,iBAAiB,EACtB,MACF,CAGA,KAAK,iBAAiB,EAAI,EAE1B,IAAMK,EAA2B,CAAC,EAC9BC,EACAC,EAAS,KAAK,QAAQ,KAAKP,EAAM,EAAG,EAAGE,CAAa,EAExD,KAAOK,IAAWD,GAAY,MAAQC,EAAO,KAAOD,GAAY,MAAQC,EAAO,MACzE,EAAAF,EAAQ,QAAU,KAAK,kBADwD,CAInFC,EAAaC,EACbF,EAAQ,KAAKC,CAAU,EACvB,IAAME,EAAO,KAAK,UAAU,KACxBC,EAAUH,EAAW,IAAMA,EAAW,KACtCI,EAAUJ,EAAW,IACrBG,GAAWD,IACbE,GAAW,KAAK,MAAMD,EAAUD,CAAI,EACpCC,EAAUA,EAAUD,GAEtBD,EAAS,KAAK,QAAQ,KAAKP,EAAMU,EAASD,EAASP,CAAa,CAClE,CAEA,KAAK,eAAe,cAAcG,EAAS,KAAK,eAAe,EAC3DH,EAAc,aAChB,KAAK,mBAAmB,2BAA2BG,EAASH,EAAc,WAAW,CAEzF,CAEQ,mBAAmBF,EAAcE,EAAgCC,EAAyD,CAChI,GAAI,CAAC,KAAK,WAAa,CAAC,KAAK,QAC3B,MAAO,GAET,GAAI,CAAC,KAAK,OAAO,kBAAkBH,CAAI,EACrC,YAAK,UAAU,eAAe,EAC9B,KAAK,iBAAiB,EACf,GAGT,IAAMO,EAAS,KAAK,QAAQ,sBAAsBP,EAAME,EAAe,KAAK,OAAO,gBAAgB,EACnG,OAAO,KAAK,cAAcK,EAAQL,GAAe,YAAaC,GAAuB,QAAQ,CAC/F,CASO,aAAaH,EAAcE,EAAgCC,EAAyD,CACzH,GAAI,CAAC,KAAK,WAAa,CAAC,KAAK,QAC3B,MAAM,IAAI,MAAM,2CAA2C,EAG7D,KAAK,gBAAgB,KAAK,EAE1B,KAAK,OAAO,kBAAoBD,EAE5B,KAAK,OAAO,yBAAyBF,EAAME,CAAa,GAC1D,KAAK,qBAAqBF,EAAME,CAAc,EAGhD,IAAME,EAAQ,KAAK,uBAAuBJ,EAAME,EAAeC,CAAqB,EACpF,YAAK,aAAaD,CAAa,EAC/B,KAAK,OAAO,iBAAmBF,EAE/B,KAAK,eAAe,KAAK,EAElBI,CACT,CAEQ,aAAaF,EAAsC,CACzD,KAAK,eAAe,mBAAmB,CAAC,CAACA,GAAe,WAAW,CACrE,CAEQ,uBAAuBF,EAAcE,EAAgCC,EAAyD,CACpI,GAAI,CAAC,KAAK,WAAa,CAAC,KAAK,QAC3B,MAAO,GAET,GAAI,CAAC,KAAK,OAAO,kBAAkBH,CAAI,EACrC,YAAK,UAAU,eAAe,EAC9B,KAAK,iBAAiB,EACf,GAGT,IAAMO,EAAS,KAAK,QAAQ,0BAA0BP,EAAME,EAAe,KAAK,OAAO,gBAAgB,EACvG,OAAO,KAAK,cAAcK,EAAQL,GAAe,YAAaC,GAAuB,QAAQ,CAC/F,CAOQ,cAAcI,EAAmClB,EAAoCsB,EAA6B,CACxH,GAAI,CAAC,KAAK,WAAa,CAAC,KAAK,mBAC3B,MAAO,GAIT,GADA,KAAK,eAAe,wBAAwB,EACxC,CAACJ,EACH,YAAK,UAAU,eAAe,EACvB,GAIT,GADA,KAAK,UAAU,OAAOA,EAAO,IAAKA,EAAO,IAAKA,EAAO,IAAI,EACrDlB,EAAS,CACX,IAAMuB,EAAmB,KAAK,mBAAmB,uBAAuBL,EAAQlB,CAAO,EACnFuB,IACF,KAAK,eAAe,mBAAqBA,EAE7C,CAEA,GAAI,CAACD,IAECJ,EAAO,KAAQ,KAAK,UAAU,OAAO,OAAO,UAAY,KAAK,UAAU,MAASA,EAAO,IAAM,KAAK,UAAU,OAAO,OAAO,WAAW,CACvI,IAAIM,EAASN,EAAO,IAAM,KAAK,UAAU,OAAO,OAAO,UACvDM,GAAU,KAAK,MAAM,KAAK,UAAU,KAAO,CAAC,EAC5C,KAAK,UAAU,YAAYA,CAAM,CACnC,CAEF,MAAO,EACT,CACF", "names": ["toDisposable", "fn", "dispose", "arg", "d", "combinedDisposable", "disposables", "DisposableStore", "o", "Disposable", "MutableDisposable", "value", "Emitter", "listener", "thisArgs", "disposables", "toDisposable", "entry", "result", "idx", "event", "listeners", "i", "len", "EventUtils", "forward", "from", "to", "e", "map", "any", "events", "store", "DisposableStore", "runAndSubscribe", "handler", "initial", "disposableTimeout", "handler", "timeout", "store", "timer", "disposable", "toDisposable", "SearchLineCache", "Disposable", "_terminal", "MutableDisposable", "toDisposable", "combinedDisposable", "delay", "disposableTimeout", "elapsed", "row", "entry", "lineIndex", "trimRight", "strings", "lineOffsets", "line", "nextLine", "lineWrapsToNext", "string", "lastCell", "SearchState", "term", "options", "newOptions", "SearchEngine", "_terminal", "_lineCache", "term", "startRow", "startCol", "searchOptions", "searchPosition", "result", "y", "cachedSearchTerm", "prevSelectedPos", "isReverseSearch", "searchIndex", "line", "row", "col", "cache", "stringLine", "offsets", "offset", "searchTerm", "searchStringLine", "resultIndex", "searchRegex", "foundTerm", "startRowOffset", "endRowOffset", "startColOffset", "endColOffset", "startColIndex", "size", "i", "cell", "char", "nextCell", "cols", "lineIndex", "DecorationManager", "Disposable", "_terminal", "toDisposable", "results", "options", "match", "decorations", "decoration", "result", "dispose", "element", "borderColor", "isActiveResult", "decorationRanges", "currentCol", "remainingSize", "markerOffset", "amountThisRow", "range", "marker", "disposables", "e", "SearchResultTracker", "Disposable", "Emitter", "decoration", "results", "maxResults", "result", "i", "match", "hasDecorations", "resultIndex", "SearchAddon", "Disposable", "options", "MutableDisposable", "SearchState", "SearchResultTracker", "Emitter", "terminal", "SearchLineCache", "SearchEngine", "DecorationManager", "toDisposable", "disposableTimeout", "term", "retainCachedSearchTerm", "searchOptions", "internalSearchOptions", "found", "results", "prevResult", "result", "cols", "nextCol", "nextRow", "noScroll", "activeDecoration", "scroll"] } diff --git a/src/SearchEngine.ts b/src/SearchEngine.ts -index 1760bc2bd1fd274d23e2032fde631b39c739f0d9..f856f1f9444a13d29fcbd2f264b0c2bfbf33db1c 100644 +index 1760bc2bd1fd274d23e2032fde631b39c739f0d9..4ce664a7b913c5c19d6bbf7feba92cbdaef38c6f 100644 --- a/src/SearchEngine.ts +++ b/src/SearchEngine.ts -@@ -250,23 +250,19 @@ export class SearchEngine { +@@ -76,6 +76,9 @@ export class SearchEngine { + // Search from startRow + 1 to end + if (!result) { + for (let y = startRow + 1; y < this._terminal.buffer.active.baseY + this._terminal.rows; y++) { ++ if (this._isRowCoveredByLineStart(y, searchOptions)) { ++ continue; ++ } + searchPosition.startRow = y; + searchPosition.startCol = 0; + result = this._findInLine(term, searchPosition, searchOptions); +@@ -127,6 +130,9 @@ export class SearchEngine { + // Search from startRow + 1 to end + if (!result) { + for (let y = startRow + 1; y < this._terminal.buffer.active.baseY + this._terminal.rows; y++) { ++ if (this._isRowCoveredByLineStart(y, searchOptions)) { ++ continue; ++ } + searchPosition.startRow = y; + searchPosition.startCol = 0; + result = this._findInLine(term, searchPosition, searchOptions); +@@ -138,6 +144,9 @@ export class SearchEngine { + // If we hit the bottom and didn't search from the very top wrap back up + if (!result && startRow !== 0) { + for (let y = 0; y < startRow; y++) { ++ if (this._isRowCoveredByLineStart(y, searchOptions)) { ++ continue; ++ } + searchPosition.startRow = y; + searchPosition.startCol = 0; + result = this._findInLine(term, searchPosition, searchOptions); +@@ -237,6 +246,19 @@ export class SearchEngine { + (((searchIndex + term.length) === line.length) || (Constants.NON_WORD_CHARACTERS.includes(line[searchIndex + term.length]))); + } + ++ /** ++ * A wrapped row's text was already searched in full when the first row of its line was, so a ++ * full-buffer scan that visits every row does O(rows^2) work over one long line. Skipping is ++ * only sound for a plain search: wholeWord and regex can both reject at one offset and match at ++ * a later one within the same line. ++ */ ++ private _isRowCoveredByLineStart(row: number, searchOptions?: ISearchOptions): boolean { ++ if (searchOptions?.regex || searchOptions?.wholeWord) { ++ return false; ++ } ++ return this._terminal.buffer.active.getLine(row)?.isWrapped === true; ++ } ++ + /** + * Searches a line for a search term. Takes the provided terminal line and searches the text line, + * which may contain subsequent terminal lines if the text is wrapped. If the provided line number +@@ -250,23 +272,19 @@ export class SearchEngine { * @returns The search result if it was found. */ private _findInLine(term: string, searchPosition: ISearchPosition, searchOptions: ISearchOptions = {}, isReverseSearch: boolean = false): ISearchResult | undefined { diff --git a/config/patches/xterm-src/@xterm__addon-search@0.17.0-beta.300.src.patch b/config/patches/xterm-src/@xterm__addon-search@0.17.0-beta.300.src.patch index 20df0381c45..41e51c66edf 100644 --- a/config/patches/xterm-src/@xterm__addon-search@0.17.0-beta.300.src.patch +++ b/config/patches/xterm-src/@xterm__addon-search@0.17.0-beta.300.src.patch @@ -1,8 +1,58 @@ diff --git a/src/SearchEngine.ts b/src/SearchEngine.ts -index 1760bc2bd1fd274d23e2032fde631b39c739f0d9..f856f1f9444a13d29fcbd2f264b0c2bfbf33db1c 100644 +index 1760bc2bd1fd274d23e2032fde631b39c739f0d9..4ce664a7b913c5c19d6bbf7feba92cbdaef38c6f 100644 --- a/src/SearchEngine.ts +++ b/src/SearchEngine.ts -@@ -250,23 +250,19 @@ export class SearchEngine { +@@ -76,6 +76,9 @@ export class SearchEngine { + // Search from startRow + 1 to end + if (!result) { + for (let y = startRow + 1; y < this._terminal.buffer.active.baseY + this._terminal.rows; y++) { ++ if (this._isRowCoveredByLineStart(y, searchOptions)) { ++ continue; ++ } + searchPosition.startRow = y; + searchPosition.startCol = 0; + result = this._findInLine(term, searchPosition, searchOptions); +@@ -127,6 +130,9 @@ export class SearchEngine { + // Search from startRow + 1 to end + if (!result) { + for (let y = startRow + 1; y < this._terminal.buffer.active.baseY + this._terminal.rows; y++) { ++ if (this._isRowCoveredByLineStart(y, searchOptions)) { ++ continue; ++ } + searchPosition.startRow = y; + searchPosition.startCol = 0; + result = this._findInLine(term, searchPosition, searchOptions); +@@ -138,6 +144,9 @@ export class SearchEngine { + // If we hit the bottom and didn't search from the very top wrap back up + if (!result && startRow !== 0) { + for (let y = 0; y < startRow; y++) { ++ if (this._isRowCoveredByLineStart(y, searchOptions)) { ++ continue; ++ } + searchPosition.startRow = y; + searchPosition.startCol = 0; + result = this._findInLine(term, searchPosition, searchOptions); +@@ -237,6 +246,19 @@ export class SearchEngine { + (((searchIndex + term.length) === line.length) || (Constants.NON_WORD_CHARACTERS.includes(line[searchIndex + term.length]))); + } + ++ /** ++ * A wrapped row's text was already searched in full when the first row of its line was, so a ++ * full-buffer scan that visits every row does O(rows^2) work over one long line. Skipping is ++ * only sound for a plain search: wholeWord and regex can both reject at one offset and match at ++ * a later one within the same line. ++ */ ++ private _isRowCoveredByLineStart(row: number, searchOptions?: ISearchOptions): boolean { ++ if (searchOptions?.regex || searchOptions?.wholeWord) { ++ return false; ++ } ++ return this._terminal.buffer.active.getLine(row)?.isWrapped === true; ++ } ++ + /** + * Searches a line for a search term. Takes the provided terminal line and searches the text line, + * which may contain subsequent terminal lines if the text is wrapped. If the provided line number +@@ -250,23 +272,19 @@ export class SearchEngine { * @returns The search result if it was found. */ private _findInLine(term: string, searchPosition: ISearchPosition, searchOptions: ISearchOptions = {}, isReverseSearch: boolean = false): ISearchResult | undefined { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e0c3a2bfe3f..b25dd932e7d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -111,7 +111,7 @@ overrides: patchedDependencies: '@vscode/windows-process-tree@0.8.0': 9217ef36c01ed74127fef5512b0c92089cdbf820fd6c109dd671137eebdc7585 '@xterm/addon-ligatures@0.11.0-beta.300': 47405b9994b5acf1b4e90b49250358c1ca03649854d59560e7732b72fe336920 - '@xterm/addon-search@0.17.0-beta.300': af96be17952171ef1ba0069a283115a8cca0b381ad54e555fed832277286ea53 + '@xterm/addon-search@0.17.0-beta.300': 7001761370c7940292deae5b7c38eabfdf7e38f6088443b49faad16bece45b23 '@xterm/addon-serialize@0.15.0-beta.300': 851eac3d75e6d8c013b9f4c053e61d824b23965cb19ecc28e335e05059f3a294 '@xterm/addon-webgl@0.20.0-beta.299': 94687e89a0115e6e6aa102837f986debdc029c091527ee5eb4a4e17ceaf9473e '@xterm/xterm@6.1.0-beta.303': 98756bcedc402bcdb7c6ab7b015d2e59cd18e97b03a2c06a27e95bb3ba429d9d @@ -320,7 +320,7 @@ importers: version: 0.11.0-beta.300(patch_hash=47405b9994b5acf1b4e90b49250358c1ca03649854d59560e7732b72fe336920)(@xterm/xterm@6.1.0-beta.303(patch_hash=98756bcedc402bcdb7c6ab7b015d2e59cd18e97b03a2c06a27e95bb3ba429d9d)) '@xterm/addon-search': specifier: 0.17.0-beta.300 - version: 0.17.0-beta.300(patch_hash=af96be17952171ef1ba0069a283115a8cca0b381ad54e555fed832277286ea53)(@xterm/xterm@6.1.0-beta.303(patch_hash=98756bcedc402bcdb7c6ab7b015d2e59cd18e97b03a2c06a27e95bb3ba429d9d)) + version: 0.17.0-beta.300(patch_hash=7001761370c7940292deae5b7c38eabfdf7e38f6088443b49faad16bece45b23)(@xterm/xterm@6.1.0-beta.303(patch_hash=98756bcedc402bcdb7c6ab7b015d2e59cd18e97b03a2c06a27e95bb3ba429d9d)) '@xterm/addon-unicode11': specifier: 0.10.0-beta.300 version: 0.10.0-beta.300(@xterm/xterm@6.1.0-beta.303(patch_hash=98756bcedc402bcdb7c6ab7b015d2e59cd18e97b03a2c06a27e95bb3ba429d9d)) @@ -9755,7 +9755,7 @@ snapshots: lru-cache: 11.5.1 opentype.js: 2.0.0 - '@xterm/addon-search@0.17.0-beta.300(patch_hash=af96be17952171ef1ba0069a283115a8cca0b381ad54e555fed832277286ea53)(@xterm/xterm@6.1.0-beta.303(patch_hash=98756bcedc402bcdb7c6ab7b015d2e59cd18e97b03a2c06a27e95bb3ba429d9d))': + '@xterm/addon-search@0.17.0-beta.300(patch_hash=7001761370c7940292deae5b7c38eabfdf7e38f6088443b49faad16bece45b23)(@xterm/xterm@6.1.0-beta.303(patch_hash=98756bcedc402bcdb7c6ab7b015d2e59cd18e97b03a2c06a27e95bb3ba429d9d))': dependencies: '@xterm/xterm': 6.1.0-beta.303(patch_hash=98756bcedc402bcdb7c6ab7b015d2e59cd18e97b03a2c06a27e95bb3ba429d9d) diff --git a/src/renderer/src/components/terminal-search-long-wrapped-line.test.ts b/src/renderer/src/components/terminal-search-long-wrapped-line.test.ts index f7553fc82b4..490518f757e 100644 --- a/src/renderer/src/components/terminal-search-long-wrapped-line.test.ts +++ b/src/renderer/src/components/terminal-search-long-wrapped-line.test.ts @@ -4,7 +4,10 @@ import { SearchAddon } from '@xterm/addon-search' import { Terminal } from '@xterm/xterm' import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' -import { DESKTOP_TERMINAL_SCROLLBACK_ROWS_MAX } from '../../../shared/terminal-scrollback-policy' +import { + DESKTOP_TERMINAL_SCROLLBACK_ROWS_DEFAULT, + DESKTOP_TERMINAL_SCROLLBACK_ROWS_MAX +} from '../../../shared/terminal-scrollback-policy' import { safeFind } from './terminal-search-safe-find' /** @@ -32,6 +35,12 @@ const ROWS = 24 /** Long enough that the wrap chain outruns V8's stack on any host. */ const WRAPPED_ROWS = 12_000 const NEEDLE = 'needle' +/** + * A full-buffer scan runs on the renderer's main thread on every keystroke in + * the find bar, so anything near this is a visible freeze rather than a slow + * search. Unfixed it is ~18s for a default-scrollback buffer; fixed, ~6ms. + */ +const FULL_SCAN_BUDGET_MS = 5_000 // Matches the decoration options TerminalSearch passes, so the highlight-all // pass (the crash's entry point) actually runs. @@ -102,4 +111,51 @@ describe('terminal search inside one very long wrapped line', () => { }).not.toThrow() expect(found).toBe(true) }) + + it('scans a long wrapped line once, not once per wrapped row', async () => { + const { terminal, search } = openTerminalWithSearch() + await write(terminal, 'x'.repeat(COLS * DESKTOP_TERMINAL_SCROLLBACK_ROWS_DEFAULT)) + + // No match, so the scan visits every row: the shape that froze the pane. + const startedAt = performance.now() + safeFind((term, options) => search.findNext(term, options), NEEDLE, { + decorations: SEARCH_DECORATIONS + }) + + expect(performance.now() - startedAt).toBeLessThan(FULL_SCAN_BUDGET_MS) + }) + + it('reports every match inside a wrapped line', async () => { + const { terminal, search } = openTerminalWithSearch() + let resultCount = -1 + search.onDidChangeResults((event) => { + resultCount = event.resultCount + }) + // One logical line wrapping over three rows with a match in each, then a + // separate unwrapped line. + const paddedNeedle = NEEDLE + 'x'.repeat(COLS - NEEDLE.length) + await write(terminal, `${paddedNeedle.repeat(3)}\r\nplain ${NEEDLE}\r\n`) + + safeFind((term, options) => search.findNext(term, options), NEEDLE, { + decorations: SEARCH_DECORATIONS + }) + + expect(resultCount).toBe(4) + }) + + it('still finds a whole-word match that only matches from a later wrapped row', async () => { + const { terminal, search } = openTerminalWithSearch() + // From the line start the first hit is `aneedlea`, which wholeWord rejects + // without looking further, so the match on the second row is only reachable + // by searching that row — it must not be skipped as already covered. + const filler = 'x'.repeat(COLS - NEEDLE.length - 2) + await write(terminal, `a${NEEDLE}a${filler} ${NEEDLE} ${filler}`) + + const found = safeFind((term, options) => search.findNext(term, options), NEEDLE, { + wholeWord: true, + decorations: SEARCH_DECORATIONS + }) + + expect(found).toBe(true) + }) })