Ofey Chan, aka 'ofey404'
Pretending a subtitle is out there...
在『玩具』以外,终端幻灯片程序的价值在于,嵌入代码 / Shell Script / 任何系统操作的灵活性。甚至幻灯片本身就是一个脚本,在工作实际发生的那台机器上、那个目录下进行演示。
太长不看版:
没有一个我试用的终端幻灯片程序达到了我心目中的效果,它们本来可以做得更加简洁、小巧而普适。因此我做了一个设计:
这个设计的最大工作量,大概来自于一个『在终端模拟器中运行的终端模拟器』,参考zellij.dev,工作量应当在一万行以下。
看到 github 上有朋友星了 maaslalani/slides 这个基于终端的幻灯片程序,我也找了几个玩了一下。
d0c-s4vage/lookatme:python 写的,可能是这类程序里面的老大哥。
maaslalani/slides:go 写的。README 里面列了一些别的终端幻灯片程序。
Slidev - Presentation Slides for Developers Beta:js 写的,15K 星。
这些程序的特点:
那么这类基于终端的幻灯片程序,除了『酷玩具』这一点以外,有没有独特的使用价值呢?
我认为有两点:
回顾一下现存的演示工具:
基于终端的幻灯片程序,肯定是不能做到和全功能的幻灯片一样,支持多种多样的富文本、多媒体材料的,甚至连绘图都有很多困难。这是 TUI 的局限。
在试用的时候,我对这些终端幻灯片程序有过这样一个想象:一边在终端里做工作,一边配上讲解的文字,最后把整个过程录下来成为幻灯片。
这比 Jupyter Notebook 走得更靠近机器一步——Jupyter Notebook 限定嵌入某个语言的代码,而终端幻灯片工具可以使用任何你想要的工具,在任何一台机器上进行演示,甚至就是工作发生的那台机器,只要有一个字符界面。
遗憾的是,没有一个试用的程序在嵌入代码的灵活性上达到了我心目中的要求。maaslalani/slides 似乎不支持交互式命令行。d0c-s4vage/lookatme 似乎是把每一张幻灯片上的代码段放到单独的交互式命令行中执行,无法像 Jupyter Notebook 上一样为所有幻灯片维护一个统一的上下文。
在我心目中,『基于终端的幻灯片工具』可以做得更加简洁、小巧而普适。
因此我设计了一个终端幻灯片工具,并且看了一些材料验证可行性。如果暑假有空,我就把它做出来。
这个设计的简洁性,让它的代码量不会很大。zellij.dev,一个 Rust 实现的 tmux,代码量大约是 3 万行,我计划在它的十分之一代码量之内实现功能。
下面介绍我的设计。
程序是单一的可执行文件,暂且称之为 shellpre
。
幻灯片文件是带有结构化注释的代码文件。以 bash 为例子:
#!/usr/bin/env shellpre
# ## Slide Page 1
# - Point 1
# - Point 2
#
# Some text
echo "Embedded in page 1"
# ---
# ## Slide Page 2
# - Unordered list
# - Unordered list
#
# Text
echo "Page 2"
# ---
代码中最外层的注释会被 shellpre 按照 Markdown 的语法进行解析。
---
之间的部分会被当成一张幻灯片。代码可以是任何支持解释执行的语言。
shellpre 所做的事:
界面使用类似 extrawurst/gitui 的设计,如果用 rust 编写的话,也可以直接使用 gitui 的包。
┌─────────────────────────────────────────────────────────┐ │ |Shortcut indicators...| | | │ │ ┌────────────────────────────────────────────────┐ │ │ │ │ │ │ │ # Slide Title │ │ │ │ │ │ │ │ - Point 1 │ │ │ │ │ │ │ │ - Point 2 │ │ │ │ │ │ │ │ │ │ │ │ Some text │ │ │ │ │ │ │ │ ``` │ │ │ │ echo "Embedded in page 1" │ │ │ │ ``` │ │ │ │ │ │ │ └────────────────────────────────────────────────┘ │ │ │ │ ┌────────────────────────────────────────────────┐ │ │ │ $ echo "Embedded in page 1" │ │ │ │ Embedded in page 1 │ │ │ │ │ │ │ │ $ # Type some new command │ │ │ │ │ │ │ └────────────────────────────────────────────────┘ │ │ Page 1/2 │ └─────────────────────────────────────────────────────────┘
演讲时,把每一页所嵌入的代码发送到页面下方的终端,演讲者可以选择运行或者不运行它,或者自动运行每一页嵌入的代码,就像 Jupyter Notebook 一样。
使用者同样也可以聚焦到下半部分的终端,然后做他想做的任何事情,比如 cat
一些数据文件看一看,或者用 vim
编辑一些文件,或者其他有助于演示的命令。
下半部分的终端,在聚焦的时候应该可以接收尽可能多的键,最好和 tmux 一样,只有一个前缀键可以用于退出聚焦。这样就可以把它当作一个完整的终端模拟器来使用,在里面使用 vim 等工具。这实际上就是写一个在终端模拟器中运行的终端模拟器。
为了估计工作量,我参考了 zellij.dev,一个 Rust 实现的 tmux,代码量大约是 3 万行。希望能在它 1/3 的规模内完成这个终端模拟器。
导出和分享是幻灯片的自然需要。我们可以简单地把注释和代码块换个位置,把幻灯片输出成 Markdown 格式的文本。之后就有 pandoc 等 Markdown 幻灯片工具来帮我们完成导出了。
我现在还没有着手开始写代码。目前确定的事情是,需要写一个类似 tmux 的终端模拟器。这大概会是一个不错的玩具。
模块结构大概会是这样:
┌──────────────────┐ │ │ │ Input │ │ │ └───────┬──────────┘ │ │ ┌───────▼──────────┐ │Keystroke Handler │ │ │ │UI, window manager│ └───────┬──────────┘ │ ├────────────────────────┐ │ │ ┌───────▼──────────┐ ┌───────▼────────┐ │ │ │ │ │Terminal Emulator │ │ Slide Render │ │ │ │ │ └───────┬──────────┘ └────────────────┘ │ │ ┌───────▼──────────┐ │ │ │Shell(bash, zsh) │ │ │ └──────────────────┘
* Style sheet refers to Dr. Brian Robert Callahan