Lösen Sie alle Aliase in einer zsh-Befehlszeile auf

12

Ich habe Aliase verschachtelt und möchte sie alle auflösen, bevor der Befehl ausgeführt wird. Wie mache ich das?

Wenn es eine Funktion gibt, die an keine Taste gebunden ist, M-x foobarist das auch für mich in Ordnung. Ich kann sogar externen Befehl ( type, command, which, was auch immer). Ich habe alles aus dem Thread probiert Warum nicht "welche" verwenden? Was ist dann zu verwenden? aber nichts funktioniert.

WeSenseASoulInSearchOfAnswers
quelle
2
C-x aErweitert den Alias ​​unter dem Cursor (vorausgesetzt, Sie verwenden das Vervollständigungssystem).
Stéphane Chazelas
Richtig _expand_alias (^Xa): expands the word the cursor is on if it is an alias. Das ist hilfreich, aber immer noch schade, dass man in bash die ganze Zeile erweitern kann, in zsh nicht.
WeSenseASoulInSearchOfAnswers
Ich nehme an, dass es möglich ist, einen bindbaren Befehl zu schreiben, der aufgerufen wird, _expand_aliasbis sich der Bearbeitungspuffer nicht mehr ändert.
Vinc17

Antworten:

10

Beachten Sie, dass Strg-Alt-E in bashnicht nur Aliase erweitert. Es erweitert auch Variablen, Befehlsersetzung (!), Prozessersetzung (!), Arithmetische Erweiterung und entfernt Anführungszeichen (es führt keine Dateinamengenerierung (Globbing) oder Tilde-Erweiterung durch).

Es gelingt nicht immer, Aliase zu erweitern. Daher ist es wichtig, zu erkennen, dass das Ergebnis möglicherweise die Bedeutung der Befehlszeile ändert, Nebenwirkungen hat und potenziell gefährlich ist.

Zum Beispiel in:

$ a=';w' b=1
$ alias foo=bar
$ b=2; echo $b $a; cd /tmp/dir && for i do foo $(pwd) <(ls); done

Wenn ich M-C-Ehier drücke , gibt mir das:

$ b=2; echo 1 ;w; cd /tmp/dir && for i do foo / /dev/fd/63; done

Das gibt mir eine völlig andere Kommandozeile (und stellen Sie sich vor, was passiert wäre, wenn ich rm -rf *statt pwdoben hätte) und erweitert den fooAlias ​​nicht.

Mit zsh, zum Aufbau auf Gilles' Hinweis auf Aliase innerhalb von Funktionen erweitert, könnten Sie tun:

expand-aliases() {
  unset 'functions[_expand-aliases]'
  functions[_expand-aliases]=$BUFFER
  (($+functions[_expand-aliases])) &&
    BUFFER=${functions[_expand-aliases]#$'\t'} &&
    CURSOR=$#BUFFER
}

zle -N expand-aliases
bindkey '\e^E' expand-aliases

Dadurch werden die Aliase nur dann erweitert, wenn die aktuelle Befehlszeile syntaktisch gültig ist (und somit auch als Syntaxprüfprogramm fungiert).

Im Gegensatz zu bashMCE werden auch die Aliase vollständig aufgelöst. Zum Beispiel, wenn Sie:

$ alias ll='ls -l'; alias ls='ls --color'
$ ll

Wird erweitert auf:

$ ls --color -l

Beachten Sie, dass es auch die Syntax kanonisiert, so dass Dinge wie:

$ for i (*) cmd $i; foo

wird geändert in:

$ for i in *
        do
                cmd $i
        done
        foo
Stéphane Chazelas
quelle
Das ist fehlerhaft. Wenn ich zu alias ls='ls --color'und geben Sie C-x aüber ls, die ich erhalten: \ls --color(so dass der neue lsnicht als Alias falsch interpretiert wird). Aber mit Ihrer verstehe expand-aliasesich ls --color:, das Ergebnis mehrdeutig zu machen.
Vinc17
@ vinc17, es ist nicht mehrdeutig, dass es den Alias ​​vollständig auflöst (in dieser Hinsicht ist es weniger fehlerhaft als das bashÄquivalent). Wenn Sie den Befehl danach ausführen, erhalten Sie eine weitere Runde der Aliaserweiterung (wie in bash). Idealerweise sollten Sie die Aliaserweiterung vorübergehend deaktivieren (){ setopt localoptions noexpandalias; ...; }. Beachten Sie, dass Sie sagen können, dass das _expand_aliasfehlerhaft ist, und dass es den Alias ​​erweitert, wenn es ausgeführt wird \ls.
Stéphane Chazelas
@ vinc17, dass Backslash-Escape von _expand_aliasauch leicht wie alias 'foo=repeat 3 foo'oder getäuscht wird alias ls='ls --color'; alias '\ls=echo fooled'. Hier gibt es keine perfekte Lösung.
Stéphane Chazelas
In Bezug _expand_aliasauf alias 'foo=repeat 3 foo'würde ich den fehlenden Backslash als Fehler betrachten. Und alias '\ls=echo fooled'sollte nicht erlaubt sein; hier ziehe ich bash, die sagt: bash: alias: '\ls': invalid alias name.
Vinc17
@ Vinc17, ich kann nicht sehen, wie das als etwas anderes als eine Einschränkung in gesehen werden kann bash. Wenn Sie Aliase mit Backslashes nicht mögen, verwenden Sie sie nicht. Warum sollte die Shell sie dann ablehnen? Während Aliase in csh (woher sie kommen) die Funktionen eines armen Mannes ersetzen, sind sie in Bourne-ähnlichen Shells Hacks, um Tricks auszuführen, die mit Funktionen, einer Form der Makro-Erweiterung, die sich früh in den Shell-Parser einfügt, nicht möglich sind Ich sehe keinen Sinn darin, die Möglichkeiten einzuschränken.
Stéphane Chazelas
6

Wenn Sie eine Befehlszeile in eine Funktionsdefinition einfügen und dann die Funktion ausdrucken, werden die Aliase erweitert. Sie erhalten auch normalisierte Leerzeichen.

% alias foo='bar -1'
% alias bar='qux -2'
% f () foo -3
% which f
f () {
        qux -2 -1 -3
}

Um all dies in einen interaktiven Befehl umzusetzen, können Sie ein zle-Widget erstellen. Sie können eine Funktion direkt definieren, indem Sie ihren Code in einen Eintrag im functionsArray einfügen . Sie erhalten den Normalisierungseffekt, wenn Sie zurücklesen.

normalize-command-line () {
  functions[__normalize_command_line_tmp]=$BUFFER
  BUFFER=${${functions[__normalize_command_line_tmp]#$'\t'}//$'\n\t'/$'\n'}
  ((CURSOR == 0 || CURSOR = #BUFFER)
  unset 'functions[__normalize_command_line_tmp]'
}
zle -N normalize-command-line
bindkey  normalize-command-line

Sie erhalten den gleichen Normalisierungseffekt im preexecHook . Aliase werden auch erweitert, wenn eine Funktion automatisch geladen wird ( autoload -Uwird häufig verwendet, um eine Alias-Erweiterung zu vermeiden).

Die _expand_aliasVervollständigungsfunktion erweitert das Wort unter dem Cursor, wenn es sich um einen Alias ​​handelt. Es verwendet das aliasesArray . Es ist nicht rekursiv. Sie könnten einen allgemeineren Alias-Expander mithilfe von implementieren aliases, dies ist jedoch etwas schwierig, da die Ermittlung der Positionen, an denen Aliase erweitert werden, eng mit der Shell-Syntax verbunden ist.

Gilles 'SO - hör auf böse zu sein'
quelle
2
Ich habe es immer autoload -Ueinfach verwendet, weil die zsh-Dokumentation es empfiehlt, aber ich habe nie verstanden, was -Uich tat, bis ich das gelesen habe :). Auch für alle Interessierten, kann man rufen die _expand_alias direkt wirken , indem Ihr Alias in die Befehlszeile eingeben, Schlagen <Esc>, xdie Minipuffer zu starten, dann die Eingabe_expand_alias<Enter>
the_velour_fog
2

Wenn Sie viele verschachtelte, ausgefallene Aliase haben und nicht sicher sind, was zsh tatsächlich mit ihnen macht und in welcher Reihenfolge Optionen an den Befehl übergeben werden, können Sie zsh immer mit -xoption starten . Dies gibt Befehle und Argumente aus, sobald sie ausgeführt werden.

Beachten Sie jedoch, dass diese Option eher für Debugging-Zwecke gedacht ist, so dass sie unmittelbar nach dem zsh -xAufruf (im Grunde genommen jede einzelne Funktion / jedes Widget / Plug-In Ihrer .zshrc) eine Menge unnötiger Informationen ausgibt. Insbesondere während der Befehlsausführung kann sie auch ausführlich sein wenn du definiert hast preexecund precmdhaken.

Ich sollte auch erwähnen, dass es nur die Befehle ausgibt, die zuletzt ausgeführt werden, und getrennte Befehle werden also nachher separat gedruckt

alias a='echo a'
alias b='echo b'
alias c='echo c'
alias d='echo d'
a && b || c; d

Du wirst sehen

+zsh:1> echo a
a
+zsh:1> echo b
b
+zsh:1> echo d
d
jimmij
quelle