Skip to content

TUI ​

文档编写中

部分内容可能尚不完整。

同一个工作区,不带 GUI:

bash
thinkterm tui [DOMAIN ...]

它是 thinkterm 可执行文件的一个子命令,而不是第二个程序,所以不运行的时候不占用任何成本。

它是平级客户端,不是镜像 ​

TUI 不是 GUI 的只读视图。它是同一个权威服务端的另一个客户端,并且遵守同样的规则:

  • Space、Project 和 Thread 数据只接受来自服务端的快照
  • 每一次改动都要等服务端确认之后,显示才会更新

因此同时开着 GUI 和 TUI,不可能出现两边对"存在什么"各执一词的情况。离线的服务端在 TUI 里根本无法修改:不会有任何改动被排队等着以后再发。

它能做什么 ​

终端里的日常工作它都覆盖:新建标签、分屏、调整大小、放大、关闭 pane 和标签、带回滚搜索的复制模式,并且完整支持鼠标。

在侧边栏上,它可以新建和改名 Space、Project 与 Thread,置顶和取消置顶 Thread,并在每一层执行删除 —— 每次都会确认,因为删除可能结束里面的会话。拖动可以在 Project 内部重排 Thread、在 Space 内部重排 Project;Space 本身的顺序不变。它还能从下文介绍的连接面板接入和重试服务端,以及跳到下一个需要你关注的 Thread。

它没有什么 ​

TUI 比桌面应用窄。它没有归档、没有 Thread 引用、没有文件、笔记、片段或 Agents 面板、没有插件、没有实时总览,也没有标签图标。它新建的 Project 不绑定你挑选的文件夹:名字由你定,起点是你的主目录。用 TUI 不会让这些东西丢失 —— 它们保持桌面端留下的样子 —— 只是要用桌面应用才能碰到它们。

终端由谁驱动 ​

数据是共享的,但一个终端同一时刻只有一个驱动者。默认是交接模式 —— 客户端在你与之交互时把终端拿过来 —— 而 TUI 可以把服务端切换成类似 tmux 的共享模式,让所有接入的客户端看到同一张网格。这个模式属于服务端,并且在它重启后依然保留,所以它是对那个服务端做的决定,而不是对当前这个客户端。在共享模式下,最后一个与某个标签交互的客户端决定它的尺寸。交接的那一面见 远程。

切换开关在标签栏的 ⋮ 菜单里,即 A · Shared (tmux-like) 和 B · Handoff (exclusive),当前模式旁边带勾。底部状态栏打开时会写明状态:A SHARED;这个 TUI 握着终端时是 B ACTIVE;另一台设备握着时是 B VIEW · example-host。在共享模式下,尺寸由另一个客户端决定的标签会改显示 A SHARED · VIEW 120×30,带上这个标签被保持的尺寸。

被另一台设备握着的终端,上面会盖一条提示,说明它正在哪里使用,以及 Click or scroll to continue。在 TUI 里只有点击或滚动能接管它,键盘永远不会:没法分辨一次按键是想接管,还是要打给下面那个终端的,所以提示还在时敲的键不会去任何地方。

退出不会结束任何东西 ​

退出 TUI 只是从服务端脱离。里面的每个会话都继续运行,与 GUI 客户端断开时完全一样。

这正是那个显而易见的用法成立的原因:SSH 到一台机器,跑 thinkterm tui,做点事,然后断开。或者在一台你本来就不想要 GUI 的机器上彻底跳过它。

用 Ctrl-b d 或 Ctrl-b q、⋮ 菜单里的 Detach,或状态栏上的 Detach 按钮脱离。

它不会在自己的服务端里打开 ​

如果 TUI 运行在它要接入的那个服务端的某个 pane 里,它就是在那个服务端的一个终端里画那个服务端自己的终端。ThinkTerm 会拒绝:它脱离所有已接入的服务端,带着错误退出,你的终端保持原样。错误信息会提示你从另一个终端应用里运行 thinkterm tui,或者换一个域。

是不是同一个,看的是服务端的身份,而不是域的名字:每个 ThinkTerm pane 都记录着承载它的服务端,报告同一身份的目标会被拒绝。旧到没有这项记录的 pane 也会被拒绝,因为从它无法证明目标是另一个服务端。

界面 ​

侧边栏是一棵树:每个已接入的服务端、它的 Space、Space 里的 Project,以及其中的 Thread。▾ 和 ▸ 用来折叠一层。每一行都带一个 ⋯ 按钮打开它的菜单,Space 行和 Project 行还带一个 +,分别用来添加 Project 和 Thread。树的上方是 ⊕ New Thread,在你所在的 Project 里添加一个 Thread;还有一个 WORKSPACES 标题,它的 + 在你所在的 Space 里添加 Project。⚙ Settings 位于底部。顶部的 ≡ 用来显示和隐藏侧边栏。

Thread 行以一个标记开头:

标记含义
*里面有东西在运行
!它需要关注,或者被标记为未读
+它的工作在你没看的时候完成了
★它已置顶

打开一个 Thread 会在服务端清除它的未读标记,对所有客户端生效。Ctrl-b o 按树的顺序跳到下一个带 ! 或 + 的 Thread,到底后从头再来。TUI 启动时如果没有记住的 Thread,就打开最需要关注的那一个。

标签栏放着所选 Thread 的标签,每个标签上有一个 ✕ 用来关闭,+ 新建标签,⋮ 是主菜单。标签放不下时,两端的 < 和 > 会标出藏起来了几个。在标签栏上滚动滚轮可以切换标签。

pane 导航栏是每个 pane 顶部的一条。左边是堆叠在这个 pane 位置上的各个 pane —— 几个终端共用同一块矩形,各自以标签的形式切换 —— 每个都带一个 ✕。右边是四个按钮:⤢ 放大(放大后变成 ⤡)、◫ 向右分屏、⊟ 向下分屏,以及 + 在同一位置上堆叠一个新终端。pane 窄到放不下四个按钮时,先去掉分屏按钮,保留放大。

状态栏在底部,默认关闭。它显示当前模式的按键、消息、访问状态、需要关注的 Thread 数 ! N —— 点一下跳到下一个 —— 以及 Detach。关闭时,消息和模式提示以浮层显示,永远不会从终端那里占走一行。

按键 ​

除了前缀 Ctrl-b 之后的按键,其余一切都交给终端。按下 Ctrl-b,松开,再按命令键。Ctrl-b Ctrl-b 会把一个字面的 Ctrl-b 发给 pane 里的程序。Ctrl-b ? 显示按键汇总,Esc 或 ? 关闭它。

前缀之后 ​

按键作用
?帮助
d 或 q脱离
b 或 s显示或隐藏侧边栏
g 或 w导航模式
C连接面板
,设置
c在所选 Thread 里新建标签
n / p下一个 / 上一个标签
1 … 9第 1 到第 9 个标签
↑ / ↓上一个 / 下一个 Thread
o下一个需要关注的 Thread
Tab下一个 pane
h j k l、← →聚焦左、下、上、右侧的 pane
v向右分屏
-向下分屏
x确认后关闭 pane
X确认后关闭标签
z放大 pane,或取消放大
r调整大小模式
[复制模式

前缀之后按其他键,除了提示一句什么也不做。

导航模式 ​

打开侧边栏并把键盘留在那里,这样不用前缀就能在树上走动。

按键作用
j / k、↓ / ↑下一个 / 上一个 Thread
h / l、← / →聚焦左 / 右侧的 pane
n / p下一个 / 上一个标签
?帮助
Enter 或 Esc离开导航模式

调整大小模式 ​

按键作用
h j k l 或方向键把当前 pane 的边朝那个方向移动一格
Enter 或 Esc结束

复制模式 ​

复制模式在当前 pane 里放一个光标,它在回滚内容中移动,与 pane 里运行的程序无关。

按键作用
h j k l 或方向键移动光标
PgUp / PgDn滚动十行
End回到底部
Space开始选择;再按一次结束
y、Y 或 Enter复制所选内容
/向前搜索
?向后搜索
n / N下一个 / 上一个匹配
Esc离开复制模式

搜索覆盖整个回滚内容,不区分大小写。向前搜索跳到第一个匹配,向后搜索跳到最后一个,并把光标移过去;没有匹配时显示 No matches。

菜单、输入框和确认 ​

场合按键
菜单j / k 或方向键移动,Enter 选择,Esc 关闭
名称输入框直接输入,Backspace 删除,Enter 确定,Esc 取消
确认对话框Enter 或 y 确认,Esc 或 n 取消

输入框留空时什么也不做。

鼠标 ​

Application mouse 打开时(默认如此),鼠标能做按键能做的大部分事:

  • 点击 Thread 打开它,点击标签显示它,点击 pane 聚焦它。在终端上点击或滚动滚轮,也会把它从另一台设备那里接管过来。
  • 在 pane 里拖动选择文本。靠近上下边缘时,选择会带着 pane 滚动。沿同一行拖动要超过三格才算数,所以手指滑开一两格的轻点仍然是点击。
  • 右键任何东西打开它的菜单。侧边栏行上的 ⋯ 打开的是同一个菜单。
  • 拖动分隔线调整两侧 pane 的大小,拖动侧边栏右边缘调整侧边栏宽度,拖动 pane 的滚动条在回滚内容中移动。侧边栏宽度会被保存。
  • 把一个 Thread 拖到同一 Project 的另一个 Thread 上,或把一个 Project 拖到同一 Space 的另一个 Project 上,就把它移到对方前面。

pane 里的程序要求接管鼠标时 —— vim、htop、开了鼠标支持的 less —— 点击和拖动会交给那个程序。按住 Shift 可以自己选择文本。Shift 加右键,以及中键,总是交给程序。

在 pane 上滚动滚轮有三种结果。程序要求了鼠标,滚轮交给它。pane 处于备用屏幕 —— 一个没有要求鼠标的全屏程序 —— 时,每一格都变成方向键,正因如此 less 和 git log 在触摸屏上也能滚动。其余情况滚动回滚内容。按住 Shift,或者已经往回滚过,总是滚动回滚内容。滚轮每一格是 scroll_lines 行。

右键菜单 ​

对象提供
服务端New Space、Retry connection、Disconnect
SpaceNew Project、Rename Space、Delete from server、End sessions and delete
ProjectNew Thread、Rename Project、End sessions and remove
ThreadOpen、New Thread、Rename Thread、Pin 或 Unpin、End session and delete
标签Open、New Tab、Rename Tab、Close Tab
paneCopy、Paste、Split Right、Split Down、Zoom、Close Pane
标签栏上的 ⋮New Tab、Split Right、Split Down、Copy Mode、Paste、Connections、A · Shared (tmux-like)、B · Handoff (exclusive)、TUI Settings、Toggle Sidebar、Help、Detach

只有当那个 pane 里有一段已完成的选择时,Copy 才可用。

新建和删除做了什么 ​

New Space 询问名称,然后建立这个 Space,里面带一个位于主目录的 Project Home 和一个 Thread main。New Project 询问名称,在主目录建立这个 Project,并带一个 main Thread。New Thread 询问名称。每一项都会打开它刚建好的东西。

删除之前一定会询问;会结束 pane 的,对话框会写明结束几个:

  • Delete from server 为所有客户端从服务端移除一个 Space,里面的会话继续运行。
  • End sessions and delete 移除这个 Space,并结束其中每一个 pane。
  • End sessions and remove 移除一个 Project,并结束它的 pane。
  • End session and delete 移除一个 Thread,并结束它的 pane。
  • Close Pane 和 Close Tab 在服务端结束那些 pane,对所有客户端生效。

服务端上的 Disconnect 不是删除:TUI 只是放开它,它的会话继续运行。

复制与粘贴 ​

Copy on select 打开时(默认如此),拖动结束即复制,复制模式里用 y 复制。关掉它,完成的选择会留在屏幕上;这时 Ctrl-C 会复制它,而不是中断程序。复制之后选择就被丢弃,所以下一次 Ctrl-C 又会送到程序那里。

TUI 通过系统自己的工具写入剪贴板:

系统使用
macOSpbcopy 和 pbpaste
LinuxWayland 下用 wl-copy 和 wl-paste,其次 xclip,再次 xsel
WindowsWindows 剪贴板

这些都写不进去时 —— 典型情况是 SSH 到一台没有显示器的 Linux 机器 —— TUI 改为把文本以 OSC 52 序列发给它所运行的那个终端,支持 OSC 52 的终端会把它放进你面前那台机器的剪贴板。行不行取决于那个终端,而不是 ThinkTerm。

菜单里的 Paste 通过同样的工具读取剪贴板,所以在 SSH 上它读的是远程机器的剪贴板,或者干脆失败。你所用终端自己的粘贴快捷键总是有效的:TUI 会把收到的内容交给当前 pane。

复制和粘贴每次最多 8 MiB。

窄屏与手机 ​

TUI 会随着所在终端的宽度改变形态。

  • 宽屏 —— 侧边栏以你设定的宽度待在终端旁边。
  • 紧凑 —— 比 narrow_width 宽不到 24 列时,侧边栏固定为 18 列。
  • 窄屏 —— 在 narrow_width 列(默认 64)或更窄时,树不再与终端共享屏幕。打开时它盖住终端,你选中一个 Thread 后它就让开;≡ 再把它叫回来。窄屏下的 TUI 总是从终端开始,在那里打开或关闭树也不会被保存,所以共用同一个 tui.toml 的手机和电脑不会互相覆盖对方的选择。

手机报告的列数差别很大,所以 narrow_width 是唯一值得手动调整的数字。

Touch targets 按指尖来设定按钮大小:按钮更宽,顶部是两行高的栏。保持 Auto 时它跟随窄屏布局,多数时候是对的,但手机横过来报告的列数多到像一台电脑时就不对了 —— 所以才有这个设置。

在手机上,pane 导航栏是手指唯一能碰到放大、分屏和新终端的地方,因为软键盘上几乎没有像样的 Ctrl-b。即使是很矮的 pane,也会保留它的导航栏。

设置 ​

Ctrl-b ,、侧边栏底部的 ⚙ Settings,或 ⋮ 菜单里的 TUI Settings 都能打开设置界面。↑ ↓ 或 j k 在行间移动;← →、h l、Enter 或 Space 改变取值;Esc 关闭。点击某一行也会改变它。每次改动立即生效并保存。

界面上有十行。另有两个设置只存在于文件中:sidebar_width(拖动侧边栏边缘也会设置它)和 narrow_width。

tui.toml 中的键界面上默认值取值
themeThememonochrome-dark下面十个主题之一
sidebar_visibleSidebartruetrue、false
pane_nav_barPane nav bartruetrue、false
pane_bordersPane borderstruetrue、false
pane_scrollbarsPane scrollbarsfalsetrue、false
show_status_barBottom status barfalsetrue、false
mouseApplication mousetruetrue、false
copy_on_selectCopy on selecttruetrue、false
touch_targetsTouch targets不设置(Auto)不设置、true、false
scroll_linesScroll lines31 到 20
sidebar_width—2618 到 36 列
narrow_width—6420 到 200 列

超出范围的值会被拉回范围内。边框需要富余的空间,滚动条要占一列,所以两者只在足够大的 pane 上画出来;滚动条默认关闭,因为它占用的那一列是服务端不知道的。

关掉 Application mouse,普通的点击、拖动和滚轮就不再以鼠标事件的形式送到程序:点击和拖动始终用来选择,滚轮用来滚动,在备用屏幕上则发送方向键。

一个最小的 tui.toml:

toml
theme = "tokyo-night"
narrow_width = 80
touch_targets = true

主题 ​

theme界面上
monochrome-darkMonochrome Dark
monochrome-lightMonochrome Light
terminalTerminal Default
catppuccinCatppuccin
tokyo-nightTokyo Night
draculaDracula
nordNord
gruvboxGruvbox
solarized-darkSolarized Dark
solarized-lightSolarized Light

主题给 TUI 自己的界面上色,不给终端上色:终端保持服务端给它们的颜色。深色主题画在你的终端原有的背景上,所以侧边栏和 pane 在背景色上永远不会不一致。两个浅色主题自带背景色,因为深色文字放在深色终端上没法看。Terminal Default 连文字也用终端自己的颜色。

NO_COLOR 不会把这些有名字的主题变成灰色。想要不带颜色,请选两个 Monochrome 主题之一。

连接面板 ​

Ctrl-b C,或 ⋮ 菜单里的 Connections,列出 TUI 能接入的每个服务端:

  • 本机,显示为 Local —— 有正在运行的 ThinkTerm 桌面应用就是它,否则是本地会话 server
  • 你配置里的多路复用域
  • 远程主机 里使用 ThinkTerm Connect 的主机,以它们的标签显示

无法接入的主机也会列出,但呈灰色并附上原因:普通 SSH 主机提示 Enable ThinkTerm Connect in Remote Hosts,Mosh 主机则说明它的会话不是 mux 服务端。

标记状态
●已接入
…正在连接
!失败
○未接入
-无法接入
按键作用
j / k、↓ / ↑移动
Enter 或 r接入,或重试
d断开 —— 服务端保留它的会话
q脱离并退出 TUI
Esc关闭面板

点击某一行也会接入它。重试 Local 时会重新寻找桌面应用,所以桌面应用退出之后,它连到的就是会话 server。

选项 ​

选项效果
[DOMAIN ...]要接入哪些服务端,按域名指定。不指定时,TUI 只接入本机;其他服务端可以之后从连接面板接入
--prefer-mux连接到后台 mux 服务端,而不是正在运行的 ThinkTerm GUI。默认优先连 GUI
--class <NAME>用于发现运行中 ThinkTerm GUI 套接字的窗口类名
--tui-config <PATH>使用另一个 TUI 设置文件。TUI 的设置独立于 GUI

它的设置文件在哪里 ​

默认文件是 ~/.config/thinkterm/tui.toml,TOML 格式,遵循 $XDG_CONFIG_HOME;不想用命令行标志时,$THINKTERM_TUI_CONFIG 也能指定另一个。这个文件可以在 TUI 内部编辑,并且只有与默认值不同的项才会被写回 —— 默认值仍然是默认值,不会被固定成今天的取值。

另外,~/.local/state/thinkterm/tui.json(遵循 $XDG_STATE_HOME)记住你上次停在哪个域、哪个 Thread 和哪个标签。

相关 ​