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.
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
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()
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.
How to enable python repl autocomplete and still allow new line tabs
You should just use IPython. It has both tab completion and auto-indenting of for loops or function definitions. For example:
# Ipython prompt
In [1]: def stuff(x):
...: |
# ^ cursor automatically moves to this position
To install it, you can use pip
:
pip install ipython
If you don't have pip
installed, you can follow the instructions on this page. On python >= 3.4, pip
is installed by default.
If you're on windows, this page contains installers for ipython (and many other python libraries that may be difficult to install).
However, if for any reason you can't install ipython, Brandon Invergo had created a python start-up script that adds several features to the python interpreter, among which is auto indentation. He has released it under GPL v3 and published the source here.
I've copied the code that handles the auto-indentation below. I had to add indent = ''
at line 11 to make it work on my python 3.4 interpreter.
import readline
def rl_autoindent():
"""Auto-indent upon typing a new line according to the contents of the
previous line. This function will be used as Readline's
pre-input-hook.
"""
hist_len = readline.get_current_history_length()
last_input = readline.get_history_item(hist_len)
indent = ''
try:
last_indent_index = last_input.rindex(" ")
except:
last_indent = 0
else:
last_indent = int(last_indent_index / 4) + 1
if len(last_input.strip()) > 1:
if last_input.count("(") > last_input.count(")"):
indent = ''.join([" " for n in range(last_indent + 2)])
elif last_input.count(")") > last_input.count("("):
indent = ''.join([" " for n in range(last_indent - 1)])
elif last_input.count("[") > last_input.count("]"):
indent = ''.join([" " for n in range(last_indent + 2)])
elif last_input.count("]") > last_input.count("["):
indent = ''.join([" " for n in range(last_indent - 1)])
elif last_input.count("{") > last_input.count("}"):
indent = ''.join([" " for n in range(last_indent + 2)])
elif last_input.count("}") > last_input.count("{"):
indent = ''.join([" " for n in range(last_indent - 1)])
elif last_input[-1] == ":":
indent = ''.join([" " for n in range(last_indent + 1)])
else:
indent = ''.join([" " for n in range(last_indent)])
readline.insert_text(indent)
readline.set_pre_input_hook(rl_autoindent)
PyCharm autocomplete fails so show all options
discord.Client
uses __getattr__
to handle attribute lookup for the user
attribute dynamically. __getattr__
is fundamentally incompatible with the kind of static analysis PyCharm uses for autocompletion.
I'd probably just live with PyCharm not being able to find this attribute. If you want to do something about it anyway, writing type stubs might help (or they might go out of sync with the implementation and cause more problems), or you could see if discord.py would accept a pull request to use properties instead of __getattr__
/__setattr__
for the attribute forwarding they're doing here.
Related Topics
How to Embed HTML into Ipython Output
Python Ftp Get the Most Recent File by Date
Django Server Killed Frequently
Call Python Code from an Existing Project Written in Swift
Strange Result When Removing Item from a List While Iterating Over It
Difference Between Re.Search and Re.Match
Flattening a Shallow List in Python
Finding the Index of an Item in a List
Best Way to Strip Punctuation from a String
Deploying a Minimal Flask App in Docker - Server Connection Issues
Checking If Element Exists With Python Selenium
Python Subprocess.Popen "Oserror: [Errno 12] Cannot Allocate Memory"
How to Make a Python, Command-Line Program Autocomplete Arbitrary Things Not Interpreter
Hex/Binary String Conversion in Swift