zshでavfs偽ディレクトリを完成させる


37

状況によっては、zshの完了システムを微調整して「偽の」ファイルを完了するにはどうすればよいですか?

より正確には、AVFSファイルシステムは、すべてのアーカイブの横に「偽のディレクトリ」を作成することにより、アーカイブをディレクトリとして公開します。デフォルトでは、マウントポイントの下にディレクトリ階層全体を複製します~/.avfs。さらに、の下には~/.avfs、などのすべてのアーカイブファイルに対して/tmp/foo.zip、アーカイブファイル自体のほかに、アーカイブのコンテンツを公開する~/.avfs/tmp/foo.zipというディレクトリ~/.avfs/tmp/foo.zip#があります。ただし、この追加のディレクトリはのリストには表示されません~/.avfs/tmp。明示的に要求された場合にのみ存在します。(これは、一部の自動マウンターの動作に似ています。)

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

上記のようなコマンドを入力しても、そのようなディレクトリがないため、のfoo.zip#~/.avfs/tmp/に補完として表示されません。フルパスが¹に$arc一致するファイルがあるときはいつでも~/.avfs/**/*.(tgz|zip)、ディレクトリが呼ばれているふりをする必要があることをzshに伝えるにはどうすればよい${arc}#ですか?

(コマンドだけでなく、_filesまたはへのすべての呼び出しで完了を機能させたいことに注意してください。可能であれば、関数のコードを複製する必要はありません。)_dirscd_files

¹ およびその他のすべての拡張機能


〜/ .avfsにはファイルシステム全体の「コピー」が含まれていますか?
ctrl-alt-delor

@richardはい、すべて/path/to/fooはとして表示され~/.avfs/path/to/fooます。
ジル 'SO-悪であるのをやめる' 14年

これはで簡単に修正できますavfs#サポートする文字列に一致するファイルのデフォルトのディレクトリエントリを提示した場合、または#エントリが必要なディレクトリのファイルをマジックでテストした場合、補完は正常に機能します。find圧縮ファイルをトロールするようになり、パフォーマンスが低下すると思います。
マット

回答:


1

偽の答えは、この偽の質問には不十分なようです。自動マウントディレクトリのzshビルトインサポートは、ディレクトリ(fake-files dir:names)で動作し、その中のファイルパターンでは動作しません。これは合うかもしれディレクトリに特定の名前のファイルを追加すると便利ですautomountsshfsまたはNetAppの.snapshotディレクトリ・ツー・マウントすることが知られている静的な名前であるタイプのセットアップ、ALAS

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

zshall(1)「名前」は文字列であり、実験はさまざまな方法で「機能しない」メタキャラクター(#または\#または'*(e:"echo hi":)')を示すため、fake-filesステートメントの名前部分にグロブを忍び込ませる方法はありません。(スルー踏み込んでSrc/Zle/computil.c名前が可能かを正確に明らかにするかもしれませんが、それはより多くの仕事になります。)(また、飛ばなかったアーカイブファイルに名前を付けるためのディレクトリ位置に再帰グロブを使用しますが、再度、それははるかにどのように確認するためにCダイビングを取るfake-filesことができますあなたは逃げます。)

を使用するcompdefと、.avfsディレクトリの補完をリストできます。

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

これが失敗することを除いて#、それは問題ではないときにのみファイルを表示し、したがってそれらで完了できないためです。(この場合はそうではありませんが、このフォームには生産的な用途があります。)

を使用zstyleすると、次のように近づきます.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'

ただし、\#/(デフォルトのavfsセットアップを使用したdebian squeeze virtで)少しだけ完了することができますが、アーカイブの仮想ファイルシステムでは完了できないため、アーカイブをタブで完了するには追加の作業が必要になります。存在しないディレクトリがそうであると信じるよりエレガントな方法がない限り_call_program ... ls、私は経由でまたはそれらの線に沿った何かを補完するために\#少し推測してzshいます。

悪いニュース!完了しても_path_files、偽のディレクトリには到達しません。これはzshのグロビングに関連していると思われます。zsh 4.something onとzsh 5.0.8の両方で問題が発生します。ですから、完全な修正には、へのパッチが必要_path_filesか、そうでなければこれらの偽のディレクトリで完了する別の何かを書く必要があると思います。誰かがこれが失敗する理由を掘り下げたい場合は、ls /root/.avfs/root/sometar.gz\#/入力してcontrol-x、その入力の最後に入力し、次に?bindkey -eその_complete_debugキーコンボにバインドされていると仮定して、完了デバッグトレースを生成できます。


0

zshではcompctl -K、独自の関数を生成完了オプションに登録するために使用できます。例えば:

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

次に、独自の関数を定義する必要があります。

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

明らかに上記にはさらに作業が必要ですが、それは最初から何かです。

同様の(ただし異なる)カスタム補完関数をbashに登録できます。

ここではbashとzshのための実装と例。(コマンドのmanページからオプションを取得することにより、コマンドラインオプションの補完を提供します。)

補完関数内で動作する可能性のあるものを簡単に推測できます。

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

またはおそらくこれ:

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

がんばろう!


補完関数の書き方を知っています。ありがとうございました。問題は、ファイルの既存の完了メカニズムを変更する方法です。私は「新しい」補完メカニズムを使用していることに注意してください。compctlつまり、何を変更したいのですか_files。あなたの答えはまったく役に立ちません。
ジル 'SO-悪であるのをやめる'

@Gilles炎の戦争を始めないで、少なくとも彼は試してみました...これは、答えられていない「屋根裏」に2年以上座っていました...努力のために+1 tを0にリセットしました。
eyoung100

@ eyoung100努力のために+1を与えないでください(その努力はここでは明らかではありません)。役に立たない答えを支持することは、このサイトにとって有害で​​す。
ジル 'SO-悪であるのをやめる'
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.