甚至通过屏幕检测我的终端支持多少Unicode


10

问题出在这里:我希望能够辨别我的终端是否能够像样的unicode,以便使用某些字符,就像一眼就能看出来一样,有时使用颜色,而其他使用下划线。

产生这种动机的原因是,在任何类型的虚拟终端中,我都得到了不错的字体,但是我了解基本的Linux控制台具有256个或512个同时出现的符号的字符集,因此您不能期望完全支持字体。

起初我以为我可以使用$TERMtty或tty,但这是要注意的地方:我也使用byobu,所以$TERM总是“ screen.linux”。tty的输出也不是很清楚:/dev/pts/<some number>无论是“真实”还是虚拟的术语。

$BYOBU_TTY也没有帮助,因为例如可能是这样,/dev/tty1并且在Ctrl+ Alt+中打开会话时,F1字符不会显示,但是从某个X术语附加到同一会话时,它们会正确显示并且仍然$BYOBU_TTY不会更改。此外,我希望能够在不假设byobu是否存在的情况下进行检测。

另外,在所有情况下,语言环境都显示为en_US.UTF-8

然而,即使我在byobu内部,也以某种方式瞥了一眼(命名为一个我看到检测到的特定工具),这取决于我连接到byobu会话的终端是否使用不同的输出。

我在使用Google时遇到了麻烦,因为终端和tty似乎太常见了。我最多$TERM只能提出解决方案推荐或tty。

Answers:


6

好吧,首先,我想指出的是,就您所说的而言,这几天几乎所有终端都是“虚拟”的,即使该终端位于真正的串行端口的另一端。我的意思是,VT- 100年代Wyse终端和其他“物理”,“真实”终端的日子已经一去不复返了!

顺便说一句,假设您要检测终端支持哪种Unicode。您可以通过将测试字符写入is并查看会发生什么来做到这一点。(您可以在编写完之后尝试删除测试字符,但是用户可能仍然会短暂看到它们,或者首先擦除它们可能无法正常工作。)

想法是让终端告诉您其光标位置,输出测试字符,再次要求终端告诉您其位置,然后比较两个位置以查看终端的光标移动了多远。

要询问终端的位置,请参见此处。实质上:

echo -e "\033[6n"; read -d R foo; echo -en "\nCurrent position: "; echo $foo | cut -d \[ -f 2

尝试输出“é”。该字符在UTF-8中占用2个字节,但仅在屏幕上的一列中显示。如果您检测到输出“é”使光标移动了2个位置,则终端根本不支持UTF-8,并且可能输出了某种垃圾。如果光标根本没有移动,则终端可能仅是ASCII。如果它移动了1位,那么恭喜您,它可能会显示法语单词。

尝试输出“あ”。此字符在UTF-8中占用3个字节,但在屏幕上仅显示两列。如果光标移动0或3,则类似于上面的坏消息。如果移动1,则表示终端支持UTF-8,但不知道宽字符(以固定宽度的字体显示)。如果它移动2列,则一切正常。

我确定您可能会发出其他探针字符,这些字符会导致有用的信息。我不知道自动执行此操作的工具。


1
谢谢您的建议,Celada。但是,它不起作用:我正确地看到了报告的高级位置(é表示1 ,,表示2)。唯一的区别是,在XI中看到的是实字符,而在tty1中看到的是菱形。因此,我猜想终端确实支持utf-8,但缺少所用字体中的字符。
亚历克斯

我现在看到了命令showconsolefont。这似乎是一个可能的解决方案(使用-v命令报告字体是512个字符集)。可悲的是,它仅在不使用byobu时有效。在后一种情况下,它会显示“无法获得引用控制台的文件描述符”。如果我明确地传递TTY(-C选项),错误变成“无法打开/ dev / PTS / 37”
亚历克斯

顺便说一句:用sh脚本确定字符串的末尾宽度(但这不是这个问题的意思)
Gilles'SO- stop

3

OP的实际问题是:Linux控制台支持哪些Unicode值,并且可以在运行时检测到这些Unicode值screen。原则上,可以通过检索控制台的Unicode映射来做到这一点。

kbd源代码树包含getunimap(和它的手册页)。手册页上说

getunimap程序很旧且过时。现在是setfont的一部分

这是不完全正确的。 setfont具有大致相同的功能的选项:

   -ou file                                  
          Save previous Unicode map in file

区别:

  • setfont写入文件,而getunimap写入标准输出
  • getunimap 显示将要映射的字符作为注释。

例如:

0x0c4   U+2500  # ─ 
0x0c4   U+2501  # ━ 
0x0b3   U+2502  # │ 
0x0b3   U+2503  # ┃ 
0x0da   U+250c  # ┌ 
0x0da   U+250d  # ┍ 
0x0da   U+250e  # ┎ 
0x0da   U+250f  # ┏ 
0x0bf   U+2510  # ┐ 
0x0bf   U+2511  # ┑ 
0x0bf   U+2512  # ┒ 
0x0bf   U+2513  # ┓ 
0x0c0   U+2514  # └ 
0x0c0   U+2515  # ┕ 
0x0c0   U+2516  # ┖ 
0x0c0   U+2517  # ┗ 

0xc4    U+2500
0xc4    U+2501
0xb3    U+2502
0xb3    U+2503
0xda    U+250c
0xda    U+250d
0xda    U+250e
0xda    U+250f
0xbf    U+2510
0xbf    U+2511
0xbf    U+2512
0xbf    U+2513
0xc0    U+2514
0xc0    U+2515
0xc0    U+2516
0xc0    U+2517

如果您正在运行screen(或例如在控制台上运行,xterm不是在控制台上运行),则会收到权限错误,可以使用解决该错误sudo

如果我碰巧知道加载了哪种字体,则可以使用进行检查(无特殊权限)psfgettable,例如,

zcat /usr/share/consolefonts/Lat2-Fixed16.psf.gz | psfgettable -

并查看setfont用于加载字体的映射数据(使用Unicode映射):

#
# Character table extracted from font -
#
0x000   U+00a9
0x001   U+00ae
0x002   U+00dd
0x003   U+0104
0x004   U+2666 U+25c8 U+fffd
0x005   U+0105
0x006   U+0111
0x007   U+0150
0x008   U+0151
0x009   U+0162
0x00a   U+0164
0x00b   U+0170
0x00c   U+0171
0x00d   U+021a 
0x00e   U+02dd  
0x00f   U+2014 U+2015
0x010   U+2020
0x011   U+2021
0x012   U+2022 U+25cf
...

两者getunimapsetfont赋予数据未排序的内容,而psfgettable看上去却是排序的(以及合并映射到同一字形的Unicode值的行)。因此存在差异,但是信息是可访问的。

进一步阅读(说明为什么无法使用它showconsolefont来解决此问题):


谢谢托马斯,澄清了我的原始问题,使我走上了正确的道路。我将尝试从您的信息中获取一个简单的清单,然后返回结果。使用sudo对我的用例而言没有障碍。
阿莱克斯

现在,这很奇怪:setfont在虚拟终端中什么也不输出(既不创建给定文件也不输出错误),但是按预期在实际终端中工作。这是在Ubuntu 16.04
亚历克斯

2

我在尝试完成同一件事时遇到了这个问题,但是不想在屏幕上留下任何东西并设置变量,所以我将以下内容放入我获取的shell脚本中:

function test_unicode {
  echo -ne "\xe2\x88\xb4\033[6n\033[1K\r"
  read -d R foo
  echo -ne "\033[1K\r"
  echo -e "${foo}" | cut -d \[ -f 2 | cut -d";" -f 2 | (
    read UNICODE
    [ $UNICODE -eq 2 ] && return 0
    [ $UNICODE -ne 2 ] && return 1
  )
}

test_unicode
RC=$?
export UNICODE_SUPPORT=`[ $RC -eq 0 ] && echo "Y" || echo "N"`
unset test_unicode

1
感谢您的贡献,杰夫。可悲的是我总是得到Ÿ甚至在基本控制台:S
亚历
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.