How to make a python, command-line program autocomplete arbitrary things NOT interpreter
I am aware of how to setup autocompletion of python objects in the python interpreter (on unix).
- Google shows many hits for explanations on how to do this.
- Unfortunately, there are so many references to that it is difficult to find what I need to do, which is slightly different.
I need to know how to enable, tab/auto completion of arbitrary items in a command-line program written in python.
My specific use case is a command-line python program that needs to send emails. I want to be able to autocomplete email addresses (I have the addresses on disk) when the user types part of it (and optionally presses the TAB key).
I do not need it to work on windows or mac, just linux.
Asked by: Ted476 | Posted: 28-01-2022
Answer 1
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.
Answered by: Victoria158 | Posted: 01-03-2022Answer 2
Follow the cmd documentation and you'll be fine
import cmd
addresses = [
'here@blubb.com',
'foo@bar.com',
'whatever@wherever.org',
]
class MyCmd(cmd.Cmd):
def do_send(self, line):
pass
def complete_send(self, text, line, start_index, end_index):
if text:
return [
address for address in addresses
if address.startswith(text)
]
else:
return addresses
if __name__ == '__main__':
my_cmd = MyCmd()
my_cmd.cmdloop()
Output for tab -> tab -> send -> tab -> tab -> f -> tab
(Cmd)
help send
(Cmd) send
foo@bar.com here@blubb.com whatever@wherever.org
(Cmd) send foo@bar.com
(Cmd)
Answered by: Victoria885 | Posted: 01-03-2022
Answer 3
Since you say "NOT interpreter" in your question, I guess you don't want answers involving python readline and suchlike. (edit: in hindsight, that's obviously not the case. Ho hum. I think this info is interesting anyway, so I'll leave it here.)
I think you might be after this.
It's about adding shell-level completion to arbitrary commands, extending bash's own tab-completion.
In a nutshell, you'll create a file containing a shell-function that will generate possible completions, save it into /etc/bash_completion.d/
and register it with the command complete
. Here's a snippet from the linked page:
_foo()
{
local cur prev opts
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
opts="--help --verbose --version"
if [[ ${cur} == -* ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
fi
}
complete -F _foo foo
In this case, the typing foo --[TAB]
will give you the values in the variable opts
, i.e. --help
, --verbose
and --version
. For your purposes, you'll essentially want to customise the values that are put into opts
.
Do have a look at the example on the linked page, it's all pretty straightforward.
Answered by: Adelaide131 | Posted: 01-03-2022Answer 4
I am surprised that nobody has mentioned argcomplete, here is an example from the docs:
from argcomplete.completers import ChoicesCompleter
parser.add_argument("--protocol", choices=('http', 'https', 'ssh', 'rsync', 'wss'))
parser.add_argument("--proto").completer=ChoicesCompleter(('http', 'https', 'ssh', 'rsync', 'wss'))
Answered by: Rafael412 | Posted: 01-03-2022
Answer 5
Here is a full-working version of the code that was very supplied by ephemient here (thank you).
import readline
addrs = ['angela@domain.com', 'michael@domain.com', 'david@test.com']
def completer(text, state):
options = [x for x in addrs if x.startswith(text)]
try:
return options[state]
except IndexError:
return None
readline.set_completer(completer)
readline.parse_and_bind("tab: complete")
while 1:
a = raw_input("> ")
print "You entered", a
Answered by: Jack579 | Posted: 01-03-2022
Answer 6
# ~/.pythonrc
import rlcompleter, readline
readline.parse_and_bind('tab:complete')
# ~/.bashrc
export PYTHONSTARTUP=~/.pythonrc
Answered by: Ryan519 | Posted: 01-03-2022
Answer 7
You can try using the Python Prompt Toolkit, a library for building interactive command line applications in Python.
The library makes it easy to add interactive autocomplete functionality, allowing the user to use the Tab key to visually cycle through the available choices. The library is cross-platform (Linux, OS X, FreeBSD, OpenBSD, Windows). Example:
(Image source: pcgli)
Answered by: Wilson927 | Posted: 01-03-2022Answer 8
The posted answers work fine but I have open sourced an autocomplete library that I wrote at work. We have been using it for a while in production and it is fast, stable and easy to use. It even has a demo mode so you can quickly test what you would get as you type words.
To install it, simply run: pip install fast-autocomplete
Here is an example:
>>> from fast_autocomplete import AutoComplete
>>> words = {'book': {}, 'burrito': {}, 'pizza': {}, 'pasta':{}}
>>> autocomplete = AutoComplete(words=words)
>>> autocomplete.search(word='b', max_cost=3, size=3)
[['book'], ['burrito']]
>>> autocomplete.search(word='bu', max_cost=3, size=3)
[['burrito']]
>>> autocomplete.search(word='barrito', max_cost=3, size=3) # mis-spelling
[['burrito']]
Checkout: https://github.com/seperman/fast-autocomplete for the source code.
And here is an explanation of how it works: http://zepworks.com/posts/you-autocomplete-me/
It deals with mis-spellings and optionally sorting by the weight of the word. (let's say burrito
is more important than book
, then you give burrito
a higher "count" and it will show up first before book
in the results.
Words is a dictionary and each word can have a context. For example the "count", how to display the word, some other context around the word etc. In this example words didn't have any context.
Answered by: Richard618 | Posted: 01-03-2022Answer 9
This works well.
#!/usr/bin/python3
import readline
readline.parse_and_bind("tab: complete")
def complete(text,state):
volcab = ['dog','cat','rabbit','bird','slug','snail']
results = [x for x in volcab if x.startswith(text)] + [None]
return results[state]
readline.set_completer(complete)
line = input('prompt> ')
Answered by: Audrey808 | Posted: 01-03-2022
Similar questions
java - OCSP command-line test tool?
Closed. This question does not meet Stack Overflow guid...
python - How to prompt for user input and read command-line arguments
Closed. This question needs to be more focused. It ...
eclipse - Integrating command-line generated python .coverage files with PyDev
My build environment is configured to compile, run and create coverage file at the command line (using Ned Batchelder coverage.py tool).
I'm using Eclipse with PyDev as my editor, but for practical reasons, it's not possible/convenient for me to convert my whole build environment to Eclipse (and thus generate the coverage data directly from the IDE, as it's designed to do)
PyDev seems to be using the same ...
c++ - How do I compile a Visual Studio project from the command-line?
I'm scripting the checkout, build, distribution, test, and commit cycle for a large C++ solution that is using Monotone, CMake, Visual Studio Express 2008, and custom tests.
All of the other parts seem pretty straight-forward, but I don't see how to compile the Visu...
How to make a simple command-line chat in Python?
I study network programming and would like to write a simple command-line chat in Python.
I'm wondering how make receving constant along with inputing available for sending at any time.
As you see, this client can do only one job at a time:
from socket import *
HOST = 'localhost'
PORT = 21567
BUFSIZE = 1024
ADDR = (HOST, PORT)
tcpCliSock = socket(AF_INET, SOCK_STREAM)
tcpCliSock.connect(A...
interpreter - Persistent Python Command-Line History
I'd like to be able to "up-arrow" to commands that I input in a previous Python interpreter. I have found the readline module which offers functions like: read_history_file, write_history_file, and set_startup_hook. I'm not quite savvy enough to put this into practice though, so could someone please help? My thoughts on the solution are:
(1) Modify .login PYTHO...
data structures - Processing command-line arguments in prefix notation in Python
I'm trying to parse a command-line in Python which looks like the following:
$ ./command -o option1 arg1 -o option2 arg2 arg3
In other words, the command takes an unlimited number of arguments, and each argument may optionally be preceded with an -o option, which relates specifically to that argument. I think this is called a "prefix notation".
In the Bourne shell I wo...
Display constantly updating information in-place in command-line window using python?
I am essentially building a timer. I have a python script that monitors for an event and then prints out the seconds that have elapsed since that event.
Instead of an ugly stream of numbers printed to the command line, I would like to display only the current elapsed time "in-place"-- so that only one number is visible at any given time.
Is there a simple way to do this?
If possible I'd like to u...
python - How to write script output to file and command-line?
I have a long-running Python script that I run from the command-line. The script writes progress messages and results to the standard output. I want to capture everything the script write to the standard output in a file, but also see it on the command line. Alternatively, I want the output to go to the file immediately, so I can use tail to view the progress. I have tried this:
python MyLongRu...
python - Linux command-line call not returning what it should from os.system?
I need to make some command line calls to linux and get the return from this, however doing it as below is just returning 0 when it should return a time value, like 00:08:19, I am testing the exact same call in regular command line and it returns the time value 00:08:19 so I am confused as to what I am doing wrong as I thought this was how to do it in python.
import os...
Still can't find your answer? Check out these communities...
PySlackers | Full Stack Python | NHS Python | Pythonist Cafe | Hacker Earth | Discord Python