【问题标题】:How can I get (and set) current bash cursor position when using python readline?使用 python readline 时如何获取(和设置)当前 bash 光标位置?
【发布时间】:2011-10-26 19:31:39
【问题描述】:

我有一个 python 脚本,它可以管理任何应用程序的标准输入、标准输出和标准错误,并允许优雅地插入 readline。想想任何具有大量控制台输出但也接受来自标准输入的命令的应用程序。

无论如何,我的脚本使用了这两个函数:

def blank_current_readline():
    # Next line said to be reasonably portable for various Unixes
    (rows,cols) = struct.unpack('hh', fcntl.ioctl(sys.stdout, termios.TIOCGWINSZ,'1234'))

    text_len = len(readline.get_line_buffer())+2

    # ANSI escape sequences (All VT100 except ESC[0G)
    sys.stdout.write('\x1b[2K')                         # Clear current line
    sys.stdout.write('\x1b[1A\x1b[2K'*(text_len/cols))  # Move cursor up and clear line
    sys.stdout.write('\x1b[0G')                         # Move to start of line

def print_line(line):
    global cmd_state
    blank_current_readline()
    print line,
    sys.stdout.write(cmd_state["prompt"] + readline.get_line_buffer())
    sys.stdout.flush()

在处理标准输出时,我调用 print_line()。这会清空用户可能正在输入的任何内容,打印该行,然后恢复用户的输入文本。这一切都是在用户没有注意到的情况下发生的。

问题发生在光标不在用户输入的任何输入的末尾时。当光标在测试中间并打印一行时,光标将自动置于输入的末尾。为了解决这个问题,我想在 print_line 中做这样的事情:

def print_line(line):
    global cmd_state
    cursorPos = getCurrentCursorPos() #Doesn't exist
    blank_current_readline()
    print line,
    sys.stdout.write(cmd_state["prompt"] + readline.get_line_buffer())
    sys.stdout.setCurrentCursorPos(cursorPos) #Doesn't exist
    sys.stdout.flush()

编辑:尝试可视化我所写的内容:

终端是这样的:

----------------------------------------------
|                                            |
|                                            |
|   <scolling command output here>           |
|                                            |
|   <scolling command output here>           |
|                                            |
|: <user inputted text here>                 |
----------------------------------------------

因此,随着新日志的出现,输出文本会不断滚动。同时,用户当前正在编辑和编写一个新命令,该命令将在按 Enter 时插入。所以它看起来像 python 控制台,但总是附加输出。

【问题讨论】:

    标签: python bash readline


    【解决方案1】:

    我可以建议Python curses吗?

    这里是Basic how-to

    curses 模块提供了curses 库的接口,curses 库是便携式高级终端处理的事实标准。

    虽然 curses 在 Unix 环境中使用最广泛,但也有适用于 DOS、OS/2 以及可能的其他系统的版本。该扩展模块旨在匹配 ncurses 的 API,ncurses 是一个托管在 Linux 上的开源 curses 库和 Unix 的 BSD 变体。


    或者

    我在这里找到了终端控制器:Using terminfo for portable color output & cursor control。它看起来比网站名称所暗示的更便携(cmets 中提到的 MacOS - 尽管有变化)。

    这是一个使用示例,显示一个进度条:

    class ProgressBar:
        """
        A 3-line progress bar, which looks like::
        
                                    Header
            20% [===========----------------------------------]
                               progress message
    
        The progress bar is colored, if the terminal supports color
        output; and adjusts to the width of the terminal.
        """
        BAR = '%3d%% ${GREEN}[${BOLD}%s%s${NORMAL}${GREEN}]${NORMAL}\n'
        HEADER = '${BOLD}${CYAN}%s${NORMAL}\n\n'
            
        def __init__(self, term, header):
            self.term = term
            if not (self.term.CLEAR_EOL and self.term.UP and self.term.BOL):
                raise ValueError("Terminal isn't capable enough -- you "
                                 "should use a simpler progress dispaly.")
            self.width = self.term.COLS or 75
            self.bar = term.render(self.BAR)
            self.header = self.term.render(self.HEADER % header.center(self.width))
            self.cleared = 1 #: true if we haven't drawn the bar yet.
            self.update(0, '')
    
        def update(self, percent, message):
            if self.cleared:
                sys.stdout.write(self.header)
                self.cleared = 0
            n = int((self.width-10)*percent)
            sys.stdout.write(
                self.term.BOL + self.term.UP + self.term.CLEAR_EOL +
                (self.bar % (100*percent, '='*n, '-'*(self.width-10-n))) +
                self.term.CLEAR_EOL + message.center(self.width))
    
        def clear(self):
            if not self.cleared:
                sys.stdout.write(self.term.BOL + self.term.CLEAR_EOL +
                                 self.term.UP + self.term.CLEAR_EOL +
                                 self.term.UP + self.term.CLEAR_EOL)
                self.cleared = 1
    

    【讨论】:

    • 我会再次研究 curses,这对我来说似乎有点过分了。
    • @Jim:好的,找到并添加了看起来很轻的替代品
    • 虽然看起来很酷,但我的问题不是输出的纯格式,而是输出后光标的索引。上面的示例没有考虑用户在生成输出的同时编辑内联命令。
    • @Jim:我想你已经错过了它可以向上、向下、BOL、EOL 等发送光标的事实?当然,您必须编写自己的输入例程。样本只是一个样本。 (我个人会选择诅咒。有现成的面板和小部件。)
    猜你喜欢
    • 1970-01-01
    • 2011-09-19
    • 1970-01-01
    • 2021-10-21
    • 1970-01-01
    • 2013-10-26
    • 2022-10-05
    • 1970-01-01
    相关资源
    最近更新 更多