Skip to content

Commit

Permalink
feat: use chalk for standard colors
Browse files Browse the repository at this point in the history
  • Loading branch information
mdonnalley committed Nov 9, 2023
1 parent 418d124 commit 52f2240
Show file tree
Hide file tree
Showing 14 changed files with 319 additions and 287 deletions.
6 changes: 4 additions & 2 deletions src/config/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,16 @@ import {Command} from '../command'
import {CLIError, error, exit, warn} from '../errors'
import {getHelpFlagAdditions} from '../help/util'
import {Hook, Hooks, PJSON, Topic} from '../interfaces'
import {ArchTypes, Config as IConfig, LoadOptions, PlatformTypes, Theme, VersionDetails} from '../interfaces/config'
import {ArchTypes, Config as IConfig, LoadOptions, PlatformTypes, VersionDetails} from '../interfaces/config'
import {Plugin as IPlugin, Options} from '../interfaces/plugin'
import {Theme} from '../interfaces/theme'
import {loadWithData} from '../module-loader'
import {OCLIF_MARKER_OWNER, Performance} from '../performance'
import {settings} from '../settings'
import {requireJson, safeReadJson} from '../util/fs'
import {getHomeDir, getPlatform} from '../util/os'
import {compact, isProd, parseTheme} from '../util/util'
import {parseTheme} from '../util/theme'
import {compact, isProd} from '../util/util'
import Cache from './cache'
import PluginLoader from './plugin-loader'
import {tsPath} from './ts-node'
Expand Down
2 changes: 1 addition & 1 deletion src/help/command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import stripAnsi from 'strip-ansi'
import {Command} from '../command'
import * as Interfaces from '../interfaces'
import {ensureArgObject} from '../util/ensure-arg-object'
import {colorize} from '../util/theme'
import {castArray, compact, sortBy} from '../util/util'
import {DocOpts} from './docopts'
import {HelpFormatter, HelpSection, HelpSectionRenderer} from './formatter'
import {colorize} from './util'

// Don't use os.EOL because we need to ensure that a string
// written on any platform, that may use \r\n or \n, will be
Expand Down
3 changes: 2 additions & 1 deletion src/help/formatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import wrap from 'wrap-ansi'
import {Command} from '../command'
import * as Interfaces from '../interfaces'
import {stdtermwidth} from '../screen'
import {colorize, template} from './util'
import {colorize} from '../util/theme'
import {template} from './util'

export type HelpSectionKeyValueTable = {description: string; name: string}[]
export type HelpSection =
Expand Down
9 changes: 2 additions & 7 deletions src/help/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,12 @@ import {error} from '../errors'
import * as Interfaces from '../interfaces'
import {load} from '../module-loader'
import {cacheDefaultValue} from '../util/cache-default-value'
import {colorize} from '../util/theme'
import {compact, sortBy, uniqBy} from '../util/util'
import {CommandHelp} from './command'
import {HelpFormatter} from './formatter'
import RootHelp from './root'
import {
colorize,
formatCommandDeprecationWarning,
getHelpFlagAdditions,
standardizeIDFromArgv,
toConfiguredId,
} from './util'
import {formatCommandDeprecationWarning, getHelpFlagAdditions, standardizeIDFromArgv, toConfiguredId} from './util'

export {CommandHelp} from './command'
export {getHelpFlagAdditions, normalizeArgv, standardizeIDFromArgv} from './util'
Expand Down
2 changes: 1 addition & 1 deletion src/help/root.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import stripAnsi from 'strip-ansi'

import * as Interfaces from '../interfaces'
import {colorize} from '../util/theme'
import {compact} from '../util/util'
import {HelpFormatter} from './formatter'
import {colorize} from './util'

export default class RootHelp extends HelpFormatter {
constructor(
Expand Down
6 changes: 0 additions & 6 deletions src/help/util.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import chalk from 'chalk'
import * as Color from 'color'
import * as ejs from 'ejs'

import {collectUsableIds} from '../config/util'
Expand Down Expand Up @@ -109,7 +107,3 @@ export function normalizeArgv(config: IConfig, argv = process.argv.slice(2)): st
if (config.topicSeparator !== ':' && !argv[0]?.includes(':')) argv = standardizeIDFromArgv(argv, config)
return argv
}

export function colorize(color: Color | undefined, text: string): string {
return color ? chalk.hex(color.hex())(text) : text
}
23 changes: 1 addition & 22 deletions src/interfaces/config.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import * as Color from 'color'

import {Command} from '../command'
import {Hook, Hooks} from './hooks'
import {PJSON} from './pjson'
import {Options, Plugin} from './plugin'
import {Theme} from './theme'
import {Topic} from './topic'

export type LoadOptions = Config | Options | string | undefined
Expand All @@ -26,26 +25,6 @@ export type VersionDetails = {
shell?: string
}

export const THEME_KEYS = [
'alias',
'bin',
'command',
'commandSummary',
'dollarSign',
'flag',
'flagDefaultValue',
'flagOptions',
'flagRequired',
'flagSeparator',
'flagType',
'sectionDescription',
'sectionHeader',
'topic',
'version',
]

export type Theme = Record<string, Color>

export interface Config {
/**
* process.arch
Expand Down
43 changes: 43 additions & 0 deletions src/interfaces/theme.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import * as Color from 'color'

// chalk doesn't export a list of standard colors, so we have to supply our own
export const STANDARD_CHALK = [
'white',
'black',
'blue',
'yellow',
'green',
'red',
'magenta',
'cyan',
'gray',
'blackBright',
'redBright',
'greenBright',
'yellowBright',
'blueBright',
'magentaBright',
'cyanBright',
'whiteBright',
'bgBlack',
'bgRed',
'bgGreen',
'bgYellow',
'bgBlue',
'bgMagenta',
'bgCyan',
'bgWhite',
'bgGray',
'bgBlackBright',
'bgRedBright',
'bgGreenBright',
'bgYellowBright',
'bgBlueBright',
'bgMagentaBright',
'bgCyanBright',
'bgWhiteBright',
] as const

export type StandardChalk = (typeof STANDARD_CHALK)[number]

export type Theme = Record<string, Color | StandardChalk>
170 changes: 170 additions & 0 deletions src/util/theme.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
import chalk from 'chalk'
import * as Color from 'color'

import {STANDARD_CHALK, StandardChalk, Theme} from '../interfaces/theme'

// eslint-disable-next-line complexity
function standardChalk(color: StandardChalk, text: string): string {
switch (color) {
case 'red': {
return chalk.red(text)
}

case 'blue': {
return chalk.blue(text)
}

case 'yellow': {
return chalk.yellow(text)
}

case 'green': {
return chalk.green(text)
}

case 'cyan': {
return chalk.cyan(text)
}

case 'magenta': {
return chalk.magenta(text)
}

case 'white': {
return chalk.white(text)
}

case 'black': {
return chalk.black(text)
}

case 'gray': {
return chalk.gray(text)
}

case 'blackBright': {
return chalk.blackBright(text)
}

case 'redBright': {
return chalk.redBright(text)
}

case 'greenBright': {
return chalk.greenBright(text)
}

case 'yellowBright': {
return chalk.yellowBright(text)
}

case 'blueBright': {
return chalk.blueBright(text)
}

case 'magentaBright': {
return chalk.magentaBright(text)
}

case 'cyanBright': {
return chalk.cyanBright(text)
}

case 'whiteBright': {
return chalk.whiteBright(text)
}

case 'bgBlack': {
return chalk.bgBlack(text)
}

case 'bgRed': {
return chalk.bgRed(text)
}

case 'bgGreen': {
return chalk.bgGreen(text)
}

case 'bgYellow': {
return chalk.bgYellow(text)
}

case 'bgBlue': {
return chalk.bgBlue(text)
}

case 'bgMagenta': {
return chalk.bgMagenta(text)
}

case 'bgCyan': {
return chalk.bgCyan(text)
}

case 'bgWhite': {
return chalk.bgWhite(text)
}

case 'bgGray': {
return chalk.bgGray(text)
}

case 'bgBlackBright': {
return chalk.bgBlackBright(text)
}

case 'bgRedBright': {
return chalk.bgRedBright(text)
}

case 'bgGreenBright': {
return chalk.bgGreenBright(text)
}

case 'bgYellowBright': {
return chalk.bgYellowBright(text)
}

case 'bgBlueBright': {
return chalk.bgBlueBright(text)
}

case 'bgMagentaBright': {
return chalk.bgMagentaBright(text)
}

case 'bgCyanBright': {
return chalk.bgCyanBright(text)
}

case 'bgWhiteBright': {
return chalk.bgWhiteBright(text)
}

default: {
return chalk.gray(text)
}
}
}

function isStandardChalk(color: any): color is StandardChalk {
return STANDARD_CHALK.includes(color)
}

export function colorize(color: Color | StandardChalk | undefined, text: string): string {
if (isStandardChalk(color)) return standardChalk(color, text)

return color ? chalk.hex(color.hex())(text) : text
}

export function parseTheme(untypedTheme: Record<string, string>): Theme {
return Object.fromEntries(Object.entries(untypedTheme).map(([key, value]) => [key, getColor(value)]))
}

export function getColor(color: string): Color
export function getColor(color: StandardChalk): StandardChalk
export function getColor(color: string | StandardChalk): Color | StandardChalk {
// eslint-disable-next-line new-cap
return isStandardChalk(color) ? color : new Color.default(color)
}
17 changes: 0 additions & 17 deletions src/util/util.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
import * as Color from 'color'

import {THEME_KEYS, Theme} from '../interfaces/config'

export function pickBy<T extends {[s: string]: T[keyof T]} | ArrayLike<T[keyof T]>>(
obj: T,
fn: (i: T[keyof T]) => boolean,
Expand Down Expand Up @@ -109,16 +105,3 @@ function get(obj: Record<string, any>, path: string): unknown {
export function mergeNestedObjects(objs: Record<string, any>[], path: string): Record<string, any> {
return Object.fromEntries(objs.flatMap((o) => Object.entries(get(o, path) ?? {})).reverse())
}

export function parseTheme(untypedTheme: Record<string, string>): Theme {
return Object.fromEntries(
Object.entries(untypedTheme)
.filter(([key]) => THEME_KEYS.includes(key))
.map(([key, value]) => [key, getColor(value)]),
)
}

export function getColor(color: string) {
// eslint-disable-next-line new-cap
return new Color.default(color)
}
6 changes: 3 additions & 3 deletions test/config/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -405,21 +405,21 @@ describe('Config', () => {
})

describe('theme', () => {
testConfig({pjson, env: {FOO_DISABLE_THEME: 'true'}}, {bin: 'red'}).it(
testConfig({pjson, env: {FOO_DISABLE_THEME: 'true'}}, {bin: '#FF0000'}).it(
'should not be set when DISABLE_THEME is true and theme.json exists',
(config) => {
expect(config).to.have.property('theme', undefined)
},
)

testConfig({pjson, env: {FOO_DISABLE_THEME: 'false'}}, {bin: 'red'}).it(
testConfig({pjson, env: {FOO_DISABLE_THEME: 'false'}}, {bin: '#FF0000'}).it(
'should be set when DISABLE_THEME is false and theme.json exists',
(config) => {
expect(config).to.nested.include({'theme.bin.color[0]': 255})
},
)

testConfig({pjson, env: {}}, {bin: 'red'}).it(
testConfig({pjson, env: {}}, {bin: '#FF0000'}).it(
'should be set when DISABLE_THEME is unset and theme.json exists',
(config) => {
expect(config).to.nested.include({'theme.bin.color[0]': 255})
Expand Down
Loading

0 comments on commit 52f2240

Please sign in to comment.