Setting up readline
¶
Readline Summary¶
Readline is implemented in the repository for a few reasons.
It’s ubiquity in open source programming
In addition, it’s utilized here to compensate for the weaknesses of other implementations.
IPython’s auto-completion is entirely non-configurable and exceedingly slow.
Frequently auto-completion will time out rather than serving a response
prompt_toolkit
has a rather rigid interface for it’s API. There areassert
's all over the code base ensuring that the proper type is passed to a class constructor, in spite of the Python’s dynamically typed foundation.
Setting up autocompletion¶
IPython provides it’s users the ability to add in custom completers.
To take advantage of this ability one can call get_ipython
and add their
custom Completers via the method set_custom_completer()
.
However, all that the function does is a simple call to types.MethodTypes
and
then tacks it on to the list bound at get_ipython().Completer.matchers
.
-
set_custom_completer
(completer, pos=0)[source] Adds a new custom completer function. The position argument (defaults to 0) is the index in the completers list where you want the completer to be inserted.
Source:
def set_custom_completer(self, completer, pos=0):
"""Adds a new custom completer function.
The position argument (defaults to 0) is the index in the completers
list where you want the completer to be inserted."""
newcomp = types.MethodType(completer,self.Completer)
self.Completer.matchers.insert(pos,newcomp)
In [1]: _ip = get_ipython()
In [2]: _ip.Completer.matchers
Out[2]:
[<bound method IPCompleter.file_matches of <IPython.core.completer.IPCompleter object at 0x0000020407BB18C0>>,
<bound method IPCompleter.magic_matches of <IPython.core.completer.IPCompleter object at 0x0000020407BB18C0>>,
<bound method IPCompleter.dict_key_matches of <IPython.core.completer.IPCompleter object at 0x0000020407BB18C0>>]
Useful to see the magic_matches
, dict_key_matches
, file_matches
and
I think there’s supposed to be a python_matches or a keyword specific one.
Interestingly, there’s also a method on the completer that returns a
IPython.utils.strdispatchers.StrDispatch
class.
If so, then that would possibly make it the only use I’ve seen in the repo of this. Still unsure of what this class is though.
In [3]: from IPython.utils.strdispatch import StrDispatch
In [4]: what = StrDispatch()
>>> dis = StrDispatch()
>>> dis.add_s('hei',34, priority = 4)
>>> dis.add_s('hei',123, priority = 2)
>>> dis.add_re('h.i', 686)
>>> print(list(dis.flat_matches('hei')))
[123, 34, 686]
In [45]: _ip.Completer.custom_completers
Out[45]: <Strdispatch {
'import': <IPython.core.hooks.CommandChainDispatcher object at 0x7f0acc3defa0>,
'from': <IPython.core.hooks.CommandChainDispatcher object at 0x7f0acc3dee50>,
'%aimport': <IPython.core.hooks.CommandChainDispatcher object at 0x7f0acc3de370>,
'%run': <IPython.core.hooks.CommandChainDispatcher object at 0x7f0acc3def40>,
'%cd': <IPython.core.hooks.CommandChainDispatcher object at 0x7f0acc3def10>,
'%reset': <IPython.core.hooks.CommandChainDispatcher object at 0x7f0acc3ded00>},
}
In [46]: dir(_ip.Completer.custom_completers)
Out[46]: ['...',
'add_re',
'add_s',
'dispatch',
'flat_matches',
'regexs',
's_matches']
So hooks are implemented in the completion mechanism too? Dude I’m counting 3 nested classes and counting.
Autogenerated Readline Docs¶
In tandem with ../pyreadlineconfig.ini
, keybindings
are set up to attempt adding the standard readline bindings
to Vim insert mode.
Extended Summary¶
The keybindings that prompt_toolkit provides are more powerful; however they’re substantially more complicated and for simple modifications of how to work with a line-editor buffer, this proves needlessly complex in addition to periodically leaving the entire terminal in an unusuable state.
See also
-
class
ViExternalEditor
(line: AnyStr = None)[source][source]¶ Bases:
object
If I’m not mistaken, there are typos that are causing Vi mode to fail.
03/22/2020: After pressing Esc to go into Normal mode, I tried invoking the external editor with k.
>>> def cd(arg): >>> pass
Let’s see what happens if we get rid of the space between file and
(
Alright well in my defense this class was created quitely poorly; however, it’s a little too easy to initialize this sucker with no state.
-
__init__
(line: AnyStr = None)[source][source]¶ Instantiate the editor vi.
- Parameters
line (str) – Line that the user is typing.
-
run_editor
(filename: Optional[Union[AnyStr, os.PathLike]] = None)[source][source]¶ It’s the goddamn ViExternalEditor default to Vim!
-
-
class
SimpleCompleter
(options: Iterable)[source][source]¶ Bases:
object
Completion mechanism that tracks candidates for different subcommands.
The SimpleCompleter class keeps a list of options that are candidates for auto-completion. The complete method for an instance is designed to be registered with
readline
as the source of completions.-
complete
(text, state)[source][source]¶ Complete a user’s input.
The arguments are a text string to complete and a state value, indicating how many times the function has been called with the same text.
The function is called repeatedly with the state incremented each time. It should return a string if there is a candidate for that state value or None if there are no more candidates.
The implementation of complete here looks for a set of matches when state is 0, and then returns all of the candidate matches one at a time on subsequent calls.
-
-
complete
(text, state)[source][source]¶ If no text in front of the cursor, return 4 spaces. Otherwise use the standard completer.
-
input_loop
()[source][source]¶ Simulate a runnnig loop with a call to
input
.Todo
Register the completer function.:
OPTIONS = ['start', 'stop', 'list', 'print'] readline.set_completer(SimpleCompleter(OPTIONS).complete)
Check what the API is to add a completer to ipython. I think it’s
InteractiveShell
`.set_custom_completer`.
-
gnu_readline_config
()[source][source]¶ Readline configuration that’s incompatible with GNU readline.
Pyreadline doesn’t recognize a lot of the standard Readline functions, so to avoid emitting warnings upon startup, a handful of bindings were separated from
readline_config
.
-
readline_config
()[source][source]¶ The main point of execution for the readline configs.
Should be cross-platform and independent of GNU readline or py readline.
This sets up history where the history file is saved to and calls
atexit
with thesetup_historyfile
andteardown_historyfile
functions as parameters.
-
pyreadline_specific
(rl=None)[source][source]¶ Utilize the pyreadline API.
:param
pyreadline.rlmain.Readline
:- Returns
Currently None. Seemingly works by modifying attributes on the instance
and relying on side effects.
-
setup_historyfile
(filename: Optional[Union[AnyStr, os.PathLike]] = None)[source][source]¶ Add a history file to readline.
- Parameters
filename (str, path, or
os.Pathlike
) – path to the history file. Internally converted to apathlib.Path
.
-
last_input
() → AnyStr[source][source]¶ Returns the user’s last input.
Utilizes the raw_cell attribute found on an
IPython.core.interactiveshell.ExecutionInfo
instance.
-
add_last_input
()[source][source]¶ Calls readline’s
add_history
function withlast_input
.