PAYATHON 2026

rustyline 如何为多行输入显示续行提示符?

数据阿明

结论

rustyline 没有专门设置只读续行提示符的参数。readline() 接收一个提示符。若用 Cmd::Insert 在换行后插入 > ,这段文本会进入输入缓冲区,用户可以编辑它,返回的字符串中也会包含它。当前 crate 的功能列表没有列出内置的续行提示符功能,Editor::readline 文档也说明,提示符通过该方法传入。

如果可以接受续行前缀属于缓冲区的一部分,可以将 ^J 绑定为插入换行和前缀,并在读取完成后移除每个后续行开头的前缀:

use rustyline::{
    Cmd, DefaultEditor, Event::KeySeq, EventHandler::Simple, KeyEvent, Modifiers,
};

const CONTINUATION_PROMPT: &str = "> ";

fn main() -> rustyline::Result<()> {
    let mut rl = DefaultEditor::new()?;
    rl.bind_sequence(
        KeySeq(vec![KeyEvent::new('j', Modifiers::CTRL)]),
        Simple(Cmd::Insert(
            0,
            format!("\n{CONTINUATION_PROMPT}"),
        )),
    );

    loop {
        match rl.readline(">> ") {
            Ok(input) => {
                let input = input
                    .lines()
                    .enumerate()
                    .map(|(index, line)| {
                        if index == 0 {
                            line
                        } else {
                            line.strip_prefix(CONTINUATION_PROMPT).unwrap_or(line)
                        }
                    })
                    .collect::<Vec<_>>()
                    .join("\n");

                dbg!(input);
                // 处理多行输入
            }
            Err(_) => break,
        }
    }

    Ok(())
}

Cmd::Insert 会把 \n> 插入当前编辑缓冲区。处理输入时,代码只尝试移除后续行开头的 > ,首行内容不会被删除。

需要注意的限制

插入的前缀不是只读的。用户移动光标或删除字符时,可能会改动提示符;如果用户在续行开头输入了相同的前缀,清理时也可能将其移除。这个方案适用于交互规则简单、能够接受这些限制的 REPL。

如果续行提示符必须保持只读,并且不受光标操作影响,单靠 Cmd::Insert 无法实现。此时需要自定义终端绘制和编辑行为,或使用提供独立续行提示符的输入组件。具体可行的 API 取决于所用的 rustyline 版本。

备注:内容仅供参考。