Python简易文本编辑器实现跨多行光标移动功能求助
Python简易文本编辑器实现跨多行光标移动功能求助
兄弟,我太懂你现在的痛点了!你用input()配合readline的思路,在单行编辑里没问题,但要实现跨多行的光标上下移动,这俩工具就不够用了——毕竟input()本身就是单行输入,readline的上下箭头默认绑定的是历史输入记录,不是行间跳转。
要搞定多行光标移动,咱们得换个思路:用Python标准库的curses,它专门用来做终端下的交互式UI,能直接控制光标位置、处理键盘输入,完美适配你的文本编辑器需求。
下面给你改了一个基于curses的版本,保留了你原来的核心功能(写内容、保存、查看、退出),还实现了上下左右光标移动:
import curses import os def main(stdscr): # 初始化curses:关闭回显,开启键盘输入,显示光标 curses.noecho() curses.cbreak() stdscr.keypad(True) curses.curs_set(1) # 初始化多行缓冲区和光标位置 lines = [""] cursor_y = 0 cursor_x = 0 max_y, max_x = stdscr.getmaxyx() # 主循环 while True: # 清屏并绘制内容 stdscr.clear() # 显示操作提示 stdscr.addstr(0, 0, "简易文本编辑器 | 上下箭头移动行 | 左右箭头移动光标 | Ctrl+S保存 | Ctrl+Q退出") # 绘制缓冲区内容(避免超出终端高度) for idx, line in enumerate(lines): if idx + 1 < max_y: stdscr.addstr(idx + 1, 0, line) # 定位光标 stdscr.move(cursor_y + 1, cursor_x) stdscr.refresh() # 处理键盘输入 key = stdscr.getch() # 可打印字符输入 if 32 <= key <= 126: lines[cursor_y] = lines[cursor_y][:cursor_x] + chr(key) + lines[cursor_y][cursor_x:] cursor_x += 1 # 退格键处理(含跨行合并逻辑) elif key == curses.KEY_BACKSPACE or key == 127: if cursor_x > 0: lines[cursor_y] = lines[cursor_y][:cursor_x-1] + lines[cursor_y][cursor_x:] cursor_x -= 1 elif cursor_y > 0: cursor_x = len(lines[cursor_y-1]) lines[cursor_y-1] += lines[cursor_y] del lines[cursor_y] cursor_y -= 1 # 回车键换行 elif key in [curses.KEY_ENTER, 10, 13]: lines.insert(cursor_y + 1, lines[cursor_y][cursor_x:]) lines[cursor_y] = lines[cursor_y][:cursor_x] cursor_y += 1 cursor_x = 0 # 上下箭头移动行 elif key == curses.KEY_UP: if cursor_y > 0: cursor_y -= 1 cursor_x = min(cursor_x, len(lines[cursor_y])) elif key == curses.KEY_DOWN: if cursor_y < len(lines) - 1: cursor_y += 1 cursor_x = min(cursor_x, len(lines[cursor_y])) # 左右箭头移动光标(含跨行跳转) elif key == curses.KEY_LEFT: if cursor_x > 0: cursor_x -= 1 elif cursor_y > 0: cursor_y -= 1 cursor_x = len(lines[cursor_y]) elif key == curses.KEY_RIGHT: if cursor_x < len(lines[cursor_y]): cursor_x += 1 elif cursor_y < len(lines) - 1: cursor_y += 1 cursor_x = 0 # Ctrl+S保存文件 elif key == 19: # ASCII码19对应Ctrl+S stdscr.clear() stdscr.addstr(0, 0, "请输入文件名: ") curses.echo() filename = stdscr.getstr(0, 16).decode('utf-8') curses.noecho() try: with open(filename, 'w', encoding='utf-8') as f: f.write('\n'.join(lines)) stdscr.addstr(1, 0, f"文件 {filename} 保存成功!按任意键继续...") stdscr.getch() except Exception as e: stdscr.addstr(1, 0, f"保存失败: {str(e)} 按任意键继续...") stdscr.getch() # Ctrl+Q退出编辑器 elif key == 17: # ASCII码17对应Ctrl+Q break # 恢复终端原有设置 curses.nocbreak() stdscr.keypad(False) curses.echo() curses.endwin() if __name__ == "__main__": curses.wrapper(main)
关键功能说明:
- 光标自由移动:上下箭头在不同行之间跳转,左右箭头支持单行移动,甚至能在行首/行尾自动跨行跳转
- 完整编辑逻辑:支持输入字符、退格删除、换行拆分,和普通编辑器行为一致
- 保留核心需求:集成了保存文件、退出功能,操作逻辑更直观
- 终端适配:自动适配终端窗口大小,不会出现内容溢出问题
为啥放弃原来的input()方案?
因为input()是阻塞式的单行输入,没办法实时监听上下箭头这类全局键盘事件,也没法直接控制终端光标位置。而curses直接接管了终端的输入输出权限,能完全自定义键盘响应和光标行为,这才是做终端文本编辑器的正确思路。
你可以直接运行这段代码试试,有细节需要调整的话再按需修改~
备注:内容来源于stack exchange,提问作者IllTime00qw
相关产品推荐
相关产品推荐

