Mostly get multi-line comments highlighted (minus the last slash...)
All checks were successful
timw4mail/scroll/pipeline/head This commit looks good

This commit is contained in:
Timothy Warren 2024-07-17 12:08:16 -04:00
parent 6d9d1113f2
commit 65ff7e5b79
3 changed files with 109 additions and 11 deletions

View File

@ -55,10 +55,13 @@ export class Document {
} }
this.type = FileType.from(filename); this.type = FileType.from(filename);
let startWithComment = false;
const rawFile = await file.openFile(filename); const rawFile = await file.openFile(filename);
rawFile.split(/\r?\n/) rawFile.split(/\r?\n/)
.forEach((row) => this.insertRow(this.numRows, row)); .forEach((row) =>
startWithComment = this.insertRow(this.numRows, row, startWithComment)
);
this.dirty = false; this.dirty = false;
@ -72,8 +75,14 @@ export class Document {
const { file } = await getRuntime(); const { file } = await getRuntime();
await file.saveFile(filename, this.rowsToString()); await file.saveFile(filename, this.rowsToString());
let startWithComment = false;
this.type = FileType.from(filename); this.type = FileType.from(filename);
// Re-highlight the file
this.#rows.forEach((row) => {
startWithComment = row.update(None, this.type, startWithComment);
});
this.dirty = false; this.dirty = false;
} }
@ -139,7 +148,7 @@ export class Document {
this.insertRow(this.numRows, c); this.insertRow(this.numRows, c);
} else { } else {
this.#rows[at.y].insertChar(at.x, c); 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 // row with the leftovers
const currentRow = this.#rows[at.y]; const currentRow = this.#rows[at.y];
const newRow = currentRow.split(at.x, this.type); const newRow = currentRow.split(at.x, this.type);
currentRow.update(None, this.type); currentRow.update(None, this.type, false);
newRow.update(None, this.type); newRow.update(None, this.type, false);
this.#rows = arrayInsert(this.#rows, at.y + 1, newRow); this.#rows = arrayInsert(this.#rows, at.y + 1, newRow);
} }
@ -211,7 +220,7 @@ export class Document {
row.delete(at.x); row.delete(at.x);
} }
row.update(None, this.type); row.update(None, this.type, false);
} }
public row(i: number): Option<Row> { public row(i: number): Option<Row> {
@ -222,16 +231,22 @@ export class Document {
return Option.from(this.#rows.at(i)); 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 = arrayInsert(this.#rows, at, Row.from(s));
this.#rows[at].update(None, this.type);
this.dirty = true; this.dirty = true;
return this.#rows[at].update(None, this.type, startWithComment);
} }
public highlight(searchMatch: Option<string>): void { public highlight(searchMatch: Option<string>): void {
let startWithComment = false;
this.#rows.forEach((row) => { this.#rows.forEach((row) => {
row.update(searchMatch, this.type); startWithComment = row.update(searchMatch, this.type, startWithComment);
}); });
} }

View File

@ -143,6 +143,8 @@ class JavaScriptFile extends AbstractFileType {
class TypeScriptFile extends JavaScriptFile { class TypeScriptFile extends JavaScriptFile {
public readonly name: FileLang = FileLang.TypeScript; public readonly name: FileLang = FileLang.TypeScript;
public readonly multiLineCommentStart: Option<string> = Some('/*');
public readonly multiLineCommentEnd: Option<string> = Some('*/');
public readonly keywords2 = [ public readonly keywords2 = [
...super.secondaryKeywords, ...super.secondaryKeywords,
// Typescript-specific // Typescript-specific

View File

@ -135,6 +135,20 @@ export class Row {
return Some(this.cxToRx(this.byteIndexToCharIndex(byteIndex))); return Some(this.cxToRx(this.byteIndexToCharIndex(byteIndex)));
} }
public rIndexOf(s: string, offset: number = 0): Option<number> {
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<number> {
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 * Convert the raw row offset to the equivalent offset for screen rendering
*/ */
@ -214,22 +228,50 @@ export class Row {
return this.chars.join(''); return this.chars.join('');
} }
public update(word: Option<string>, syntax: FileType): void { public update(
word: Option<string>,
syntax: FileType,
startWithComment: boolean = false,
): boolean {
const newString = this.chars.join('').replaceAll( const newString = this.chars.join('').replaceAll(
'\t', '\t',
' '.repeat(SCROLL_TAB_SIZE), ' '.repeat(SCROLL_TAB_SIZE),
); );
this.rchars = strChars(newString); this.rchars = strChars(newString);
this.highlight(word, syntax); return this.highlight(word, syntax, startWithComment);
} }
public highlight(word: Option<string>, syntax: FileType): void { public highlight(
word: Option<string>,
syntax: FileType,
startWithComment: boolean,
): boolean {
this.hl = []; this.hl = [];
let i = 0; 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;) { for (; i < this.rsize;) {
const ch = this.rchars[i]; 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) const maybeNext = this.highlightComment(i, syntax, ch)
.orElse(() => this.highlightPrimaryKeywords(i, syntax)) .orElse(() => this.highlightPrimaryKeywords(i, syntax))
@ -251,6 +293,19 @@ export class Row {
} }
this.highlightMatch(word); 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<string>): void { protected highlightMatch(word: Option<string>): void {
@ -410,6 +465,32 @@ export class Row {
return None; return None;
} }
protected highlightMultilineComment(
i: number,
syntax: FileType,
ch: string,
): Option<number> {
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( protected highlightNumber(
i: number, i: number,
syntax: FileType, syntax: FileType,