Можно ли настроить способ завершения имен каталогов в bash?

Можно ли настроить способ завершения имен каталогов в bash?

Я хотел бы указать bash использовать специальный метод для выполнения автодополнения определенных имен каталогов. Например, bash вызовет мою программу для выполнения автодополнения, если путь начинается с "$$", и выполнит автодополнение обычным образом в противном случае.

Возможно ли это вообще? Как бы вы это реализовали?

Награда: Я был бы очень признателен за ответ на этот вопрос. Цель состоит в том, чтобы позволитьавтопрыжокдля завершения путей для всех команд, когда пользователь начинает их с определенного префикса. Так, например, при копировании файла из дальнего каталога, вы можете ввести:

cp $$patern + <Tab>

и автопрыжок завершится

cp /home/user/CompliCatedDireCTOry/long/path/bla/bla

и вам просто нужно будет добавить, куда вы хотите поместить файл. Конечно, я могу использовать комментарий ott, чтобы добавить его к нескольким конкретным командам, но если у кого-то есть идея получше, я буду очень благодарен.

решение1

Это можно сделать, переопределив привязку по умолчанию для TAB(^i). Сначала вам нужно переопределить привязку TAB, затем вам нужно создать функцию, которая вызывает вашу команду, и, наконец, вам нужно взять вывод этой команды и обновить переменную, содержащую текущую командную строку.

Эта функция берет текущую командную строку и изменяет последние два символа на «huugs».

function my_awesome_tab_completion_function () {
  set -- $READLINE_LINE
  command="$1"
  shift
  argument="$*"
  argument_length=$(echo -n $argument | wc -c)
  if echo $argument | grep '^$$' >/dev/null 2>&1; then
    new_argument=$(echo $argument | sed 's/..$/huugs/') # put your autojump here
  else
    new_argument=$(compgen -d $argument)
  fi
  new_argument_length=$(echo -n $new_argument | wc -c)
  READLINE_POINT=$(( $new_argument_length - $argument_length + $READLINE_POINT ))
  READLINE_LINE="$command $new_argument"
}

В вашем примере вы, вероятно, захотите изменить строку new_argument так, чтобы она выглядела следующим образом:

  new_argument=$(autojump $argument)

Теперь переопределим привязку ^i:

$ bind -x '"\C-i"':'my_awesome_tab_completion_function'

Теперь проверьте, работает ли это:

$ cd /ro<TAB>
changes my command to:
$ cd /root

так что нормальное завершение все еще работает, вы можете проверить часть $$, выполнив cd $$... и т. д.

Если у вас возникли проблемы, включите подробный режим:

$ set -x

Он распечатает все, что делает функция.

Я протестировал это на Ubuntu 11, используя bash 4.2.8(1)-release (по умолчанию).

решение2

Процедуру завершения bash можно запрограммировать как скрипт оболочки.

Вот пример скрипта оболочки, который заменит любой параметр $$[Tab]на my replacement string, но только для определенной команды mycommandи только если параметр равен именно "$$":

_mycomplete()
{
        if [ ${COMP_WORDS[COMP_CWORD]} == \$\$ ]
        then
                COMPREPLY='my replacement string'
        fi
}
complete -o default -o bashdefault -F _mycomplete mycommand

Чтобы запустить скрипт, необходимо подключить его к bash source <file-name>(или использовать команду dot), а затем:

mycommand $$[Tab] -> mycommand my replacement string
mycommand $$$[Tab] -> mycommand $$$ (beep)
mycommand whatever[Tab] -> (will complete "whatever" in the normal bash manner)

Чтобы это всегда работало для некоторых или всех пользователей, включите это в один изпроцедуры профиля bash.

Проблема с completeкомандой в том, что она будет работать только для одного или нескольких имен команд, указанных в качестве параметров. Можно просто дать ей список всех команд, которые могут быть использованы пользователями, или в отчаянных случаях расширить /bin/* /usr/bin/* ~/bin/*.

Протестировано на CentOS 5.5.

Этот простой скрипт основан на источниках, которые я перечислил в другом своем ответе - том, который был удален модератором studiohack. Если интересно, просто попросите его восстановить его.

Связанный контент