如何计算各种字符的终端列宽?

时间:2015-01-11 21:00:41

标签: javascript node.js bash terminal ascii

我希望计算各种打印和非打印ascii / unicode字符在终端视图中占用的终端列数。

例如,水平制表符(\t)占用8列,颜色代码(即\x1b32m)占用0列,固定大小的宽字符串(即한)占用2列。当然,主ASCII组中有许多只占用1列(即a-Z/0-9,标点符号等。)。

我遇到过node.js模块,wcwidth,它似乎有助于计算宽字符字符串,但不能满足我对其他字符的期望,比如颜色代码和标签。

例如:

var wcwidth = require('wcwidth');

console.log("TAB WIDTH", wcwidth('\t'));
console.log("한 WIDTH", wcwidth('한'));
console.log("Color Code WIDTH", wcwidth('\x1b32m'));
console.log("X WIDTH", wcwidth('X'));

输出:

TAB WIDTH 0
한 WIDTH 2
Color Code WIDTH 3
X WIDTH 1

我似乎无法在任何地方找到有关此事的任何信息,但我想这将是人们在古代过去必须解决的常见问题。

如果可能有使用bash脚本或任何库,应用程序或工具的方式,我也完全对此持开放态度。

任何帮助非常感谢! :) 感谢

2 个答案:

答案 0 :(得分:3)

标签不占用8列。它输出一个空格,然后输出足够的空格,以确保下一个字符将在索引为0 mod 8的下一列输出(如果从1开始计数,则为1 mod 8)。换句话说,你无法分辨出多大的空间选项卡除非您知道自己在哪里。

颜色代码(\x1b[32m)可能占用零空间,但也可能没有;它取决于控制台终端仿真器的性质。大多数终端仿真器都会识别CSI[Pm代码,但还有其他代码更加特殊。例如,

printf $'\x1b]2;A window\x1b\\'

会在xterm中设置窗口标题,因此不会产生任何输出。但是在Linux控制台中,将显示文本;A window,占用9个字符。

简而言之,这不是一个容易出问题的问题,你只能用很多背景来回答它,因为没有绝对的答案。

答案 1 :(得分:2)

对于任何需要知道光标在屏幕上的位置的程序,从ls的表格输出到可编辑的命令行到全屏应用程序,这确实是一个问题。正如您所注意到的那样,wcwidth或wcswidth并未解决这个问题,而wcwidth或wcswidth仅针对(字符串)可打印字符定义。 (对于许多角色来说,即使是not well defined。)此外,控制序列不仅可以改变颜色,还可以改变光标定位,甚至可以支持字体大小效果。

相反,有时会使用终端控制库,例如ncurses [npm search]。这些似乎也没有告诉你字符串宽度,但是因为它们分别跟踪文本属性(如颜色),并自己生成控制序列以定位和设置文本,所以它们可以在给定位置的屏幕上提供一些帮助。 / p>

不幸的是,我不相信除此之外还有很多可用的东西,应用程序要么忽视复杂性,要​​么以临时方式处理它们。


澄清一个常见的误解:水平标签(HT,\t)没有这样的宽度;它是一种格式效应器,如Carriage Return或Form Feed,可根据特定规则重新定位光标。

  

HT(水平制表):一种控制格式的格式效应器      打印位置移动到一系列的下一个      沿着印刷线的预定位置。 (也适用于      穿孔卡上的显示设备和跳过功能。)

     

- 美国信息交换标准码[ASCII],1968年,转载于RFC 20

最常见的实现是每八列固定制表位

                                1       2
                1.......9.......7.......5.....

1\tXYZ          1       XYZ
12\tXYZ         12      XYZ
1234567\tXYZ    1234567 XYZ
12345678\tXYZ   12345678        XYZ
123456789\tXYZ  123456789       XYZ

虽然有些系统支持控制序列或其他方法来设置制表位在任意距离的位置,例如某些文字处理器中的标尺栏。