Dodaj argumenty z poprzedniego polecenia do zakończenia zsh

22

W Zsh (jak również w bash) możesz użyć niektórych rozszerzeń słów historii, aby oznaczyć argumenty z poprzednich poleceń.

Ten przykład pokazuje uzyskanie 2. parametru z poprzedniego polecenia w historii z !:#rozszerzeniem:

% echo foo bar baz
foo bar baz
% echo !:2
echo bar
bar

Często zapominam, jaki dokładnie jest parametr # danego argumentu, a pisanie !:#nie zawsze jest takie szybkie, gdy pamiętam, który to argument. Wiem o meta-.zamianie ostatniego argumentu, ale czasami nie jest to ostatni argument, którego chcę.

Chciałbym dodać argumenty z poprzedniego polecenia jako sugestie wykonania dowolnego polecenia, które wpisuję w Zsh.

Byłem w stanie dowiedzieć się, jak utworzyć funkcję powłoki, która może utworzyć tablicę argumentów (0..N) z ostatniego polecenia i powiązać go z konkretnym poleceniem.

_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

Tak to wygląda po ukończeniu foo, w którym nacisnąłem klawisz tab <TAB>:

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

Działa to świetnie do wykonania polecenia „foo”, ale chciałbym, aby były to opcje dla każdego rozszerzenia zsh, które wykonuję. Wydaje mi się, że ma to coś wspólnego z elementami uzupełniającymi zstyle, ale po kilku godzinach hackowania dookoła zdałem sobie sprawę, że nie jestem już tak głęboki.

Jak mogę uzyskać argumenty z poprzedniego polecenia jako sugerowane uzupełnienia dowolnego polecenia w Zsh?

Mam udostępniony mój pełny plik kompilacji zshrc na bitbucket, jeśli to pomaga. Wiele z nich pochodzi z różnych źródeł, a niektóre samodzielnie zhakowałem.

AKTUALIZACJA:

Odpowiedź Juliena Nicoulauda zbliżyła mnie, zaznaczam ją jako zaakceptowaną, ponieważ doprowadziła mnie tam, gdzie potrzebowałem.

W mojej konkretnej konfiguracji, używając sugerowanego:

zstyle ':completion:*' completer _last_command_args _complete

Nie działało to dla mnie całkiem dobrze, ponieważ powodowało, że uzupełnianie tabulatorami wyświetlało tylko listę argumentów z ostatniego polecenia (chociaż faktycznie uzupełniałoby to również nazwy plików, po prostu ich nie wyświetlał). Zmiana kolejności _complete _last_command_argsna odwrotną. Wyświetla normalne nazwy plików, ale nie ostatnie_polecenia_args

Zgaduję, że ma to coś wspólnego ze sposobem działania narzędzia uzupełniającego. Myślę, że wyświetla tylko dane wyjściowe z pierwszej metody, która powraca pomyślnie, ale mam problem z analizowaniem źródła zsh, aby w pełni zrozumieć, co się dzieje. Byłem w stanie dostosować moją metodę, aby zawierała wywołanie, aby _completewyświetlała zarówno ostatnie polecenia argumentu, jak i zwykłe autouzupełnianie. Nie do końca tak oddzielny, ale działa wystarczająco dobrze dla mnie.

Oto pełna funkcja, której użyłem wraz z innymi rzeczami zstyle, które mam:

# 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 

Inne linie zstyle, które mam, nie są konieczne, aby to działało, ale mogą mieć wpływ na to, dlaczego to działa dla mnie:

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

Teraz, gdy jestem w katalogu z file1.txti file2.txt, a moim ostatnim poleceniem było echo foo bar baz, otrzymuję to do autouzupełniania, czego właśnie chciałem:

% ls
bar   baz   echo  foo 
- files -
file1.txt   file2.txt 
Ted Naleid
źródło
2
To spektakularny pomysł
Michael Mrozek
2
Do uzupełnienia ^[ .( insert-last-word) podoba mi się to copy-earlier-word, które przełącza między słowami linii osiągniętej przez insert-last-word. Dla twojego .zshrc:autoload copy-earlier-word && zle -N copy-earlier-word && bindkey '^[,' copy-earlier-word
Gilles 'SO- przestań być zły'
@Gilles dzięki! To przybliża mnie do funkcjonalności, jeśli nie jestem w stanie uzyskać pełnego autouzupełniania. ~ 80% czasu, jeśli nie jest to ostatni argument, to od 2 do ostatniego argumentu chcę i C-. + C-, jest całkiem niezły.
Ted Naleid

Odpowiedzi:

6

Możesz dodać swojego wypełniacza do listy domyślnie używanych wypełniaczy:

zstyle ':completion:*' completer _last_command_args _complete
nicoulaj
źródło
1
Jeśli są jakieś _last_command_argsuzupełnienia, pozostałe nie są wyświetlane. Jak je zdobyć oprócz zwykłych?
Gilles „SO- przestań być zły”
1
Dzięki za odpowiedź, dzięki temu znalazłem się wystarczająco blisko, aby coś dla mnie działało, więc akceptuję to. To, co zrobiłem inaczej, zostało odnotowane jako aktualizacja powyższego pytania. Twoje rozwiązanie nie wydrukowało zarówno argumentów z ostatniego polecenia, jak i plików itp. Z normalnego programu uzupełniającego. Skomponowałem się _completew funkcji, którą utworzyłem i działa tak, jak chciałem.
Ted Naleid
Masz rację, moja odpowiedź jest nieprawidłowa.
nicoulaj