Refactor again
All checks were successful
timw4mail/scroll/pipeline/head This commit looks good

This commit is contained in:
Timothy Warren 2024-07-25 11:47:44 -04:00
parent 501f5e10d5
commit 8b44e250e2
29 changed files with 172 additions and 120 deletions

View File

@ -13,5 +13,6 @@
"semiColons": true,
"singleQuote": true
},
"nodeModulesDir": true
"nodeModulesDir": true,
"exclude": ["src/bun/"]
}

View File

@ -14,7 +14,7 @@ check: deno-check bun-check
# Generate source docs
docs:
deno doc --html --name="Scroll" ./src/scroll.ts ./src/common/*.ts ./src/deno/mod.ts ./src/bun/mod.ts ./src/tsx/mod.ts
deno doc --html --name="Scroll" ./src/common/*.ts ./src/common/**/*.ts
# Generate source docs and open in default browser
open-docs: docs

View File

@ -1,7 +1,7 @@
/**
* The main entrypoint when using Bun as the runtime
*/
import { CommonRuntime, IRuntime, RunTimeType } from '../common/runtime/mod.ts';
import { CommonRuntime, IRuntime, RunTimeType } from '../common/runtime.ts';
/**
* The Bun Runtime implementation

View File

@ -2,17 +2,16 @@ import Ansi, * as _Ansi from './ansi.ts';
import Buffer from './buffer.ts';
import Document from './document.ts';
import Editor from './editor.ts';
import { FileLang } from './filetype/mod.ts';
import { highlightToColor, HighlightType } from './highlight.ts';
import { FileLang } from './filetype.ts';
import Option, { None, Some } from './option.ts';
import Position from './position.ts';
import Row from './row.ts';
import FileType, * as FT from './filetype/mod.ts';
import FileType, * as FT from './filetype.ts';
import * as Fn from './fns.ts';
import { defaultTerminalSize, SCROLL_TAB_SIZE } from './config.ts';
import { getTestRunner } from './runtime/mod.ts';
import { SearchDirection } from './types.ts';
import { getTestRunner } from './runtime.ts';
import { HighlightType, SearchDirection } from './types.ts';
import fs from 'node:fs';
@ -51,6 +50,7 @@ const fnTest = () => {
isAsciiDigit,
strlen,
truncate,
highlightToColor,
} = Fn;
return {
@ -78,6 +78,21 @@ const fnTest = () => {
assertExists(noop);
assertEquals(noop(), undefined);
},
'highlightToColor()': () => {
[
HighlightType.Number,
HighlightType.Match,
HighlightType.String,
HighlightType.SingleLineComment,
HighlightType.MultiLineComment,
HighlightType.Keyword1,
HighlightType.Keyword2,
HighlightType.Operator,
HighlightType.None,
].forEach((type) => {
assertTrue(highlightToColor(type).length > 0);
});
},
'posSub()': () => {
assertEquals(posSub(14, 15), 0);
assertEquals(posSub(15, 1), 14);
@ -201,24 +216,6 @@ const readKeyTest = () => {
};
};
const highlightToColorTest = {
'highlightToColor()': () => {
[
HighlightType.Number,
HighlightType.Match,
HighlightType.String,
HighlightType.SingleLineComment,
HighlightType.MultiLineComment,
HighlightType.Keyword1,
HighlightType.Keyword2,
HighlightType.Operator,
HighlightType.None,
].forEach((type) => {
assertTrue(highlightToColor(type).length > 0);
});
},
};
// ----------------------------------------------------------------------------
// Tests by module
// ----------------------------------------------------------------------------
@ -708,7 +705,6 @@ const RowTest = {
testSuite({
fns: fnTest(),
highlightToColorTest,
'readKey()': readKeyTest(),
'ANSI utils': ANSITest(),
Buffer: BufferTest,

View File

@ -117,6 +117,9 @@ const rgb = (
ground: Ground = Ground.Fore,
): string => textFormat([ground, AnsiColor.TypeRGB, r, g, b]);
/**
* Ansi terminal codes and helper functions
*/
export const Ansi = {
ClearLine: code('K'),
ClearScreen: code('2J'),

View File

@ -1,6 +1,9 @@
import { strlen, truncate } from './fns.ts';
import { getRuntime } from './runtime/mod.ts';
import { getRuntime } from './runtime.ts';
/**
* A simple string buffer
*/
class Buffer {
#b = '';

View File

@ -1,7 +1,7 @@
import Ansi from './ansi.ts';
import { HighlightType, ITerminalSize } from './types.ts';
export const SCROLL_VERSION = '0.0.1';
export const SCROLL_VERSION = '0.1.0';
export const SCROLL_QUIT_TIMES = 3;
export const SCROLL_TAB_SIZE = 4;

View File

@ -1,8 +1,8 @@
import Row from './row.ts';
import { FileType } from './filetype/mod.ts';
import { FileType } from './filetype.ts';
import { arrayInsert } from './fns.ts';
import Option, { None, Some } from './option.ts';
import { getRuntime, logWarning } from './runtime/mod.ts';
import { getRuntime, logWarning } from './runtime.ts';
import { Position, SearchDirection } from './types.ts';
export class Document {
@ -52,7 +52,7 @@ export class Document {
const rawFile = await file.openFile(filename);
rawFile.split(/\r?\n/)
.forEach((row) => {
.forEach((row: string) => {
this.#rows.push(Row.from(row));
});

View File

@ -13,7 +13,7 @@ import {
truncate,
} from './fns.ts';
import Option, { None, Some } from './option.ts';
import { getRuntime, logDebug, logWarning } from './runtime/mod.ts';
import { getRuntime, logDebug, logWarning } from './runtime.ts';
import { ITerminalSize, Position, SearchDirection } from './types.ts';
/**

5
src/common/filetype.ts Normal file
View File

@ -0,0 +1,5 @@
export * from './filetype/base.ts';
export * from './filetype/filetype.ts';
import FileType from './filetype/filetype.ts';
export default FileType;

View File

@ -1,4 +1,4 @@
import { node_path as path } from '../runtime/mod.ts';
import { node_path as path } from '../runtime.ts';
import { AbstractFileType } from './base.ts';
import { CFile } from './c.ts';
import { CSSFile } from './css.ts';

View File

@ -1,5 +0,0 @@
export * from './base.ts';
export * from './filetype.ts';
import FileType from './filetype.ts';
export default FileType;

View File

@ -1,4 +1,6 @@
import { KeyCommand } from './ansi.ts';
import Ansi, { KeyCommand } from './ansi.ts';
import { SCROLL_COLOR_SCHEME } from './config.ts';
import { HighlightType } from './types.ts';
const decoder = new TextDecoder();
@ -57,6 +59,16 @@ export function readKey(raw: Uint8Array): string {
}
}
/**
* Return the configured ANSI formatting escape codes for the
* type of syntax specified
*
* @param type The type of syntax to highlight
*/
export function highlightToColor(type: HighlightType): string {
return SCROLL_COLOR_SCHEME.get(type) ?? Ansi.ResetFormatting;
}
// ----------------------------------------------------------------------------
// Array manipulation
// ----------------------------------------------------------------------------

View File

@ -1,38 +0,0 @@
import Ansi from './ansi.ts';
import { SCROLL_COLOR_SCHEME } from './config.ts';
/**
* The type of Syntax being highlighted
*/
export enum HighlightType {
/** No highlighting */
None,
/** Number literals */
Number,
/** Search results */
Match,
/** Character literals */
Character,
/** String literals */
String,
/** Single line comments */
SingleLineComment,
/** Multi-line comments */
MultiLineComment,
/** Primary keywords */
Keyword1,
/** Secondary keywords */
Keyword2,
/** Math/logic operators */
Operator,
}
/**
* Return the configured ANSI formatting escape codes for the
* type of syntax specified
*
* @param type The type of syntax to highlight
*/
export function highlightToColor(type: HighlightType): string {
return SCROLL_COLOR_SCHEME.get(type) ?? Ansi.ResetFormatting;
}

View File

@ -4,10 +4,15 @@ import {
logError,
logWarning,
node_process as process,
} from './runtime/mod.ts';
} from './runtime.ts';
import Editor from './editor.ts';
export async function main() {
/**
* The main runtime loop
*
* Only returns on error or quit
*/
export async function main(): Promise<void> {
const rt = await getRuntime();
const { term } = rt;
@ -18,7 +23,7 @@ export async function main() {
});
// Setup error handler to log to file
rt.onEvent('error', (error) => {
rt.onEvent('error', (error: any) => {
process.stdin.setRawMode(false);
logError(JSON.stringify(error, null, 2));
});

View File

@ -4,14 +4,23 @@
export class Position {
private constructor(public x: number = 0, public y: number = 0) {}
/**
* Create a new `Position` at the specified location
*/
public static at(x: number, y: number): Position {
return new Position(x, y);
}
/**
* Create a new `Position` from an existing one
*/
public static from(p: Position): Position {
return new Position(p.x, p.y);
}
/**
* Create a new `Position` at the origin (0, 0)
*/
public static default(): Position {
return new Position();
}

View File

@ -3,16 +3,16 @@ import Ansi from './ansi.ts';
import { SCROLL_TAB_SIZE } from './config.ts';
import {
arrayInsert,
highlightToColor,
isAsciiDigit,
isSeparator,
strChars,
strlen,
substr,
} from './fns.ts';
import { FileType } from './filetype/mod.ts';
import { highlightToColor, HighlightType } from './highlight.ts';
import { FileType } from './filetype.ts';
import Option, { None, Some } from './option.ts';
import { SearchDirection } from './types.ts';
import { HighlightType, SearchDirection } from './types.ts';
const SINGLE_QUOTE = "'";
const DOUBLE_QUOTE = '"';

11
src/common/runtime.ts Normal file
View File

@ -0,0 +1,11 @@
export * from './runtime/file_io.ts';
export * from './runtime/helpers.ts';
export * from './runtime/log.ts';
export * from './runtime/node.ts';
export * from './runtime/runtime.ts';
export * from './runtime/terminal_io.ts';
export * from './runtime/test_base.ts';
export { RunTimeType } from './types.ts';
import { CommonRuntime } from './runtime/runtime.ts';
export default CommonRuntime;

View File

@ -1,8 +1,11 @@
import { appendFile, readFile, writeFile } from 'node:fs/promises';
import { resolve } from 'node:path';
import { IFileIO } from './mod.ts';
import { IFileIO } from './runtime.ts';
/**
* File IO implementation using shared node APIs
*/
export const CommonFileIO: IFileIO = {
openFile: async function (path: string): Promise<string> {
const filePath = resolve(path);

View File

@ -3,8 +3,9 @@
*/
import { logError, logWarning } from './log.ts';
import { node_path as path, node_process as process } from './node.ts';
import { RunTimeType } from './runtime.ts';
import { IRuntime, ITestBase } from '../types.ts';
import { IRuntime } from './runtime.ts';
import { ITestBase } from './test_base.ts';
import { RunTimeType } from '../types.ts';
let scrollRuntime: IRuntime | null = null;

View File

@ -1,6 +1,6 @@
import { noop } from '../fns.ts';
import { SCROLL_LOG_FILE_PREFIX, SCROLL_LOG_FILE_SUFFIX } from '../config.ts';
import { getRuntime } from './mod.ts';
import { getRuntime } from './helpers.ts';
/**
* The label for type/severity of the log entry
@ -14,7 +14,11 @@ export enum LogLevel {
}
/**
* Basic logging -
* Basic logging
*
* @param s The string or data to display first
* @param level The log severity
* @param data Any additional data to display with the log entry
*/
export function log(
s: unknown,
@ -34,12 +38,31 @@ export function log(
});
}
/**
* Make a log entry of `LogLevel.Debug` severity
*/
export const logDebug = (s: unknown, data?: any) =>
log(s, LogLevel.Debug, data);
/**
* Make a log entry of `LogLevel.Info` severity
*/
export const logInfo = (s: unknown, data?: any) => log(s, LogLevel.Info, data);
/**
* Make a log entry of `LogLevel.Notice` severity
*/
export const logNotice = (s: unknown, data?: any) =>
log(s, LogLevel.Notice, data);
/**
* Make a log entry of `LogLevel.Warning` severity
*/
export const logWarning = (s: unknown, data?: any) =>
log(s, LogLevel.Warning, data);
/**
* Make a log entry of `LogLevel.Error` severity
*/
export const logError = (s: unknown, data?: any) =>
log(s, LogLevel.Warning, data);

View File

@ -1,10 +0,0 @@
export * from './file_io.ts';
export * from './helpers.ts';
export * from './log.ts';
export * from './node.ts';
export * from './runtime.ts';
export * from './terminal_io.ts';
export * from './test_base.ts';
import { CommonRuntime } from './runtime.ts';
export default CommonRuntime;

View File

@ -1,6 +1,7 @@
import { node_process as process } from './node.ts';
import CommonFileIO from './file_io.ts';
import CommonTerminalIO from './terminal_io.ts';
import { RunTimeType } from '../types.ts';
// ----------------------------------------------------------------------------
// Runtime adapter interfaces
@ -14,16 +15,6 @@ export interface ITerminalSize {
cols: number;
}
/**
* Which Typescript runtime is currently being used
*/
export enum RunTimeType {
Bun = 'bun',
Deno = 'deno',
Tsx = 'tsx',
Unknown = 'common',
}
/**
* Runtime-specific terminal functionality
*/
@ -131,6 +122,9 @@ export interface IRuntime {
exit(code?: number): void;
}
/**
* Base runtime using shared Node APIs
*/
export const CommonRuntime: IRuntime = {
name: RunTimeType.Unknown,
term: CommonTerminalIO,

View File

@ -2,6 +2,9 @@ import { node_process as process } from './node.ts';
import { readKey } from '../fns.ts';
import { ITerminal, ITerminalSize } from '../types.ts';
/**
* Terminal IO using shared Node APIs
*/
export const CommonTerminalIO: ITerminal = {
argv: (process.argv.length > 2) ? process.argv.slice(2) : [],
inputLoop: async function* (): AsyncGenerator<Uint8Array, null> {

View File

@ -4,6 +4,10 @@
import { deepStrictEqual, notStrictEqual, strictEqual } from 'node:assert';
import Option from '../option.ts';
/**
* The shared interface for tests, running on a different test
* runner for each runtime
*/
export interface ITestBase {
assertEquivalent(actual: unknown, expected: unknown): void;
assertExists(actual: unknown): void;
@ -20,6 +24,9 @@ export interface ITestBase {
testSuite(testObj: any): void;
}
/**
* The base testing implementation using Node assert API
*/
export abstract class AbstractTestBase implements Partial<ITestBase> {
/**
* The values (often objects) have all the same property values

View File

@ -1,13 +1,42 @@
export { HighlightType } from './highlight.ts';
export { Position } from './position.ts';
export type { ITestBase } from './runtime/test_base.ts';
export type {
IFileIO,
IRuntime,
ITerminal,
ITerminalSize,
RunTimeType,
} from './runtime/mod.ts';
export type { IFileIO, IRuntime, ITerminal, ITerminalSize } from './runtime.ts';
/**
* Which Typescript runtime is currently being used
*/
export enum RunTimeType {
Bun = 'bun',
Deno = 'deno',
Tsx = 'tsx',
Unknown = 'unknown',
}
/**
* The type of Syntax being highlighted
*/
export enum HighlightType {
/** No highlighting */
None,
/** Number literals */
Number,
/** Search results */
Match,
/** Character literals */
Character,
/** String literals */
String,
/** Single line comments */
SingleLineComment,
/** Multi-line comments */
MultiLineComment,
/** Primary keywords */
Keyword1,
/** Secondary keywords */
Keyword2,
/** Math/logic operators */
Operator,
}
/**
* Which direction to search in the current document

View File

@ -1,4 +1,4 @@
import { IFileIO } from '../common/runtime/mod.ts';
import { IFileIO } from '../common/runtime.ts';
const DenoFileIO: IFileIO = {
openFile: async function (path: string): Promise<string> {

View File

@ -1,7 +1,7 @@
/**
* The main entrypoint when using Deno as the runtime
*/
import { CommonRuntime, IRuntime, RunTimeType } from '../common/runtime/mod.ts';
import { CommonRuntime, IRuntime, RunTimeType } from '../common/runtime.ts';
import DenoTerminalIO from './terminal_io.ts';
import DenoFileIO from './file_io.ts';

View File

@ -1,7 +1,7 @@
/**
* The main entrypoint when using Tsx as the runtime
*/
import { CommonRuntime, IRuntime, RunTimeType } from '../common/runtime/mod.ts';
import { CommonRuntime, IRuntime, RunTimeType } from '../common/runtime.ts';
/**
* The Tsx Runtime implementation