readline — GNU readline 库
优质
小牛编辑
134浏览
2023-12-01
配置
# readline_parse_and_bind.py
try:
import gnureadline as readline
except ImportError:
import readline
readline.parse_and_bind('tab: complete')
readline.parse_and_bind('set editing-mode vi')
while True:
line = input('Prompt ("stop" to quit): ')
if line == 'stop':
break
print('ENTERED: {!r}'.format(line))
# myreadline.rc
# Turn on tab completion
tab: complete
# Use vi editing mode instead of emacs
set editing-mode vi
# readline_read_init_file.py
try:
import gnureadline as readline
except ImportError:
import readline
readline.read_init_file('myreadline.rc')
while True:
line = input('Prompt ("stop" to quit): ')
if line == 'stop':
break
print('ENTERED: {!r}'.format(line))
Completing Text
# readline_completer.py
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 SimpleCompleter:
def __init__(self, options):
self.options = sorted(options)
def complete(self, text, state):
response = None
if state == 0:
# This is the first time for this text,
# so build a match list.
if text:
self.matches = [
s
for s in self.options
if s and s.startswith(text)
]
logging.debug('%s matches: %s',
repr(text), self.matches)
else:
self.matches = self.options[:]
logging.debug('(empty input) matches: %s',
self.matches)
# Return the state'th item from the match list,
# if we have that many.
try:
response = self.matches[state]
except IndexError:
response = None
logging.debug('complete(%s, %s) => %s',
repr(text), state, repr(response))
return response
def input_loop():
line = ''
while line != 'stop':
line = input('Prompt ("stop" to quit): ')
print('Dispatch {}'.format(line))
# Register the completer function
OPTIONS = ['start', 'stop', 'list', 'print']
readline.set_completer(SimpleCompleter(OPTIONS).complete)
# Use the tab key for completion
readline.parse_and_bind('tab: complete')
# Prompt the user for text
input_loop()
Accessing the Completion Buffer
# readline_buffer.py
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()
输入历史
# readline_history.py
try:
import gnureadline as readline
except ImportError:
import readline
import logging
import os
LOG_FILENAME = '/tmp/completer.log'
HISTORY_FILENAME = '/tmp/completer.hist'
logging.basicConfig(
format='%(message)s',
filename=LOG_FILENAME,
level=logging.DEBUG,
)
def get_history_items():
num_items = readline.get_current_history_length() + 1
return [
readline.get_history_item(i)
for i in range(1, num_items)
]
class HistoryCompleter:
def __init__(self):
self.matches = []
def complete(self, text, state):
response = None
if state == 0:
history_values = get_history_items()
logging.debug('history: %s', history_values)
if text:
self.matches = sorted(
h
for h in history_values
if h and h.startswith(text)
)
else:
self.matches = []
logging.debug('matches: %s', self.matches)
try:
response = self.matches[state]
except IndexError:
response = None
logging.debug('complete(%s, %s) => %s',
repr(text), state, repr(response))
return response
def input_loop():
if os.path.exists(HISTORY_FILENAME):
readline.read_history_file(HISTORY_FILENAME)
print('Max history file length:',
readline.get_history_length())
print('Startup history:', get_history_items())
try:
while True:
line = input('Prompt ("stop" to quit): ')
if line == 'stop':
break
if line:
print('Adding {!r} to the history'.format(line))
finally:
print('Final history:', get_history_items())
readline.write_history_file(HISTORY_FILENAME)
# Register our completer function
readline.set_completer(HistoryCompleter().complete)
# Use the tab key for completion
readline.parse_and_bind('tab: complete')
# Prompt the user for text
input_loop()
Hooks 钩子
# readline_hooks.py
try:
import gnureadline as readline
except ImportError:
import readline
def startup_hook():
readline.insert_text('from startup_hook')
def pre_input_hook():
readline.insert_text(' from pre_input_hook')
readline.redisplay()
readline.set_startup_hook(startup_hook)
readline.set_pre_input_hook(pre_input_hook)
readline.parse_and_bind('tab: complete')
while True:
line = input('Prompt ("stop" to quit): ')
if line == 'stop':
break
print('ENTERED: {!r}'.format(line))