动机
今天在 GitHub 上看到了一个项目 Carbonyl,这是一个基于 Chromium 将网页渲染到命令行中的项目,看到演示视频后,非常震撼。
命令行竟然能被搞成这个样子!
下面是使用上述项目浏览 YouTube 时的画面,整体有点像素游戏的味道,并且还可以进行滚动浏览和点击。
本文仅讨论命令行的各种展示能力,有关 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'
并不是所有命令行终端都支持 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'
绘制像素
我们了解了如何设置颜色,现在让我们看一下 Carbonyl 是如何绘制每个像素的。
Carbonyl 选择了一个 unicode 字符 U+2584:▄,这是一个占据了下半块的方形。而一个命令行的单元格通常是1:2的纵横比,于是我们通过设置背景颜色控制顶部像素颜色,设置前景色控制底部像素颜色。
这让我们获取了绘制复杂界面的基础。
鼠标事件
现代的命令行终端 iTerm2 甚至还支持鼠标事件。可以使用 \x1b[?1000h 来启用鼠标点击事件,使用 \x1b[?1000l 来禁用鼠标点击事件。
展示图片
iTerm2 甚至支持展示图片,命令格式如下:
echo '\x1b]1337;File=name=图像文件名;size=图像大小;inline=0:图像内容(Sixel编码);\a'
关闭回显
命令行终端默认都会开启输入回显,可以用以下方法关闭。
stty -echo