Python:正确使用set_completion_display_matches_hook

时间:2013-05-15 21:36:01

标签: python python-3.x readline

我正在尝试编写一个功能,以便在用户按下标签按钮时显示自定义视图。显然“set_completion_display_matches_hook”功能是我需要的,我可以显示自定义视图,但问题是我必须按Enter才能再次获得提示。

Python2中的解决方案似乎是(solution here):

def match_display_hook(self, substitution, matches, longest_match_length):
    print ''
    for match in matches:
        print match
    print self.prompt.rstrip(),
    print readline.get_line_buffer(),
    readline.redisplay()

但它不适用于Python3。我做了这些语法更改:

def match_display_hook(self, substitution, matches, longest_match_length):
        print('\n----------------------------------------------\n')
        for match in matches:
            print(match)
        print(self.prompt.rstrip() + readline.get_line_buffer())
        readline.redisplay()

有什么想法吗?

3 个答案:

答案 0 :(得分:1)

redisplay()函数

  

void rl_redisplay (void)
  更改屏幕上显示的内容以反映rl_line_buffer的当前内容。

在您的示例中,您已写入stdout,但没有更改该缓冲区。

按照other answer中所述进行打印和冲洗应该可以。

但是,您将遇到的一个问题是光标位置。假设您有这种情况:

$ cmd   some_file
      ^
      +---- User has back-tracked here and want to insert an option.
            <TAB> completion with print and flush will put cursor
            at end of `some_file' and the line will get an extra 15
            spaces after that ...

要纠正这种情况,首先要获取光标位置,然后使用ANSI序列重新定位光标。

buf = readline.get_line_buffer()
x = readline.get_endidx()

print(self.prompt + buf, end = '')

if x < len(buf):
    """ Set cursor at old column position """
    print("\r\033[%dC" % (x + len(self.prompt)), end = '')

sys.stdout.flush()

现在,如果prompt本身具有ANSI序列,那么您当然会遇到另一个问题。通常为彩色等。然后,您将无法使用len(prompt),而必须找到已打印的/可见的长度。

一个人必须在其他地方使用打开和关闭字节,通常分别为\0x01\0x02

所以通常会得到:

prompt = '\001\033[31;1m\002VISIBLE_TEXT\001\033[0m\002 '

代替:

prompt = '\033[31;1mVISIBLE_TEXT\033[0m '

有了这些警卫,应该很容易地去除可见的文本。

通常类似:

clean_prompt = re.sub(r'\001[^\002]*\002', '', prompt))

缓存该长度并在手动打印readline时使用。请注意,当您手动使用护罩时,还必须卸下护罩-如挂钩功能一样。 (但是input(prompt)

中需要

答案 1 :(得分:0)

首先,Python 2代码使用逗号来保留未完成的行。在Python 3中,它使用end关键字完成:

print(self.prompt.rstrip(), readline.get_line_buffer(), sep='', end='')

然后,需要刷新才能实际显示未完成的行(由于行缓冲):

sys.stdout.flush()

似乎不需要redisplay()来电。

最终代码:

def match_display_hook(self, substitution, matches, longest_match_length):
    print()
    for match in matches:
        print(match)
    print(self.prompt.rstrip(), readline.get_line_buffer(), sep='', end='')
    sys.stdout.flush()

答案 2 :(得分:0)

这个对我有用,用于重新显示替换,并且显示python3的比赛结束:

    def match_display_hook(self, substitution, matches, longest_match_length):
        print("")
        for match in matches:
            print(match)
        print("")
        sys.stdout.write(substitution)
        sys.stdout.flush()
        return None

,而以前使用打印提示的人没有。 (没有找到问题的根本)