Howto do python command-line autocompletion but NOT only at the beginning of a string
I'm not sure I understand the problem. You could use readline.clear_history and readline.add_history to set up the completable strings you want, then control-r to search backword in the history (just as if you were at a shell prompt). For example:
#!/usr/bin/env python
import readline
readline.clear_history()
readline.add_history('foo')
readline.add_history('bar')
while 1:
print raw_input('> ')
Alternatively, you could write your own completer version and bind the appropriate key to it. This version uses caching in case your match list is huge:
#!/usr/bin/env python
import readline
values = ['Paul Eden <paul@domain.com>',
'Eden Jones <ejones@domain.com>',
'Somebody Else <somebody@domain.com>']
completions = {}
def completer(text, state):
try:
matches = completions[text]
except KeyError:
matches = [value for value in values
if text.upper() in value.upper()]
completions[text] = matches
try:
return matches[state]
except IndexError:
return None
readline.set_completer(completer)
readline.parse_and_bind('tab: menu-complete')
while 1:
a = raw_input('> ')
print 'said:', a
How to make a python, command-line program autocomplete arbitrary things NOT interpreter
Use Python's readline
bindings. For example,
import readline
def completer(text, state):
options = [i for i in commands if i.startswith(text)]
if state < len(options):
return options[state]
else:
return None
readline.parse_and_bind("tab: complete")
readline.set_completer(completer)
The official module docs aren't much more detailed, see the readline docs for more info.
TAB autocomplete python CLI
That is a feature of the shell, not of the Python script being called. See this question on SO for more info on shell completion. In particular, you're looking for programmable completion.
Autocompletion in Python shell only when it makes sense
I found ptpython ptpython, which can be easily embedded in a shell.
Edit: that project has too many features for me. I can use ipython instead of the python shell
Cmd module : having completion on the first word
The answer is actually simple : Cmd.completenames
. More info here. A similar question here.
Command-line autocompletion for python -m module
As said in the comment section, you need to extend the bash-completion tool. Then, you'll create a script which handles the cases you need (ie: when the last argument was -m
).
This little sample below shows a start for your custom completion script. Let's name it python_completion.sh
.
_python_target() {
local cur prev opts
# Retrieving the current typed argument
cur="${COMP_WORDS[COMP_CWORD]}"
# Retrieving the previous typed argument ("-m" for example)
prev="${COMP_WORDS[COMP_CWORD-1]}"
# Preparing an array to store available list for completions
# COMREPLY will be checked to suggest the list
COMPREPLY=()
# Here, we'll only handle the case of "-m"
# Hence, the classic autocompletion is disabled
# (ie COMREPLY stays an empty array)
if [[ "$prev" != "-m" ]]
then
return 0
fi
# Retrieving paths and converts their separators into dots
# (if packages doesn't exist, same thing, empty array)
if [[ ! -e "./package" ]]
then
return 0
fi
# Otherwise, we retrieve first the paths starting with "./package"
# and converts their separators into dots
opts="$(find ./package -type d | sed -e 's+/+.+g' -e 's/^\.//' | head)"
# We store the whole list by invoking "compgen" and filling
# COMREPLY with its output content.
COMPREPLY=($(compgen -W "$opts" -- "$cur"))
}
complete -F _python_target python
(Warning. This script has a flaw, it won't work with filenames containing spaces). To test it, run it in the current environnement:
. ./python_completion.sh
And test it:
python -m packag[TAB]
Here is a tutorial to continue in this way.
How to write code to autocomplete words and sentences?
(I'm aware this isn't exactly what you're asking for, but) If you're happy with the auto-completion/suggestions appearing on TAB (as used in many shells), then you can quickly get up and running using the readline module.
Here's a quick example based on Doug Hellmann's PyMOTW writeup on readline.
import readline
class MyCompleter(object): # Custom completer
def __init__(self, options):
self.options = sorted(options)
def complete(self, text, state):
if state == 0: # on first trigger, build possible matches
if text: # cache matches (entries that start with entered text)
self.matches = [s for s in self.options
if s and s.startswith(text)]
else: # no text entered, all matches possible
self.matches = self.options[:]
# return match indexed by state
try:
return self.matches[state]
except IndexError:
return None
completer = MyCompleter(["hello", "hi", "how are you", "goodbye", "great"])
readline.set_completer(completer.complete)
readline.parse_and_bind('tab: complete')
input = raw_input("Input: ")
print "You entered", input
This results in the following behaviour (<TAB>
representing a the tab key being pressed):
Input: <TAB><TAB>
goodbye great hello hi how are you
Input: h<TAB><TAB>
hello hi how are you
Input: ho<TAB>ow are you
In the last line (HOTAB entered), there is only one possible match and the whole sentence "how are you" is auto completed.
Check out the linked articles for more information on readline
.
"And better yet would be if it would complete words not only from the beginning ... completion from arbitrary part of the string."
This can be achieved by simply modifying the match criteria in the completer function, ie. from:
self.matches = [s for s in self.options
if s and s.startswith(text)]
to something like:
self.matches = [s for s in self.options
if text in s]
This will give you the following behaviour:
Input: <TAB><TAB>
goodbye great hello hi how are you
Input: o<TAB><TAB>
goodbye hello how are you
Updates: using the history buffer (as mentioned in comments)
A simple way to create a pseudo-menu for scrolling/searching is to load the keywords into the history buffer. You will then be able to scroll through the entries using the up/down arrow keys as well as use Ctrl+R to perform a reverse-search.
To try this out, make the following changes:
keywords = ["hello", "hi", "how are you", "goodbye", "great"]
completer = MyCompleter(keywords)
readline.set_completer(completer.complete)
readline.parse_and_bind('tab: complete')
for kw in keywords:
readline.add_history(kw)
input = raw_input("Input: ")
print "You entered", input
When you run the script, try typing Ctrl+r followed by a. That will return the first match that contains "a". Enter Ctrl+r again for the next match. To select an entry, press ENTER.
Also try using the UP/DOWN keys to scroll through the keywords.
Change how Python Cmd Module handles autocompletion
It shouldn't need to be overly complicated. Something like the following:
import cmd
completions = [
'Mage Slayer (Alara Reborn)',
'Magefire Wings (Alara Reborn)',
'Sages of the Anima (Alara Reborn)',
'Sanctum Plowbeast (Alara Reborn)',
'Sangrite Backlash (Alara Reborn)',
'Sanity Gnawers (Alara Reborn)',
'Sen Triplets (Alara Reborn)'
]
class mycmd(cmd.Cmd):
def __init__(self):
cmd.Cmd.__init__(self)
def do_quit(self, s):
return True
def do_add(self, s):
pass
def complete_add(self, text, line, begidx, endidx):
mline = line.partition(' ')[2]
offs = len(mline) - len(text)
return [s[offs:] for s in completions if s.startswith(mline)]
if __name__ == '__main__':
mycmd().cmdloop()
Tab Completion in Python Command Line Interface - how to catch Tab events
For that you use the readline
module.
Simplest code I can think:
import readline
COMMANDS = ['extra', 'extension', 'stuff', 'errors',
'email', 'foobar', 'foo']
def complete(text, state):
for cmd in COMMANDS:
if cmd.startswith(text):
if not state:
return cmd
else:
state -= 1
readline.parse_and_bind("tab: complete")
readline.set_completer(complete)
raw_input('Enter section name: ')
Example usage:
Enter section name: <tab>
email errors extension extra foo foobar stuff
Enter section name: e<tab>
email errors extension extra
Enter section name: ext<tab>
extension extra
Besides completion, readline
provides you with:
- Line editing
- Keybinding configuration (emacs and vi modes included)
- History (up arrow to recall previous values)
- History searching, saving and loading
Related Topics
Error: Could Not Build Wheels for Glpk Which Use Pep 517 and Cannot Be Installed Directly
Python Not Displaying Executable Output Properly
Cat, Grep and Cut - Translated to Python
Error: Command 'Gcc' Failed with Exit Status 1 on Centos
What Does --Enable-Optimizations Do While Compiling Python
Cannot "Pip Install Cryptography" in Docker Alpine Linux 3.3 with Openssl 1.0.2G and Python 2.7
Bash: Variable in Single Quote
How to Get Each Dependent Command Execution Output Using Paramiko Exec_Command
Attribute Bold Doesn't Seem to Work in My Curses
How to Cleanly Kill Subprocesses in Python
Why Not Just Use 'Shell=True' in Subprocess.Popen in Python
Typeerror: Argument 1 Must Be Pygame.Surface, Not Str How to Fix
Can't Install Gcloud on Amazon Linux:Invalid Syntax
How to Disable Stdout Buffer When Running Shell
What Are the Tkinter Events for Horizontal Edge Scrolling (In Linux)
Detect User Logout/Shutdown in Python/Gtk Under Linux - Sigterm/Hup Not Received