Bagaimana cara menyesuaikan mode vim zsh?

25

Ok, akhirnya saya membuat perubahan besar. Di .zshenv saya, saya mengubah EDITOR saya:

export EDITOR=vim

Ada beberapa pertanyaan yang saya miliki yang sangat kecil sehingga saya tidak ingin memulai pertanyaan terpisah untuk mereka. Di sini mereka:

  1. Bagaimana cara mendapatkan zsh untuk membedakan antara mode insert dan mode perintah seperti di vim? Lebih disukai ini akan mengubah kursor dari garis bawah ke blok seperti di vim, tetapi menampilkan teks di bagian bawah akan bekerja juga.

  2. Bagaimana saya membuatnya bertindak lebih seperti vim? Sebagai contoh, saya lebih suka dalam mode perintah secara default dan tidak keluar setelah satu perintah.

Jason Baker
sumber
//, Apakah Anda mendapatkan perilaku aneh dengan suntingan baris perintah? Saya telah menemukan ~karakter yang dimasukkan ketika saya menekan Deletetombol zsh. Saya mengajukan pertanyaan tentang hal ini di sini: superuser.com/questions/997593/...
Nathan Basanese

Jawaban:

25

1. ) (lihat http://zshwiki.org/home/examples/zlewidgets dan http://pthree.org/2009/03/28/add-vim-editing-mode-to-your-zsh-prompt/ ) :

fungsi 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

Dimana:

2. ) saya menduga Anda harus menulis zsh-widget lain untuk melakukan itu, dapatkan inspirasi dari tautan pertama dari dua untuk masalah pertama.

akira
sumber
22

solusi akira memiliki masalah berikut ketika menggunakan prompt multi-line: ketika beralih dari mode ins ke cmd, redraw prompt menyebabkan beberapa baris dihapus dari output sebelumnya (dan prompt baru ditampilkan beberapa baris di atas). Berapa banyak baris tergantung pada berapa banyak baris yang Anda miliki di prompt Anda.

Cara untuk menghadapinya adalah menggunakan zle-line-finish, tanpa menggunakannya zle reset-prompt. Sebuah contoh:

# 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

Dan kemudian Anda dapat menambahkannya ke prompt kanan Anda, misalnya:

RPROMPT='${vim_mode}'

Ini langsung dari posting blog saya tentang hal itu:

Paweł Gościcki
sumber
Jawaban ini harus mendapatkan banyak suara. Ini adalah pertama kalinya saya melihat solusi ini, dan ini berfungsi di mana yang lain tidak. Saya menghabiskan satu jam bermain-main dengan zle-line-initwidget tetapi tidak berhasil. Mengubahnya agar sesuai dengan apa yang disediakan Pawel dan bingo!
Colin R
Terima kasih! Itu masih tidak 100% anti peluru - dari waktu ke waktu saya mengalami situasi di mana beberapa baris dari output saya sebelumnya dihapus - tetapi itu terjadi sangat jarang sehingga saya mengabaikannya.
Paweł Gościcki
1
RPROMPT2harus diatur juga sehingga status ditampilkan dalam garis lanjutan. Juga, saat menggunakan ini, Anda mungkin ingin melakukannya setopt transient_rpromptagar mode untuk saluran yang diterima sebelumnya tidak ditampilkan.
qqx
Satu hal yang masih hilang: Jika saya beralih kembali ke mode emacs ( bindkey -e) masih muncul [INS].
Daniel
1
@ cheflo Anda dapat melihat versi pengaturan saya saat ini di sini: github.com/pjg/dotfiles/blob/master/.zshrc#L518-L584 - mungkin itu akan membantu Anda
Paweł Gościcki
5
zle-line-init() { zle -K vicmd; }
zle -N zle-line-init

dua baris ini memastikan itu dimulai dalam mode perintah

Ketenangan
sumber
Tidak berfungsi, zsh mulai dalam mode insert
baldrs
0

Di bawah ini akan mengatur Anda dengan kursor yang dimodifikasi dan prompt menampilkan mode yang Anda masuki. Anda dapat mengubah DEFAULT_VI_MODEsalah satu viinsatau vicmd. Cukup rekatkan di bawah ini ke dalam segar .zshrcuntuk memulai:

# 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)'

Catatan: Saya hanya menguji ini di Terminal.app (2.7.3) pada MacOS (10.12.6) dengan zsh (5.3.1). Juga, jika Anda pernah menambahkan edit-command-linemaka mode akan diatur dengan benar juga.

Casr
sumber