From 3e541e14f302eeb8aff7dd2004d042f1703acf4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ey=C3=BE=C3=B3r=20Magn=C3=BAsson?= Date: Wed, 26 Sep 2018 15:40:54 +0000 Subject: [PATCH] fix(logger): only print emoji if env supports it --- docs/reference/commands.md | 1 + garden-cli/src/cli/cli.ts | 10 ++++++++-- garden-cli/src/cli/helpers.ts | 9 ++++++++- garden-cli/src/logger/log-entry.ts | 2 ++ garden-cli/src/logger/logger.ts | 14 ++++++++------ garden-cli/src/logger/renderers.ts | 13 ++++++++++--- garden-cli/src/logger/writers/file-writer.ts | 1 - 7 files changed, 37 insertions(+), 13 deletions(-) diff --git a/docs/reference/commands.md b/docs/reference/commands.md index 39e5b294e9..653db9e6ab 100644 --- a/docs/reference/commands.md +++ b/docs/reference/commands.md @@ -18,6 +18,7 @@ The following option flags can be used with any of the CLI commands: | `--env` | `-e` | string | The environment (and optionally namespace) to work against | `--loglevel` | `-l` | `error` `warn` `info` `verbose` `debug` `silly` `0` `1` `2` `3` `4` `5` | Set logger level. Values can be either string or numeric and are prioritized from 0 to 5 (highest to lowest) as follows: error: 0, warn: 1, info: 2, verbose: 3, debug: 4, silly: 5 | `--output` | `-o` | `json` `yaml` | Output command result in specified format (note: disables progress logging). + | `--emoji` | | boolean | Enable emoji in output (defaults to true if the environment supports it). ### garden build diff --git a/garden-cli/src/cli/cli.ts b/garden-cli/src/cli/cli.ts index f8df74fcd3..8bd527a218 100644 --- a/garden-cli/src/cli/cli.ts +++ b/garden-cli/src/cli/cli.ts @@ -52,6 +52,7 @@ import { prepareArgConfig, prepareOptionConfig, styleConfig, + envSupportsEmoji, } from "./helpers" import { GardenConfig } from "../config/base" import { defaultEnvironments } from "../config/project" @@ -125,6 +126,10 @@ export const GLOBAL_OPTIONS = { choices: Object.keys(OUTPUT_RENDERERS), help: "Output command result in specified format (note: disables progress logging).", }), + emoji: new BooleanParameter({ + help: "Enable emoji in output (defaults to true if the environment supports it).", + defaultValue: envSupportsEmoji(), + }), } const GLOBAL_OPTIONS_GROUP_NAME = "Global options" const DEFAULT_CLI_LOGGER_TYPE = LoggerType.fancy @@ -206,10 +211,11 @@ export class GardenCli { const action = async (argv, cliContext) => { // Sywac returns positional args and options in a single object which we separate into args and opts + const parsedArgs = filterByKeys(argv, argKeys) const parsedOpts = filterByKeys(argv, optKeys.concat(globalKeys)) const root = resolve(process.cwd(), parsedOpts.root) - const { env, loglevel, silent, output } = parsedOpts + const { emoji, env, loglevel, silent, output } = parsedOpts // Init logger const level = getLogLevelFromArg(loglevel) @@ -223,7 +229,7 @@ export class GardenCli { } } - const logger = Logger.initialize({ level, writers }) + const logger = Logger.initialize({ level, writers, useEmoji: emoji }) let garden: Garden let result do { diff --git a/garden-cli/src/cli/helpers.ts b/garden-cli/src/cli/helpers.ts index 831b59be01..bfae0108ca 100644 --- a/garden-cli/src/cli/helpers.ts +++ b/garden-cli/src/cli/helpers.ts @@ -51,13 +51,20 @@ ${chalk.bold(str.slice(0, 5).toUpperCase())} export const getKeys = (obj): string[] => Object.keys(obj || {}) export const filterByKeys = (obj: any, keys: string[]): any => { return keys.reduce((memo, key) => { - if (obj[key]) { + if (obj.hasOwnProperty(key)) { memo[key] = obj[key] } return memo }, {}) } +// Add platforms/terminals? +export function envSupportsEmoji() { + return process.platform === "darwin" + || process.env.TERM_PROGRAM === "Hyper" + || process.env.TERM_PROGRAM === "HyperTerm" +} + export type FalsifiedParams = { [key: string]: false } /** diff --git a/garden-cli/src/logger/log-entry.ts b/garden-cli/src/logger/log-entry.ts index 83405cb33d..974c012c1c 100644 --- a/garden-cli/src/logger/log-entry.ts +++ b/garden-cli/src/logger/log-entry.ts @@ -14,6 +14,7 @@ import { LogNode, LogLevel } from "./log-node" import { getChildEntries } from "./util" import { GardenError } from "../exceptions" import { Omit } from "../util/util" +import { Logger } from "./logger" export type EmojiName = keyof typeof nodeEmoji.emoji export type LogSymbol = keyof typeof logSymbols | "empty" @@ -51,6 +52,7 @@ export function resolveParam(param?: string | T): T { export class LogEntry extends LogNode { public opts: UpdateOpts + public root: Logger constructor({ level, opts, parent }: LogEntryConstructor) { const { id, ...otherOpts } = opts diff --git a/garden-cli/src/logger/logger.ts b/garden-cli/src/logger/logger.ts index 4360c3cdbd..c013babf65 100644 --- a/garden-cli/src/logger/logger.ts +++ b/garden-cli/src/logger/logger.ts @@ -6,18 +6,17 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import * as nodeEmoji from "node-emoji" import chalk from "chalk" import { RootLogNode, LogNode } from "./log-node" -import { LogEntry, CreateOpts, resolveParam } from "./log-entry" +import { LogEntry, CreateOpts, resolveParam, EmojiName } from "./log-entry" import { getChildEntries } from "./util" import { Writer } from "./writers/base" import { InternalError, ParameterError } from "../exceptions" import { LogLevel } from "./log-node" import { FancyTerminalWriter } from "./writers/fancy-terminal-writer" import { BasicTerminalWriter } from "./writers/basic-terminal-writer" -import { combine } from "./renderers" +import { combine, printEmoji } from "./renderers" export enum LoggerType { quiet = "quiet", @@ -45,10 +44,12 @@ export function getCommonConfig(loggerType: LoggerType): LoggerConfig { export interface LoggerConfig { level: LogLevel writers?: Writer[] + useEmoji?: boolean } export class Logger extends RootLogNode { public writers: Writer[] + public useEmoji: boolean private static instance: Logger @@ -90,6 +91,7 @@ export class Logger extends RootLogNode { private constructor(config: LoggerConfig) { super(config.level) this.writers = config.writers || [] + this.useEmoji = config.useEmoji === false ? false : true } createNode(level: LogLevel, _parent: LogNode, opts: CreateOpts) { @@ -109,11 +111,11 @@ export class Logger extends RootLogNode { } header( - { command, emoji, level = LogLevel.info }: { command: string, emoji?: string, level?: LogLevel }, + { command, emoji, level = LogLevel.info }: { command: string, emoji?: EmojiName, level?: LogLevel }, ): LogEntry { const msg = combine([ [chalk.bold.magenta(command)], - [emoji ? " " + nodeEmoji.get(emoji) : ""], + [emoji && this.useEmoji ? " " + printEmoji(emoji) : ""], ["\n"], ]) const lvlStr = LogLevel[level] @@ -124,7 +126,7 @@ export class Logger extends RootLogNode { { showDuration = true, level = LogLevel.info }: { showDuration?: boolean, level?: LogLevel } = {}, ): LogEntry { const msg = combine([ - [`\n${nodeEmoji.get("sparkles")} Finished`], + [this.useEmoji ? `\n${printEmoji("sparkles")} Finished` : "Finished"], [showDuration ? ` in ${chalk.bold(this.getDuration() + "s")}` : "!"], ["\n"], ]) diff --git a/garden-cli/src/logger/renderers.ts b/garden-cli/src/logger/renderers.ts index 37980dca07..0118cf19ea 100644 --- a/garden-cli/src/logger/renderers.ts +++ b/garden-cli/src/logger/renderers.ts @@ -24,7 +24,7 @@ import cliTruncate = require("cli-truncate") import stringWidth = require("string-width") import hasAnsi = require("has-ansi") -import { LogEntry } from "./log-entry" +import { LogEntry, EmojiName } from "./log-entry" export type ToRender = string | ((...args: any[]) => string) export type Renderer = [ToRender, any[]] | ToRender[] @@ -63,6 +63,13 @@ export function combine(renderers: Renderers): string { return applyRenderers(renderers)(initOutput).join("") } +export function printEmoji(emoji: EmojiName) { + if (nodeEmoji.hasEmoji(emoji)) { + return `${nodeEmoji.get(emoji)} ` + } + return "" +} + /*** RENDERERS ***/ export function leftPad(entry: LogEntry): string { return padStart("", (entry.opts.indentationLevel || 0) * 3) @@ -70,8 +77,8 @@ export function leftPad(entry: LogEntry): string { export function renderEmoji(entry: LogEntry): string { const { emoji } = entry.opts - if (emoji && nodeEmoji.hasEmoji(emoji)) { - return `${nodeEmoji.get(emoji)} ` + if (emoji && entry.root.useEmoji) { + return printEmoji(emoji) } return "" } diff --git a/garden-cli/src/logger/writers/file-writer.ts b/garden-cli/src/logger/writers/file-writer.ts index a9f0b69fc0..87098f05f4 100644 --- a/garden-cli/src/logger/writers/file-writer.ts +++ b/garden-cli/src/logger/writers/file-writer.ts @@ -109,7 +109,6 @@ export class FileWriter extends Writer { const out = this.render(entry) if (out) { if (!this.fileLogger) { - this.fileLogger = this.initFileLogger() } this.fileLogger.log(levelToStr(entry.level), out)