Додайте аргументи з попередньої команди до завершення zsh


22

У zsh (як і bash) ви можете використовувати деякі розширення слів історії історії для позначення аргументів попередніх команд.

Цей приклад показує отримання 2-го параметра з попередньої команди в історії з !:#розширенням:

% 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>:

% echo bar baz qux
bar baz qux
% foo <TAB>
bar   baz   echo  qux 

Це чудово підходить для виконання команди "foo", але я хотів би, щоб це були варіанти для будь-якого розширення zsh, яке я роблю. Я думаю, що це має щось спільне з елементами zstyle kompleter, але через кілька годин злому я зрозумів, що я вийшов з глибини.

Як я можу отримати аргументи з попередньої команди як запропоновані доповнення для будь-якої команди в zsh?

У мене повноцінний файл комп’ютерної програми zshrc ділиться на bitbucket, якщо це допомагає. Багато його посилається з найрізноманітніших джерел, а деякі з них я сам зламав.

ОНОВЛЕННЯ:

@ Відповідь Юлієна Нікуло мене наблизила, я відзначаю це як прийняте, оскільки отримало мене там, де мені потрібно було дістатися.

З моєю конкретною конфігурацією, використовуючи запропоновані:

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 

2
Це ефектна ідея
Майкл Мрозек

2
Щоб доповнити ^[ .( insert-last-word), мені подобається copy-earlier-word, який цикли між словами рядка, досягнутого insert-last-word. Для вашого .zshrc:autoload copy-earlier-word && zle -N copy-earlier-word && bindkey '^[,' copy-earlier-word
Жил "ТАК - перестаньте бути злим"

@Gilles дякую! Це наближає мене до функціональності, якщо я не в змозі отримати повне автозавершення. ~ 80% часу, якщо це не останній аргумент, це 2-й останній аргумент, який я хочу, і C-. + C-, досить добре.
Тед Налейд

Відповіді:


6

Ви можете додати свій комплект до списку комплектуючих, які використовуються за замовчуванням:

zstyle ':completion:*' completer _last_command_args _complete

1
Якщо є _last_command_argsдоповнення, інші не відображаються. Як ви їх отримуєте крім звичайних?
Жил 'ТАК - перестань бути злим'

1
Дякую за відповідь, це змусило мене наблизитися, щоб щось працювало для мене, тому я приймаю це. Те, що я робив по-іншому, відзначається як оновлення до цього питання. У вашому рішенні не було виведено як аргументи з останньої команди, так і файли тощо з звичайного завершальника. Я склав _completeусередині створеної мною функції, і вона працює так, як я цього хотів.
Тед Налейд

Ви маєте рацію, моя відповідь невірна.
nicoulaj
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.