Update src/util.ts
This commit is contained in:
parent
0df11bdcc8
commit
a140ffac9d
1 changed files with 75 additions and 18 deletions
75
src/util.ts
75
src/util.ts
|
@ -7,7 +7,6 @@ import moment from "moment"
|
||||||
import chalk from "chalk"
|
import chalk from "chalk"
|
||||||
import { LOG_DATETIME_FORMAT } from "./constants"
|
import { LOG_DATETIME_FORMAT } from "./constants"
|
||||||
import { E_CANDIDATE_FUNCTION_REQUIRES_THIS_PARAMETER } from "./diagnostics"
|
import { E_CANDIDATE_FUNCTION_REQUIRES_THIS_PARAMETER } from "./diagnostics"
|
||||||
|
|
||||||
export function isPowerOf(x: number, n: number):boolean {
|
export function isPowerOf(x: number, n: number):boolean {
|
||||||
const a = Math.log(x) / Math.log(n);
|
const a = Math.log(x) / Math.log(n);
|
||||||
return Math.pow(a, n) == x;
|
return Math.pow(a, n) == x;
|
||||||
|
@ -72,7 +71,12 @@ export function* flatMap<T, R>(iterator: Iterator<T>, func: (value: T) => Iterab
|
||||||
yield element;
|
yield element;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function pushAll<T>(array: T[], elements: T[]) {
|
||||||
|
for (const element of elements) {
|
||||||
|
array.push(element);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function comparator<T>(pred: (a: T, b: T) => boolean): (a: T, b: T) => number {
|
export function comparator<T>(pred: (a: T, b: T) => boolean): (a: T, b: T) => number {
|
||||||
|
@ -463,7 +467,7 @@ export function getFileStem(filepath: string): string {
|
||||||
return path.basename(filepath).split('.')[0];
|
return path.basename(filepath).split('.')[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function enumerate(elements: string[]) {
|
export function enumOr(elements: string[]) {
|
||||||
if (elements.length === 1) {
|
if (elements.length === 1) {
|
||||||
return elements[0]
|
return elements[0]
|
||||||
} else {
|
} else {
|
||||||
|
@ -500,35 +504,88 @@ export interface MapLike<T> {
|
||||||
|
|
||||||
export type FormatArg = any;
|
export type FormatArg = any;
|
||||||
|
|
||||||
|
enum FormatScanMode {
|
||||||
|
Text,
|
||||||
|
ScanningParamName,
|
||||||
|
ScanningParamModifier,
|
||||||
|
}
|
||||||
|
|
||||||
|
type FormatModifierFn = (value: any) => any;
|
||||||
|
|
||||||
|
const FORMAT_MODIFIERS: MapLike<FormatModifierFn> = {
|
||||||
|
enum(elements) {
|
||||||
|
return enumOr(elements);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function format(message: string, data: MapLike<FormatArg>) {
|
export function format(message: string, data: MapLike<FormatArg>) {
|
||||||
|
|
||||||
let out = ''
|
let out = ''
|
||||||
|
|
||||||
let name = '';
|
let name = '';
|
||||||
let insideParam = false;
|
let modifierName = '';
|
||||||
|
let modifiers: string[] = [];
|
||||||
|
let mode = FormatScanMode.Text;
|
||||||
|
|
||||||
for (const ch of message) {
|
for (const ch of message) {
|
||||||
if (insideParam) {
|
switch (mode) {
|
||||||
|
case FormatScanMode.ScanningParamModifier:
|
||||||
if (ch === '}') {
|
if (ch === '}') {
|
||||||
out += data[name]!.toString();
|
modifiers.push(modifierName);
|
||||||
reset();
|
push();
|
||||||
|
} else if (ch === ':') {
|
||||||
|
if (modifierName.length === 0) {
|
||||||
|
throw new Error(`Parameter modfifier name in format string is empty.`)
|
||||||
|
}
|
||||||
|
modifiers.push(modifierName);
|
||||||
|
modifierName = '';
|
||||||
|
} else {
|
||||||
|
modifierName += ch;
|
||||||
|
}
|
||||||
|
case FormatScanMode.ScanningParamName:
|
||||||
|
if (ch === '}') {
|
||||||
|
push();
|
||||||
|
} else if (ch === ':') {
|
||||||
|
mode = FormatScanMode.ScanningParamModifier;
|
||||||
} else {
|
} else {
|
||||||
name += ch;
|
name += ch;
|
||||||
}
|
}
|
||||||
} else {
|
break;
|
||||||
|
case FormatScanMode.Text:
|
||||||
if (ch === '{') {
|
if (ch === '{') {
|
||||||
insideParam = true;
|
mode = FormatScanMode.ScanningParamName;
|
||||||
} else {
|
} else {
|
||||||
out += ch;
|
out += ch;
|
||||||
}
|
}
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
throw new Error(`Invalid format scanning mode.`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
|
|
||||||
|
function push() {
|
||||||
|
let value = data[name]!;
|
||||||
|
if (value === undefined) {
|
||||||
|
throw new Error(`Format string requires key '${name}' but it was not provided.`)
|
||||||
|
}
|
||||||
|
for (const modifier of modifiers) {
|
||||||
|
const modifierFn = FORMAT_MODIFIERS[modifier];
|
||||||
|
if (modifierFn === undefined) {
|
||||||
|
throw new Error(`A format modifier named '${modifier}' was not found.`)
|
||||||
|
}
|
||||||
|
value = modifierFn(value);
|
||||||
|
}
|
||||||
|
out += value.toString();
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
function reset() {
|
function reset() {
|
||||||
name = '';
|
name = '';
|
||||||
insideParam = false;
|
modifierName = '';
|
||||||
|
mode = FormatScanMode.Text;
|
||||||
|
modifiers = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue