CMD-Modul + Pfadvervollständigung

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
pyuser
User
Beiträge: 4
Registriert: Samstag 31. März 2012, 15:53

Hi Leute,

ich benutze das CMD-Modul und würde gerne für das Argument eines bestimmten Befehls (hier 'xxx') eine automatische Pfadvervollständigung mittels <tab> realisieren.
Z.B. "xxx /home/pyus<tab>" wird zu "xxx /home/pyuser/". Dazu benutze ich folgenden Code:

Code: Alles auswählen

   
    def _listdir(self, root):
        res = []
        for name in os.listdir(root):
            path = os.path.join(root, name)
            if os.path.isdir(path):
                name += os.sep
            res.append(name)
        return res
    
    def _complete_path(self, path=None):
        if not path:
            return self._listdir('.')
        dirname, rest = os.path.split(path)
        tmp = dirname if dirname else '.'
        res = [os.path.join(dirname, p)
                for p in self._listdir(tmp) if p.startswith(rest)]
        if len(res) > 1 or not os.path.exists(path):
            return res
        if os.path.isdir(path):
            return [os.path.join(path, p) for p in self._listdir(path)]
        return [path + ' ']

   def complete_xxx(self, text, line, begidx, endidx):
        if not text:
            return self._complete_path()
        return self._complete_path(line.split()[1])
Leider funktioniert das Ganze nicht wie geplant. Kann mir da jemand weiterhelfen?
Oder erfinde ich damit gerade das Rad neu und es gibt eine viel einfachere Lösung?

Danke schon mal!
Zuletzt geändert von Anonymous am Sonntag 1. April 2012, 11:44, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Code-Tags gesetzt.
pyuser
User
Beiträge: 4
Registriert: Samstag 31. März 2012, 15:53

Hmm, hat keiner eine Ahnung davon? Oder ist die Frage nicht eindeutig genug gestellt?
Bin für jede Hilfe dankbar!
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Willkommen im Forum,

Eine Beschreibung des Fehlers wäre hilfreich, "funktioniert nicht" ist etwas unspezifisch. Außerdem denke ich nicht, dass hier viele das `cmd`-Modul nutzen, aber ich kann mich irren.

PS: Es gibt hier

Code: Alles auswählen

[code=python]
[/code] Code-Tags.
the more they change the more they stay the same
BlackJack

@pyuser: Was mir als erstes mal auffällt, ist dass Du `line` benutzt und das zerlegst, und dabei die beiden Indizes ignorierst. Viel einfacher wäre es doch `text` zu benutzen, denn das enthält nur den Wert der vervollständigt werden soll.

Zur Form: Weder `_listdir()` noch `_complete_path()` sind semantisch gesehen Methoden. Deshalb würde ich da entweder Funktionen, aber zumindest `classmethod()`\s oder `staticmethod()`\s draus machen um zu zeigen, dass das Absicht ist.
pyuser
User
Beiträge: 4
Registriert: Samstag 31. März 2012, 15:53

Danke erstmal an euch beide!
Außerdem denke ich nicht, dass hier viele das `cmd`-Modul nutzen, aber ich kann mich irren.
Was wird stattdessen verwendet um interaktive Programme zu realisieren? Oder werden solche Programm nicht so häufig verwendet? Sorry, bin ein Neuling in Sachen Python :)
Was mir als erstes mal auffällt, ist dass Du `line` benutzt und das zerlegst, und dabei die beiden Indizes ignorierst. Viel einfacher wäre es doch `text` zu benutzen, denn das enthält nur den Wert der vervollständigt werden soll.
Bei der Benutzung von 'text' hatte ich das Problem, dass bspw. bei "testdir1/testdir2" nur "testdir2" in 'text' stand und nicht der gesamte Pfad. Ich vermute, dass das '/' dazu geführt hat. Deswegen hatte ich das auf "line.split()[1]" abgeändert.

Es war von mir vermutlich etwas unklug, nur die drei Funktionen zu posten. Der vollständige lauffähige Code ist folgender:

Code: Alles auswählen

import cmd
import os

class MyCmd(cmd.Cmd):

    def _listdir(self, root):
        res = []
        for name in os.listdir(root):
            path = os.path.join(root, name)
            if os.path.isdir(path):
                name += os.sep
            res.append(name)
        return res
    
    def _complete_path(self, path=None):
        if not path:
            return self._listdir('.')
        dirname, rest = os.path.split(path)
        tmp = dirname if dirname else '.'
        res = [os.path.join(dirname, p)
                for p in self._listdir(tmp) if p.startswith(rest)]
        if len(res) > 1 or not os.path.exists(path):
            return res
        if os.path.isdir(path):
            return [os.path.join(path, p) for p in self._listdir(path)]
        return [path + ' ']

    def complete_xxx(self, text, line, begidx, endidx):
        if not text:
            return self._complete_path()
        return self._complete_path(line.split()[1])
    
    def do_xxx(self, line):
        pass
    
    def do_EOF(self, line):
        return True
    
if __name__ == '__main__':
    MyCmd().cmdloop()
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

pyuser hat geschrieben:Was wird stattdessen verwendet um interaktive Programme zu realisieren? Oder werden solche Programm nicht so häufig verwendet? Sorry, bin ein Neuling in Sachen Python :)
Curses bzw. Urwid, welches auf curses basiert. Allerdings, funktioniert das erstmals nur auf Unix. Damit urwid auch auf Windows läuft brauchst du entweder Cygwin oder PDCurses.
the more they change the more they stay the same
BlackJack

@Dav1d: Das sind beides Module um eine andere Art von interaktiven Programmen zu schreiben. `cmd` ist eher für interaktive Shells.
BlackJack

@pyuser: Du hast ja selber geschrieben, dass `text` nur den Teil nach einem '/' enthält. Nun schau doch mal was Du dann machst…
Antworten