终端双列显示实现:如何支持单列多行内容复制?
CLI双列显示:解决单列多行复制问题
原方案用普通空格填充左列实现对齐,但复制单列多行时,会带上中间的分隔符和右列内容(比如urxvt中复制左列aaa和bbb会得到混有|xxx的内容)。以下是几种适配部分终端的优化方案:
方案一:用OSC 8空标记包裹填充空格(适配多数现代终端)
利用终端支持的OSC 8控制序列,将填充的空格标记为“不可复制”的内容。当终端识别到这个序列时,复制操作会忽略被包裹的填充部分,只保留实际的列内容。
修改后的代码:
from itertools import zip_longest from shutil import get_terminal_size left_lines = ["aaa", "bbb"] right_lines = ["xxx", "yyy", "zzz"] columns = min(get_terminal_size().columns, 80) column_width = (columns - 1) // 2 # OSC 8 空链接控制序列:标记不可复制区域 OSC8_START = "\033]8;;\033\\" OSC8_END = "\033]8;;\033\\" for left, right in zip_longest(left_lines, right_lines, fillvalue=""): assert len(left) <= column_width assert len(right) <= column_width pad_length = column_width - len(left) # 用OSC8包裹填充空格,复制时会被忽略 padding = OSC8_START + " " * pad_length + OSC8_END print(left + padding + "|" + right)
适配终端:iTerm2、Gnome Terminal、Konsole、Alacritty等现代终端;urxvt不支持OSC 8,此方案无效。
方案二:用ncurses库实现精准布局(适配绝大多数终端)
ncurses可以直接控制屏幕的坐标位置,将左列、分隔符、右列分别渲染到对应区域。虽然普通行选择仍会复制整行,但用户可以通过终端的块选择模式(通常是按住Alt拖动鼠标,或Ctrl+Shift+方向键)精准选中单列内容。
代码示例:
import curses from itertools import zip_longest left_lines = ["aaa", "bbb"] right_lines = ["xxx", "yyy", "zzz"] def main(stdscr): height, width = stdscr.getmaxyx() width = min(width, 80) column_width = (width - 1) // 2 # 渲染左列 for idx, line in enumerate(left_lines): if idx >= height: break stdscr.addstr(idx, 0, line) # 渲染分隔符竖线 for idx in range(max(len(left_lines), len(right_lines))): if idx >= height: break stdscr.addstr(idx, column_width, "|") # 渲染右列 for idx, line in enumerate(right_lines): if idx >= height: break stdscr.addstr(idx, column_width + 1, line) stdscr.refresh() stdscr.getch() curses.wrapper(main)
适配终端:几乎所有支持CLI的终端,包括urxvt。
方案三:提示用户使用块选择(兼容所有终端)
如果不想修改代码逻辑,可以在输出时添加提示,告知用户使用终端的块选择模式来复制单列内容。比如在输出双列前打印一行提示:
print("提示:按住Alt拖动鼠标可精准复制单列内容")
这种方式无需依赖任何终端特性,全终端兼容,但需要用户配合操作。
内容的提问来源于stack exchange,提问作者Manuel Jacob
相关产品推荐
相关产品推荐

