Я пытаюсь написать завершение bash, которое позволит мне заполнить имена каталогов, в которых находятся другие оболочки.
Например, предположим, что у меня есть другая оболочка, открытая в /very/long/path/name
, и я сейчас нахожусь в каталоге, содержащем подкаталоги foo
и bar
. Когда я набираю cd <Tab>
, я хочу видеть:
$ cd <Tab>
foo/ bar/ /very/long/path/name
У меня есть эта команда для создания списка возможных завершений:
ps -Cbash -opid= | xargs pwdx | cut -d" " -f2 | sort -u | while read; do echo ${REPLY#$PWD/}; done | grep -v "^$"
Для краткости я напишу это как ...pipeline...
.
В моей системе есть функция _cd
, которая выполняет обычное завершение:
$ complete -p cd
complete -o nospace -F _cd cd
Я хотел бы повторно использовать эту функцию _cd
, потому что она нетривиальна (~30 строк кода, согласно type _cd
). Бонусные баллы, если решение повторно использует уже определенное завершение, независимо от того, основано оно на функции с именем _cd
.
Я думал, что вариант -C
для complete
звучит многообещающе, но я не могу заставить его работать:
$ complete -C '...pipeline...' cd
$ cd <Tab>grep: cd: No such file or directory
grep: : No such file or directory
grep: cd: No such file or directory
Написание моей собственной функции-оболочки для -F
, которая добавляется к массиву COMPREPLY
, также не совсем сработало:
$ function _cd2() { _cd; COMPREPLY=( ${COMPREPLY[@]} $(...pipeline...) ); }
$ cd <Tab>
foo/ bar/ name/
Он удаляет все компоненты пути, кроме последнего. Я полагаю, это должно быть что-то, установленное _cd
, но я не знаю, как этому противодействовать.
Если я уберу вызов _cd
из _cd2
, я увижу завершения, но они не будут правильно завершать частичные имена каталогов. Если я наберу cd /ve<Tab>
, он все равно покажет полный путь без фактического завершения моей командной строки.
Как я могу заставить это делать то, что я хочу?
Приложение: полное определение _cd
:
$ type _cd
_cd is a function
_cd ()
{
local cur prev words cword;
_init_completion || return;
local IFS='
' i j k;
compopt -o filenames;
if [[ -z "${CDPATH:-}" || "$cur" == ?(.)?(.)/* ]]; then
_filedir -d;
return 0;
fi;
local -r mark_dirs=$(_rl_enabled mark-directories && echo y);
local -r mark_symdirs=$(_rl_enabled mark-symlinked-directories && echo y);
for i in ${CDPATH//:/'
'};
do
k="${#COMPREPLY[@]}";
for j in $( compgen -d $i/$cur );
do
if [[ ( -n $mark_symdirs && -h $j || -n $mark_dirs && ! -h $j ) && ! -d ${j#$i/} ]]; then
j+="/";
fi;
COMPREPLY[k++]=${j#$i/};
done;
done;
_filedir -d;
if [[ ${#COMPREPLY[@]} -eq 1 ]]; then
i=${COMPREPLY[0]};
if [[ "$i" == "$cur" && $i != "*/" ]]; then
COMPREPLY[0]="${i}/";
fi;
fi;
return 0
}
_cd
вызывает_init_completion
,_filedir
и, возможно, некоторые другие функции: каковы определения этих функций? - person bishop   schedule 24.10.2014