Atasi semua alias dalam baris perintah zsh


12

Saya telah membuat alias alias bersarang dan ingin menyelesaikan semuanya sebelum menjalankan perintah. Bagaimana aku melakukan itu?

Jika ada fungsi yang tidak terikat pada tombol apa pun M-x foobarjuga baik untuk saya. Aku bahkan bisa menggunakan perintah eksternal ( type, command, which, apa pun). Saya mencoba semuanya dari utas Mengapa tidak menggunakan "yang"? Lalu apa yang harus digunakan? tapi tidak ada yang berhasil.


2
C-x aperluas alias di bawah kursor (dengan asumsi Anda menggunakan sistem penyelesaian).
Stéphane Chazelas

Benar _expand_alias (^Xa): expands the word the cursor is on if it is an alias,. Itu membantu, namun masih sayang bahwa di bash seseorang dapat memperluas seluruh baris tetapi dalam zsh tidak.
WeSenseASoulInSearchOfAnswers

Saya mengira bahwa adalah mungkin untuk menulis perintah bindable yang memanggil _expand_aliashingga edit buffer tidak lagi berubah.
vinc17

Jawaban:


10

Perhatikan bahwa Ctrl-Alt-E di bashtidak hanya memperluas alias. Itu juga memperluas variabel, substitusi perintah (!), Substitusi proses (!), Memperluas aritmatika dan menghapus tanda kutip (itu tidak melakukan generasi nama file (globbing) atau ekspansi tilde).

Itu tidak selalu berhasil memperluas alias. Jadi, meskipun memiliki kegunaannya, penting untuk menyadari hasilnya berpotensi mengubah makna baris perintah, memiliki efek samping dan berpotensi berbahaya.

Misalnya di:

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

Jika saya menekan di M-C-Esini, itu memberi saya:

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

Yang memberi saya baris perintah yang sama sekali berbeda (dan bayangkan apa yang akan terjadi jika saya memiliki rm -rf *alih-alih di pwdatas) dan tidak memperluas fooalias.

Dengan zsh, untuk membangun catatan Gilles di alias yang diperluas di dalam fungsi, Anda bisa melakukan:

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

Itu akan memperluas alias hanya jika baris perintah saat ini secara sintaksis valid (sehingga berfungsi sebagai pemeriksa sintaksis).

Berlawanan dengan bashMCE, ia juga menyelesaikan alias sepenuhnya. Misalnya jika Anda memiliki:

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

Akan diperluas ke:

$ ls --color -l

Perhatikan bahwa itu juga membuat kanon sintaksis sehingga hal-hal seperti:

$ for i (*) cmd $i; foo

akan diubah menjadi:

$ for i in *
        do
                cmd $i
        done
        foo

Ini buggy. Jika saya memiliki alias ls='ls --color'dan ketik C-x alebih ls, saya mendapatkan: \ls --color(sehingga baru lstidak disalahartikan sebagai alias). Tapi dengan Anda expand-aliases, saya dapatkan ls --color:, membuat hasilnya ambigu.
vinc17

@ vinc17, itu tidak ambigu dalam menyelesaikan alias sepenuhnya (dalam hal itu, itu kurang buggy daripada yang bashsetara). Tapi itu benar jika Anda menjalankan perintah setelah itu, Anda akan mendapatkan putaran alias ekspansi (seperti di bash), jadi idealnya Anda ingin menonaktifkan sementara ekspansi alias, jadi misalnya bungkus dalam a (){ setopt localoptions noexpandalias; ...; }. Perhatikan bahwa Anda bisa mengatakan _expand_aliasbuggy juga memperluas alias saat dijalankan \ls.
Stéphane Chazelas

@ vinc17, backslash yang lolos yang dilakukan _expand_aliasjuga mudah dibodohi seperti alias 'foo=repeat 3 foo'atau alias ls='ls --color'; alias '\ls=echo fooled'. Tidak ada solusi sempurna di sini.
Stéphane Chazelas

Mengenai _expand_aliasuntuk alias 'foo=repeat 3 foo', saya akan menganggap backslash hilang sebagai bug. Dan alias '\ls=echo fooled'seharusnya tidak diizinkan; di sini saya lebih memilih bash, yang mengatakan: bash: alias: '\ls': invalid alias name.
vinc17

@ vinc17, saya tidak bisa melihat bagaimana itu bisa dilihat sebagai hal lain selain batasan dalam bash. Jika Anda tidak suka alias dengan garis miring terbalik, jangan gunakan itu, tetapi mengapa Anda ingin shell menolaknya? Sementara alias adalah penggantian fungsi orang miskin di csh (dari mana asalnya), dalam cangkang mirip Bourne, mereka adalah peretasan untuk melakukan trik yang tidak dapat dilakukan dengan fungsi, beberapa bentuk ekspansi makro yang menghubungkan awal pengurai shell di awal , Saya tidak melihat gunanya membatasi apa yang bisa dilakukan.
Stéphane Chazelas

6

Jika Anda memasukkan baris perintah ke dalam definisi fungsi dan kemudian mencetak fungsinya, alias akan diperluas. Anda juga akan mendapatkan spasi putih yang dinormalisasi.

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

Untuk memasukkan semua ini ke dalam perintah interaktif, Anda dapat membuat widget zle. Anda dapat mendefinisikan suatu fungsi secara langsung dengan memasukkan kodenya ke dalam entri dalam functionsarray; Anda akan mendapatkan efek normalisasi ketika Anda membaca kembali.

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

Anda mendapatkan efek normalisasi yang sama di preexechook . Alias ​​juga diperluas pada saat suatu fungsi dimuat secara otomatis ( autoload -Ubiasanya digunakan untuk menghindari ekspansi alias).

Fungsi _expand_aliaspenyelesaian memperluas kata di bawah kursor jika itu alias. Menggunakan aliasesarray . Itu tidak rekursif. Anda bisa mengimplementasikan alias menggunakan expander yang lebih umum aliases, tetapi agak sulit, karena mencari tahu lokasi di mana alias diperluas diperluas terkait dengan sintaksis shell.


2
Saya selalu menggunakan autoload -Uhanya karena dokumentasi zsh merekomendasikannya, tetapi saya tidak pernah mengerti apa yang -Usebenarnya saya lakukan sampai saya membaca ini :). Juga bagi siapa saja yang tertarik, kita dapat memohon _expand_alias berfungsi langsung dengan mengetikkan alias Anda ke baris perintah, memukul <Esc>, x, untuk meluncurkan minibuffer, kemudian mengetik_expand_alias<Enter>
the_velour_fog

2

Jika Anda memiliki banyak alias alias bersarang dan Anda tidak yakin apa yang sebenarnya dilakukan zsh dengan mereka dan di mana opsi pesanan dilewatkan ke perintah maka Anda selalu dapat memulai zsh dengan -xopsi. Ini akan mencetak perintah dan argumen saat dijalankan.

Perlu diketahui bahwa opsi ini dimaksudkan untuk tujuan debugging sehingga mencetak banyak hal yang tidak berguna setelah zsh -xdoa (pada dasarnya masing-masing dan setiap fungsi / widget / plugin .zshrc Anda), dan selama eksekusi perintah itu bisa juga bertele-tele, terutama jika Anda telah menetapkan preexecdan precmdhook.

Saya juga harus menyebutkan, bahwa ia hanya mencetak perintah-perintah yang akhirnya dieksekusi, dan perintah-perintah yang terpisah dicetak secara terpisah

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

Kamu akan lihat

+zsh:1> echo a
a
+zsh:1> echo b
b
+zsh:1> echo d
d
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.