зробити мій режим швидкого показу 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.