diff options
author | Ruben Bridgewater <ruben@bridgewater.de> | 2020-01-11 21:48:40 +0300 |
---|---|---|
committer | Ruben Bridgewater <ruben@bridgewater.de> | 2020-01-22 17:33:03 +0300 |
commit | 8fb5fe28a45cc884567cd39e3b2f6b4272917af6 (patch) | |
tree | 3d27acb62947f1d2344b8f55bafc0e898ae7629f /lib/internal/readline | |
parent | 2606e1ed25b63694adccf7756d10ef51722a14ce (diff) |
util: improve unicode support
The array grouping function relies on the width of the characters.
It was not calculated correct so far, since it used the string
length instead.
This improves the unicode output by calculating the mono-spaced
font width (other fonts might differ).
PR-URL: https://github.com/nodejs/node/pull/31319
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Steven R Loomis <srloomis@us.ibm.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Minwoo Jung <nodecorelab@gmail.com>
Diffstat (limited to 'lib/internal/readline')
-rw-r--r-- | lib/internal/readline/utils.js | 117 |
1 files changed, 0 insertions, 117 deletions
diff --git a/lib/internal/readline/utils.js b/lib/internal/readline/utils.js index ffe0cee9d4b..0b9fe8cde4f 100644 --- a/lib/internal/readline/utils.js +++ b/lib/internal/readline/utils.js @@ -1,25 +1,13 @@ 'use strict'; const { - RegExp, Symbol, } = primordials; -// Regex used for ansi escape code splitting -// Adopted from https://github.com/chalk/ansi-regex/blob/master/index.js -// License: MIT, authors: @sindresorhus, Qix-, arjunmehta and LitoMore -// Matches all ansi escape code sequences in a string -const ansiPattern = '[\\u001B\\u009B][[\\]()#;?]*' + - '(?:(?:(?:[a-zA-Z\\d]*(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)' + - '|(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))'; -const ansi = new RegExp(ansiPattern, 'g'); - const kUTF16SurrogateThreshold = 0x10000; // 2 ** 16 const kEscape = '\x1b'; const kSubstringSearch = Symbol('kSubstringSearch'); -let getStringWidth; - function CSI(strings, ...args) { let ret = `${kEscape}[`; for (let n = 0; n < strings.length; n++) { @@ -59,109 +47,6 @@ function charLengthAt(str, i) { return str.codePointAt(i) >= kUTF16SurrogateThreshold ? 2 : 1; } -if (internalBinding('config').hasIntl) { - const icu = internalBinding('icu'); - // icu.getStringWidth(string, ambiguousAsFullWidth, expandEmojiSequence) - // Defaults: ambiguousAsFullWidth = false; expandEmojiSequence = true; - // TODO(BridgeAR): Expose the options to the user. That is probably the - // best thing possible at the moment, since it's difficult to know what - // the receiving end supports. - getStringWidth = function getStringWidth(str) { - let width = 0; - str = stripVTControlCharacters(str); - for (let i = 0; i < str.length; i++) { - // Try to avoid calling into C++ by first handling the ASCII portion of - // the string. If it is fully ASCII, we skip the C++ part. - const code = str.charCodeAt(i); - if (code >= 127) { - width += icu.getStringWidth(str.slice(i)); - break; - } - width += code >= 32 ? 1 : 0; - } - return width; - }; -} else { - /** - * Returns the number of columns required to display the given string. - */ - getStringWidth = function getStringWidth(str) { - let width = 0; - - str = stripVTControlCharacters(str); - - for (const char of str) { - const code = char.codePointAt(0); - if (isFullWidthCodePoint(code)) { - width += 2; - } else if (!isZeroWidthCodePoint(code)) { - width++; - } - } - - return width; - }; - - /** - * Returns true if the character represented by a given - * Unicode code point is full-width. Otherwise returns false. - */ - const isFullWidthCodePoint = (code) => { - // Code points are partially derived from: - // http://www.unicode.org/Public/UNIDATA/EastAsianWidth.txt - return code >= 0x1100 && ( - code <= 0x115f || // Hangul Jamo - code === 0x2329 || // LEFT-POINTING ANGLE BRACKET - code === 0x232a || // RIGHT-POINTING ANGLE BRACKET - // CJK Radicals Supplement .. Enclosed CJK Letters and Months - (code >= 0x2e80 && code <= 0x3247 && code !== 0x303f) || - // Enclosed CJK Letters and Months .. CJK Unified Ideographs Extension A - (code >= 0x3250 && code <= 0x4dbf) || - // CJK Unified Ideographs .. Yi Radicals - (code >= 0x4e00 && code <= 0xa4c6) || - // Hangul Jamo Extended-A - (code >= 0xa960 && code <= 0xa97c) || - // Hangul Syllables - (code >= 0xac00 && code <= 0xd7a3) || - // CJK Compatibility Ideographs - (code >= 0xf900 && code <= 0xfaff) || - // Vertical Forms - (code >= 0xfe10 && code <= 0xfe19) || - // CJK Compatibility Forms .. Small Form Variants - (code >= 0xfe30 && code <= 0xfe6b) || - // Halfwidth and Fullwidth Forms - (code >= 0xff01 && code <= 0xff60) || - (code >= 0xffe0 && code <= 0xffe6) || - // Kana Supplement - (code >= 0x1b000 && code <= 0x1b001) || - // Enclosed Ideographic Supplement - (code >= 0x1f200 && code <= 0x1f251) || - // Miscellaneous Symbols and Pictographs .. Emoticons - (code >= 0x1f300 && code <= 0x1f64f) || - // CJK Unified Ideographs Extension B .. Tertiary Ideographic Plane - (code >= 0x20000 && code <= 0x3fffd) - ); - }; - - const isZeroWidthCodePoint = (code) => { - return code <= 0x1F || // C0 control codes - (code > 0x7F && code <= 0x9F) || // C1 control codes - (code >= 0x0300 && code <= 0x036F) || // Combining Diacritical Marks - (code >= 0x200B && code <= 0x200F) || // Modifying Invisible Characters - (code >= 0xFE00 && code <= 0xFE0F) || // Variation Selectors - (code >= 0xFE20 && code <= 0xFE2F) || // Combining Half Marks - (code >= 0xE0100 && code <= 0xE01EF); // Variation Selectors - }; -} - -/** - * Tries to remove all VT control characters. Use to estimate displayed - * string width. May be buggy due to not running a real state machine - */ -function stripVTControlCharacters(str) { - return str.replace(ansi, ''); -} - /* Some patterns seen in terminal key escape codes, derived from combos seen at http://www.midnight-commander.org/browser/lib/tty/key.c @@ -477,8 +362,6 @@ module.exports = { charLengthLeft, commonPrefix, emitKeys, - getStringWidth, kSubstringSearch, - stripVTControlCharacters, CSI }; |