Vervollständigen von gefälschten avfs-Verzeichnissen in zsh

37

Wie kann ich das Vervollständigungssystem von zsh optimieren, um unter bestimmten Umständen "gefälschte" Dateien zu vervollständigen?

Genauer gesagt, das AVFS- Dateisystem macht Archive als Verzeichnisse verfügbar, indem neben jedem Archiv ein „falsches Verzeichnis“ erstellt wird. Standardmäßig wird die gesamte Verzeichnishierarchie unter ihrem Bereitstellungspunkt repliziert ~/.avfs. Außerdem gibt es unter ~/.avfsfür jede Archivdatei, z. B. /tmp/foo.zipneben der Archivdatei selbst ~/.avfs/tmp/foo.zip, ein Verzeichnis, ~/.avfs/tmp/foo.zip#das den Inhalt des Archivs anzeigt. Dieses zusätzliche Verzeichnis erscheint jedoch nicht in der Liste von ~/.avfs/tmp: es existiert nur auf ausdrücklichen Wunsch. (Dies ähnelt der Funktionsweise einiger Automounters.)

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

Wenn ich einen Befehl wie oben eingebe, foo.zip#wird er nicht als Vervollständigung angezeigt ~/.avfs/tmp/, da es kein solches Verzeichnis gibt. Wie kann ich zsh mitteilen, dass immer, wenn es eine Datei gibt, deren vollständiger Pfad $arcmit ~/.avfs/**/*.(tgz|zip)¹ übereinstimmt , so getan werden sollte, als gäbe es ein Verzeichnis mit dem Namen ${arc}#?

(Beachten Sie, dass die Vervollständigung bei jedem Aufruf von _filesoder funktionieren soll _dirs, nicht nur für den cdBefehl. _filesWenn möglich, möchte ich nicht den Code der Funktion duplizieren müssen .)

¹ und alle anderen Erweiterungen

Gilles 'SO - hör auf böse zu sein'
quelle
Enthält ~ / .avfs eine "Kopie" des gesamten Dateisystems?
Strg-Alt-Delor
@richard Ja, jeder /path/to/fooist sichtbar als ~/.avfs/path/to/foo.
Gilles 'SO - hör auf böse zu sein'
Dies könnte einfacher behoben werden avfs. Wenn der Standardverzeichniseintrag #für alle Dateien angezeigt wird , die mit den von ihm unterstützten Zeichenfolgen übereinstimmen, oder die Dateien in einem Verzeichnis von Magic auf die erforderlichen Einträge geprüft werden #, funktioniert die Vervollständigung einfach. Ich denke, es würde einen Performance-Hit für so etwas geben, findda es jetzt komprimierte Dateien durchwühlen würde.
Matt

Antworten:

1

Eine gefälschte Antwort scheint für diese gefälschte Frage unzureichend zu sein. Die in zsh integrierte Unterstützung für Automount-Verzeichnisse gilt für Verzeichnisse ( fake-files dir:names) und nicht für darin enthaltene Dateimuster . Dies ist praktisch, um einem Verzeichnis bestimmte benannte Dateien hinzuzufügen, die für automountoder sshfsNetApp- .snapshotSetups geeignet sind, bei denen das anzuhängende Verzeichnis ein bekannter statischer Name ist ALAS.

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

zshall(1)sagt, dass die "Namen" Zeichenfolgen sind und Experimente zeigen, dass Metazeichen (z. B. #oder \#oder '*(e:"echo hi":)') auf verschiedene Weise "nicht funktionieren", so dass ich keine Möglichkeit kenne, einen Glob auf den Namensteil der fake-filesAnweisung zu schleichen . (Durchblättern Src/Zle/computil.ckönnte genau zeigen, was die Namen sein können, aber das wäre mehr Arbeit.) (Auch die Verwendung von rekursiven Globs in der Verzeichnisposition zum Benennen von Archivdateien hat nicht geflogen, aber es wird wiederum C-Tauchen erfordern, um zu sehen, wie viel fake-filesLässt du kommst davon mit.)

Mit compdefkann man die .avfsVerzeichnisvervollständigungen auflisten:

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

Dies schlägt jedoch fehl, da die #Dateien nur angezeigt werden, wenn es keine Rolle spielt und sie daher nicht vervollständigen können. (Es gibt produktive Verwendungen für dieses Formular, jedoch nicht für diesen Fall.)

Mit kommen zstyleSie näher .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'

Es kann jedoch nur bis zum \#/Bit abgeschlossen werden (auf einem Debian-Squeeze-Virt mit einem Standard-AVFS-Setup), nicht jedoch in das virtuelle Dateisystem für ein Archiv, sodass zusätzliche Arbeit erforderlich ist, um den Tab-Abschluss in den Archiven vorzunehmen. Ich vermute über _call_program ... lsoder etwas in dieser Richtung für Vervollständigungen am \#Stück, es sei denn, es gibt eine elegantere Möglichkeit, zshzu glauben, dass Verzeichnisse, die nicht existieren, es tun.

Schlechte Nachrichten! Die Fertigstellung schafft es nicht _path_filesfür die gefälschten Verzeichnisse; Ich vermute, das hängt mit zsh globbing zusammen. Sowohl zsh 4.something on als auch zsh 5.0.8 weisen das Problem auf. Ich vermute also, dass für eine vollständige Korrektur Patches für _path_filesdiese falschen Verzeichnisse erforderlich sind oder dass Sie etwas anderes schreiben müssen, das ansonsten vollständig ist. Ein Abschluss Debug - Trace kann in durch Eingabe erzeugt wird ls /root/.avfs/root/sometar.gz\#/und dann diese Typisierung am Ende , control-xund dann ?, unter der Annahme , bindkey -eund das _complete_debugist an dem keycombo gebunden, wenn jemand vertiefen durch will , warum dies versagt.

Thrig
quelle
0

In zsh können Sie compctl -KIhre eigene Funktion für die Optionen zum Abschluss der Generierung registrieren. Beispielsweise:

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

Dann müssen Sie Ihre eigene Funktion definieren:

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 ... )
}

Offensichtlich erfordert das oben Genannte etwas mehr Arbeit, aber es ist etwas, mit zu beginnen.

Eine ähnliche (aber andere) benutzerdefinierte Vervollständigungsfunktion kann für die Bash registriert werden.

Hier ist ein Beispiel mit Implementierungen für bash und zsh . (Ermöglicht das Vervollständigen der Befehlszeilenoptionen, indem die Optionen aus der Manpage des Befehls abgerufen werden.)

Und hier sind ein paar schnelle Ratschläge zu Dingen, die in Ihrer Vervollständigungsfunktion funktionieren könnten:

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

Oder vielleicht das:

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

Viel Glück!

joeytwiddle
quelle
Ich kann eine Vervollständigungsfunktion schreiben, vielen Dank. Das Problem besteht darin, wie Sie den vorhandenen Vervollständigungsmechanismus für Dateien ändern können. Beachten Sie, dass ich den „neuen“ Vervollständigungsmechanismus verwende, nicht compctl, dh ich möchte ändern, was _filestut. Ihre Antwort ist überhaupt nicht hilfreich.
Gilles 'SO- hör auf böse zu sein'
@Gilles Um keinen Flammenkrieg auszulösen und auf die Gefahr eines Fehlschlags zu reagieren, versuchte er es zumindest ... Dies wurde auf dem unbeantworteten "Dachboden" 2 Jahre plus ... +1 t zurückgesetzt auf 0 für die Anstrengung .
Eyoung100
@ eyoung100 Bitte geben Sie nicht +1 für Mühe (nicht, dass Mühe hier offensichtlich ist). Das Aufwerten nicht hilfreicher Antworten schadet der Website.
Gilles 'SO- hör auf böse zu sein'