【问题标题】:Python : correct use of set_completion_display_matches_hookPython:正确使用 set_completion_display_matches_hook
【发布时间】:2013-05-10 15:13:00
【问题描述】:

我正在尝试编写一个函数来在用户按下选项卡按钮时显示自定义视图。显然“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()

有什么想法吗?

【问题讨论】:

    标签: python python-3.x readline


    【解决方案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()
    

    【讨论】:

      【解决方案2】:

      redisplay() 函数

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

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

      other answer 中描述的打印和刷新应该可以工作。

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

      $ cmd some_file ^ +---- 用户已在此处回溯并想插入一个选项。 使用 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)需要它

      【讨论】:

        【解决方案3】:

        这个对我有用,用于重新显示替换,并为 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
        

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

        【讨论】:

          猜你喜欢
          • 2015-03-18
          • 1970-01-01
          • 2020-05-03
          • 2017-08-20
          • 2016-03-26
          • 1970-01-01
          • 2016-05-17
          • 2013-05-23
          • 1970-01-01
          相关资源
          最近更新 更多