buat mode tayangan cepat zsh saya dalam mode vi


44

Saya menggunakan bindkey -v(untuk bash-ers set -o visaya pikir itu berfungsi dalam mode zsh juga) atau vi (m). tetapi itu menggangguku bahwa saya tidak memiliki isyarat visual untuk memberi tahu saya apakah saya dalam mode insert atau mode perintah. Adakah yang tahu bagaimana saya bisa membuat prompt saya menampilkan mode?

Jawaban:


25

Saya menemukan ini melalui SU . Inilah contoh dasar, meskipun saya masih mengubahnya sendiri:

function 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

Saya akan menjelaskannya kecuali saya belum benar-benar memahaminya


1
Saya mencoba pendekatan ini tetapi menemukan satu masalah. Jika Anda melakukan sesuatu seperti CTRL+Csaat dalam mode vi-command, prompt akan mengatur ulang, tetapi tunjukkan Anda dalam mode perintah ketika Anda benar-benar dalam mode insert. zle-line-initharus selalu mengubah indikator untuk memasukkan mode. Untuk beberapa alasan $KEYMAPtidak diperbarui dengan benar ketika zle-line-init dipanggil.
Patrick

2
zle reset-promptakan menghapus 1 (atau lebih) baris di atas prompt (jika prompt Anda multiline) saat menggambar ulang :( Ini adalah showstopper untuk saya.
Paweł Gościcki

@ PawełGościcki tampaknya menjadi masalah ketika Anda memiliki dua baris PS1 atau lebih.
Metaphox

@Metaphox Saya tahu, itu sebabnya saya mengatakan "(jika prompt Anda multiline)". Adakah perbaikan untuk itu?
Paweł Gościcki

@ PawełGościcki aww maaf saya entah bagaimana melewatkan kata dalam tanda kurung, kebiasaan buruk. Tidak, saya tidak menemukan perbaikan untuk itu. Anda berada di platform apa? Bertanya-tanya apakah ini OS X khusus.
Metaphox

18

Anda sudah menemukan zle-keymap-selectyang dieksekusi setiap kali mode berubah. Anda dapat menggunakannya untuk mengatur beberapa indikator visual selain permintaan, tergantung pada apa yang didukung terminal Anda (dan selera Anda dalam tampilan indikator mode, tentu saja).

Ada kemampuan terminfo standar untuk mengubah bentuk kursor. Namun beberapa terminal menampilkan kursor yang sama di kedua mode. Gagasan Xterm tentang kursor yang kurang terlihat adalah membuatnya berkedip (dan ini harus diaktifkan dengan -bcargumen baris perintah atau cursorBlinksumber daya).

zle-keymap-select () {
  case $KEYMAP in
    vicmd) print -rn -- $terminfo[cvvis];; # block cursor
    viins|main) print -rn -- $terminfo[cnorm];; # less visible cursor
  esac
}

Dengan beberapa terminal, Anda juga dapat mengubah warna kursor dengan print -n '\e]12;pink\a'(berdasarkan nama warna) atau print -n '\e]12;#abcdef\a'(dengan spesifikasi RGB). Urutan ini dijelaskan dalam dokumentasi xterm, dalam ctlseqsfile; emulator terminal modern biasanya meniru xterm, meskipun mereka mungkin tidak mendukung semua fitur-fiturnya.


Untuk beberapa alasan saya mendapatkan alih main- KEYMAPalih viins, tidak yakin mengapa.
Graeme

1
@Graeme mainadalah alias untuk viinsatau emacstergantung pada apakah zsh mengira editor favorit Anda vi atau tidak ketika mulai. Saya pikir itu akan digunakan viinsketika beralih dari mode kembali vicmd, tetapi tampaknya itu menggunakan mainsebagai gantinya. Diperbarui.
Gilles 'SANGAT berhenti menjadi jahat'

1
Anda masih perlu menggandakan dengan zle-line-init(atau alternatif apa pun) karena zle-keymap-selecttidak dipanggil jika menekan masuk mengubah keymap.
Graeme

9

Untuk orang-orang yang memiliki masalah menggunakan reset-prompt dengan prompt multiline, ini bekerja untuk saya: http://zeitlens.com/posts/2014-06-29-howto-zsh-vi-style.html Dalam kombinasi dengan https: // stackoverflow.com/questions/3622943/zsh-vi-mode-status-line Saya akhirnya melakukan:

terminfo_down_sc=$terminfo[cud1]$terminfo[cuu1]$terminfo[sc]$terminfo[cud1]

function insert-mode () { echo "-- INSERT --" }
function normal-mode () { echo "-- NORMAL --" }

precmd () {
    # yes, I actually like to have a new line, then some stuff and then 
    # the input line
    print -rP "
[%D{%a, %d %b %Y, %H:%M:%S}] %n %{$fg[blue]%}%m%{$reset_color%}"

    # this is required for initial prompt and a problem I had with Ctrl+C or
    # Enter when in normal mode (a new line would come up in insert mode,
    # but normal mode would be indicated)
    PS1="%{$terminfo_down_sc$(insert-mode)$terminfo[rc]%}%~ $ "
}
function set-prompt () {
    case ${KEYMAP} in
      (vicmd)      VI_MODE="$(normal-mode)" ;;
      (main|viins) VI_MODE="$(insert-mode)" ;;
      (*)          VI_MODE="$(insert-mode)" ;;
    esac
    PS1="%{$terminfo_down_sc$VI_MODE$terminfo[rc]%}%~ $ "
}

function zle-line-init zle-keymap-select {
    set-prompt
    zle reset-prompt
}
preexec () { print -rn -- $terminfo[el]; }

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

5

Anda dapat mencoba VimMode


4
Saya berharap untuk sesuatu yang sedikit kurang linkish dan lebih jelas. Saya suka tahu cara kerja.
xenoterracide

1
Sebenarnya semuanya ada di sana. Lihatlah komentar fungsi dan bagaimana mereka terikat dengan peristiwa perubahan mode.
Martin

5

Inilah yang saya gunakan untuk mengubah kursor antara bentuk 'Blok' dan 'Balok' di zsh:

(Diuji dengan Rayap , terminal gnome , dan terminal pasangan )

# vim mode config
# ---------------

# Activate vim mode.
bindkey -v

# Remove mode switching delay.
KEYTIMEOUT=5

# Change cursor shape for different vi modes.
function zle-keymap-select {
  if [[ ${KEYMAP} == vicmd ]] ||
     [[ $1 = 'block' ]]; then
    echo -ne '\e[1 q'

  elif [[ ${KEYMAP} == main ]] ||
       [[ ${KEYMAP} == viins ]] ||
       [[ ${KEYMAP} = '' ]] ||
       [[ $1 = 'beam' ]]; then
    echo -ne '\e[5 q'
  fi
}
zle -N zle-keymap-select

# Use beam shape cursor on startup.
echo -ne '\e[5 q'

# Use beam shape cursor for each new prompt.
preexec() {
   echo -ne '\e[5 q'
}

Ini hanya akan bekerja pada terminal dan emulator terminal yang memahami DECSCUSR.
JdeBP

1
Saya suka ini. Saya khawatir bahwa menulis ke preexec dapat berinteraksi dengan penggunaan lain, jadi saya memodifikasinya sedikit untuk digunakan add-zsh-hookseperti: gist.github.com/MatrixManAtYrService/…
MatrixManAtYrService

4

Solusi lain untuk mengubah bentuk kursor antara balok-I dan balok (untuk garis bawah, gunakan \033[4 q). Tambahkan ini ke ~/.zshrc.

zle-keymap-select () {
if [ $KEYMAP = vicmd ]; then
    printf "\033[2 q"
else
    printf "\033[6 q"
fi
}
zle -N zle-keymap-select
zle-line-init () {
zle -K viins
printf "\033[6 q"
}
zle -N zle-line-init
bindkey -v

Dimodifikasi dari https://bbs.archlinux.org/viewtopic.php?id=95078 . Diuji di terminal gnome 3.22.


Memperbarui

Namun solusi lain untuk mengubah bentuk kursor dapat ditemukan di sini . Yang ini tampaknya berfungsi untuk iTerm2, yang saya tidak punya alat untuk menguji, tetapi menambahkannya di sini kalau-kalau itu berguna untuk orang lain. Tambahan terakhir untuk Anda ~/.zshrcadalah

function zle-keymap-select zle-line-init
{
    # change cursor shape in iTerm2
    case $KEYMAP in
        vicmd)      print -n -- "\E]50;CursorShape=0\C-G";;  # block cursor
        viins|main) print -n -- "\E]50;CursorShape=1\C-G";;  # line cursor
    esac

    zle reset-prompt
    zle -R
}

function zle-line-finish
{
    print -n -- "\E]50;CursorShape=0\C-G"  # block cursor
}

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

1
Saya mengkonfirmasi bahwa skrip yang diperbarui untuk iTerm2 memang berfungsi.
Jason Denney

Script pertama hanya akan bekerja pada terminal dan emulator terminal yang memahami DECSCUSR.
JdeBP

Ini adalah solusi yang sangat elegan yang tidak mengacaukan cangkang saya
tsturzl

3

Saat ini saya menggunakan tema Zsh with Bullet Train . Mengikuti contoh yang diberikan oleh jawaban Sebastian Blask , saya berakhir dengan kode di bawah

bindkey -v
KEYTIMEOUT=1

function zle-line-init zle-keymap-select {
    case ${KEYMAP} in
        (vicmd)      BULLETTRAIN_PROMPT_CHAR="N" ;;
        (main|viins) BULLETTRAIN_PROMPT_CHAR="I" ;;
        (*)          BULLETTRAIN_PROMPT_CHAR="I" ;;
    esac
    zle reset-prompt
}

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

Ini hanya akan mengubah de default $ ke huruf N ke mode normal dan I ke mode insert.

Gambar ini adalah contoh ketika dalam mode normal saya menekan Ctrl+ C:

masukkan deskripsi gambar di sini


2

Ini adalah versi lain, berdasarkan dari pos Sebastian Blask . Ini dimaksudkan agar tidak mengganggu sebanyak mungkin, karena semua solusi lain yang bisa saya temukan menggunakan garis tambahan, status di sebelah kanan, atau karakter tambahan.

Ini hanya mengubah warna $dari putih ke merah ketika mode normal diaktifkan. Edit prompt sesuai keinginan Anda

bindkey -v
function zle-line-init zle-keymap-select {
    case ${KEYMAP} in
        (vicmd)      PROMPT=$'%{\e[0;32m%}%~%{\e[0m%} %{\e[0;31m%}$%{\e[0m%} ' ;;
        (main|viins) PROMPT=$'%{\e[0;32m%}%~%{\e[0m%} $ ' ;;
        (*)          PROMPT=$'%{\e[0;32m%}%~%{\e[0m%} $ ' ;;
    esac
    zle reset-prompt
}

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


1

The zsh-vim-mode Plugin mampu menunjukkan indikator untuk insert, perintah, pencarian, mengganti, dan mode visual. Ia menggunakan teknik dasar dari jawaban lain untuk menghubungkan ke berbagai kait ZLE (zle-keymap-select, zle-isearch-update, dll.). Ini memeriksa [[ $ZLE_STATE = *overwrite* ]]mode ganti. Ia memeriksa $REGION_ACTIVEuntuk mengidentifikasi mode visual.

Logikanya diperumit oleh beberapa keanehan tentang bagaimana ZSH memecat peristiwa ketika meninggalkan mode pencarian.

Fitur bagus lainnya dari modul ini adalah kemampuan untuk mengubah bentuk dan warna kursor berdasarkan mode. Misalnya, Anda dapat menggunakan bilah vertikal dalam mode INSERT dan garis bawah yang berkedip dalam mode SEARCH.


Plugin ini bagus.
jdhao
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.