зробити мій режим швидкого показу zsh у режимі vi


44

Я використовую bindkey -v(для башерів, set -o viя думаю, що це працює і в zsh) або в режимі vi (m). але це клопочеться про те, що я не маю жодної візуальної підказки, щоб сказати мені, чи я перебуваю в режимі вставки або режимі команд. Хтось знає, як я можу зробити своє швидке відображення режиму?

Відповіді:


25

Я знайшов це через SU . Ось основний приклад, хоча я все ще налаштовую його для себе:

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

Я б пояснив це, за винятком того, що я ще цього не розумію


1
Я спробував такий підхід, але знайшов одне питання. Якщо ви робите щось на кшталт роботи CTRL+Cв режимі командування vi, підказка буде скинуто, але вкажіть, що ви знаходитесь в командному режимі, коли ви дійсно перебуваєте в режимі вставки. zle-line-initзавжди повинен змінювати індикатор, щоб вставити режим. Чомусь $KEYMAPне оновлюється належним чином, коли викликається zle-line-init.
Патрік

2
zle reset-promptбуде видалено 1 (або більше) рядків над підказкою (якщо ваш запит є багаторядковим) при перемальовуванні :( Це для мене
показовий проміжок

@ PawełGościcki це здається проблемою, коли у вас є два або більше рядків PS1.
Метафокс

@Metaphox Я знаю, що тому я сказав "(якщо ваш запит є багаторядковим)". Будь-яке виправлення для цього?
Paweł Gościcki

@ PawełGościcki aww вибачте, що я якось пропустив слова в дужках, шкідлива звичка. Ні, я не знайшов цього виправлення. На якій платформі ви знаходитесь? Цікаво, чи це специфічно для ОС X
Метафокс

18

Ви вже знайшли, zle-keymap-selectщо виконується, коли режим змінюється. Ви можете використовувати його, щоб встановити якийсь інший візуальний індикатор, крім підказки, залежно від того, що підтримує ваш термінал (і, звичайно, ваш смак у індикаторі режиму).

Існує стандартна можливість terminfo змінити форму курсору. Однак деякі термінали відображають однаковий курсор в обох режимах. Поняття Xterm про менш видимий курсор полягає в тому, щоб він моргнув (і це потрібно активувати за -bcдопомогою аргументу або cursorBlinkресурсу командного рядка ).

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

З деякими терміналами ви також можете змінити колір курсору за допомогою print -n '\e]12;pink\a'(за назвою кольору) або print -n '\e]12;#abcdef\a'(за специфікацією RGB). Ці послідовності описані в документації xterm, у ctlseqsфайлі; сучасні емулятори терміналів зазвичай емулюють xterm, хоча вони можуть не підтримувати всі його функції.


З якої - то причини , я отримую mainза KEYMAPзамість viins, не знаю , чому.
Graeme

1
@Graeme main- псевдонім для viinsабо emacsзалежно від того, вважав zsh, коли улюблений редактор був vi чи ні під час його запуску. Я думав, що це використовуватиметься viinsпри перемиканні режиму назад vicmd, але здається, що він використовує mainзамість цього. Оновлено.
Жил 'ТАК - перестань бути злим'

1
Вам все одно потрібно подвоїтись zle-line-init(або будь-яка інша альтернатива), оскільки zle-keymap-selectне дзвонить, якщо натиснути Enter, змінить карту клавіш.
Graeme

9

Для людей, які мають проблеми із використанням функції "reset-prompt" за допомогою рядкових підказок, це спрацювало для мене: http://zeitlens.com/posts/2014-06-29-howto-zsh-vi-style.html У поєднанні з https: // stackoverflow.com/questions/3622943/zsh-vi-mode-status-line Я закінчила робити:

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

ви можете спробувати VimMode


4
Я сподівався на щось трохи менш посилання і трохи більш пояснювальне. Мені подобається знати, як все працює.
ксенотеррацид

1
Насправді це все є. Подивіться у коментарях функції та те, як вони пов'язані з подіями зміни режиму.
Мартін

5

Це те, що я використовую для зміни курсору між "Блокувати" та "Промінь" у zsh:

(Тестували за допомогою Termite , gnome-terminal і mate-terminal )

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

Це буде працювати лише на терміналах та емуляторах терміналів, які розуміють DECSCUSR.
JdeBP

1
Мені подобається це. Я переживаю, що запис у preexec може взаємодіяти з іншими звичаями, тому я трохи змінив його, щоб використовуватись add-zsh-hookтак: gist.github.com/MatrixManAtYrService/…
MatrixManAtYrService

4

Ще одне рішення для зміни форми курсору між I-променем та блоком (для підкреслення, використання \033[4 q). Додайте це до свого ~/.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

Змінено з https://bbs.archlinux.org/viewtopic.php?id=95078 . Випробуваний у гномному терміналі 3.22.


Оновлення

Ще одне рішення зміни форми курсору можна знайти тут . Цей, мабуть, працює для iTerm2, що я не маю коштів для тестування, але додаю його сюди, якщо він корисний для когось іншого. Остаточним доповненням до вашого ~/.zshrcбуде

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
Я підтвердив, що оновлений сценарій для iTerm2 справді працював.
Джейсон Денні

Перший скрипт працюватиме лише на терміналах та емуляторах терміналів, які розуміють DECSCUSR.
JdeBP

Це дійсно елегантне рішення, яке не захаращує мою оболонку
tsturzl

3

Зараз я використовую тему Zsh з Bullet Train . Наслідуючи приклад відповіді Себастьяна Бласка , я завершив опис коду

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

Це змінить лише дефолт $ на букви N в звичайний режим, а я на режим вставки.

Це зображення є прикладом, коли в звичайному режимі натискаю Ctrl+ C:

введіть тут опис зображення


2

Ось ще одна версія, заснована на публікації Себастьяна Бласка . Це повинно було бути максимально ненав'язливим, оскільки всі інші рішення, які я міг знайти, використовували додаткові рядки, статус праворуч або додані символи.

Це просто змінює колір $від білого до червоного, коли ввімкнено звичайний режим. Відредагуйте підказку на свій смак

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

2

Версія для oh-my-zshкористувачів

Тут є плагін для oh-my-zshвиклику, vi-modeякий можна знайти тут:

robbyrussell / oh-my-zsh / plugins / vi-mode

Я використовую Antigen для управління своїми плагінами, тому включення його було таким же простим, як додавання цього до мого .zshrc:

antigen bundle vi-mode

1

ЗШ-ВІМ-режим плагін здатний показувати індикатор для вставки, команди пошуку, заміни і візуальних режимів. Він використовує основну техніку інших відповідей для підключення до різних гачків ZLE (zle-keymap-select, zle-isearch-update тощо). Він перевіряє [[ $ZLE_STATE = *overwrite* ]]режим заміни. Він перевіряє, $REGION_ACTIVEщоб виявити візуальний режим.

Логіка ускладнюється деякими химерностями того, як ZSH справляє події під час виходу з режиму пошуку.

Ще одна приємна особливість модуля - це можливість зміни форми та кольору курсора залежно від режиму. Наприклад, ви можете використовувати вертикальну смугу в режимі INSERT, а миготливе підкреслення в режимі ПОШУК.


Цей плагін чудовий.
jdhao
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.