如何用Prompt toolkit实现按CTRL+E保存的多行终端文本编辑器
问题原因
你的代码存在三个核心问题:
new_content是session.prompt()执行结束后的返回值,按下CTRL+E触发回调时,prompt方法还处于阻塞运行状态,new_content仍为初始的None,写入操作自然无法生效。- 文件操作未做异常处理,也没有正确关闭句柄,首次运行如果目标文件不存在会直接报错,写入后也可能因为缓冲区没刷新导致内容未正确落盘。
- 底部工具栏的HTML标签做了多余的转义,实际运行时会显示原始字符而非预期的样式。
修复后完整代码
from prompt_toolkit import PromptSession from prompt_toolkit.lexers import PygmentsLexer from pygments.lexers.python import PythonLexer from prompt_toolkit.formatted_text import HTML from prompt_toolkit.key_binding import KeyBindings file_path = 'output.txt' # 读取文件,不存在则默认内容为空 try: with open(file_path, 'r', encoding='utf-8') as f: content = f.read() except FileNotFoundError: content = "" session = PromptSession() bindings = KeyBindings() @bindings.add('c-e') def _(event): # 直接从当前缓冲区获取最新内容,无需等prompt返回 current_content = event.app.current_buffer.text # 用上下文管理器自动处理文件关闭和缓冲刷新 with open(file_path, 'w', encoding='utf-8') as f: f.write(current_content) # 退出程序 event.app.exit() def show_prompt(): # 修正HTML转义问题,更新提示文案 bottom_toolbar = HTML('<b><style background-color="white" color="green">按 CTRL+E 保存并退出</style></b>') lexer = PygmentsLexer(PythonLexer) session.prompt('\n', default=content, lexer=lexer, multiline=True, bottom_toolbar=bottom_toolbar, key_bindings=bindings) if __name__ == '__main__': show_prompt()
调整说明
- 快捷键回调中直接从输入缓冲区读取实时内容,解决了原代码拿不到编辑后内容的问题
- 增加文件不存在的异常兼容,所有文件操作都用with上下文管理器自动处理资源释放,保证内容正确写入磁盘
- 修正了底部工具栏的HTML转义错误,更新提示文案更符合功能逻辑
- 移除了无用的全局变量,减少逻辑冗余
内容的提问来源于stack exchange,提问作者SomeName
相关产品推荐
相关产品推荐

