命令行的能力超越你的想象

452 阅读3分钟

动机

今天在 GitHub 上看到了一个项目 Carbonyl,这是一个基于 Chromium 将网页渲染到命令行中的项目,看到演示视频后,非常震撼。

命令行竟然能被搞成这个样子!

下面是使用上述项目浏览 YouTube 时的画面,整体有点像素游戏的味道,并且还可以进行滚动浏览和点击。

image.png

本文仅讨论命令行的各种展示能力,有关 Carbonyl 如何更改 Chromium 将网页绘制到命令行中,将会在另外的文章中进行叙述。

ANSI 转义序列

命令行除了展示普通的字符,大部分还可以使用 ANSI 转义序列来执行一些特殊操作,比如把光标置于屏幕上的某个位置。

所有 ANSI 转义序列都以 ASCII 字符 ESC(在 GNU echo 命令中使用 \x1b\e 转义字符来进行输入)开头,第二个字符可以是 ASCII @A–Z[]^_ 范围内的任意字符。

其中,当 ANSI 转义序列的第二个字符为 [ 时被称为 CSI 序列,这一类的序列用于控制光标位置、文字颜色。CSI 后跟随其他数字作为参数,参数间用分号 ; 分隔,最后以一个特定的字母结尾,不同的操作使用不同的字母。

设置颜色

CSI 序列以 m 结尾时,当第一个参数为 38 时表示设置前景色,为 48 时表示设置背景色。第二个参数为 5 表示使用256色模式,为 2 表示使用 rgb 模式。使用 rgb 模式时,命令的格式如下:

\x1b[38;2;<r>;<g>;<b>m 选择RGB前景色
\x1b[48;2;<r>;<g>;<b>m 选择RGB背景色

下面的 Bash 代码将在 iTerm 中打印一个前景色为黄色,背景色为红色的 hello, world

echo '\x1b[38;2;255;255;0m\x1b[48;2;238;28;37mhello, world'

image.png

并不是所有命令行终端都支持 rgb 模式,比如 Mac 自带的终端,此时只能去使用256色模式。使用256色模式时,命令的格式如下:

\x1b[38;5;<n>m 选择RGB前景色
\x1b[48;5;<n>m 选择RGB背景色

下面的 Bash 代码使用256色模式,打印一个前景色为黄色,背景色为红色的 hello, world

echo '\x1b[38;5;11m\x1b[48;5;9mhello, world'

image.png

绘制像素

我们了解了如何设置颜色,现在让我们看一下 Carbonyl 是如何绘制每个像素的。

Carbonyl 选择了一个 unicode 字符 U+2584:▄,这是一个占据了下半块的方形。而一个命令行的单元格通常是1:2的纵横比,于是我们通过设置背景颜色控制顶部像素颜色,设置前景色控制底部像素颜色。

image.png

这让我们获取了绘制复杂界面的基础。

鼠标事件

现代的命令行终端 iTerm2 甚至还支持鼠标事件。可以使用 \x1b[?1000h 来启用鼠标点击事件,使用 \x1b[?1000l 来禁用鼠标点击事件。

展示图片

iTerm2 甚至支持展示图片,命令格式如下:

echo '\x1b]1337;File=name=图像文件名;size=图像大小;inline=0:图像内容(Sixel编码);\a'

关闭回显

命令行终端默认都会开启输入回显,可以用以下方法关闭。

stty -echo

参考资料

  1. Carbonyl
  2. ANSI转义序列
  3. Inline Images Protocol