From 9fdbab76d37d5cf8becff1ec18277d936d6e71df Mon Sep 17 00:00:00 2001 From: Ido Frenkel Date: Thu, 29 Aug 2024 17:16:21 +0300 Subject: [PATCH] Add the option to search with regex --- src/components/LazyLog/index.tsx | 14 ++++++++++-- src/components/Utils/search.ts | 39 +++++++++++++++++++++++++++++--- src/stories/LazyLog.stories.tsx | 1 + 3 files changed, 49 insertions(+), 5 deletions(-) diff --git a/src/components/LazyLog/index.tsx b/src/components/LazyLog/index.tsx index 81b3e00..d4e2d23 100644 --- a/src/components/LazyLog/index.tsx +++ b/src/components/LazyLog/index.tsx @@ -92,6 +92,10 @@ export interface LazyLogProps { * Enable hyperlinks to be discovered in log text and made clickable links. Default is false. */ enableLinks?: boolean; + /** + * Use Regex for search + */ + regexSearch?: boolean; /** * Enable the search feature. */ @@ -304,6 +308,7 @@ export default class LazyLog extends Component { overflow: "initial", }, caseInsensitive: false, + regexSearch: false, enableGutters: false, enableHotKeys: false, enableLineNumbers: true, @@ -732,11 +737,16 @@ export default class LazyLog extends Component { handleSearch = (keywords: string | undefined) => { const { resultLines, searchKeywords } = this.state; - const { caseInsensitive, stream, websocket } = this.props; + const { caseInsensitive, stream, websocket, regexSearch } = this.props; const currentResultLines = !stream && !websocket && keywords === searchKeywords ? resultLines - : searchLines(keywords, this.encodedLog!, caseInsensitive!); + : searchLines( + keywords, + this.encodedLog!, + caseInsensitive!, + regexSearch! + ); this.setState( { diff --git a/src/components/Utils/search.ts b/src/components/Utils/search.ts index d076eb0..73cc297 100644 --- a/src/components/Utils/search.ts +++ b/src/components/Utils/search.ts @@ -65,18 +65,50 @@ export const searchIndexes = ( return results; }; +/** + * Search for a given pattern in the text + * + * @param rawKeywords - The Regex pattern to search. + * @param {Uint8Array} rawLog - The log data to search within. + * @returns {number[]} An array of indices where the keyword is found in the log. + */ +export const searchIndexesRegex = ( + rawKeywords: string | undefined, + rawLog: Uint8Array +) => { + if (!rawKeywords) return []; + + const decodedLog = new TextDecoder("utf-8").decode(rawLog); + const indexes: number[] = []; + + try { + const regex = new RegExp(rawKeywords, "g"); + let match; + + while ((match = regex.exec(decodedLog)) !== null) { + indexes.push(match.index); + } + } catch (e) { + return []; + } + + return indexes; +}; + /** * Searches for keywords within log lines, handling case sensitivity. * * @param {string | undefined} rawKeywords - The search term to look for. * @param {Uint8Array} rawLog - The log data to search within. * @param {boolean} isCaseInsensitive - Whether the search should be case-insensitive. + * @param {boolean} regexSearch - Search with regex. * @returns {number[]} An array of line numbers where the keyword is found. */ export const searchLines = ( rawKeywords: string | undefined, rawLog: Uint8Array, - isCaseInsensitive: boolean + isCaseInsensitive: boolean, + regexSearch: boolean ) => { let keywords = rawKeywords; let log = rawLog; @@ -91,8 +123,9 @@ export const searchLines = ( decodedLog = decodedLog.endsWith("\n") ? decodedLog : decodedLog + "\n"; log = encode(decodedLog); - // Perform the search - const results = searchIndexes(keywords, log); + const results = regexSearch + ? searchIndexesRegex(keywords, log) + : searchIndexes(keywords, log); const linesRanges = getLinesLengthRanges(log); const maxLineRangeIndex = linesRanges.length; const maxResultIndex = results.length; diff --git a/src/stories/LazyLog.stories.tsx b/src/stories/LazyLog.stories.tsx index 8e0441b..d145bfe 100644 --- a/src/stories/LazyLog.stories.tsx +++ b/src/stories/LazyLog.stories.tsx @@ -12,6 +12,7 @@ type Story = StoryObj; const BaseStory = { caseInsensitive: true, + regexSearch: false, enableGutters: false, enableHotKeys: true, enableLineNumbers: true,