Comment faire un Python, un programme de ligne de commande qui remplit automatiquement des choses arbitraires PAS un interpréteur


92

Je sais comment configurer l'auto-complétion des objets python dans l'interpréteur python (sous unix).

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

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

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

Je n'en ai pas besoin pour fonctionner sur Windows ou Mac, juste Linux.


Ce blog devrait faire les astuces avec la configuration du fichier .pythonrc.
Kris Roofe

Réponses:


63

Utilisez les readlineliaisons 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 documents officiels du module ne sont pas beaucoup plus détaillés, consultez les documents readline pour plus d'informations.


1
notez que si vous écrivez votre ligne de commande avec le module cmd, il existe de meilleures façons de le faire.
Florian Bösch

60

Suivez la documentation cmd et tout ira bien

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()

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

(Cmd)
help  send
(Cmd) send
foo@bar.com            here@blubb.com         whatever@wherever.org
(Cmd) send foo@bar.com
(Cmd)

Existe-t-il un moyen de contrôler la manière dont readline colore sa sortie? Disons donc que je voudrais qu'il soit en colonne avec deux espaces entre chaque élément.
Fnord

Lorsque j'exécute ce code, les onglets sont simplement imprimés dans la ligne de commande. En fait, cela est vrai que j'utilise cmd ou straight readline.
Hack Saw

38

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

Je pense que vous pourriez être après ça .

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

En un mot, vous allez créer un fichier contenant une fonction shell qui générera des complétions possibles, l'enregistrer /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, le typage foo --[TAB]vous donnera les valeurs de la variable opts, c'est --help-à- dire --verboseet --version. Pour vos besoins, vous souhaiterez essentiellement personnaliser les valeurs insérées opts.

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


10
En fait, je suis venu ici à cause de cela
user1767754

Merci, c'est exactement ce que je cherchais!
Teekeks

27

Je suis surpris que personne n'ait mentionné argcomplete, voici un exemple tiré 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'))

C'est un vieux post, peut-être qu'argcomplete n'existait pas à l'époque? Merci de l'avoir mentionné, je pense que c'est exactement ce dont mon projet a besoin!
FrustratedWithFormsDesigner

Très bien en combinaison avec argparse aussi!
AstroFloyd

13

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

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

10
# ~/.pythonrc
import rlcompleter, readline
readline.parse_and_bind('tab:complete')

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

1
Pour mac OS, remplacez readline.parse_and_bind('tab:complete') parreadline.parse_and_bind ("bind ^I rl_complete")
Mani

C'est génial. A travaillé pour moi. Merci d'avoir partagé.
Ajay Ahuja

@Mani J'étais coincé là-dedans pendant longtemps. Merci beaucoup
AnaS Kayed

5

Vous pouvez essayer d'utiliser le 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 la Tabclé pour parcourir visuellement les choix disponibles. La bibliothèque est multiplateforme (Linux, OS X, FreeBSD, OpenBSD, Windows). Exemple:

pgcli - Boîte à outils d'invite Python

(Source de l'image: pcgli )


1

Les réponses publiées fonctionnent bien, mais j'ai ouvert une bibliothèque à 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 dispose même d'un mode démo pour que vous puissiez rapidement tester ce que vous obtiendriez en tapant des mots.

Pour l'installer, exécutez 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 burritoc'est plus important que book, alors vous donnez burritoun "compte" plus élevé et il apparaîtra en premier bookdans les résultats.

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

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.