En el modo bash vi, asigne jk para salir del modo insertar

11

Estoy usando una nueva instalación de ubuntu 16.04, con el shell bash. Hay dos cosas que quiero hacer:

  1. Configure el modo vi para que pueda tener movimientos similares a vim desde la terminal
  2. salir del modo de inserción escribiendo jk

Leí en otra publicación cómo se puede hacer esto zsh, ¿cómo puedo hacerlo bash?

tl; dr

poner bind '"jk":vi-movement-mode'en su .bashrcarchivo después set -o vi:)

server@thinkpad:~$ tail -n 2 .bashrc
set -o vi
bind '"jk":vi-movement-mode'

Consulte la respuesta de @ grochmal para obtener una explicación más detallada.

mbigras
fuente
1
¿Qué quieres decir con reasignar a jk? ¿Es esa una tecla especial en tu teclado?
Stephen Harris
ver edición
mbigras
Por primera vez, .bashrcgeneralmente se invoca en cada shell (por ejemplo, si se desvanece vi) pero .bash_profilesolo se invoca en shells de inicio de sesión. Entonces .bashrces el lugar adecuado para set -o vi. No tengo una respuesta para su segunda pregunta revisada :-(
Stephen Harris
¿Cómo estás empezando tu bash shell? Aquí hay una buena explicación de la diferencia entre .bashrc y .bash_profile
the_velour_fog
set -o vientra .bashrc, vea ¿Por qué no funciona mi ~ / .bash_profile?
Gilles 'SO- deja de ser malvado'

Respuestas:

10

TL; DR

Bash tiene una funcionalidad similar a zsh'es bindkeya través bind, pero no tener varios vimodos como zsh. Después de set -o vique puedas hacer:

bind '"jk":vi-movement-mode'

que es el equivalente de zsh'sbindkey -M <all vi modes> jk vi-movement-mode

Las vi-movement-modefunciones provienen de inputrc(ver /etc/inputrcuna lista de ellas).

Texto completo

Como Stephen Harris señala en su comentario:

  • .bashrces llamado por bashsiempre (y notablemente no por otros shells).

  • .bash_profile solo se llama en shells de inicio de sesión (y nuevamente, solo bash).

Varias distribuciones vienen con un .bash_profileesqueleto que se ve de la siguiente manera:

# ~/.bash_profile
[[ -f ~/.bashrc ]] && . ~/.bashrc

Que es un buen contenido .bash_profileya que simplemente puedes olvidar que existe.

Ahora, para mapear jk a Escla sesión de shell, que no es realmente posible. Cuando tu lo hagas:

inoremap jk <esc>

En Vim, después de escribir j , Vim sabe que debe esperar un poco para ver si escribe a kcontinuación y debe invocar la asignación (o que escriba otra tecla y la asignación no debe activarse). Como anexo, esto se controla :set timeoutlen=<miliseconds>en Vim (ver :h timeoutlen).

Varios shell o X11 no tienen ese control de tiempo de espera y no permiten asignaciones de caracteres múltiples. Solo se permite la asignación de una sola clave (pero consulte las notas de soporte a continuación).

set -o vi

No lee .vimrc, solo imita algunas combinaciones de teclas vi(ni siquiera vim) que se pueden usar en el shell. Lo mismo se puede decir sobre-o emacs , no viene con todo el poder de emacs.


soporte zsh

zshen realidad admite el tiempo de espera del mapa. Y se puede utilizar el siguiente para asignar jka <esc>:

bindkey -v  # instead of set -o vi
bindkey -e jk \\e

(Eso tendrá que ir a ~/.zshrc no ~/.bashrc)

Sin embargo, desaconsejo esto. Yo uso vimy la zshmayoría de las veces. Tengo inoremap jk <esc>en mi vimrce intenté usar la bindkeycombinación anterior. zshespera demasiado tiempo para imprimir jcuando lo uso, y eso me molestó mucho.


apoyo bash

bashSoportes readline bind. Creo que bashse puede compilar sin, readilnepor lo tanto, puede haber algunos sistemas raros que tienen bash que no son compatibles bind(esté atento). Para asignar jka <esc>en la bashque tiene que hacer:

set -o vi
bind '"jk":"\e"'

(sí, es un doble nivel de cita, es necesario)

Nuevamente, esto hace que escribir sea jbastante molesto. Pero de alguna manera menos molesto que la zshsolución en mi máquina (probablemente el tiempo de espera predeterminado es más corto).


Solución alternativa (para shells que no sean bash y no zsh)

La razón para reasignar la Esctecla es que se encuentra bastante lejos en el teclado, y escribirla lleva tiempo. Un truco que se puede pedir prestado a los emacschicos es reasignar, CapsLockya que de todos modos es una clave inútil. emacschicos lo reasignan Ctrlpero lo haremos de nuevo Esc.

Usemos xev -event keyboardpara verificar el código clave de CapsLock:

KeyPress event, serial 25, synthetic NO, window 0x1c00001,
    root 0x496, subw 0x0, time 8609026, (764,557), root:(765,576),
    state 0x0, keycode 66 (keysym 0xffe5, Caps_Lock), same_screen YES,
    XLookupString gives 0 bytes: 
    XmbLookupString gives 0 bytes: 
    XFilterEvent returns: False

Y para verificar la función de Esc:

KeyPress event, serial 25, synthetic NO, window 0x1c00001,
    root 0x496, subw 0x0, time 9488531, (571,525), root:(572,544),
    state 0x0, keycode 9 (keysym 0xff1b, Escape), same_screen YES,
    XLookupString gives 1 bytes: (1b) "
    XmbLookupString gives 1 bytes: (1b) "
    XFilterEvent returns: False

Muy bien, CapsLockes el código clave 66 y Escsu función se llama "Escape". Ahora podemos hacer:

# diable caps lock
xmodmap -e "remove lock = Caps_Lock"
# make an Esc key from the keycode 66
xmodmap -e "keycode 66 = Escape"

Lo anterior debe hacerse en este orden. Ahora cada vez que golpeas CapsLockfunciona como una Esctecla.


La parte difícil es dónde configurar esto. Un archivo ~/.Xmodmapcon el contenido:

remove lock = Caps_Lock
keycode 66 = Escape

Debería ser respetada por la mayoría de las distribuciones (en realidad, los administradores de pantallas, pero digo distros por simplicidad), pero vi las que no respetan varios ~/X*archivos. Para tales distribuciones puedes probar algo como:

if [ "x" != "x$DISPLAY" ]; then
    xmodmap -e "remove lock = Caps_Lock"
    xmodmap -e "keycode 66 = Escape"
fi

En su .bashrc.

(En teoría, sería mejor ubicarlo, ~/.xinitrcpero si un administrador de pantallas no respeta .Xmodmap, definitivamente no lo respetará ~/.xnintrc).

Nota adicional: Esto sólo se vuelve a asignar CapsLocka Escuna sesión X11, por lo tanto, el mapa sólo se trabajan en emuladores de terminal. Los reales ttyno verán el mapa.

Referencias y lecturas adicionales:

grochmal
fuente
Gracias por la explicación detallada. ¿Estaría dispuesto a ilustrar el mismo proceso, excepto el mapeo en jklugar de CapsLock? Lo tengo configurado en mi máquina osx; sin embargo, no lo tengo para el resto del fin de semana y no puedo recordar cómo lo hice :)
mbigras
@mbigras - ¿Estás seguro de que lo hiciste en bash? Bash no tiene mapas ambiguos. Yo sé de una manera de hacerlo en zsh: bindkey -v; bindkey -s jk \\e. Pero eso es algo que va a volver y reprimir cuando se necesita jk, debido a que el temporizador no es configurable y que no tienen <leader>en zsh.
grochmal
Definitivamente lo hice zshy no bash, ¿ no es posible en bash?
mbigras
@mbigras - ¡Espera, me equivoqué! Leyendo man bashencontré bindque el trabajo es bastante similar al de zsh's bindkey. Actualizaré la respuesta. Ahí tienes, estoy usando zshdemasiado.
grochmal
2
@Jason - Hola, este es el Vi SE, aquí todos escriben una palabra TODAS LAS MAYÚSCULAS con: "escriba la palabra" <Esc> viwU :). No se necesita completar
grochmal
2

Gracias, por respuestas anteriores, uso esto en mi ~ / .zshrc para accesos directos similares a vi en mi terminal. Espero que ayude a alguien.

bindkey -v
bindkey 'jk' vi-cmd-mode
om2c0de
fuente
Vine aquí buscando una respuesta que funcione para vincular la tecla '^ G' para ingresar al "modo normal" en zsh habilitado para vi, y este es el único que funcionó.
Dalker