Wypełnianie fałszywych katalogów avfs w Zsh

37

Jak mogę ulepszyć system kompletacji zsh, aby w niektórych okolicznościach uzupełniać „fałszywe” pliki?

Dokładniej, system plików AVFS udostępnia archiwa jako katalogi, tworząc „fałszywy katalog” obok każdego archiwum. Domyślnie replikuje całą hierarchię katalogów pod punktem montowania ~/.avfs. Ponadto pod ~/.avfskażdym plikiem archiwum, takim jak /tmp/foo.zipsam plik archiwum ~/.avfs/tmp/foo.zip, znajduje się katalog o nazwie, ~/.avfs/tmp/foo.zip#który ujawnia zawartość archiwum. Jednak ten dodatkowy katalog nie pojawia się na liście ~/.avfs/tmp: istnieje tylko na wyraźne żądanie. (Jest to podobne do działania niektórych automounterów.)

mountavfs
cd ~/.avfs/tmp/foo.zip\#

Kiedy wpisuję polecenie takie jak powyższe, foo.zip#nie pojawia się jako uzupełnienie pod ~/.avfs/tmp/, ponieważ nie ma takiego katalogu. Jak mogę powiedzieć zsh, że ilekroć jest plik, którego pełna ścieżka jest $arczgodna ~/.avfs/**/*.(tgz|zip)¹, powinien udawać, że istnieje katalog o nazwie ${arc}#?

(Zauważ, że chcę, aby zakończenie działało z każdym wywołaniem _fileslub _dirsnie tylko dla cdpolecenia. Wolę nie kopiować kodu _filesfunkcji, jeśli to możliwe.)

¹ i wszystkie pozostałe rozszerzenia

Gilles „SO- przestań być zły”
źródło
Czy ~ / .avfs zawiera „kopię” całego systemu plików?
ctrl-alt-delor
@richard Tak, każdy /path/to/foojest widoczny jako ~/.avfs/path/to/foo.
Gilles „SO- przestań być zły”
Można to łatwiej naprawić avfs. Jeśli przedstawiłby domyślną #pozycję katalogu dla dowolnych plików, które pasowałyby do obsługiwanych przez nią łańcuchów, a nawet magicznie przetestował pliki w katalogu pod kątem tego, co wymagało posiadania #pozycji, wówczas zakończenie byłoby po prostu działać. Wydaje mi się, że byłby to hit wydajnościowy dla czegoś takiego, findjak gdyby teraz przeszukiwał skompresowane pliki.
Matt

Odpowiedzi:

1

Fałszywa odpowiedź wydaje się niewystarczająca na to fałszywe pytanie; wbudowana obsługa zsh dla katalogów automount działa na katalogach ( fake-files dir:names), a nie na wzorcach plików w nich zawartych. Jest to przydatne, aby dodać konkretnych nazwach plików do katalogu, który może spełnić automountlub sshfsczy NetApp .snapshottypu konfiguracje gdzie katalog-być montowane jest znaną nazwę statycznych ALAS.

autoload -U compinit
compinit
zstyle ':completion:*' fake-files $HOME/.avfs:'ALAS POOR YORICK'

zshall(1)mówi, że „nazwy” są łańcuchami, a eksperymenty wskazują metaznaki (np. #lub \#lub '*(e:"echo hi":)') „nie działają” na różne sposoby, więc nie wiem, jak wślizgnąć glob do części nazwy w fake-filesinstrukcji. (Przejrzenie Src/Zle/computil.cmoże ujawnić dokładnie, jakie mogą być nazwy, ale byłoby to więcej pracy.) (Również użycie globów rekurencyjnych w pozycji katalogu do nazw plików archiwów nie latało, ale ponownie zajmie C nurkowanie, aby zobaczyć, ile fake-filespozwala uciekasz.)

Za pomocą compdefmożna wyświetlić listę .avfsuzupełnień katalogu:

compdef '_files -g $HOME/.avfs/\*' -p \^
function andthehash {
  reply=($REPLY $REPLY\#)
}
compdef "_files -g $HOME/.avfs/'*(+andthehash)'" -p \^

Tyle że to się nie powiedzie, ponieważ pokaże #pliki tylko wtedy, gdy nie ma to znaczenia, a zatem nie można ich uzupełnić. (Dla tego formularza istnieją produktywne zastosowania, ale nie w tym przypadku).

Korzystanie zstyleprzybliża Cię do następujących czynności .zshrc:

autoload -U compinit
compinit

function UnderAVFS {
  local pdir
  [[ -z $1 ]] && return 1
  pdir=$1:a
  [[ ! -d $pdir ]] && pdir=$pdir:h
  [[ ! -d $pdir || $pdir == . ]] && return 1
  while [[ $pdir != / ]]; do
    [[ $pdir == $HOME/.avfs ]] && return 0
    pdir=$pdir:h
  done
  return 1
}

function AVFSExtras {
  if UnderAVFS $REPLY; then
    reply=($REPLY)
    # TODO embiggen list of archive suffixes
    [[ $REPLY == *.(bz2|tbz2) ]] && reply+=($REPLY\#)
  fi
}

# Try to match avfs, otherwise the default pattern. Probably could greatly
# benefit from caching, to avoid hits on UnderAVFS function.
zstyle ':completion:*' file-patterns '*(+AVFSExtras):avfs-files' '%p:all-files'

Można go jednak uzupełnić tylko do \#/bitu (w debian squeeze virt z domyślną konfiguracją avfs), ale nie do wirtualnego systemu plików dla archiwum, więc dodatkowe prace będą konieczne, aby tabulowanie przejść do archiwów. Zgaduję za pomocą _call_program ... lslub coś w tym rodzaju dla uzupełnień \#, chyba że istnieje bardziej elegancki sposób, aby zshprzekonać się, że nie istnieją katalogi, które nie istnieją.

Złe wieści! Ukończenie nie _path_filesprzebije fałszywych katalogów; Podejrzewam, że jest to związane z globowaniem zsh. Zarówno 4. zsh 4. coś włączone, jak i zsh 5.0.8 wykazują problem. Podejrzewam więc, że pełna poprawka wymagałaby łat _path_fileslub napisać coś innego, co w przeciwnym razie uzupełniałoby te fałszywe katalogi. Śledzenie zakończenia debugowania można wygenerować, wpisując, ls /root/.avfs/root/sometar.gz\#/a następnie na końcu tego wpisywania, control-xa następnie ?, zakładając, bindkey -eże _complete_debugjest to związane ze wspomnianym keycombo, jeśli ktoś chce dowiedzieć się, dlaczego tak się nie dzieje.

gałązka
źródło
0

W zsh możesz użyć compctl -Kdo zarejestrowania własnej funkcji do opcji zakończenia generowania. Na przykład:

compctl -f -c -u -r -K myAVFScompletion "*" -tn

Następnie musisz zdefiniować własną funkcję:

myAVFScompletion () {
    read -c COMMAND ARGS

    # Decide what paths you want to suggest completion for
    # by looking inside the ~/.avfs folder.

    # Place your suggestions into an array:
    reply=( a_path b_path ... )
}

Oczywiście powyższe wymaga trochę więcej pracy, ale na początek jest coś.

Podobną (ale inną) niestandardową funkcję uzupełniania można zarejestrować dla bash.

Oto przykład z implementacjami bash i zsh . (Oferuje uzupełnianie opcji wiersza poleceń poprzez pobranie opcji ze strony man polecenia).

A oto kilka szybkich domysłów na temat rzeczy, które mogą działać w twojej funkcji uzupełniania:

if [[ -d "$ARGS#" ]]
then reply=( "$ARGS#" )
else reply=
fi

A może to:

reply=( $(find ~/.avfs -type f -name "*.tgz" -or -name "*.zip" | sed 's+$+#+') )

Powodzenia!

joeytwiddle
źródło
Wiem, jak napisać funkcję uzupełniania, dziękuję bardzo. Problem polega na tym, jak zmodyfikować istniejący mechanizm uzupełniania plików. Zauważ, że używam „nowego” mechanizmu uzupełniania, a nie compctl, tzn. Chcę zmienić to, co _filesrobi. Twoja odpowiedź w ogóle nie jest pomocna.
Gilles „SO- przestań być zły”
@Gilles Nie rozpoczynać wojny z płomieniami i ryzykując, że się nie uda, przynajmniej próbował ... To siedziało na „strychu” bez odpowiedzi plus 2 lata plus ... +1 t resetu do 0 dla wysiłku .
eyoung100
@ eyoung100 Proszę nie dawać +1 za wysiłek (nie ten wysiłek jest tutaj widoczny). Promowanie niepomocnych odpowiedzi jest szkodliwe dla witryny.
Gilles 'SO - przestań być zły'