Це не ідеально, але знову ж таки завершення баш - досить складна справа ...
Найпростіший спосіб - це команда, трохи гнучкіша, ніж 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 не в змозі надійно встановити змінні завершення, коли ви створюєте резервну копію та намагаєтеся виконати в середині команди.)