Highlight character type separate from string type
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
58490f1c51
commit
c31933ed9b
@ -77,13 +77,9 @@ export class CFile extends AbstractFileType {
|
|||||||
public readonly operators = [
|
public readonly operators = [
|
||||||
'>>>=',
|
'>>>=',
|
||||||
'**=',
|
'**=',
|
||||||
'<<=',
|
|
||||||
'>>=',
|
|
||||||
'&&=',
|
'&&=',
|
||||||
'||=',
|
'||=',
|
||||||
'??=',
|
'??=',
|
||||||
'===',
|
|
||||||
'!==',
|
|
||||||
'>>>',
|
'>>>',
|
||||||
'<=>',
|
'<=>',
|
||||||
'<<=',
|
'<<=',
|
||||||
@ -137,6 +133,7 @@ export class CFile extends AbstractFileType {
|
|||||||
'%',
|
'%',
|
||||||
'-',
|
'-',
|
||||||
'+',
|
'+',
|
||||||
|
'*',
|
||||||
'&',
|
'&',
|
||||||
'|',
|
'|',
|
||||||
'^',
|
'^',
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { node_path as path } from '../runtime/mod.ts';
|
import { node_path as path } from '../runtime/mod.ts';
|
||||||
import { AbstractFileType } from './base.ts';
|
import { AbstractFileType } from './base.ts';
|
||||||
import { CFile } from './c.ts'
|
import { CFile } from './c.ts';
|
||||||
import { CSSFile } from './css.ts';
|
import { CSSFile } from './css.ts';
|
||||||
import { JavaScriptFile, TypeScriptFile } from './javascript.ts';
|
import { JavaScriptFile, TypeScriptFile } from './javascript.ts';
|
||||||
import { ShellFile } from './shell.ts';
|
import { ShellFile } from './shell.ts';
|
||||||
|
@ -4,6 +4,7 @@ export enum HighlightType {
|
|||||||
None,
|
None,
|
||||||
Number,
|
Number,
|
||||||
Match,
|
Match,
|
||||||
|
Character,
|
||||||
String,
|
String,
|
||||||
SingleLineComment,
|
SingleLineComment,
|
||||||
MultiLineComment,
|
MultiLineComment,
|
||||||
@ -20,11 +21,14 @@ export function highlightToColor(type: HighlightType): string {
|
|||||||
case HighlightType.Match:
|
case HighlightType.Match:
|
||||||
return Ansi.color256(21);
|
return Ansi.color256(21);
|
||||||
|
|
||||||
|
case HighlightType.Character:
|
||||||
|
return Ansi.color256(207);
|
||||||
|
|
||||||
case HighlightType.String:
|
case HighlightType.String:
|
||||||
return Ansi.color256(45);
|
return Ansi.color256(45);
|
||||||
|
|
||||||
case HighlightType.SingleLineComment:
|
case HighlightType.SingleLineComment:
|
||||||
return Ansi.color256(201);
|
return Ansi.color256(248);
|
||||||
|
|
||||||
case HighlightType.MultiLineComment:
|
case HighlightType.MultiLineComment:
|
||||||
return Ansi.color256(240);
|
return Ansi.color256(240);
|
||||||
|
@ -88,14 +88,14 @@ export class Option<T> {
|
|||||||
/**
|
/**
|
||||||
* The wrapped value is not null or undefined
|
* The wrapped value is not null or undefined
|
||||||
*/
|
*/
|
||||||
isSome(): boolean {
|
public isSome(): boolean {
|
||||||
return isSome(this.inner);
|
return isSome(this.inner);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The wrapped value is null or undefined
|
* The wrapped value is null or undefined
|
||||||
*/
|
*/
|
||||||
isNone(): boolean {
|
public isNone(): boolean {
|
||||||
return !this.isSome();
|
return !this.isSome();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,7 +107,7 @@ export class Option<T> {
|
|||||||
*
|
*
|
||||||
* @param fn A boolean check to run on the wrapped value
|
* @param fn A boolean check to run on the wrapped value
|
||||||
*/
|
*/
|
||||||
isSomeAnd(fn: (a: T) => boolean): boolean {
|
public isSomeAnd(fn: (a: T) => boolean): boolean {
|
||||||
return isSome(this.inner) ? fn(this.inner.value) : false;
|
return isSome(this.inner) ? fn(this.inner.value) : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,7 +119,7 @@ export class Option<T> {
|
|||||||
*
|
*
|
||||||
* @param fn A function returning a boolean value
|
* @param fn A function returning a boolean value
|
||||||
*/
|
*/
|
||||||
isNoneAnd(fn: () => boolean): boolean {
|
public isNoneAnd(fn: () => boolean): boolean {
|
||||||
return this.isNone() ? fn() : false;
|
return this.isNone() ? fn() : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,7 +130,7 @@ export class Option<T> {
|
|||||||
*
|
*
|
||||||
* @param fn A function that takes the inner value of the `Option` and returns a new one
|
* @param fn A function that takes the inner value of the `Option` and returns a new one
|
||||||
*/
|
*/
|
||||||
map<U>(fn: (a: T) => U): Option<U> {
|
public map<U>(fn: (a: T) => U): Option<U> {
|
||||||
return isSome(this.inner) ? Option.from(fn(this.inner.value)) : Option.None;
|
return isSome(this.inner) ? Option.from(fn(this.inner.value)) : Option.None;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,7 +142,7 @@ export class Option<T> {
|
|||||||
* @param def The default value to return if this `Option` is `None`
|
* @param def The default value to return if this `Option` is `None`
|
||||||
* @param fn A function that takes the inner value of this `Option` and returns a new value
|
* @param fn A function that takes the inner value of this `Option` and returns a new value
|
||||||
*/
|
*/
|
||||||
mapOr<U>(def: U, fn: (a: T) => U): U {
|
public mapOr<U>(def: U, fn: (a: T) => U): U {
|
||||||
return isSome(this.inner) ? fn(this.inner.value) : def;
|
return isSome(this.inner) ? fn(this.inner.value) : def;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,7 +154,7 @@ export class Option<T> {
|
|||||||
* @param def A function to return a value if this `Option` is `None`
|
* @param def A function to return a value if this `Option` is `None`
|
||||||
* @param fn A function that takes the inner value of this `Option` and returns a new value
|
* @param fn A function that takes the inner value of this `Option` and returns a new value
|
||||||
*/
|
*/
|
||||||
mapOrElse<U>(def: () => U, fn: (a: T) => U): U {
|
public mapOrElse<U>(def: () => U, fn: (a: T) => U): U {
|
||||||
return isSome(this.inner) ? fn(this.inner.value) : def();
|
return isSome(this.inner) ? fn(this.inner.value) : def();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,7 +164,7 @@ export class Option<T> {
|
|||||||
*
|
*
|
||||||
* @param err
|
* @param err
|
||||||
*/
|
*/
|
||||||
assert(err: string): T | never {
|
public assert(err: string): T | never {
|
||||||
if (isSome(this.inner)) {
|
if (isSome(this.inner)) {
|
||||||
return this.inner.value;
|
return this.inner.value;
|
||||||
}
|
}
|
||||||
@ -177,7 +177,7 @@ export class Option<T> {
|
|||||||
*
|
*
|
||||||
* If `None`, throws an exception.
|
* If `None`, throws an exception.
|
||||||
*/
|
*/
|
||||||
unwrap(): T | never {
|
public unwrap(): T | never {
|
||||||
return this.assert("Called unwrap on a 'None'");
|
return this.assert("Called unwrap on a 'None'");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,7 +187,7 @@ export class Option<T> {
|
|||||||
*
|
*
|
||||||
* @param def Value to return on `None` value
|
* @param def Value to return on `None` value
|
||||||
*/
|
*/
|
||||||
unwrapOr(def: T): T {
|
public unwrapOr(def: T): T {
|
||||||
return isSome(this.inner) ? this.inner.value : def;
|
return isSome(this.inner) ? this.inner.value : def;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -197,7 +197,7 @@ export class Option<T> {
|
|||||||
*
|
*
|
||||||
* @param f Function to run on `None` value
|
* @param f Function to run on `None` value
|
||||||
*/
|
*/
|
||||||
unwrapOrElse(f: () => T): T {
|
public unwrapOrElse(f: () => T): T {
|
||||||
return isSome(this.inner) ? this.inner.value : f();
|
return isSome(this.inner) ? this.inner.value : f();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,7 +207,7 @@ export class Option<T> {
|
|||||||
*
|
*
|
||||||
* @param optb Another `Option` to check
|
* @param optb Another `Option` to check
|
||||||
*/
|
*/
|
||||||
and<U>(optb: Option<U>): Option<U> {
|
public and<U>(optb: Option<U>): Option<U> {
|
||||||
return isSome(this.inner) ? optb : Option.None;
|
return isSome(this.inner) ? optb : Option.None;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,7 +219,7 @@ export class Option<T> {
|
|||||||
*
|
*
|
||||||
* @param f function to run on the wrapped value
|
* @param f function to run on the wrapped value
|
||||||
*/
|
*/
|
||||||
andThen<U>(f: (a: T) => Option<U>): Option<U> {
|
public andThen<U>(f: (a: T) => Option<U>): Option<U> {
|
||||||
return isSome(this.inner) ? f(this.inner.value) : Option.None;
|
return isSome(this.inner) ? f(this.inner.value) : Option.None;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,7 +228,7 @@ export class Option<T> {
|
|||||||
*
|
*
|
||||||
* @param optb The `Option` to return if this `Option` is `None`
|
* @param optb The `Option` to return if this `Option` is `None`
|
||||||
*/
|
*/
|
||||||
or(optb: Option<T>): Option<T> {
|
public or(optb: Option<T>): Option<T> {
|
||||||
return this.isNone() ? optb : this;
|
return this.isNone() ? optb : this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,7 +239,7 @@ export class Option<T> {
|
|||||||
*
|
*
|
||||||
* @param f A function to return a different `Option`
|
* @param f A function to return a different `Option`
|
||||||
*/
|
*/
|
||||||
orElse(f: () => Option<T>): Option<T> {
|
public orElse(f: () => Option<T>): Option<T> {
|
||||||
return this.isNone() ? f() : this;
|
return this.isNone() ? f() : this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -247,7 +247,7 @@ export class Option<T> {
|
|||||||
* Create a string representation of the `Option`,
|
* Create a string representation of the `Option`,
|
||||||
* mostly for debugging
|
* mostly for debugging
|
||||||
*/
|
*/
|
||||||
toString(): string {
|
public toString(): string {
|
||||||
const innerValue = (isSome(this.inner))
|
const innerValue = (isSome(this.inner))
|
||||||
? JSON.stringify(this.inner.value)
|
? JSON.stringify(this.inner.value)
|
||||||
: '';
|
: '';
|
||||||
|
@ -14,6 +14,9 @@ import { highlightToColor, HighlightType } from './highlight.ts';
|
|||||||
import Option, { None, Some } from './option.ts';
|
import Option, { None, Some } from './option.ts';
|
||||||
import { SearchDirection } from './types.ts';
|
import { SearchDirection } from './types.ts';
|
||||||
|
|
||||||
|
const SINGLE_QUOTE = "'";
|
||||||
|
const DOUBLE_QUOTE = '"';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* One row of text in the current document. In order to handle
|
* One row of text in the current document. In order to handle
|
||||||
* multi-byte graphemes, all operations are done on an
|
* multi-byte graphemes, all operations are done on an
|
||||||
@ -321,20 +324,22 @@ export class Row {
|
|||||||
.orElse(() => this.highlightPrimaryKeywords(i, syntax))
|
.orElse(() => this.highlightPrimaryKeywords(i, syntax))
|
||||||
.orElse(() => this.highlightSecondaryKeywords(i, syntax))
|
.orElse(() => this.highlightSecondaryKeywords(i, syntax))
|
||||||
.orElse(() => this.highlightString(i, syntax))
|
.orElse(() => this.highlightString(i, syntax))
|
||||||
|
.orElse(() => this.highlightCharacter(i, syntax))
|
||||||
.orElse(() => this.highlightNumber(i, syntax))
|
.orElse(() => this.highlightNumber(i, syntax))
|
||||||
.orElse(() => this.highlightOperators(i, syntax));
|
.orElse(() => this.highlightOperators(i, syntax));
|
||||||
|
|
||||||
if (maybeNext.isSome()) {
|
if (maybeNext.isNone()) {
|
||||||
|
this.hl.push(HighlightType.None);
|
||||||
|
i += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const next = maybeNext.unwrap();
|
const next = maybeNext.unwrap();
|
||||||
if (next >= this.rsize) {
|
if (next >= this.rsize) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
i = next;
|
i = next;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
this.hl.push(HighlightType.None);
|
|
||||||
i += 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.highlightMatch(word);
|
this.highlightMatch(word);
|
||||||
@ -391,8 +396,9 @@ export class Row {
|
|||||||
// Highlight single-line comments
|
// Highlight single-line comments
|
||||||
if (syntax.singleLineComment.isSome()) {
|
if (syntax.singleLineComment.isSome()) {
|
||||||
const commentStart = syntax.singleLineComment.unwrap();
|
const commentStart = syntax.singleLineComment.unwrap();
|
||||||
|
const hasCommentStart = this.rIndexOf(commentStart).isSome();
|
||||||
if (
|
if (
|
||||||
this.toString().indexOf(commentStart) === this.charIndexToByteIndex(i)
|
hasCommentStart && this.rIndexOf(commentStart).unwrap() === i
|
||||||
) {
|
) {
|
||||||
for (; i < this.rsize; i++) {
|
for (; i < this.rsize; i++) {
|
||||||
this.hl.push(HighlightType.SingleLineComment);
|
this.hl.push(HighlightType.SingleLineComment);
|
||||||
@ -516,13 +522,58 @@ export class Row {
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected highlightCharacter(
|
||||||
|
i: number,
|
||||||
|
syntax: FileType,
|
||||||
|
): Option<number> {
|
||||||
|
if (!syntax.flags.characters) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Highlight character literals
|
||||||
|
const ch = this.rchars[i];
|
||||||
|
if (ch === SINGLE_QUOTE) {
|
||||||
|
while (true) {
|
||||||
|
this.hl.push(HighlightType.Character);
|
||||||
|
i += 1;
|
||||||
|
if (i === this.rsize) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nextChar = this.rchars[i];
|
||||||
|
// Make sure to continue highlighting if
|
||||||
|
// you have an escaped character delimeter
|
||||||
|
if (nextChar === '\\') {
|
||||||
|
this.hl.push(HighlightType.Character);
|
||||||
|
i += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (nextChar === ch) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.hl.push(HighlightType.Character);
|
||||||
|
i += 1;
|
||||||
|
return Some(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
protected highlightString(
|
protected highlightString(
|
||||||
i: number,
|
i: number,
|
||||||
syntax: FileType,
|
syntax: FileType,
|
||||||
): Option<number> {
|
): Option<number> {
|
||||||
|
if (!syntax.flags.strings) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
// Highlight strings
|
// Highlight strings
|
||||||
const ch = this.rchars[i];
|
const ch = this.rchars[i];
|
||||||
if (syntax.flags.strings && ch === '"' || ch === "'") {
|
if (
|
||||||
|
ch === DOUBLE_QUOTE ||
|
||||||
|
((!syntax.flags.characters) && ch === SINGLE_QUOTE)
|
||||||
|
) {
|
||||||
while (true) {
|
while (true) {
|
||||||
this.hl.push(HighlightType.String);
|
this.hl.push(HighlightType.String);
|
||||||
i += 1;
|
i += 1;
|
||||||
|
Loading…
Reference in New Issue
Block a user