From 65ff7e5b795185036c53a5cfdd67a8767057ed2f Mon Sep 17 00:00:00 2001 From: "Timothy J. Warren" Date: Wed, 17 Jul 2024 12:08:16 -0400 Subject: [PATCH] Mostly get multi-line comments highlighted (minus the last slash...) --- src/common/document.ts | 31 +++++++++--- src/common/filetype/filetype.ts | 2 + src/common/row.ts | 87 +++++++++++++++++++++++++++++++-- 3 files changed, 109 insertions(+), 11 deletions(-) diff --git a/src/common/document.ts b/src/common/document.ts index 7e28037..057cd2e 100644 --- a/src/common/document.ts +++ b/src/common/document.ts @@ -55,10 +55,13 @@ export class Document { } this.type = FileType.from(filename); + let startWithComment = false; const rawFile = await file.openFile(filename); rawFile.split(/\r?\n/) - .forEach((row) => this.insertRow(this.numRows, row)); + .forEach((row) => + startWithComment = this.insertRow(this.numRows, row, startWithComment) + ); this.dirty = false; @@ -72,8 +75,14 @@ export class Document { const { file } = await getRuntime(); await file.saveFile(filename, this.rowsToString()); + let startWithComment = false; this.type = FileType.from(filename); + // Re-highlight the file + this.#rows.forEach((row) => { + startWithComment = row.update(None, this.type, startWithComment); + }); + this.dirty = false; } @@ -139,7 +148,7 @@ export class Document { this.insertRow(this.numRows, c); } else { this.#rows[at.y].insertChar(at.x, c); - this.#rows[at.y].update(None, this.type); + this.#rows[at.y].update(None, this.type, false); } } @@ -164,8 +173,8 @@ export class Document { // row with the leftovers const currentRow = this.#rows[at.y]; const newRow = currentRow.split(at.x, this.type); - currentRow.update(None, this.type); - newRow.update(None, this.type); + currentRow.update(None, this.type, false); + newRow.update(None, this.type, false); this.#rows = arrayInsert(this.#rows, at.y + 1, newRow); } @@ -211,7 +220,7 @@ export class Document { row.delete(at.x); } - row.update(None, this.type); + row.update(None, this.type, false); } public row(i: number): Option { @@ -222,16 +231,22 @@ export class Document { return Option.from(this.#rows.at(i)); } - public insertRow(at: number = this.numRows, s: string = ''): void { + public insertRow( + at: number = this.numRows, + s: string = '', + startWithComment: boolean = false, + ): boolean { this.#rows = arrayInsert(this.#rows, at, Row.from(s)); - this.#rows[at].update(None, this.type); this.dirty = true; + + return this.#rows[at].update(None, this.type, startWithComment); } public highlight(searchMatch: Option): void { + let startWithComment = false; this.#rows.forEach((row) => { - row.update(searchMatch, this.type); + startWithComment = row.update(searchMatch, this.type, startWithComment); }); } diff --git a/src/common/filetype/filetype.ts b/src/common/filetype/filetype.ts index 4ed8c7a..20fa6c6 100644 --- a/src/common/filetype/filetype.ts +++ b/src/common/filetype/filetype.ts @@ -143,6 +143,8 @@ class JavaScriptFile extends AbstractFileType { class TypeScriptFile extends JavaScriptFile { public readonly name: FileLang = FileLang.TypeScript; + public readonly multiLineCommentStart: Option = Some('/*'); + public readonly multiLineCommentEnd: Option = Some('*/'); public readonly keywords2 = [ ...super.secondaryKeywords, // Typescript-specific diff --git a/src/common/row.ts b/src/common/row.ts index cfb2980..2d5c553 100644 --- a/src/common/row.ts +++ b/src/common/row.ts @@ -135,6 +135,20 @@ export class Row { return Some(this.cxToRx(this.byteIndexToCharIndex(byteIndex))); } + public rIndexOf(s: string, offset: number = 0): Option { + const rstring = this.rchars.join(''); + const byteIndex = rstring.indexOf(s, this.charIndexToByteIndex(offset)); + + return (byteIndex >= 0) ? Some(this.byteIndexToCharIndex(byteIndex)) : None; + } + + public rLastIndexOf(s: string, offset: number = 0): Option { + const rstring = this.rchars.join(''); + const byteIndex = rstring.lastIndexOf(s, this.charIndexToByteIndex(offset)); + + return (byteIndex >= 0) ? Some(this.byteIndexToCharIndex(byteIndex)) : None; + } + /** * Convert the raw row offset to the equivalent offset for screen rendering */ @@ -214,22 +228,50 @@ export class Row { return this.chars.join(''); } - public update(word: Option, syntax: FileType): void { + public update( + word: Option, + syntax: FileType, + startWithComment: boolean = false, + ): boolean { const newString = this.chars.join('').replaceAll( '\t', ' '.repeat(SCROLL_TAB_SIZE), ); this.rchars = strChars(newString); - this.highlight(word, syntax); + return this.highlight(word, syntax, startWithComment); } - public highlight(word: Option, syntax: FileType): void { + public highlight( + word: Option, + syntax: FileType, + startWithComment: boolean, + ): boolean { this.hl = []; let i = 0; + let inMlComment = startWithComment; + if (inMlComment && syntax.hasMultilineComments()) { + const maybEnd = this.rIndexOf(syntax.multiLineCommentEnd.unwrap(), i); + const closingIndex = (maybEnd.isSome()) + ? maybEnd.unwrap() + 1 + : this.rsize; + + for (; i < closingIndex; i++) { + this.hl.push(HighlightType.MultiLineComment); + } + } + for (; i < this.rsize;) { const ch = this.rchars[i]; + const maybeMultiline = this.highlightMultilineComment(i, syntax, ch); + if (maybeMultiline.isSome()) { + inMlComment = true; + i = maybeMultiline.unwrap(); + continue; + } + + inMlComment = false; const maybeNext = this.highlightComment(i, syntax, ch) .orElse(() => this.highlightPrimaryKeywords(i, syntax)) @@ -251,6 +293,19 @@ export class Row { } this.highlightMatch(word); + if (inMlComment && syntax.hasMultilineComments()) { + const commentEnd = syntax.multiLineCommentEnd.unwrap(); + const maybeIndex = this.rLastIndexOf(commentEnd); + + if (maybeIndex.isNone()) { + return true; + } + + const lastIndex = maybeIndex.unwrap(); + return lastIndex !== this.rsize - 2; + } + + return false; } protected highlightMatch(word: Option): void { @@ -410,6 +465,32 @@ export class Row { return None; } + protected highlightMultilineComment( + i: number, + syntax: FileType, + ch: string, + ): Option { + if (syntax.hasMultilineComments()) { + const startChars = syntax.multiLineCommentStart.unwrap(); + const endChars = syntax.multiLineCommentEnd.unwrap(); + if (ch === startChars[0] && this.rchars[i + 1] == startChars[1]) { + const maybeEnd = this.rIndexOf(endChars, i); + const end = (maybeEnd.isSome()) + ? maybeEnd.unwrap() + strlen(endChars) + 1 + : this.rsize; + + for (; i < end; i++) { + this.hl.push(HighlightType.MultiLineComment); + } + return Some(i); + } + + return None; + } + + return None; + } + protected highlightNumber( i: number, syntax: FileType,