8

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

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

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

cp $$patern + <Tab>

и автопрыжки будут завершены

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

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

2 ответа2

3

Вы можете сделать это, переопределив привязку по умолчанию для 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)-релиз (по умолчанию).

1

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

Вот пример shell-скрипта, который заменит в любом параметре $$[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. Если интересно, просто попроси его восстановить его.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .