终端 session 与 viewport
Ansiq 的 surface 层不负责业务状态,也不负责 widget 语义。
它负责的是另一件非常底层、但又极其关键的事:
把一个普通终端会话变成一个可管理的 runtime viewport。
如果没有这一层,Ansiq 的 runtime 很快就会陷入两个问题:
- 不知道自己到底能控制终端的哪一块区域
- 不知道历史输出、live viewport、退出光标位置应该怎么协调
surface 这一层具体负责什么
当前 surface 层负责:
- 进入和退出 raw mode
- viewport reservation
- reanchor 与 resize plan
- 安全的 exit row 处理
这看起来像 terminal plumbing,但实际上它是一层非常明确的系统边界。
为什么 viewport 不是“顺手分一块 rect”
在 GUI 里,一个 app 往往天然拥有一个窗口。
但在终端里,情况不是这样:
- 你可能是在 shell 中 inline 启动应用
- 你可能希望保留上方历史输出
- 你可能希望应用结束后 shell prompt 回到一个可预测位置
这意味着 runtime 不能假设自己天然拥有整块屏幕。
所以 Ansiq 需要显式建立 viewport 语义:
- 当前 live 区域从哪里开始
- 占多少行
- resize 时怎么调
- history commit 后怎么重锚
为什么 session 语义必须留在 surface
一个很自然的诱惑是:
“既然 app 更了解自己的布局,那 viewport 和 history 的事是不是也该由 app 管?”
但这样做的问题很明显:
- 每个 app 都会重新发明自己的终端会话管理
- runtime 很难给出统一的 patch / exit 语义
- 历史提交和 live viewport 边界会越来越混乱
因此 Ansiq 的选择是:
- app 决定自己的 shell 长什么样
- surface 决定这块 shell 如何和真实 terminal 会话对接
当前有哪些 viewport policy
目前最常见的是:
PreserveVisibleReservePreferredReserveFitContent
它们并不是纯视觉选项,而是在回答不同问题:
PreserveVisible
重点是:
- 尽量不要扰动当前已有 terminal 内容
适合:
- 小工具
- 临时 UI
- 不需要长期驻留的场景
ReservePreferred
重点是:
- 给 live viewport 一个偏好的工作高度
- 但在 history commit / reanchor 后重新收回到这个偏好高度
这非常适合:
- 会话型应用
- 有 composer/footer 的终端工作区
ReserveFitContent
重点是:
- 让 viewport 高度随内容范围变化,但仍然受 clamp 控制
适合:
- 示例
- 比较轻的嵌入式 UI
resize 和 reanchor 为什么必须是 plan,而不是直接写 terminal
现在 surface 里已经把这两件事尽量做成了 plan function:
resize_viewport_planreanchor_viewport_plan
这件事的重要性在于:
- 它们更容易测试
- 不依赖真实终端行为就能验证
- 可以先把 terminal 语义算清楚,再去执行 ANSI 操作
这是 Ansiq 在 runtime 成熟化过程里一个很重要的方向:
把“可以纯计算的 terminal 行为”从“真正写 terminal”里拆出来。
为什么历史提交后不应该继续盲目保留扩大的 viewport
这是最近一轮 surface 硬化里非常重要的一个语义:
- live viewport 可能会因为当前内容而临时增高
- 但 history commit / reanchor 后,不应把这个临时高度当成新的稳态
否则会出现典型问题:
- 第一轮对话还正常
- 第二轮、第三轮之后 viewport 越来越高
- 最后像整个终端都被应用占满了一样
这也是为什么 ReservePreferred 现在在 commit/reanchor 后会回到 preferred height。
退出时的终端状态为什么也属于 surface
用户真正感受到“这个框架稳不稳”,往往不是看树更新多先进,而是看这些瞬间:
- 启动时会不会顶掉 shell
- resize 时会不会乱跳
- 退出后 prompt 会不会落在奇怪位置
所以 exit_row、safe clamp、raw mode 恢复这些事情都必须在 surface 层被认真对待。
它们不是工程细枝末节,而是产品体验。
这页的结论
terminal session 和 viewport 不是 runtime 的附属品,也不是 app shell 的细节。
它们是 Ansiq 里一层明确的系统边界:
- runtime 负责更新和 patch
- app 负责场景结构
- surface 负责让这些结构在真实终端里安全、稳定、可预测地成立
这一层必须保持 terminal-native,不应该吞掉应用层 shell 语义;但它也不能退化成“只会调用几条 ANSI 命令”的薄封装。