For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt, and this page is available as Markdown at /designs/composer.md.
  • 简体中文
  • 输入框

    Hunea 里用户使用频率最高的,是输入框(在 Hunea 内部叫 composer)。其实其他产品也是如此。

    它不是「底部固定、输入内容多了就在框里滚动」的那种输入区,而是和上方 transcript 一起,排在同一份可滚动文档里。你多写几行,它会跟着往下延伸;哪怕占满视口时,也可以和整份文档一起滚动,而不是在输入框内部再开一层滚动。这点和 前言 里讲的 altscreen / 主文档布局是一致的。

    空的时候会看到类似 Enter to send Prompt 的占位提示(这个占位提示未来也会进行优化哦)。提示符样式会随 user_input_style 变化(cx / cc / ms),但用法一样:在这里写草稿、插入引用、回填历史,然后发出去。

    效果简要预览:

    鼠标点击与选区替换|690x409

    在 TUI 中获得与平时使用其他软件一致的体验。

    留言

    输入框的功能设计,我在 26 年初,也就是前言部分提到的刚开始尝试用 go 做的时候,就已经想的差不多了。

    其实也没有什么特别的原因,就是纯觉得这样好用不少。

    我个人有时候会写不少的提示词,或者包括一些笔记什么的。我知道可以先打好草稿,然后复制粘贴,或者放在某处,让 AI 自己调用工具去阅读。或者用快捷键使用外部编辑器比如 vim 或者 nvim 编辑,然后保存好的……

    但是我大部分情况下就是喜欢在输入框中写东西。然后我用换行也多,因为我要排一下版(说不定排一下版 AI 理解更舒服呢是不是哈哈?)。所以一不小心就会输入超过十行的内容。

    而碰到那种只能用键盘方向键移动光标的,或者那种固定输入框高度然后内部滚动的,还有更让我不舒服的,就是这两个结合起来的同时,我才写了几十行,就在内部移动卡顿的不得了要卡死的!!!甚至还不能启用外部编辑器编辑的!!!我就不说是哪个了。

    总之体验非常糟糕。

    所以输入框这部分我在做的时候还是尽可能进行了优化的,就是为了体验感更好。毕竟我想做的产品是给人用的,所以我觉得很有必要。

    不过也需要见谅的是,限于精力,我也不可能做的十全十美。所以也希望能够多理解和包容。以后如果碰到了类似的情况,会继续打磨的。

    比如一个常见的示例就是,我复制了几千行的日志进行粘贴的时候,因为当前输入框的无界设计,会直接将这些内容展示。那么就不便于我们进行提示词的撰写,因为内容太多,翻阅起来也比较麻烦(这里暂不考虑新建一个文件将日志放进去的场景)。

    所以后续会考虑实现一个可选的功能,或者,是一种渐进式的设计,就是对于长内容粘贴,第一次粘贴的话是会变成一个"缩写"的标记。表示这里粘贴了多少行或者多少字的内容。这样的占位设计也是很值得借鉴的。

    如果需要展开的话,可以考虑在同位置再次粘贴同样的内容,或者,可以进行点击亦或是其他的操作进行展开。

    总之这个部分的设计还是有很多可以优化的地方的~

    发送与换行

    默认语义:

    按键作用
    Enter发送当前草稿
    Shift + Enter插入换行
    Ctrl + J插入换行
    Alt + Enter插入换行
    Ctrl + M插入换行(仅在终端能区分时;老终端常会报成普通 Enter

    哈哈,这么多换行的方式!这也是兼容性考虑了!选择一个自己喜欢的就可以了

    如果你更习惯「回车换行、组合键发送」,可以把 swap_enter_and_send 设为 true:此时 Enter 改成换行,Shift + Enter / Ctrl + J 改成发送。Alt + Enter / Ctrl + M 始终是换行,不受这项交换影响。

    发送前会做几道检查:

    1. 草稿去掉空白后为空 → 不发送
    2. 还没选好模型 → toast 提示先配置模型
    3. 当前已有一轮对话在跑 → toast 提示请求已在进行
    4. 选中的 provider 不可用、或 OpenAI 兼容端点缺 base_url → 同样拦住并提示

    过了这些检查,草稿会作为用户消息进 transcript,composer 清空,并真正发起这一轮对话。

    文本编辑

    编辑键贴近常见的 readline / shell 习惯:

    按键作用
    方向键 / Ctrl + B Ctrl + F左右移动
    Alt + B / Alt + F,或 Option/Alt + ← 按词移动
    Ctrl + A / Home行首
    Ctrl + E / End行尾
    Ctrl + Home / Ctrl + End整段草稿开头 / 结尾
    / Ctrl + P Ctrl + N在多行草稿里上下移动(见下方「历史回填」的例外)
    PageUp / PageDown在草稿内按页移动,并尽量带着文档视口一起走
    Backspace / Ctrl + H向前删字符
    Delete / Ctrl + D向后删字符
    Ctrl + W / Alt + Backspace删前一个词
    Alt + D / Alt + Delete删后一个词
    Ctrl + U删掉光标前到行首
    Ctrl + K删到行尾(进 kill buffer)
    Ctrl + Y粘贴最近一次 kill 的内容
    Ctrl + Z撤回草稿编辑

    几点实现上的取舍,用起来会直接感觉到:

    • Undo 是按 grapheme 分组的。连续输入同一个 emoji / 组合字符时,不会拆成半个字符才能撤回来;Ctrl + G 开外部编辑、发送等会成为 undo 边界。
    • Undo 深度composer_undo_limit 控制(默认 50,范围 1..200),只作用在当前进程里,不写进会话。
    • Kill buffer 只保留最近一次 Ctrl + K / 词删除等 kill 结果;Ctrl + Y 不是完整的系统剪贴板。
    • 草稿里若已有完成态选区,再敲普通字符、粘贴、换行、删除类按键时,会先替换/删掉选区,而不是在旁边另插一段。

    粘贴走 bracketed paste:大段文本一次进来,换行会规范化(\r\n / 单独的 \r 都会收成 \n),同样支持「有选区就替换选区」。

    Ctrl + C 在输入框已有草稿时,默认会先清空草稿(ctrl_c_clears_input = true),而不是直接走退出确认;空输入时仍是退出确认那套。清空时,纯文本草稿还会记进消息历史,方便后面回填;带图片附件的草稿则不会硬塞进那份文本历史。

    鼠标

    主界面默认是应用捕获鼠标(见 前言),所以 composer 上可以:

    • 单击:把光标落到对应字符位置(空草稿时没有可点内容,点了也不会硬定位)
    • 拖拽:在输入内容上拉出选区;有选区后,键盘输入 / 粘贴 / 删除会按「替换选区」处理
    • 中键:复制当前屏幕选区(和 transcript 上的中键复制是同一套选区路径)

    这样的实现可以让我们在输入的时候更自然。尽量不用借助外部的工具来完成长提示词的编辑。

    外部编辑器

    长草稿不想一直在 TUI 里改时,按 Ctrl + G 会把当前内容丢进临时文件,挂起 TUI,打开外部编辑器;保存退出后再回写草稿。

    • 编辑器命令由 external_editor 配置;不配则依次尝试 VISUALEDITOR 和平台常见编辑器
    • GUI 编辑器(VS Code / Cursor / Zed / Sublime 等)需要带「等关闭再返回」的参数,例如 ["code", "--wait"],否则 Hunea 会在编辑器刚起来时就回到 TUI
    • 草稿变多行时,状态区可能短暂提示 ctrl+g to edit in …;可用 show_external_editor_helper = false 关掉
    • 外部编辑器回写是一次可撤销的整段替换:Ctrl + Z 能回到打开编辑器之前的草稿

    前缀补全与附件

    这个部分未来会进行优化,因为触发符号有些多,不利于上手和使用

    未来优化后这里的内容也会更新的

    composer 里有几类「打前缀就出浮窗」的能力,都锚在光标附近的 token 上,而不是另开一套命令行:

    前缀做什么
    /(输入框整体像一条斜杠命令时)打开内联 斜杠菜单,继续键入可过滤
    @统一搜索文件与 skill;选中图片路径时会变成图片附件占位符
    #选择自定义 prompt,并建立结构化绑定
    #选择自定义 prompt,并建立结构化绑定

    @ 文件、skill 与图片

    • @ 是统一 mention:默认 All 档同时搜索文件与 skill, / All / Files / Skills 三档间切换,Tab 循环。
    • 普通文件:插入的是路径引用(例如 @src/main.rs)。TUI 不会在发送时把文件内容展开进 prompt;需要读内容时,模型应再走 read 一类工具。这样用户指令和文件快照不会混在一起(也许会调整,但是当前的设计应该是合理的)。
    • 图片(当前支持 png / jpeg / gif / webp):选中后会在草稿里变成图片占位标签,并作为结构化附件一起发送(需要注意:使用的模型需要支持多模态识图能力,否则会报错)。
    • 选中 skill 会建立结构化绑定:发送时按绑定展开 skill 正文,会话里会留下 @skill名 可见标记。
    • 浮窗高度由 file_picker_popup_height 控制(默认 9 行);宽度铺满终端,垂直方向以 @ 位置为锚,空间不够会自动翻转到另一侧。

    #

    选中后会把当前 token 换成可读名称,并在消息里带上对应绑定。之后发送时,runtime 能区分「这是用户正文」和「这是挂上的 custom prompt」。skill 的绑定走 @ mention(见上)。

    / 斜杠菜单

    只有输入框内容整体落在「斜杠命令查询」形态时才会出菜单(空输入后键入 /,再继续过滤)。输入框里已经写了一大段正文时,中间再敲 / 不会突然弹出整份菜单,这点和 斜杠菜单 一致。

    历史回填

    composer 上有两条「把以前写过的东西再拿回来」的路径,侧重点不同:

    1. 盲回填(Up / Down)
      在适合的边界条件下(常见是空草稿,或光标落在整段草稿的首尾边界), / 会在本地 + 已持久化的消息历史里前后翻,把旧文本直接填回输入框。
      草稿已经多行、光标在中间时,上下键优先在草稿内部移动,而不会误触发历史翻页。
    2. 消息历史面板(Ctrl + R//resend
      打开全屏/面板式的历史列表,适合「我想搜一下、看一眼再决定回填哪条」。
      全局历史条数上限由 message_history_limit 控制(默认 100)。

    和状态行、样式的关系

    输入框下方可以挂状态行(status_line / status_line_2),用来显示分支、目录、当前模型、吞吐、首 token 延迟、上下文已用/剩余百分比等。没配置、或当前一项都拿不到内容时,状态行会直接隐藏,不会空占一行。

    user_input_style 只影响「输入中 / 发送后用户消息」的视觉框和着色,不改变发送、补全、鼠标这些交互语义。

    相关配置速查

    都在 [tui] 下,改完需重启才生效:

    配置项默认作用
    swap_enter_and_sendfalse交换 Enter 发送 / 组合键换行
    ctrl_c_clears_inputtrue有草稿时 Ctrl+C 先清空
    composer_undo_limit50Ctrl+Z 可撤回快照数
    external_editor自动探测Ctrl+G 外部编辑器 argv
    show_external_editor_helpertrue多行时是否提示 ctrl+g
    file_picker_popup_height9@ / # 浮窗可见行数
    message_history_limit100全局消息历史条数上限
    user_input_style"cx"输入与用户消息外观
    status_line / status_line_2未配置则隐藏输入框下状态信息(含 context-used / context-remaining 等)
    scroll_animation"smooth"滚轮平滑滚动手感;motion = "reduced" 时强制瞬时

    综合来讲,Hunea 的 composer 想解决的是「在终端里也能舒服地写长输入」:无界增高、鼠标可点可选、外部编辑器可逃、历史可回填、@/#// 就地补全,同时尽量不把文件内容偷偷塞进 prompt。