第十四章:应用构建模块-readline: GNU readline库-访问完成缓冲区

博客介绍了SimpleCompleter中的完成算法,该算法只查看传入函数的文本参数,未用readline内部状态其他信息。还可使用readline函数管理输入缓冲区文本。以完成有子选项的命令为例,说明了不同情况下的完成候选项,如顶层命令及‘list’后的完成情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

14.3.3 访问完成缓冲区
SimpleCompleter中的完成算法只查看传入函数的文本参数,而没有使用readline内部状态的任何其他信息。还可以使用readline函数来管理输入缓冲区的文本。

try:
    import gnureadline as readline
except ImportError:
    import readline
import logging

LOG_FILENAME = '/tmp/completer.log'
logging.basicConfig(
    format='%(message)s',
    filename=LOG_FILENAME,
    level=logging.DEBUG,
    )

class BufferAwareCompleter:

    def __init__(self,options):
        self.options = options
        self.current_candidates = []

    def complete(self,text,state):
        response = None
        if state == 0:
            # This is the first time for this text,
            # so build a match list.

            origline = readline.get_line_buffer()
            begin = readline.get_begidx()
            end = readline.get_endidx()
            being_completed = origline[begin:end]
            words = origline.split()

            logging.debug('origline=%s',repr(origline))
            logging.debug('begin=%s',begin)
            logging.debug('end=%s',end)
            logging.debug('being_completed=%s',being_completed)
            logging.debug('words=%s',words)

            if not words:
                self.current_candidates = sorted(
                    self.options.keys()
                    )
            else:
                try:
                    if begin == 0:
                        # First word
                        candidates = self.options.keys()
                    else:
                        # Later word
                        first = words[0]
                        candidates = self.options[first]

                    if being_completed:
                        # Match options with portion of input
                        # being completed
                        self.current_candidates = [
                            w for w in candidates
                            if w.startswith(being_completed)
                            ]
                    else:
                        # Matching empty string,
                        # use all candidates
                        self.current_candidates = candidates

                    logging.debug('candidates=%s',
                                  self.current_candidates)

                except (KeyError,IndexError) as err:
                    logging.error('completion error: %s',err)
                    self.current_candidates = []

        try:
            response = self.current_candidates[state]
        except IndexError:
            response = None
        logging.debug('complete(%s,%s) => %s',
                        repr(text),state,response)
        return response

def input_loop():
    line = ''
    while line != 'stop':
        line = input('Prompt ("stop" to quit): ')
        print('Dispatch {}'.format(line))

# Register our completer function.
completer = BufferAwareCompleter({
    'list':['files','directories'],
    'print':['byname','bysize'],
    'stop':[],
    })
readline.set_completer(completer.complete)

# Use the tab key for completion.
readline.parse_and_bind('tab: complete')

# Prompt the user for text.
input_loop()

这个例子要完成有子选项的命令。complete()方法需要在输入缓冲区中查看完成的位置,来确定它是第一个词的一部分还是后一个词的一部分。如果目标是第一个词,则将使用选项字典的键作为候选项。如果不是第一个词,则使用第一个词在选项字典中查找候选项。
这里有3个顶层命令,其中两个有子命令。

list

files

directories

print

byname

bysize

stop

按照前面的同样的动作序列,两次按下tab会给出3个顶层命令。
在这里插入图片描述
日志包括以下信息:

在这里插入图片描述
如果第一个词是’list’(单词后面有一个空格),则完成候选项是不同的。

从日志可以看到,所完成的文本不是一整行,则只是list后的部分。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值