Як налаштувати vim режим zsh?


25

Гаразд, тому я нарешті зробив велику зміну. У своєму .zshenv я змінив редактор:

export EDITOR=vim

У мене є кілька питань, які є настільки незначними, що я не хотів починати окремі запитання до них. Ось вони:

  1. Як змусити zsh розрізняти режим вставки та режим команд, наприклад, у vim? Переважно, це змінює курсор від підкреслення до блоку, як in vim, але відображення тексту внизу також буде працювати.

  2. Як змусити його діяти більше як vim? Наприклад, я вважаю за краще, щоб він був у командному режимі за замовчуванням і не виходив з нього після однієї команди.


// Чи були у вас якісь дивні поведінки з редагуванням командного рядка? Я стикався з ~персонажем, який вставляється, коли натискаю 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 -} / (основні | viins) / - INSERT -}"
    RPS2 = $ RPS1
    zle reset-prompt
}
zle -N zle-line-init
zle -N zle-keymap-select

Де:

  • "RPS" означає "правильний рядок підказки" і визначає підказку, що з'являється в правій частині терміналу, а синтаксис $ {змінної / шаблон / заміна} - "розширення параметра", див. Http: // mywiki .wooledge.org / BashSheet # Параметр_Операції .

  • 'zle -N' призводить до встановлення користувачем віджетів 'zle-line-init' та 'zle-keymap-select' (для оболонок функцій з однаковими іменами), так що вони будуть викликані при ініціалізації редактора рядків а ключову карту змінено відповідно, див .: http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#SEC125 .

2. ) Я підозрюю, що для цього вам потрібно написати ще один zsh-віджет, надихайтеся першим із двох посилань на першу проблему.


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віджетом, безрезультатно. Змінив це, щоб відповідати тому, що надав Пауел та бінго!
Colin R

Спасибі! Це все ще не 100% бронезахисне - час від часу я відчуваю ситуацію, коли деякі рядки з мого попереднього результату видаляються - але це трапляється так рідко, що я просто ігнорую це.
Paweł Gościcki

1
RPROMPT2слід також встановити так, щоб стан відображався у рядках продовження. Також, використовуючи це, можливо, ви захочете зробити setopt transient_rpromptтак, щоб режими попередньо прийнятих рядків не відображалися.
qqx

Ще не вистачає однієї речі: якщо я переключусь у режим emacs ( bindkey -e), він все одно відображатиметься [INS].
Даніель

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 все одно починається у режимі вставки
лисини

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режим буде також встановлений правильно.

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