mirror of
https://github.com/denoland/deno.git
synced 2024-11-30 16:40:57 -05:00
Rework color API (#134)
This commit is contained in:
parent
4283c26b89
commit
fa5b3dfc9c
5 changed files with 147 additions and 118 deletions
|
@ -1,18 +1,19 @@
|
|||
# colors
|
||||
|
||||
Is a basic console color module intended for [Deno](https://deno.land/). It is
|
||||
inspired by [chalk](https://www.npmjs.com/package/chalk) and
|
||||
inspired by [chalk](https://www.npmjs.com/package/chalk),
|
||||
[kleur](https://www.npmjs.com/package/kleur), and
|
||||
[colors](https://www.npmjs.com/package/colors) on npm.
|
||||
|
||||
## Usage
|
||||
|
||||
The main modules exports a single function name `color` which is a function that
|
||||
provides chaining to stack colors. Basic usage looks like this:
|
||||
The main modules exports several functions which can color the output to the
|
||||
console:
|
||||
|
||||
```ts
|
||||
import { color } from "https://deno.land/x/std/colors/mod.ts";
|
||||
import { bgBlue, red, bold } from "https://deno.land/x/std/colors/mod.ts";
|
||||
|
||||
console.log(color.bgBlue.red.bold("Hello world!"));
|
||||
console.log(bgBlue(red(bold("Hello world!"))));
|
||||
```
|
||||
|
||||
## TODO
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
import { color } from "./mod.ts";
|
||||
import { bgBlue, red, bold, italic } from "./mod.ts";
|
||||
|
||||
console.log(color.bgBlue.red.bold("Hello world!"));
|
||||
console.log(bgBlue(italic(red(bold("Hello world!")))));
|
||||
|
|
158
colors/mod.ts
158
colors/mod.ts
|
@ -1,33 +1,131 @@
|
|||
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
|
||||
import { styles } from "./styles.ts";
|
||||
|
||||
type Styles = { readonly [S in keyof typeof styles]: Color };
|
||||
|
||||
type Color = Styles & {
|
||||
(str: string): string;
|
||||
};
|
||||
|
||||
const styleStack: string[] = [];
|
||||
|
||||
export const color = function color(str: string): string {
|
||||
styleStack.reverse();
|
||||
while (styleStack.length) {
|
||||
const style = styleStack.pop();
|
||||
const code = styles[style];
|
||||
str = `${code.open}${str.replace(code.closeRe, code.open)}${
|
||||
code.close
|
||||
}`.replace(/\r?\n/g, `${code.close}$&${code.open}`);
|
||||
}
|
||||
return str;
|
||||
} as Color;
|
||||
|
||||
for (const style of Object.keys(styles)) {
|
||||
Object.defineProperty(color, style, {
|
||||
get() {
|
||||
styleStack.push(style);
|
||||
return color;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: false
|
||||
});
|
||||
interface Code {
|
||||
open: string;
|
||||
close: string;
|
||||
regexp: RegExp;
|
||||
}
|
||||
|
||||
let enabled = true;
|
||||
|
||||
export function setEnabled(value: boolean) {
|
||||
enabled = value;
|
||||
}
|
||||
|
||||
export function getEnabled(): boolean {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
function code(open: number, close: number): Code {
|
||||
return {
|
||||
open: `\x1b[${open}m`,
|
||||
close: `\x1b[${close}m`,
|
||||
regexp: new RegExp(`\\x1b\\[${close}m`, "g")
|
||||
};
|
||||
}
|
||||
|
||||
function run(str: string, code: Code) {
|
||||
return enabled
|
||||
? `${code.open}${str.replace(code.regexp, code.open)}${code.close}`
|
||||
: str;
|
||||
}
|
||||
|
||||
export function reset(str: string): string {
|
||||
return run(str, code(0, 0));
|
||||
}
|
||||
|
||||
export function bold(str: string): string {
|
||||
return run(str, code(1, 22));
|
||||
}
|
||||
|
||||
export function dim(str: string): string {
|
||||
return run(str, code(2, 22));
|
||||
}
|
||||
|
||||
export function italic(str: string): string {
|
||||
return run(str, code(3, 23));
|
||||
}
|
||||
|
||||
export function underline(str: string): string {
|
||||
return run(str, code(4, 24));
|
||||
}
|
||||
|
||||
export function inverse(str: string): string {
|
||||
return run(str, code(7, 27));
|
||||
}
|
||||
|
||||
export function hidden(str: string): string {
|
||||
return run(str, code(8, 28));
|
||||
}
|
||||
|
||||
export function strikethrough(str: string): string {
|
||||
return run(str, code(9, 29));
|
||||
}
|
||||
|
||||
export function black(str: string): string {
|
||||
return run(str, code(30, 39));
|
||||
}
|
||||
|
||||
export function red(str: string): string {
|
||||
return run(str, code(31, 39));
|
||||
}
|
||||
|
||||
export function green(str: string): string {
|
||||
return run(str, code(32, 39));
|
||||
}
|
||||
|
||||
export function yellow(str: string): string {
|
||||
return run(str, code(33, 39));
|
||||
}
|
||||
|
||||
export function blue(str: string): string {
|
||||
return run(str, code(34, 39));
|
||||
}
|
||||
|
||||
export function magenta(str: string): string {
|
||||
return run(str, code(35, 39));
|
||||
}
|
||||
|
||||
export function cyan(str: string): string {
|
||||
return run(str, code(36, 39));
|
||||
}
|
||||
|
||||
export function white(str: string): string {
|
||||
return run(str, code(37, 39));
|
||||
}
|
||||
|
||||
export function gray(str: string): string {
|
||||
return run(str, code(90, 39));
|
||||
}
|
||||
|
||||
export function bgBlack(str: string): string {
|
||||
return run(str, code(40, 49));
|
||||
}
|
||||
|
||||
export function bgRed(str: string): string {
|
||||
return run(str, code(41, 49));
|
||||
}
|
||||
|
||||
export function bgGreen(str: string): string {
|
||||
return run(str, code(42, 49));
|
||||
}
|
||||
|
||||
export function bgYellow(str: string): string {
|
||||
return run(str, code(43, 49));
|
||||
}
|
||||
|
||||
export function bgBlue(str: string): string {
|
||||
return run(str, code(44, 49));
|
||||
}
|
||||
|
||||
export function bgMagenta(str: string): string {
|
||||
return run(str, code(45, 49));
|
||||
}
|
||||
|
||||
export function bgCyan(str: string): string {
|
||||
return run(str, code(46, 49));
|
||||
}
|
||||
|
||||
export function bgWhite(str: string): string {
|
||||
return run(str, code(47, 49));
|
||||
}
|
||||
|
|
|
@ -1,66 +0,0 @@
|
|||
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
|
||||
const matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g;
|
||||
function escapeStringRegexp(str: string): string {
|
||||
return str.replace(matchOperatorsRe, "\\$&");
|
||||
}
|
||||
|
||||
const codes = {
|
||||
reset: [0, 0],
|
||||
bold: [1, 22],
|
||||
dim: [2, 22],
|
||||
italic: [3, 23],
|
||||
underline: [4, 24],
|
||||
inverse: [7, 27],
|
||||
hidden: [8, 28],
|
||||
strikethrough: [9, 29],
|
||||
|
||||
black: [30, 39],
|
||||
red: [31, 39],
|
||||
green: [32, 39],
|
||||
yellow: [33, 39],
|
||||
blue: [34, 39],
|
||||
magenta: [35, 39],
|
||||
cyan: [36, 39],
|
||||
white: [37, 39],
|
||||
|
||||
blackBright: [90, 39],
|
||||
redBright: [91, 39],
|
||||
greenBright: [92, 39],
|
||||
yellowBright: [93, 39],
|
||||
blueBright: [94, 39],
|
||||
magentaBright: [95, 39],
|
||||
cyanBright: [96, 39],
|
||||
whiteBright: [97, 39],
|
||||
|
||||
bgBlack: [40, 49],
|
||||
bgRed: [41, 49],
|
||||
bgGreen: [42, 49],
|
||||
bgYellow: [43, 49],
|
||||
bgBlue: [44, 49],
|
||||
bgMagenta: [45, 49],
|
||||
bgCyan: [46, 49],
|
||||
bgWhite: [47, 49],
|
||||
|
||||
bgBlackBright: [100, 49],
|
||||
bgRedBright: [101, 49],
|
||||
bgGreenBright: [102, 49],
|
||||
bgYellowBright: [103, 49],
|
||||
bgBlueBright: [104, 49],
|
||||
bgMagentaBright: [105, 49],
|
||||
bgCyanBright: [106, 49],
|
||||
bgWhiteBright: [107, 49]
|
||||
};
|
||||
|
||||
type Styles<T> = {
|
||||
[S in keyof T]: { open: string; close: string; closeRe: RegExp }
|
||||
};
|
||||
|
||||
export const styles: Styles<typeof codes> = {} as any;
|
||||
|
||||
for (const [style, [open, close]] of Object.entries(codes)) {
|
||||
styles[style] = {
|
||||
open: `\u001b[${open}m`,
|
||||
close: `\u001b[${close}m`,
|
||||
closeRe: new RegExp(escapeStringRegexp(`\u001b[${close}m`), "g")
|
||||
};
|
||||
}
|
|
@ -1,25 +1,21 @@
|
|||
import { assertEqual, test } from "../testing/mod.ts";
|
||||
import { color } from "./mod.ts";
|
||||
import { assert, test } from "../testing/mod.ts";
|
||||
import { red, bgBlue, setEnabled, getEnabled } from "./mod.ts";
|
||||
import "./example.ts";
|
||||
|
||||
test(function singleColor() {
|
||||
assertEqual(color.red("Hello world"), "[31mHello world[39m");
|
||||
assert.equal(red("Hello world"), "[31mHello world[39m");
|
||||
});
|
||||
|
||||
test(function doubleColor() {
|
||||
assertEqual(color.red.bgBlue("Hello world"),
|
||||
"[44m[31mHello world[39m[49m");
|
||||
});
|
||||
|
||||
test(function newLinesContinueColors() {
|
||||
assertEqual(color.red("Hello\nworld"),
|
||||
"[31mHello[39m\n[31mworld[39m");
|
||||
assertEqual(color.red("Hello\r\nworld"),
|
||||
"[31mHello[39m\r\n[31mworld[39m");
|
||||
assertEqual(color.red("Hello\n\nworld"),
|
||||
"[31mHello[39m\n[31m[39m\n[31mworld[39m");
|
||||
assert.equal(bgBlue(red("Hello world")), "[44m[31mHello world[39m[49m");
|
||||
});
|
||||
|
||||
test(function replacesCloseCharacters() {
|
||||
assertEqual(color.red("Hel[39mlo"), "[31mHel[31mlo[39m");
|
||||
assert.equal(red("Hel[39mlo"), "[31mHel[31mlo[39m");
|
||||
});
|
||||
|
||||
test(function enablingColors() {
|
||||
assert.equal(getEnabled(), true);
|
||||
setEnabled(false);
|
||||
assert.equal(bgBlue(red("Hello world")), "Hello world");
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue