Wdrażanie dokończenie nazw plików z cmd jest nieco kłopotliwe, ponieważ bazowy readline biblioteka interpretuje znaki specjalne takie jak „/” i „-” (i inni) jako separatory, a to ustawia który podciąg ciągu linii jest zostać zastąpione przez uzupełnienia.
Na przykład
> load /hom<tab>
rozmowy complete_load() z
text='hom', line='load /hom', begidx=6, endidx=9
text is line[begidx:endidx]
'tekst' nie "/ hom", ponieważ biblioteki readline analizowana linia i zwraca ciąg znaków po '/"separator. Funkcja complete_load() powinna zwrócić listę ciągów ukończenia, które zaczynają się od "hom", a nie "/ hom", ponieważ uzupełnienia zastąpią podciąg rozpoczynający się na początku łańcucha. Jeśli funkcja complete_load() niepoprawnie zwraca [ '/ home'], linia staje
> load //home
który nie jest dobrym rozwiązaniem.
Pozostałe znaki są uważane za separatory za pomocą readline, a nie tylko ukośników, , więc nie można przejąć podciągu, zanim "text" będzie katalogiem nadrzędnym.Dla przykład:
> load /home/mike/my-file<tab>
rozmowy complete_load() z
text='file', line='load /home/mike/my-file', begidx=19, endidx=23
Zakładając/home/mike zawiera pliki my-plik1 oraz my-file2 Z uzupełnienia powinny być [ 'plik1', ' file2 '], nie [' my-plik1 ',' mój-plik2 '], ani ['/home/mike/my-file1 ','/home/mike/my-file2 ']. Jeśli zwrócisz pełne ścieżki, wynikiem będzie:
> load /home/mike/my-file/home/mike/my-file1
Podejście, którego użyłem, polegało na użyciu modułu globu w celu znalezienia pełnych ścieżek. Glob działa dla ścieżek bezwzględnych i ścieżek względnych. Po znalezieniu ścieżek usuwam "stałą" część, która jest podciągana przed łańcuchem znaków.
Najpierw należy przeanalizować stały argument, który jest podłańcem między spacją a begidx.
index = line.rindex(' ', 0, begidx) # -1 if not found
fixed = line[index + 1: begidx]
Argument jest między spacją a końcem linii. Dołącz gwiazdkę, aby utworzyć globalny wzór wyszukiwania.
I dołączania a „/” do wyników, które są katalogi, a to sprawia, że łatwiej przemierzać katalogi z zakończeniem zakładki (w przeciwnym razie trzeba nacisnąć klawisz tabulatora dwukrotnie dla każdego katalogu), a to sprawia, że jest oczywiste, użytkownik, którego elementami uzupełniającymi są katalogi i które są plikami.
Na końcu usuń "ustaloną" część ścieżek, więc readline zastąpi tylko część "tekstową".
import os
import glob
import cmd
def _append_slash_if_dir(p):
if p and os.path.isdir(p) and p[-1] != os.sep:
return p + os.sep
else:
return p
class MyShell(cmd.Cmd):
prompt = "> "
def do_quit(self, line):
return True
def do_load(self, line):
print("load " + line)
def complete_load(self, text, line, begidx, endidx):
before_arg = line.rfind(" ", 0, begidx)
if before_arg == -1:
return # arg not found
fixed = line[before_arg+1:begidx] # fixed portion of the arg
arg = line[before_arg+1:endidx]
pattern = arg + '*'
completions = []
for path in glob.glob(pattern):
path = _append_slash_if_dir(path)
completions.append(path.replace(fixed, "", 1))
return completions
MyShell().cmdloop()
trudno mi uwierzyć, że nikt nie odpowiedział na ten –