Mostly get multi-line comments highlighted (minus the last slash...)
All checks were successful
timw4mail/scroll/pipeline/head This commit looks good
All checks were successful
timw4mail/scroll/pipeline/head This commit looks good
This commit is contained in:
parent
6d9d1113f2
commit
65ff7e5b79
@ -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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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,
|
||||||
|
Loading…
Reference in New Issue
Block a user