2010-10-22 18 views
8

Mam ustawioną konsolę Cmd do automatycznego uzupełniania nazw kart dla systemu zarządzania kolekcjami Magic: the Gathering.Zmień sposób, w jaki moduł Python Cmd obsługuje autouzupełnianie

Używa parametru tekstowego do zapytania bazy danych o karty i wykorzystuje wyniki do automatycznego uzupełniania/sugerowania kart.

Jednak te nazwy kart mają wiele słów, a Cmd wykonuje automatyczne uzupełnianie z przestrzeni ostatniej na końcu linii.

Na przykład:

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) 

Próbowałem ręcznie chwytając co chciałem od parametru line, który dostaje wyniki chcę z bazy danych, ale to się nie powiedzie, aby zastąpić pierwsze słowo:

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

W końcu muszę automatycznego Completer pracować tak:

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

Oprócz powyższej próby ręcznego parsowania, próbowałem również zastąpić spacje znakami plusa i odkryłem, że Cmd jest również całkowicie zadowolony z podziału na te. Zastępuje spacje znakami podkreślenia, ale w Unhinged jest jedna karta o nazwie _____, więc muszę przejść akrobacje, aby zdemontować ciągi, ponieważ nie mogę po prostu line.replace("_", " ").

Oto niektóre runnable kodu testu:

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

Tu jest kilka dobrych informacji: http://stackoverflow.com/questions/187621/how-to-make-a-python-command-line-program-autocomplete-arbitrary-things-not- –

+0

czy możesz podać działający kod testowy? Wydaje się, że można to naprawić. – nosklo

+0

Tak, widziałem też to, @offsound, to tam wpadłem na pomysł użycia Cmd. Zanurzę jakiś kod testowy. –

Odpowiedz

10

Nie powinno być zbyt skomplikowane. Coś podobnego do następującego:

+0

Używam tej samej" sztuczki "do dozwolonego zakończenia ścieżki. Zamieniam ostatnią linię na powrót [fp [offs:] dla fp w glob.glob (mline + '*')] –

+0

Jeśli wrzucisz kilka wywołań .lower(), możesz również ustawić wielkość liter bez względu na wielkość liter. 'return [s [offs:] dla s w uzupełnieniach, jeśli s.lower(). Startswith (mline.lower())]' –

0

Można zrobić readline.set_completer_delims('').

Jednak twoje funkcje complete_* nie będą już wywoływane; będziesz musiał zastąpić Cmd.complete lub Cmd.completenames. Przyjrzyj się kodowi źródłowemu modułu cmd w celu uzyskania szczegółowych informacji.

+0

Wysyłanie funkcji "complete_ *" nie jest czymś, co chcę zrobić, ale zmiana sposobu ich wysyłania jest idealna. Nie tylko 'Cmd.complete', ale' Cmd.parseline'. Opublikuję to, co zmienię w pytaniu, po tym, jak się zorientuję. Dzięki! –

+1

w rzeczywistości to robi: 'readline.set_completer_delims ('\ t \ n ... @ # $%^& *() - = + [{]} \\ |;: \'", <>? ') ' – wesen

0

Zminimalizowałem funkcję cmdloop i było to całkiem proste. Nie musiałem zmieniać niczego innego. Wystarczy skopiować funkcję cmdloop z modułu (znaleźć kod wykonując import cmd, cmd.__file__) i dodać dwie linie do zmieniających ograniczników:

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 

że zrobił to dla mnie. W twoim przypadku możesz usunąć dowolny ogranicznik powodujący problemy.

Powiązane problemy