4

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

Python2 中的解决方案似乎是(这里的解决方案):

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()

请问有什么想法吗?

4

3 回答 3

1

首先,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()
于 2016-06-08T21:10:41.900 回答
1

redisplay()功能_

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

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

如其他答案中所述的打印和刷新应该可以工作。

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

$ cmd some_file
      ^
      +---- 用户已在此处回溯并想插入一个选项。
            <TAB> 使用 print 和 flush 完成将放置光标
            在“some_file”的末尾,该行将获得额外的 15
            之后的空格...

解决这个问题的方法是首先获取光标位置,然后使用 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)

于 2019-10-06T23:25:16.927 回答
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

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

于 2020-11-11T12:07:42.663 回答