Це не ідеально, але знову ж таки завершення баш - досить складна справа ...
Найпростіший спосіб - це команда, трохи гнучкіша, ніж FIGNORE
ви можете:
complete -f -X "/myproject/data/*" vi
Це дає vi
змогу автоматично заповнити, що завершення призначено для файлів, та видалити шаблони, що відповідають -X
фільтру. Мінус полягає в тому, що модель не нормалізується, тому ../data
варіації не збігаються.
Наступна найкраща річ може бути спеціальною PROMPT_COMMAND
функцією:
# associative arrays of non-autocomplete directories
declare -A noacdirs=([/myproject/data]=1 )
function _myprompt {
[[ -n "${noacdirs[$PWD]}" ]] && {
echo autocomplete off
bind 'set disable-completion on'
} || {
echo autocomplete on
bind 'set disable-completion off'
}
}
PROMPT_COMMAND=_myprompt
Це вимикає завершення (повністю), коли ви знаходитесь в каталозі, але вимикає його для кожного шляху, а не лише файлів у цьому каталозі.
Більш корисним було б вибіркове відключення цього для визначених шляхів, але я вважаю, що єдиним способом є використання функції завершення за замовчуванням (bash-4.1 та пізнішої версії complete -D
) та багато возитися.
Це повинно працювати для вас, але це може мати небажані побічні ефекти (тобто зміни в очікуваному завершенні в деяких випадках):
declare -A noacdirs=([/myproject/data]=1 )
_xcomplete() {
local cur=${COMP_WORDS[COMP_CWORD]} # the current token
name=$(readlink -f "${cur:-./}") # poor man's path canonify
dirname=$(dirname "$name/.")
[[ -n "${noacdirs[$dirname]}" ]] && {
COMPREPLY=( "" ) # dummy to prevent completion
return
}
# let default kick in
COMPREPLY=()
}
complete -o bashdefault -o default -F _xcomplete vi
Це працює для завершення vi
, за потреби можна додавати інші команди. Він повинен зупинити заповнення файлів у названих каталогах незалежно від шляху чи робочого каталогу.
Я вважаю, що загальним підходом complete -D
є динамічне додавання функцій завершення для кожної команди, коли вона зустрічається. Також може знадобитися додати complete -E
(завершення імені команди, коли вхідний буфер порожній).
Оновлення
Ось гібридна версія рішень PROMPT_COMMAND
і функцій завершення функцій, це трохи легше зрозуміти і зламати, я думаю:
declare -A noacdirs=([/myproject/data]=1 [/project2/bigdata]=1)
_xcomplete() {
local cmd=${COMP_WORDS[0]}
local cur=${COMP_WORDS[COMP_CWORD]} # the current token
[[ -z "$cur" && -n "$nocomplete" ]] && {
printf "\n(restricted completion for $cmd in $nocomplete)\n"
printf "$PS2 $COMP_LINE"
COMPREPLY=( "" ) # dummy to prevent completion
return
}
COMPREPLY=() # let default kick in
}
function _myprompt {
nocomplete=
# uncomment next line for hard-coded list of directories
[[ -n "${noacdirs[$PWD]}" ]] && nocomplete=$PWD
# uncomment next line for per-directory ".noautocomplete"
# [[ -f ./.noautocomplete ]] && nocomplete=$PWD
# uncomment next line for size-based guessing of large directories
# [[ $(stat -c %s .) -gt 512*1024 ]] && nocomplete=$PWD
}
PROMPT_COMMAND=_myprompt
complete -o bashdefault -o default -F _xcomplete vi cp scp diff
Ця функція підказок встановлює nocomplete
змінну при введенні одного з налаштованих каталогів. Модифікована поведінка завершення запускається лише тоді, коли ця змінна не є порожньою і лише тоді, коли ви намагаєтесь заповнити порожній рядок, таким чином дозволяючи заповнити часткові імена (видаліть -z "$cur"
умову, щоб уникнути повного завершення). Прокоментуйте два printf
рядки для безшумної роботи.
Інші параметри включають .noautocomplete
файл прапора для кожного каталогу, який ви можете мати touch
в каталозі за потреби; та відгадування розміру каталогу за допомогою GNU stat
. Ви можете використовувати будь-який або всі ці три варіанти.
( stat
Метод - лише здогадка. Розмір повідомленого каталогу зростає разом із його вмістом, це "високий показник води", який зазвичай не зменшується, коли файли видаляються без певного втручання адміністрації. Це дешевше, ніж визначення реального вмісту потенційно великого Точна поведінка та приріст у файлі залежить від базової файлової системи. Я вважаю її надійним індикатором принаймні для систем Linux Linux ext2 / 3/4.)
bash додає додатковий простір навіть при поверненні порожнього завершення (це відбувається лише при заповненні в кінці рядка). Ви можете додати -o nospace
до complete
команди, щоб запобігти цьому.
Одне, що залишилось, - якщо створити резервну копію курсору до початку вкладки маркера та натискання, завершення за замовчуванням розпочнеться знову. Вважайте це особливістю ;-)
(Або ви можете пограбувати, ${COMP_LINE:$COMP_POINT-1:1}
якщо вам подобається надмірна інженерія, але я вважаю, що сам Bash не в змозі надійно встановити змінні завершення, коли ви створюєте резервну копію та намагаєтеся виконати в середині команди.)