В zsh (также как и в bash) вы можете использовать некоторые расширения исторического слова для обозначения аргументов из предыдущих команд.
Этот пример показывает получение второго параметра из предыдущей команды в истории с !:#
расширением:
% echo foo bar baz
foo bar baz
% echo !:2
echo bar
bar
Я часто забываю, что конкретно является параметром # конкретного аргумента, и ввод !:#
не всегда такой быстрый, когда я помню, что это за аргумент. Я знаю о meta-.
замене последнего аргумента, но иногда это не последний аргумент, который я хочу.
Я хотел бы добавить аргументы предыдущей команды в качестве предложений для завершения любой команды, которую я набираю в zsh.
Мне удалось выяснить, как создать функцию оболочки, которая может создать массив аргументов (0..N) из последней команды и связать ее с конкретной командой.
_last_command_args() {
last_command=$history[$[HISTCMD-1]]
last_command_array=("${(s/ /)last_command}")
_sep_parts last_command_array
}
# trying to get last_command_args to be suggested for any command, this just works for foo
compdef _last_command_args foo
Вот как это выглядит для завершения просто foo, где я нажимаю клавишу Tab <TAB>
:
% echo bar baz qux
bar baz qux
% foo <TAB>
bar baz echo qux
Это прекрасно подходит для выполнения команды "foo", но я бы хотел, чтобы это были опции для любого расширения zsh, которое я делаю. Я думаю, что это как-то связано с завершающим материалом zstyle, но после нескольких часов хакерских атак я понял, что я не в себе.
Как я могу получить аргументы из моей предыдущей команды в качестве предлагаемых дополнений для любой команды в zsh?
Я распространил свой полный файл zshrc compinstall на bitbucket, если это поможет. Многие из них взяты из разных источников, и некоторые из них я сам взломал.
ОБНОВИТЬ:
@Julien Nicoulaud ответил мне близко, я отмечаю его как принятый, так как я получил то, что мне нужно было получить.
С моим конкретным конфигом, используя предложенное:
zstyle ':completion:*' completer _last_command_args _complete
У меня не совсем получилось, так как это приводило к тому, что при завершении табуляции отображался только список аргументов из последней команды (хотя на самом деле он также заканчивался именами файлов, просто не отображал их). Изменив порядок, _complete _last_command_args
сделал обратное. Он будет отображать обычные имена файлов, но не last_command_args
Я предполагаю, что это как-то связано с тем, как завершает работу. Я думаю, что он отображает только вывод первого метода, который успешно возвращается, но у меня возникают проблемы при синтаксическом анализе исходного кода zsh, чтобы полностью понять, что происходит. Я смог настроить свой метод, включив в него вызов _complete
так, чтобы он показывал как последние команды аргумента, так и обычные вещи автозаполнения. Не совсем так, как отдельно, но для меня это достаточно хорошо работает.
Вот полная функция, которую я использовал вместе с другими имеющимися у меня средствами zstyle:
# adds the arguments from the last commadn to the autocomplete list
# I wasn't able to get this to work standalone and still print out both regular
# completion plus the last args, but this works well enough.
_complete_plus_last_command_args() {
last_command=$history[$[HISTCMD-1]]
last_command_array=("${(s/ /)last_command}")
_sep_parts last_command_array
_complete
}
_force_rehash() {
(( CURRENT == 1 )) && rehash
return 1 # Because we didn't really complete anything
}
zstyle ':completion:::::' completer _force_rehash _complete_plus_last_command_args _approximate
Другие строки zstyle, которые у меня есть, не обязательны для работы, но могут повлиять на то, почему это работает для меня:
zstyle -e ':completion:*:approximate:*' max-errors 'reply=( $(( ($#PREFIX + $#SUFFIX) / 3 )) )'
zstyle ':completion:*:descriptions' format "- %d -"
zstyle ':completion:*:corrections' format "- %d - (errors %e})"
zstyle ':completion:*:default' list-prompt '%S%M matches%s'
zstyle ':completion:*' group-name ''
zstyle ':completion:*:manuals' separate-sections true
zstyle ':completion:*' menu select
zstyle ':completion:*' verbose yes
Теперь, если я нахожусь в каталоге с file1.txt
и file2.txt
, и моя последняя команда была echo foo bar baz
, я получаю это для автозаполнения, что именно то, что я хотел:
% ls
bar baz echo foo
- files -
file1.txt file2.txt
^[ .
( insert-last-word
), copy-earlier-word
которое циклически повторяет слова строки, достигнутой insert-last-word
. Для вашего .zshrc
:autoload copy-earlier-word && zle -N copy-earlier-word && bindkey '^[,' copy-earlier-word