web-dev-qa-db-fra.com

Comment faire un python, un programme en ligne de commande autocomplete des choses arbitraires PAS un interprète

Je sais comment configurer la saisie semi-automatique des objets python dans l'interpréteur python (sous Unix)).

  • Google affiche de nombreux résultats pour obtenir des explications sur la façon de procéder.
  • Malheureusement, il y a tellement de références qu'il est difficile de trouver ce que je dois faire, ce qui est légèrement différent.

J'ai besoin de savoir comment activer, tabulation/complétion automatique des éléments arbitraires dans un programme en ligne de commande écrit en python.

Mon cas d'utilisation spécifique est une ligne de commande python qui doit envoyer des e-mails. Je veux pouvoir compléter automatiquement les adresses e-mail (j'ai les adresses sur le disque) lorsque l'utilisateur tape une partie de celui-ci (et appuie éventuellement sur la touche TAB).

Je n'en ai pas besoin pour travailler sur windows ou mac, juste linux.

82
Paul D. Eden

Utilisez les liaisons readline de Python. Par exemple,

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)

Les module docs officiels ne sont pas beaucoup plus détaillés, voir les readline docs pour plus d'informations.

57
ephemient

Suivez la documentation cmd et tout ira bien

import cmd

addresses = [
    '[email protected]',
    '[email protected]',
    '[email protected]',
]

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 __== '__main__':
    my_cmd = MyCmd()
    my_cmd.cmdloop()

Sortie pour onglet -> onglet -> envoyer -> onglet -> onglet -> f -> onglet

(Cmd)
help  send
(Cmd) send
[email protected]            [email protected]         [email protected]
(Cmd) send [email protected]
(Cmd)
57
Florian Bösch

Puisque vous dites "PAS interprète" dans votre question, je suppose que vous ne voulez pas de réponses impliquant python readline et autres. ( éditez: avec le recul, ce n'est évidemment pas le cas. Ho hum. Je pense que cette info est intéressante de toute façon, donc je vais la laisser ici. =)

Je pense que vous pourriez être après ceci .

Il s'agit d'ajouter la complétion au niveau du shell à des commandes arbitraires, étendant la propre complétion par tabulation de bash.

En bref, vous allez créer un fichier contenant une fonction Shell qui générera des complétions possibles, enregistrez-le dans /etc/bash_completion.d/ et l'enregistrer avec la commande complete. Voici un extrait de la page liée:

_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

Dans ce cas, la saisie foo --[TAB] vous donnera les valeurs de la variable opts, c'est-à-dire --help, --verbose et --version. Pour vos besoins, vous souhaiterez essentiellement personnaliser les valeurs qui sont mises dans opts.

Jetez un oeil à l'exemple sur la page liée, tout est assez simple.

34
Owen

Je suis surpris que personne n'ait mentionné argcomplete, voici un exemple de la documentation:

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'))
23
qed

Voici une version complète du code qui a été très fournie par ephemient ici (merci).

import readline

addrs = ['[email protected]', '[email protected]', '[email protected]']

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
12
Paul D. Eden
# ~/.pythonrc
import rlcompleter, readline
readline.parse_and_bind('tab:complete')

# ~/.bashrc
export PYTHONSTARTUP=~/.pythonrc
9
user178047

Vous pouvez essayer d'utiliser Python Prompt Toolkit , une bibliothèque pour créer des applications de ligne de commande interactives en Python.

La bibliothèque facilite l'ajout d'une fonctionnalité de saisie semi-automatique interactive, permettant à l'utilisateur d'utiliser le Tab pour parcourir visuellement les choix disponibles. La bibliothèque est multiplateforme (Linux, OS X, FreeBSD, OpenBSD, Windows). Exemple:

pgcli - Python Prompt Toolkit

(Source de l'image: pcgli )

1
Flux

Les réponses publiées fonctionnent bien, mais j'ai ouvert une bibliothèque de saisie semi-automatique que j'ai écrite au travail. Nous l'utilisons depuis un certain temps en production et il est rapide, stable et facile à utiliser. Il a même un mode démo afin que vous puissiez tester rapidement ce que vous obtiendriez en tapant des mots.

Pour l'installer, lancez simplement: pip install fast-autocomplete

Voici un exemple:

>>> 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']]

Paiement: https://github.com/wearefair/fast-autocomplete pour le code source.

Et voici une explication de son fonctionnement: http://zepworks.com/posts/you-autocomplete-me/

Il traite des fautes d'orthographe et éventuellement du tri en fonction du poids du mot. (disons que burrito est plus important que book, alors vous donnez à burrito un "count" plus élevé et il apparaîtra d'abord avant book dans les résultats .

Les mots sont un dictionnaire et chaque mot peut avoir un contexte. Par exemple, le "nombre", comment afficher le mot, un autre contexte autour du mot, etc. Dans cet exemple, les mots n'avaient pas de contexte.

0
Seperman