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