ฉันจะกำหนดโหมดกลุ่มของ zsh ได้อย่างไร


25

ตกลงดังนั้นในที่สุดฉันก็ทำการเปลี่ยนแปลงที่ดี ใน. zshenv ของฉันฉันเปลี่ยน EDITOR ของฉัน:

export EDITOR=vim

มีคำถามสองสามข้อที่ฉันมีซึ่งเล็กมากจนฉันไม่ต้องการเริ่มคำถามแยกต่างหาก ที่นี่พวกเขาคือ:

  1. ฉันจะรับ zsh เพื่อแยกความแตกต่างระหว่างโหมดแทรกและโหมดคำสั่งเหมือนในกลุ่มได้อย่างไร? สิ่งนี้จะเปลี่ยนเคอร์เซอร์จากขีดเส้นใต้เป็นบล็อกเช่นเดียวกับในกลุ่ม แต่การแสดงข้อความที่ด้านล่างก็ใช้งานได้เช่นกัน

  2. ฉันจะทำให้มันทำตัวเหมือนเป็นกลุ่มได้อย่างไร? ตัวอย่างเช่นฉันต้องการอยู่ในโหมดคำสั่งโดยค่าเริ่มต้นและไม่ออกไปหลังจากคำสั่งเดียว


//, คุณเคยมีพฤติกรรมแปลก ๆ กับการแก้ไขบรรทัดคำสั่งหรือไม่? ฉันได้รับการทำงานเป็น~ตัวละครที่ได้รับการแทรกเมื่อกดสำคัญในการDelete zshฉันถามคำถามเกี่ยวกับที่นี่: superuser.com/questions/997593/…
นาธานบาซาเนเซ

คำตอบ:


25

1. ) (ดูhttp://zshwiki.org/home/examples/zlewidgetsและhttp://pthree.org/2009/03/28/add-vim-editing-mode-to-your-zsh-prompt/ ) :

ฟังก์ชัน zle-line-init zle-keymap-select {
    RPS1 = "$ {$ {KEYMAP / vicmd / - NORMAL -} / (main | viins) / - INSERT -}"
    RPS2 = $ RPS1
    zle reset-prompt
}
zle -N zle-line-init
zle -N zle-keymap-select

ที่ไหน:

  • "RPS" หมายถึง 'สตริงพรอมต์ขวา' และกำหนดพรอมต์ที่ปรากฏทางด้านขวามือของเทอร์มินัลและไวยากรณ์ $ {ตัวแปร / รูปแบบ / การแทนที่} คือ 'การขยายพารามิเตอร์' ดูที่http: // mywiki .wooledge.org

  • 'zle -N' ทำให้วิดเจ็ตที่ผู้ใช้กำหนดเองได้ 'zle-line-init' และ 'zle-keymap-select' ถูกผูกไว้ (ไปยังฟังก์ชันเชลล์ในชื่อเดียวกัน) ดังนั้นพวกเขาจะถูกเรียกเมื่อตัวแก้ไขบรรทัดเริ่มต้น และรูปแบบแป้นที่มีการเปลี่ยนแปลงตามลำดับดู: http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#SEC125

2. ) ฉันสงสัยว่าคุณต้องเขียน zsh-widget อีกอันเพื่อทำเช่นนั้นรับแรงบันดาลใจจากลิงค์แรกจากสองลิงก์สำหรับปัญหาแรก


22

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

วิธีจัดการกับสิ่งนั้นคือการใช้zle-line-finishโดยไม่ต้องใช้ที่zle reset-promptนั่น ตัวอย่าง:

# perform parameter expansion/command substitution in prompt
setopt PROMPT_SUBST

vim_ins_mode="[INS]"
vim_cmd_mode="[CMD]"
vim_mode=$vim_ins_mode

function zle-keymap-select {
  vim_mode="${${KEYMAP/vicmd/${vim_cmd_mode}}/(main|viins)/${vim_ins_mode}}"
  zle reset-prompt
}
zle -N zle-keymap-select

function zle-line-finish {
  vim_mode=$vim_ins_mode
}
zle -N zle-line-finish

จากนั้นคุณสามารถเพิ่มลงในพรอมต์ขวาของคุณตัวอย่างเช่น

RPROMPT='${vim_mode}'

ตรงจากบทความในบล็อกของฉัน:


คำตอบนี้ควรได้รับคะแนนโหวตเป็นจำนวนมาก นี่เป็นครั้งแรกที่ฉันได้เห็นวิธีการแก้ปัญหานี้ ฉันใช้เวลาเล่นซอชั่วโมงกับzle-line-initวิดเจ็ตไม่มีประโยชน์ เปลี่ยนให้ตรงกับสิ่งที่ Pawel จัดหาให้และบิงโก!
โคลิน R

ขอบคุณ! มันยังไม่กันกระสุนได้ 100% เป็นครั้งคราวฉันพบสถานการณ์ที่บางบรรทัดจากผลลัพธ์ก่อนหน้าของฉันถูกลบ - แต่มันเกิดขึ้นน้อยมากจนฉันไม่สนใจเลย
PawełGościcki

1
RPROMPT2ควรตั้งค่าเช่นกันเพื่อให้สถานะแสดงในบรรทัดต่อเนื่อง นอกจากนี้เมื่อใช้สิ่งนี้คุณอาจต้องดำเนินการsetopt transient_rpromptเพื่อไม่ให้แสดงโหมดสำหรับบรรทัดที่ยอมรับก่อนหน้านี้
qqx

สิ่งหนึ่งที่ยังขาดหายไป: หากฉันเปลี่ยนกลับไปใช้โหมด emacs ( bindkey -e) แสดงว่ายังคง[INS]อยู่
Daniel

1
@cheflo คุณสามารถดูรุ่นปัจจุบันของฉันของการตั้งค่านี้ที่นี่: github.com/pjg/dotfiles/blob/master/.zshrc#L518-L584 - บางทีนั่นอาจจะช่วยคุณได้
PawełGościcki

5
zle-line-init() { zle -K vicmd; }
zle -N zle-line-init

สองบรรทัดนี้ตรวจสอบให้แน่ใจว่าเริ่มต้นในโหมดคำสั่ง


ไม่ทำงาน, zsh เริ่มต้นในโหมดแทรกอยู่แล้ว
baldrs

0

ด้านล่างนี้จะตั้งขึ้นกับคุณเคอร์เซอร์แก้ไขและพรอมต์โหมดการแสดงที่คุณอยู่ใน. คุณสามารถเปลี่ยนDEFAULT_VI_MODEไปอย่างใดอย่างหนึ่งหรือviins vicmdเพียงวางด้านล่างลงในรายการสด.zshrcเพื่อเริ่มต้น:

# Prefer vi shortcuts
bindkey -v
DEFAULT_VI_MODE=viins
KEYTIMEOUT=1

__set_cursor() {
    local style
    case $1 in
        reset) style=0;; # The terminal emulator's default
        blink-block) style=1;;
        block) style=2;;
        blink-underline) style=3;;
        underline) style=4;;
        blink-vertical-line) style=5;;
        vertical-line) style=6;;
    esac

    [ $style -ge 0 ] && print -n -- "\e[${style} q"
}

# Set your desired cursors here...
__set_vi_mode_cursor() {
    case $KEYMAP in
        vicmd)
          __set_cursor block
          ;;
        main|viins)
          __set_cursor vertical-line
          ;;
    esac
}

__get_vi_mode() {
    local mode
    case $KEYMAP in
        vicmd)
          mode=NORMAL
          ;;
        main|viins)
          mode=INSERT
          ;;
    esac
    print -n -- $mode
}

zle-keymap-select() {
    __set_vi_mode_cursor
    zle reset-prompt
}

zle-line-init() {
    zle -K $DEFAULT_VI_MODE
}

zle -N zle-line-init
zle -N zle-keymap-select

# Optional: allows you to open the in-progress command inside of $EDITOR
autoload -Uz edit-command-line
bindkey -M vicmd 'v' edit-command-line
zle -N edit-command-line

# PROMPT_SUBST enables functions and variables to re-run everytime the prompt
# is rendered
setopt PROMPT_SUBST

# Single quotes are important so that function is not run immediately and saved
# in the variable
RPROMPT='$(__get_vi_mode)'

หมายเหตุ: ฉันทดสอบเฉพาะใน Terminal.app (2.7.3) บน MacOS (10.12.6) ด้วย zsh (5.3.1) นอกจากนี้หากคุณเคยเพิ่มedit-command-lineโหมดจะถูกตั้งค่าอย่างถูกต้องเช่นกัน

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