Skrót klawiaturowy historii Bash dla! *

8

W Bash istnieje kilka przydatnych operatorów do powtarzania części ostatniego polecenia:

  • !^ rozwija się do pierwszego argumentu poprzedniego polecenia, np.

    $ echo one "two three"
    one two three
    $ echo !^
    echo one
    one
    
  • !$ rozwija się do ostatniego argumentu poprzedniego polecenia, np.

    $ echo one "two three"
    one two three
    $ echo !$
    echo "two three"
    two three
    
  • !* rozwija się do wszystkich argumentów poprzedniego polecenia, np.

    $ echo one "two three"
    one two three
    $ echo !*
    echo one "two three"
    one two three
    

(O ile dobrze rozumiem, to cukier syntaktyczny dla !!:^, !!:$i !!:*, odpowiednio, gdzie !!jest oznaczenie zdarzenie, które rozwija się do poprzedniego polecenia, a także ^, $i *to Oznaczenia słowne, zobacz Bash Reference Manual lub man bash).

Często są one bardzo przydatne. Ale robi się jeszcze fajniej dzięki skrótom klawiaturowym:

  • Kiedy naciśniesz Alt+ .lub Alt+ _, ostatni argument poprzedniego polecenia zostanie wstawiony do bieżącego polecenia, podobnie jak gdybyś napisał !$w tym momencie.

  • Możliwe jest także naciśnięcie Alt+ Ctrl+, yaby wstawić pierwszy argument poprzedniego polecenia, tak jakbyś napisał !^w tym momencie.

(Zobacz bibliotekę GNU Readline lub info readline.)

Wolę skróty klawiaturowe niż operatory historii Basha, ponieważ widzę, co wstawiam, zanim faktycznie wykonam polecenie. Wydaje się jednak, że nie ma skrótu, który pozwala mi wstawić wszystkie słowa poprzedniego polecenia, tzn. Takiego, który wykonuje swoją !*pracę. Przynajmniej nie mogłem tego znaleźć.

Czy istnieje taki skrót? Jeśli nie, to czy można skonfigurować bibliotekę readline, aby ją dodać i jak?

Malte Skoruppa
źródło
AFAIK, skróty klawiaturowe są obsługiwane przez emulator terminala. Więc przypuszczam, że używasz terminala gnome?
Seth
1
Po zshwpisaniu, echo !*a następnie naciśnięciu klawisza TAB, uzyskasz pożądany efekt. Ogólnie rzecz biorąc, TAB podczas odczytu rozszerzy wszystkie rozwijane. Bardzo przydatny; prawdopodobnie bash będzie miał konfigurację z tym samym skutkiem? @Seth, myślę, że to readline na bash, a nie emulator terminala - choć nie jestem pewien.
Rmano
2
@Seth Nie, skróty z Q są obsługiwane przez bash. Możesz man bash
szukać
@ RaduRădeanu Oh ciekawe! Nie wiedziałem tego Moje złe dla złych założeń.
Seth
1
\e.i \e_są mapowane na funkcję readline yank-last-argi \e\C-yjest mapowane na yank-nth-arg. Niestety wydaje się, że nie ma (pojedynczego) polecenia, które dodałoby wiele poprzednich argumentów jednocześnie.
Adaephon

Odpowiedzi:

5

Jeśli spojrzysz na wynik następującego polecenia:

bind -l

lub lepiej:

bind -l | grep arg

widać, że nie istnieje żadna funkcja readline dla wszystkich argumentów, jak na przykład yank-last-argdla ostatniego argumentu - który może wstawić ostatni argument do poprzedniego polecenia (ostatnie słowo poprzedniego wpisu historii). Jeśli więc taka funkcja nie istnieje, najprawdopodobniej nie istnieje skrót do osiągnięcia tego, co chcesz.

Spróbujmy stworzyć skrzynkę z jednym podejściem do twojego żądania ...

Najpierw spójrz na przykład na następujące polecenie:

bind -p | grep yank-nth-arg

Dane wyjściowe to:

"\e\C-y": yank-nth-arg

i można je przetłumaczyć w następujący sposób: yank-nth-arg(który wstawia pierwszy argument do poprzedniej komendy - z argumentem n wstawia nty argument z poprzedniej komendy) jest powiązany z Alt+ Ctrl+ y.

W ten sam sposób można interpretować dowolny wiersz z wyjścia bind -ppolecenia.

Teraz zwróć uwagę na następujące scenariusze:

  • Jeśli ustawisz następujące powiązanie:

    bind '"\ea": "\e2\e."'

    Alt+ Azostanie zamapowany na Alt+ 2Alt+, .który jest zamapowany, aby wstawić drugi argument poprzedniego polecenia. Tak więc, po po naciśnięciu Alt+ AThe drugi argument poprzedniego polecenia jest włożona do bieżącego polecenia.

  • Jeśli ustawisz:

    bind '"\ea": "\e1\e. \e2\e."'

    Po po naciśnięciu Alt+ A, te dwa pierwsze argumenty poprzedniego polecenia jest włożona do bieżącego polecenia. Jeśli liczba argumentów z poprzedniego polecenia wynosi maksymalnie 2, oczywiście wszystkie poprzednie polecenia są wstawiane do bieżącego polecenia.

  • Jeśli ustawisz:

    bind '"\ea": "\e1\e. \e2\e. \e3\e."'

    Po po naciśnięciu Alt+ A, że pierwsze trzy argumenty poprzedniego polecenia jest włożona do bieżącego polecenia. Jeśli liczba argumentów z poprzedniego polecenia wynosi maksymalnie 3 (jak w twoim przypadku), oczywiście wszystkie poprzednie polecenia są wstawiane do bieżącego polecenia.

  • I tak dalej.

Do pierwszych 10 argumentów możesz użyć:

bind '"\ea": "\e1\e. \e2\e. \e3\e. \e4\e. \e5\e. \e6\e. \e7\e. \e8\e. \e9\e. \e1\e0\e."'

I myślę, że to wystarczająco długo, o ile nie używam zbyt często poleceń z tyloma argumentami.

Aby było trwałe, dodaj do ~/.inputrcpliku następującą linię :

"\ea": "\e1\e. \e2\e. \e3\e. \e4\e. \e5\e. \e6\e. \e7\e. \e8\e. \e9\e. \e1\e0\e."

W tym przykładzie wybrałem Alt+, Aaby wstawić wszystkie argumenty (jeśli liczba argumentów nie jest większa niż 10) poprzedniego polecenia, ale możesz wybrać dowolną inną kombinację, zastępując w poprzednim poleceniu \eaciąg.

Zasoby:

Radu Rădeanu
źródło
Cóż, jest to trochę hacking i będzie działać tylko dla ograniczonej liczby argumentów, ale wydaje się, że jest to najbliższe, co możemy łatwo dostać - wezmę to;) Właściwie to właśnie rzuciłem okiem na kod źródłowy readline. Na pierwszy rzut oka wygląda to tak, jak w pliku funmap.c, funkcja yank-nth-argjest odwzorowana na funkcję C rl_yank_nth_arg, która z kolei jest zdefiniowana w kill.c. Analogicznie dla yank-last-arg. Oczywiście byłoby możliwe rozszerzenie readline o taką funkcjonalność, ale nie chcę tego robić; Wolę zarządzać moim readline apt, a ta funkcja nie jest tak ważna;)
Malte Skoruppa