Завершення фальшивих каталогів avfs в zsh


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/, оскільки немає такого каталогу. Як я можу сказати zsh, що всякий раз, коли є файл, повний шлях якого $arcвідповідає ~/.avfs/**/*.(tgz|zip)¹, він повинен робити вигляд, що існує названий каталог ${arc}#?

(Зверніть увагу, що я хочу, щоб завершення працювало з кожним викликом _filesабо _dirs, не тільки з cdкомандою. Я вважаю за краще не дублювати код _filesфункції, якщо це можливо.)

¹ та всі інші розширення


Чи містить ~ / .avfs "копію" всієї файлової системи?
ctrl-alt-delor

@richard Так, кожен /path/to/fooвидно як ~/.avfs/path/to/foo.
Жил 'ТАК - перестань бути злим'

Це може бути легше виправлено avfs. Якщо він представив #запис каталогу за замовчуванням для будь-яких файлів, які відповідали рядкам, які він підтримує, або навіть магія перевірила файли в каталозі на те, що потрібно, щоб мати #запис, то завершення буде просто працювати. Я здогадуюсь, що це буде хіт продуктивності для чогось такого, як, findяк зараз, він би проходив через стислі файли.
Метт

Відповіді:


1

Підроблена відповідь видається недостатньою для цього підробленого питання; підтримка zsh вбудована для автоматичних каталогів працює на каталогах ( fake-files dir:names), а не на шаблонах файлів. Це зручно , щоб додати конкретні іменовані файли в каталог, який може задовольнити automountабо sshfsабо NetApp .snapshotрозстановок типу , де каталог-бути-змонтованим є відомим статичним ім'ям ALAS.

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

zshall(1)каже , що «імена» є рядками, і експерименти показують , метасимволу (наприклад , #чи \#або '*(e:"echo hi":)') «не працюють» по - різному, так що немає ніякого способу , я НЕ знаю, щоб проникнути Glob на частини імен в 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'

Однак він може завершувати лише \#/біт (на debian сціснути virt з налаштуваннями avfs за замовчуванням), але не у віртуальну файлову систему для архіву, тому для вкладки в архіви буде потрібно додаткова робота. Я здогадуюсь через _call_program ... lsабо щось у цьому напрямку для завершення на \#трохи, хіба що є більш елегантний спосіб zshпереконатись у тому, що каталоги не існують.

Погані новини! Завершення не дозволяє зробити це _path_filesдля підроблених каталогів; Я підозрюю, що це пов'язано з zsh globing. І проблема zsh 4.something on zsh 5.0.8 проявляє проблему. Тож я підозрюю, що для повного виправлення знадобиться виправлення _path_filesабо написати щось інше, що інакше завершується на цих фальшивих папах. Слід налагодження завершення може бути сформований шляхом введення, ls /root/.avfs/root/sometar.gz\#/а потім в кінці цього введення, control-xа потім ?, припускаючи, bindkey -eщо _complete_debugце пов'язане із зазначеним keycombo, якщо хтось хоче заглибитись, чому це не вдається.


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 . (Він пропонує завершити параметри командного рядка, перехопивши параметри зі сторінки чоловічої команди.)

Ось декілька швидких здогадок про речі, які можуть працювати у вашій функції завершення:

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

А може це:

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

Удачі!


Я знаю, як написати функцію завершення, дуже дякую. Проблема полягає в тому, як змінити існуючий механізм завершення файлів. Зауважте, що я використовую "новий" механізм завершення, ні compctl, тобто я хочу змінити те, що _filesробить. Ваша відповідь зовсім не корисна.
Жил "ТАК - перестань бути злим"

@Gilles Не розпочинати полум’яну війну, і ризикуючи зірватися не так, принаймні, він намагався ... Це сидів на "горищі" без відповіді 2 роки плюс ... +1 t скинути до 0 за зусилля .
eyoung100

@ eyoung100 Будь ласка, не приділяйте +1 зусиллям (не це зусилля очевидно). Оголошення непотрібних відповідей шкодить сайту.
Жил 'ТАК - перестань бути злим'
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.