แก้ไขสมนามทั้งหมดในบรรทัดคำสั่ง zsh


12

ฉันมีนามแฝงซ้อนกันและฉันต้องการแก้ไขทั้งหมดก่อนที่จะดำเนินการคำสั่ง ฉันจะทำอย่างไร

หากมีฟังก์ชั่นที่ไม่ได้ผูกไว้กับปุ่มใด ๆ ก็M-x foobarเป็นสิ่งที่ดีสำหรับฉันเช่นกัน ฉันยังสามารถใช้คำสั่งภายนอก ( type, command, which, อะไรก็ตาม) ฉันลองทุกอย่างจากเธรดทำไมไม่ใช้ "อัน" จะใช้อะไรดี? แต่ไม่มีอะไรทำงาน


2
C-x aขยายนามแฝงใต้เคอร์เซอร์ (สมมติว่าคุณกำลังใช้ระบบเสร็จสิ้น)
Stéphane Chazelas

_expand_alias (^Xa): expands the word the cursor is on if it is an aliasขวา ที่เป็นประโยชน์ แต่ก็ยังน่าเสียดายที่ในทุบตีหนึ่งสามารถขยายสายทั้งหมด แต่ใน zsh ไม่
WeSenseASoulInSearchOfAnswers

ฉันคิดว่ามันเป็นไปได้ที่จะเขียนคำสั่ง bindable ที่เรียกใช้_expand_aliasจนกว่าบัฟเฟอร์การแก้ไขจะไม่เปลี่ยนแปลงอีกต่อไป
vinc17

คำตอบ:


10

โปรดทราบว่า Ctrl-Alt-E ในbashไม่เพียง แต่ขยายนามแฝง นอกจากนี้ยังขยายตัวแปร, การแทนที่คำสั่ง (!), การทดแทนโปรเซส (!), เลขคณิตขยายและลบเครื่องหมายคำพูด (มันไม่ได้สร้างชื่อไฟล์ (globbing) หรือการขยายตัวหนอน

ไม่สามารถขยายชื่อแทนได้เสมอไป ดังนั้นในขณะที่มีการใช้งานสิ่งสำคัญคือการตระหนักถึงผลลัพธ์ที่อาจเปลี่ยนแปลงความหมายของบรรทัดคำสั่งมีผลข้างเคียงและอาจเป็นอันตราย

ตัวอย่างเช่นใน:

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

ถ้าฉันกดM-C-Eที่นี่นั่นจะให้ฉัน:

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

ซึ่งทำให้ฉันมีบรรทัดคำสั่งที่แตกต่างอย่างสิ้นเชิงโดยสิ้นเชิง (และจินตนาการว่าจะเกิดอะไรขึ้นถ้าฉันมีrm -rf *แทนที่จะเป็นpwdด้านบน) และไม่ขยายfooนามแฝง

ด้วยzshการสร้างบันทึกย่อของ Gilles ในนามแฝงที่ขยายภายในฟังก์ชั่นคุณสามารถทำได้:

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

ที่จะขยายนามแฝงเฉพาะถ้าบรรทัดคำสั่งปัจจุบันมีความถูกต้อง syntactically (ดังนั้นจึงเป็นสองเท่าเป็นตัวตรวจสอบไวยากรณ์)

ตรงกันข้ามกับbashMCE ของมันก็ยังแก้ไขนามแฝงได้อย่างสมบูรณ์ เช่นถ้าคุณมี:

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

จะถูกขยายเป็น:

$ ls --color -l

โปรดทราบว่ามันยังเป็นที่ยอมรับไวยากรณ์ดังนั้นสิ่งที่ชอบ:

$ for i (*) cmd $i; foo

จะถูกเปลี่ยนเป็น:

$ for i in *
        do
                cmd $i
        done
        foo

นี่คือรถม้าชนิดเล็ก หากฉันมีalias ls='ls --color'และพิมพ์C-x aทับlsฉันจะได้รับ: \ls --color(เพื่อlsไม่ให้ตีความใหม่เป็นชื่อแทน) แต่ด้วยความที่คุณexpand-aliasesได้รับ: ls --colorทำให้เกิดผลลัพธ์ที่ไม่ชัดเจน
vinc17

@ vinc17 มันไม่ได้คลุมเครือในการที่จะแก้ไขนามแฝงอย่างเต็มที่ (ในเรื่องที่เกี่ยวกับมันเป็นรถที่น้อยกว่าbashเทียบเท่า) แต่มันเป็นความจริงถ้าคุณเรียกใช้คำสั่งหลังจากนั้นคุณจะได้รับรอบของการขยายตัวนามแฝง (เหมือนในอีกbash) (){ setopt localoptions noexpandalias; ...; }ดังนั้นความนึกคิดที่คุณต้องการที่จะขยายตัวนามแฝงปิดการใช้งานชั่วคราวดังนั้นสำหรับห่อเช่นว่าใน โปรดทราบว่าคุณอาจจะบอกว่าเป็นรถเช่นเดียวกับที่มันขยายนามแฝงเมื่อทำงานบน_expand_alias \ls
Stéphane Chazelas

@ vinc17 ที่ทับขวา Escape ที่ทำโดย_expand_aliasยังหลอกได้อย่างง่ายดายเหมือนหรือalias 'foo=repeat 3 foo' alias ls='ls --color'; alias '\ls=echo fooled'ไม่มีทางออกที่สมบูรณ์แบบที่นี่
Stéphane Chazelas

เกี่ยวกับ_expand_aliasสำหรับalias 'foo=repeat 3 foo'ผมจะถือว่าทับขวาหายไปเป็นข้อผิดพลาด และalias '\ls=echo fooled'ไม่ควรได้รับอนุญาต bash: alias: '\ls': invalid alias nameนี่ฉันชอบทุบตีซึ่งพูดว่า:
vinc17

@ vinc17 ฉันไม่สามารถดูวิธีการที่สามารถมองเห็นเป็นสิ่งอื่น แต่มีข้อ จำกัด bashใน หากคุณไม่ชอบนามแฝงที่มีแบ็กสแลชอย่าใช้มัน แต่ทำไมคุณถึงต้องการให้เชลล์ปฏิเสธพวกเขา ในขณะที่นามแฝงเป็นฟังก์ชั่นของคนยากจนแทนที่ใน csh (ซึ่งมาจาก) ในเชลล์เหมือนบอร์นพวกเขามีแฮ็กที่จะเล่นกลที่ไม่สามารถทำได้ด้วยฟังก์ชั่น แต่รูปแบบการขยายมาโครบางรูปแบบ ฉันไม่เห็นจุดในการ จำกัด สิ่งที่สามารถทำได้
Stéphane Chazelas

6

หากคุณใส่บรรทัดคำสั่งลงในนิยามฟังก์ชันแล้วพิมพ์ฟังก์ชันออกมานามแฝงจะถูกขยายออก นอกจากนี้คุณยังจะได้ช่องว่างปกติ

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

ในการทำให้ทั้งหมดนี้เป็นคำสั่งแบบโต้ตอบคุณสามารถสร้างวิดเจ็ต zle คุณสามารถกำหนดฟังก์ชั่นโดยตรงโดยการบรรจุโค้ดลงในรายการในfunctionsอาร์เรย์ คุณจะได้รับผลการทำให้ปกติเมื่ออ่านกลับ

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

คุณจะได้รับผลกระทบการฟื้นฟูเดียวกันในเบ็ดpreexec นามแฝงจะถูกขยายในเวลาที่ฟังก์ชันถูกโหลดอัตโนมัติ ( autoload -Uใช้เพื่อหลีกเลี่ยงการขยายชื่อแทน)

_expand_aliasฟังก์ชั่นเสร็จสิ้นการขยายคำภายใต้เคอร์เซอร์ถ้ามันเป็นนามแฝง มันใช้อาร์เรย์aliases มันไม่ได้วนซ้ำ คุณสามารถใช้ตัวขยายนามแฝงทั่วไปที่ใช้มากขึ้นaliasesแต่มันค่อนข้างยากเนื่องจากการค้นหาตำแหน่งที่ตั้งที่มีการขยายชื่อแทนเชื่อมต่ออย่างใกล้ชิดกับไวยากรณ์เชลล์


2
ฉันมักจะใช้autoload -Uเพียงเพราะเอกสารแนะนำ zsh แต่ฉันไม่เคยเข้าใจสิ่งที่-Uทำจริง ๆ จนกว่าฉันจะอ่าน :) นอกจากนี้สำหรับทุกคนที่สนใจหนึ่งสามารถเรียก_expand_aliasทำงานโดยตรงโดยพิมพ์นามแฝงของคุณลงในบรรทัดคำสั่งตี<Esc>, xการเปิดตัว minibuffer แล้วพิมพ์_expand_alias<Enter>
the_velour_fog

2

หากคุณมีนามแฝงแฟนซีที่ซ้อนกันมากมายและคุณไม่แน่ใจว่า zsh ทำอะไรกับพวกเขาจริง ๆ และตัวเลือกคำสั่งใดถูกส่งผ่านไปยังคำสั่งคุณสามารถเริ่ม zsh ด้วย-xตัวเลือกได้เสมอ สิ่งนี้จะพิมพ์คำสั่งและอาร์กิวเมนต์ตามที่ดำเนินการ

โปรดทราบว่าตัวเลือกนี้มีจุดประสงค์เพื่อการดีบักดังนั้นจึงพิมพ์สิ่งที่ไร้ประโยชน์มากมายหลังจากzsh -xการเรียกใช้ (โดยทั่วไปแต่ละฟังก์ชั่น / วิดเจ็ต / ปลั๊กอินของ. zshrc ของคุณ) และระหว่างการดำเนินการคำสั่งอาจเป็น verbose โดยเฉพาะ หากคุณได้กำหนดpreexecและprecmdขอ

ฉันควรจะพูดถึงว่ามันพิมพ์เฉพาะคำสั่งเหล่านั้นซึ่งในที่สุดก็ดำเนินการและคำสั่งแยกจะถูกพิมพ์แยกต่างหากดังนั้นหลังจาก

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

แล้วคุณจะได้เห็น

+zsh:1> echo a
a
+zsh:1> echo b
b
+zsh:1> echo d
d
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.