2010-10-22 11 views
8

Ich habe eine Cmd-Konsole eingerichtet, um Kartennamen für ein Magic: the Gathering-Sammlungsverwaltungssystem automatisch zu vervollständigen.Ändern, wie Python-Cmd-Modul Autovervollständigung behandelt

Es verwendet den Textparameter, um die Datenbank nach Karten abzufragen, und verwendet die Ergebnisse zur automatischen Vervollständigung/Andeutung von Karten.

Diese Kartennamen haben jedoch mehrere Wörter, und Cmd führt Autovervollständigung vom letzten Speicherplatz bis zum Ende der Zeile aus.

Zum Beispiel:

mtgdb> add Mage<tab><tab> 
Mage Slayer (Alara Reborn)  Magefire Wings (Alara Reborn) 
mtgdb> add Mage S<tab><tab> 
Sages of the Anima (Alara Reborn) 
Sanctum Plowbeast (Alara Reborn) 
Sangrite Backlash (Alara Reborn) 
Sanity Gnawers (Alara Reborn) 
Sen Triplets (Alara Reborn) 
[...] 
mtgdb> add Mage Sl<tab> 
mtgdb> add Mage Slave of Bolas (Alara Reborn) 

Ich habe versucht, von Hand greifen, was ich aus dem line Parameter wollte, die die Ergebnisse, die ich aus der Datenbank wollen wird, aber dies nicht das erste Wort zu überschreiben:

mtgdb> add Mage Sl<tab> 
mtgdb> add Mage Mage Slayer (Alara Reborn) 

Am Ende muss ich die auto-Vervollständiger wie dies funktioniert:

mtgdb> add Mage Sl<tab> 
mtgdb> add Mage Slayer (Alara Reborn) 

Abgesehen von dem oben beschriebenen manuellen Parsing-Versuch, habe ich auch versucht, Leerzeichen durch Pluszeichen zu ersetzen, und festgestellt, dass Cmd perfekt daran ist, auch diese zu teilen. Ersetzen von Leerzeichen durch Unterstriche funktioniert, aber es gibt eine Karte in Unhinged, die _____ heißt, also muss ich durch Akrobatik gehen, um die Strings zu verlieren, da ich nicht einfach line.replace("_", " ").

Hier ist ein lauffähiges Testcode:

import cmd 

commands = [ 
    "foo", 
    "foo bar blah", 
    "bar", 
    "bar baz blah", 
    "baz", 
    "baz foo blah"] 

class Console(cmd.Cmd): 
    intro = "Test console for" + \ 
      "http://stackoverflow.com/questions/4001708/\n" + \ 
      "Type \"cmd<space><tab><tab>\" to test " + \ 
      "auto-completion with spaces in commands\nwith " + \ 
      "similar beginings." 

    def do_cmd(self, line): 
     print(line) 

    def complete_cmd(self, text, line, start_index, end_index): 
     if text: 
      return [command for command in commands 
        if command.startswith(text)] 
     else: 
      return commands 

if __name__ == "__main__": 
    command = Console() 
    command.cmdloop() 
+1

Es gibt einige gute Informationen hier: http://stackoverflow.com/questions/187621/how-to-make-a-python-command-line-program-autocomplete-arbitrary-things-not-int –

+0

können Sie zur Verfügung stellen lauffähiger Testcode? Das scheint zu beheben – nosklo

+0

Ja, ich sah auch, @offsound, es ist, wo ich die Idee hatte, Cmd zu verwenden. Ich werde einen Testcode erstellen. –

Antwort

10

Es sollte nicht übermäßig kompliziert sein. Etwas wie das Folgende:

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

Ich habe den gleichen" Trick "verwendet, um den Pfad zu vervollständigen. Ich tausche die letzte Zeile für die Rückgabe [fp [offs:] für fp in glob.glob (mline + '*')] –

+0

Wenn Sie ein paar Aufrufe von .lower() einfügen, können Sie die Groß-/Kleinschreibung Ihres Befehls auch nicht beachten. 'return [s [offs:] für s in Vervollständigungen wenn s.lower(). Startswith (mline.lower())]' –

0

Sie readline.set_completer_delims('') tun könnte.

Ihre complete_* Funktionen werden jedoch nicht mehr aufgerufen; Sie müssen Cmd.complete oder Cmd.completenames überschreiben. Sehen Sie sich den Quellcode des Moduls cmd für Details an.

+0

Die "complete_" -Funktionen zu sprengen, ist nicht etwas, was ich tun möchte, sondern die Art, wie sie versandt werden, ist perfekt. Nicht nur "Cmd.complete", sondern auch "Cmd.parseline". Ich poste, was ich in der Frage ändere, nachdem ich es herausgefunden habe. Vielen Dank! –

+1

tatsächlich, das tut es: 'readline.set_completer_delims ('\ t \ n ... @ # $%^& *() - = + [{]} \\ |;: \'", <>? ') ' – wesen

0

Ich habe die Cmdloop-Funktion überschreiben, und es war ziemlich einfach. Ich musste nichts anderes ändern. Kopieren Sie einfach den cmdloop Funktion aus dem Modul (Finden Sie Code von import cmd tun, cmd.__file__), und fügen Sie die zwei Zeilen zum Ändern Trennzeichen:

try: 
     import readline 
     self.old_completer = readline.get_completer() 
     readline.set_completer(self.complete) 
     readline.parse_and_bind(self.completekey+": complete") 
     # do not use - as delimiter 
     old_delims = readline.get_completer_delims() # <- 
     readline.set_completer_delims(old_delims.replace('-', '')) # <- 
    except ImportError: 
     pass 

, dass es für mich getan hat. In Ihrem Fall möchten Sie möglicherweise das Trennzeichen entfernen, das die Probleme verursacht.

Verwandte Themen