Trong chế độ bash vi, ánh xạ jk để thoát chế độ chèn


11

Tôi đang sử dụng bản cài đặt mới của Ubuntu 16.04, với vỏ bash. Có hai điều mà tôi muốn làm:

  1. Thiết lập chế độ vi để tôi có thể có các chuyển động giống như vim từ thiết bị đầu cuối
  2. thoát chế độ chèn bằng cách gõ jk

Tôi đã đọc trong một bài viết khác làm thế nào điều này có thể được thực hiện với zsh, làm thế nào tôi có thể làm điều đó với bash?

tl; dr

đưa bind '"jk":vi-movement-mode'vào .bashrctập tin của bạn sau set -o vi:)

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

vui lòng xem câu trả lời của @ grochmal để được giải thích chi tiết hơn


1
Bạn có ý nghĩa gì khi ánh xạ lại jk? Đó có phải là một số phím đặc biệt trên bàn phím của bạn?
Stephen Harris

vui lòng xem chỉnh sửa
mbigras

Đối với lần đầu tiên của bạn, .bashrcthường được gọi trên mọi shell (ví dụ: nếu bạn thoát ra vi) nhưng .bash_profilechỉ được gọi trên shell đăng nhập. Vì vậy, .bashrclà nơi thích hợp cho set -o vi. Tôi không có câu trả lời cho câu hỏi thứ 2 sửa đổi của bạn :-(
Stephen Harris

Làm thế nào bạn bắt đầu vỏ bash của bạn? Dưới đây là một lời giải thích tốt về Sự khác biệt giữa .bashrc và .bash_profile
the_velour_fog

Câu trả lời:


10

TL; DR

Bash có chức năng tương tự như zshbindkeythông qua bind, nhưng nó không có nhiều vichế độ như zsh. Sau khi set -o vibạn có thể làm:

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

đó là tương đương với zsh'sbindkey -M <all vi modes> jk vi-movement-mode

Các vi-movement-modechức năng đến từ inputrc(xem /etc/inputrcdanh sách của chúng).

Toàn văn

Như Stephen Harris đã chỉ ra trong bình luận của mình:

  • .bashrcđược gọi bởi bashluôn luôn (và đáng chú ý là không phải bởi các shell khác).

  • .bash_profile chỉ được gọi trên shell đăng nhập (và một lần nữa, chỉ bash).

Một số distro đi kèm với một .bash_profilebộ xương trông như sau:

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

Đó là một nội dung tốt .bash_profilevì bạn có thể quên nó tồn tại.

Bây giờ, để ánh xạ jktới Esctrong phiên shell, điều đó thực sự không thể. Khi bạn làm:

inoremap jk <esc>

Trong Vim, sau khi bạn nhập j, Vim biết rằng bạn cần đợi một chút để xem bạn có nhập ktiếp không và nó sẽ gọi ánh xạ (hoặc bạn nhập khóa khác và ánh xạ không được kích hoạt). Là một phụ lục, điều này được kiểm soát bởi :set timeoutlen=<miliseconds>trong Vim (xem :h timeoutlen).

Một số shell hoặc X11 không có kiểm soát thời gian chờ như vậy và không cho phép ánh xạ nhiều ký tự. Chỉ cho phép ánh xạ một khóa duy nhất (Nhưng xem các ghi chú hỗ trợ bên dưới.).

set -o vi

Không đọc .vimrc, nó chỉ bắt chước một số tổ hợp phím vi(thậm chí không vim) có thể được sử dụng trong trình bao. Điều tương tự cũng có thể nói -o emacs, nó không đi kèm với toàn bộ sức mạnh của emacs.


hỗ trợ zsh

zshthực sự hỗ trợ thời gian chờ bản đồ. Và bạn có thể sử dụng như sau để ánh xạ jktới <esc>:

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

(Điều đó sẽ cần phải đi đến ~/.zshrckhông ~/.bashrc)

Tuy nhiên, tôi khuyên chống lại điều này. Tôi sử dụng vimzshhầu hết thời gian. Tôi có inoremap jk <esc>trong tôi vimrcvà tôi đã thử bằng cách sử dụng bindkeysự kết hợp trên. zshChờ đợi quá lâu để in jkhi sử dụng nó, và điều đó làm tôi khó chịu rất nhiều.


hỗ trợ bash

bashhỗ trợ readline bind. Tôi tin rằng bashcó thể được biên dịch mà không có readilnedo đó có thể có một số hệ thống hiếm có bash không hỗ trợ bind(cảnh giác). Để ánh xạ jkđến <esc>trong bashbạn cần làm:

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

(vâng, đó là một mức trích dẫn kép, nó là cần thiết)

Một lần nữa, điều này làm cho việc gõ jkhá khó chịu. Nhưng bằng cách nào đó ít gây phiền nhiễu hơn zshgiải pháp trên máy của tôi (có lẽ thời gian chờ mặc định ngắn hơn).


Giải pháp thay thế (cho các vỏ không bash và không zsh)

Lý do để ánh xạ lại Escphím là nó nằm khá xa trên bàn phím và việc gõ phím cần có thời gian. Một mẹo có thể mượn từ những emacskẻ đó là ánh xạ lại CapsLockvì dù sao nó cũng là một chìa khóa vô dụng. emacsCác bạn sắp xếp lại Ctrlnhưng chúng tôi sẽ sắp xếp lại Esc.

Hãy sử dụng xev -event keyboardđể kiểm tra mã khóa của 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

Và để kiểm tra chức năng của 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

Rất tốt, CapsLocklà mã khóa 66 và Escchức năng của nó được gọi là "Thoát". Bây giờ chúng ta có thể làm:

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

Trên đây phải được thực hiện theo thứ tự này. Bây giờ mỗi khi bạn nhấn CapsLocknó hoạt động như một Escphím.


Phần khó khăn là nơi để thiết lập này. Một tập tin ~/.Xmodmapcó nội dung:

remove lock = Caps_Lock
keycode 66 = Escape

Nên được hầu hết các distro tôn trọng (thực tế là các trình quản lý hiển thị, nhưng tôi đang nói các distro vì đơn giản), nhưng tôi đã thấy các distro không tôn trọng một số ~/X*tệp. Đối với các bản phân phối như vậy, bạn có thể thử một cái gì đó như:

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

Trong của bạn .bashrc.

(Về lý thuyết sẽ được đặt tốt hơn ~/.xinitrcnhưng nếu người quản lý hiển thị không tôn trọng .Xmodmapthì chắc chắn sẽ không tôn trọng ~/.xnintrc.)

Lưu ý thêm: Điều này chỉ CapsLocknhắc lại Esctrong phiên X11, do đó bản đồ sẽ chỉ hoạt động trong trình giả lập thiết bị đầu cuối. Thực tế ttysẽ không nhìn thấy bản đồ.

Tài liệu tham khảo và đọc thêm:


Cảm ơn vì lời giải thích chi tiết. Bạn có sẵn sàng minh họa quá trình tương tự ngoại trừ ánh xạ jkthay vì CapsLock? Tôi có nó được đặt trên máy osx của tôi; tuy nhiên, tôi không có nó cho đến cuối tuần và tôi không thể nhớ mình đã làm như thế nào :)
mbigras

@mbigras - Bạn có chắc là bạn đã làm điều đó trong bash? Bash không có bản đồ ambiguos. Tôi biết một cách để làm điều đó trong zsh: bindkey -v; bindkey -s jk \\e. Nhưng đó là thứ sẽ quay trở lại và cắn bạn trở lại khi bạn cần jk, bởi vì bộ đếm thời gian không thể cấu hình và bạn không có <leader>trong zsh.
hóa dầu

Tôi chắc chắn đã làm nó trong zshvà không bash, nó không thể trong bash?
mbigras

@mbigras - Đợi đã, tôi đã nhầm! Đọc man bashtôi thấy bindrằng công việc khá giống với zsh's bindkey. Tôi sẽ cập nhật câu trả lời. Có bạn đi, tôi đang sử dụng zshquá nhiều.
hóa dầu

2
@Jason - Này, đây là Vi SE, Ở đây mọi người đều viết một từ TẤT CẢ CAPS với: "gõ từ" <Esc> viwU :). Không cần hoàn thành
hóa học

2

Cảm ơn, đối với các câu trả lời trước, tôi sử dụng điều này trong ~ / .zshrc cho các phím tắt giống như vi trong thiết bị đầu cuối của tôi. Tôi hy vọng nó sẽ giúp được ai đó.

bindkey -v
bindkey 'jk' vi-cmd-mode

Tôi đến đây để tìm câu trả lời hoạt động để ràng buộc phím '^ G' để vào "chế độ bình thường" trong zsh kích hoạt vi và đây là cách duy nhất hoạt động.
Dalker
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.