2010-10-19 32 views
4

J'essaye de faire un CLI, préférablement écrit en Python. J'ai besoin d'une interface de ligne de commande à plusieurs niveaux, et je veux compléter l'onglet.Comment faire une CLI multi-niveau en Python?

J'ai regardé le module cmd (à partir de la bibliothèque standard Python) et readline avec la fonction "complete" (pour l'achèvement de l'onglet).

Ils ont tous deux manqué quelque chose, à savoir que je ne l'ai pas compris comment gérer plusieurs niveaux tels que:

level1 
level2 
    level2_subcommand_1 
    level2_subcommand_2 
level3 
    level3_subcommand_1 

Exemple: Si je tapais:

cmd> level2 

, je veux voir level2_subcommand_1 et level2_subcommand_2 apparaissent lorsque j'appuie sur la touche de tabulation, mais pas de niveau1 et pas de niveau3.

Je ne pouvais pas le faire avec cmd lib aussi bien qu'avec readline.

Répondre

10

Cela fonctionne parfaitement bien avec le module cmd en Python 2.6.5. Voici l'exemple de code que j'utilisais pour tester ceci:

import cmd 

class MyInterpreter(cmd.Cmd): 
    def do_level1(self, args): 
     pass 

    def do_level2_subcommand_1(self, args): 
     pass 

    def do_level2_subcommand_2(self, args): 
     pass 

    def do_level3_subcommand_1(self, args): 
     pass 

MyInterpreter().cmdloop() 

Lorsque je tape « niveau 2 » sur la ligne de commande, puis appuyez sur Tab, la ligne s'étendu à level2_subcommand_ comme cela est le préfixe commun à tous l'achèvement les propositions. Lorsque j'appuie à nouveau sur Tab sans rien taper, la ligne suivante affiche correctement level2_subcommand_1 et level2_subcommand_2. Est-ce ce que vous recherchez?

Une autre variante pour le cas des sous-commandes est de créer un sous-interprète pour eux:

class SubInterpreter(cmd.Cmd): 
    prompt = "(level2) " 

    def do_subcommand_1(self, args): 
     pass 

    def do_subcommand_2(self, args): 
     pass 

    def do_quit(self, args): 
     return True 
    do_EOF = do_quit 

class MyInterpreter(cmd.Cmd): 
    def do_level1(self, args): 
     pass 

    def do_level2(self, args): 
     sub_cmd = SubInterpreter() 
     sub_cmd.cmdloop() 

    def do_level3(self, args): 
     pass 

La variante ci-dessus vous donne level1, level2 et level3 dans votre interprète « principal ». Lorsque vous appelez level2 dans votre interpréteur principal, il construit le sous-interpréteur et appelle ses boucles de commande. Le sous-interprète a une invite différente de l'interpréteur principal, donc vous pouvez toujours dire dans quel interprète vous êtes. Le sous-interprète vous donne alors subcommand_1, subcommand_2, subcommand_3 et quit. quit vous ramène à l'interpréteur principal, tout comme le caractère EOF.

+0

Salut, merci pour votre réponse. Le deuxième exemple semble pouvoir faire ce que je veux. Je l'ai modifié (il appelle SubInterpreter au lieu de SubInterpreterForLevel2) mais cela ne fonctionne pas. C'est comme si j'étais bloqué au premier niveau (MyInterpreter). –

+0

Bon, j'ai testé mon second exemple dans un interpréteur Python. On dirait que 'SubInterpreterForLevel2' devrait s'appeler' SubInterpreter' (comme vous l'avez noté correctement), plus la fonction 'do_quit' manquait l'argument' args', mais sinon ça marche parfaitement bien pour moi. Taper 'level2' change l'invite en' (level2) 'et me conduit au sous-interprète. Taper 'quit' dans' (level2) 'me ramène à' (Cmd) '. Recevez-vous un message d'erreur lorsque vous tapez 'level2'? –

0

Le module argpext de pypi implémente des sous-commandes multiniveaux pour l'interface de ligne de commande. il n'y a pas de support pour l'achèvement de l'onglet (pas encore?).