From 93409294e65f83fcab56f522dee8d4405ad0ee4c Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Sun, 7 Feb 2021 08:51:19 +0800 Subject: [PATCH] CLI: clear printed long filenames (#10217) --- changelog_unreleased/cli/10217.md | 17 +++++++++++ cspell.json | 1 + package.json | 3 +- src/cli/format.js | 24 +++++++++------- src/cli/logger.js | 48 +++++++++++++++++++++++++++---- yarn.lock | 20 +++++++++++++ 6 files changed, 97 insertions(+), 16 deletions(-) create mode 100644 changelog_unreleased/cli/10217.md diff --git a/changelog_unreleased/cli/10217.md b/changelog_unreleased/cli/10217.md new file mode 100644 index 000000000..aba596519 --- /dev/null +++ b/changelog_unreleased/cli/10217.md @@ -0,0 +1,17 @@ +#### Clear printed long filenames of formatting file (#10217 by @fisker) + + +```console +# Prettier stable +$ prettier tests/flow-repo/config_module_system_node_resolve_dirname --check +Checking formatting... +tests\flow-repo\config_module_system_node_resolve_dirname\custom_resolve_dir\tes +tests\flow-repo\config_module_system_node_resolve_dirname\custom_resolve_dir\tes +tests\flow-repo\config_module_system_node_resolve_dirname\subdir\custom_resolve_ +All matched files use Prettier code style! + +// Prettier main +$ prettier tests/flow-repo/config_module_system_node_resolve_dirname --check +Checking formatting... +All matched files use Prettier code style! +``` diff --git a/cspell.json b/cspell.json index 81a7a1e1f..70cb29467 100644 --- a/cspell.json +++ b/cspell.json @@ -411,6 +411,7 @@ "Vue's", "Wadler", "Wadler's", + "wcwidth", "webcompat", "webstorm", "Weixin", diff --git a/package.json b/package.json index eb609cea6..063213466 100644 --- a/package.json +++ b/package.json @@ -78,10 +78,12 @@ "resolve": "1.19.0", "semver": "7.3.4", "string-width": "4.2.0", + "strip-ansi": "6.0.0", "typescript": "4.1.3", "unicode-regex": "3.0.0", "unified": "9.2.0", "vnopts": "1.0.2", + "wcwidth": "1.0.1", "yaml-unist-parser": "1.3.1" }, "devDependencies": { @@ -127,7 +129,6 @@ "rollup-plugin-terser": "7.0.2", "shelljs": "0.8.4", "snapshot-diff": "0.8.1", - "strip-ansi": "6.0.0", "synchronous-promise": "2.0.15", "tempy": "1.0.0", "terser-webpack-plugin": "5.1.1", diff --git a/src/cli/format.js b/src/cli/format.js index d9fcc8d12..e611408cb 100644 --- a/src/cli/format.js +++ b/src/cli/format.js @@ -1,7 +1,6 @@ "use strict"; const fs = require("fs"); -const readline = require("readline"); const path = require("path"); const chalk = require("chalk"); @@ -22,13 +21,15 @@ function diff(a, b) { }); } -function handleError(context, filename, error) { +function handleError(context, filename, error, printedFilename) { if (error instanceof errors.UndefinedParserError) { // Can't test on CI, `isTTY()` is always false, see ./is-tty.js /* istanbul ignore next */ - if ((context.argv.write || context.argv["ignore-unknown"]) && isTTY()) { - readline.clearLine(process.stdout, 0); - readline.cursorTo(process.stdout, 0, null); + if ( + (context.argv.write || context.argv["ignore-unknown"]) && + printedFilename + ) { + printedFilename.clear(); } if (context.argv["ignore-unknown"]) { return; @@ -308,8 +309,12 @@ function formatFiles(context) { filepath: filename, }; + let printedFilename; if (isTTY()) { - context.logger.log(filename, { newline: false }); + printedFilename = context.logger.log(filename, { + newline: false, + clearable: true, + }); } let input; @@ -347,16 +352,15 @@ function formatFiles(context) { result = format(context, input, options); output = result.formatted; } catch (error) { - handleError(context, filename, error); + handleError(context, filename, error, printedFilename); continue; } const isDifferent = output !== input; - if (isTTY()) { + if (printedFilename) { // Remove previously printed filename to log it with duration. - readline.clearLine(process.stdout, 0); - readline.cursorTo(process.stdout, 0, null); + printedFilename.clear(); } if (context.argv.write) { diff --git a/src/cli/logger.js b/src/cli/logger.js index c899381d5..f85a8df9a 100644 --- a/src/cli/logger.js +++ b/src/cli/logger.js @@ -1,7 +1,33 @@ "use strict"; +const readline = require("readline"); const chalk = require("chalk"); +const stripAnsi = require("strip-ansi"); +const wcwidth = require("wcwidth"); +const countLines = (stream, text) => { + const columns = stream.columns || 80; + let lineCount = 0; + for (const line of stripAnsi(text).split("\n")) { + lineCount += Math.max(1, Math.ceil(wcwidth(line) / columns)); + } + return lineCount; +}; + +const clear = (stream, text) => () => { + const lineCount = countLines(stream, text); + + for (let line = 0; line < lineCount; line++) { + if (line > 0) { + readline.moveCursor(stream, 0, -1); + } + + readline.clearLine(stream, 0); + readline.cursorTo(stream, 0); + } +}; + +const emptyLogResult = { clear() {} }; function createLogger(logLevel) { return { warn: createLogFunc("warn", "yellow"), @@ -12,14 +38,26 @@ function createLogger(logLevel) { function createLogFunc(loggerName, color) { if (!shouldLog(loggerName)) { - return () => {}; + return () => emptyLogResult; } const prefix = color ? `[${chalk[color](loggerName)}] ` : ""; - return function (message, opts) { - opts = { newline: true, ...opts }; - const stream = process[loggerName === "log" ? "stdout" : "stderr"]; - stream.write(message.replace(/^/gm, prefix) + (opts.newline ? "\n" : "")); + const stream = process[loggerName === "log" ? "stdout" : "stderr"]; + + return (message, options) => { + options = { + newline: true, + clearable: false, + ...options, + }; + message = message.replace(/^/gm, prefix) + (options.newline ? "\n" : ""); + stream.write(message); + + if (options.clearable) { + return { + clear: clear(stream, message), + }; + } }; } diff --git a/yarn.lock b/yarn.lock index 5e988ac5a..591822cc6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2381,6 +2381,11 @@ cliui@^6.0.0: strip-ansi "^6.0.0" wrap-ansi "^6.2.0" +clone@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" + integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= + co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" @@ -2731,6 +2736,13 @@ deepmerge@^4.2.2: resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== +defaults@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" + integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730= + dependencies: + clone "^1.0.2" + define-properties@^1.1.2, define-properties@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" @@ -3055,6 +3067,7 @@ eslint-plugin-jest@24.1.3: "eslint-plugin-prettier-internal-rules@link:scripts/tools/eslint-plugin-prettier-internal-rules": version "0.0.0" + uid "" eslint-plugin-react@7.22.0: version "7.22.0" @@ -7280,6 +7293,13 @@ watchpack@^2.0.0: glob-to-regexp "^0.4.1" graceful-fs "^4.1.2" +wcwidth@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" + integrity sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g= + dependencies: + defaults "^1.0.3" + webidl-conversions@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff"