Làm cách nào tôi có thể làm cho chế độ vi của zsh hoạt động giống như chế độ vi của bash?


24

Tôi thực sự thích tốc độ chung của zsh, nhưng có hai điều gây khó chịu cho tôi.

  1. Tôi phải nhấn chờ một lát giữa đánh thoát và đánh chém để vào tìm kiếm lịch sử (nếu nó bị chém quá nhanh thì nó nói zsh: do you wish to see all 514 possibilities (172 lines))
  2. Sau khi vào chế độ chèn vì nhấn ahoặc A, tôi không thể lùi lại điểm mà tôi đã vào chế độ chèn.

Tôi biết rằng 2 giống như vi cổ điển, nhưng tôi thích phong cách vim hơn.


Nếu bất cứ ai đang gặp phải vấn đề rất khó chịu là thoát kép khiến bạn phải đánh ihai lần để quay lại chế độ chèn, tôi rất khuyến nghị cách khắc phục này !
cchamberlain 24/07/2015

Ngoài ra còn có một bản tóm tắt hay ở đây: dougblack.io/words/zsh-vi-mode.html
jackcogdill

Câu trả lời:


22

(1). Vì một số lý do, bindkey hành xử kỳ quặc khi nói đến "/": <esc>theo sau nhanh chóng /được hiểu là <esc-/>. (Tôi đã quan sát hành vi này vào một ngày khác; không chắc chắn nguyên nhân gây ra nó.) Tôi không biết đây là lỗi hay tính năng, và nếu đó là một tính năng nếu nó có thể bị vô hiệu hóa, nhưng bạn có thể làm việc xung quanh nó khá dễ dàng .

Tổ hợp phím này có thể bị ràng buộc _history-complete-older, tạo ra kết quả không mong muốn - bạn có thể sử dụng bindkey -Lđể xem nếu đây là trường hợp.

Ở bất cứ giá nào, nếu bạn không hy sinh ràng buộc thực tế <esc-/> (được nhấn với nhau, như một hợp âm), bạn có thể liên kết lại nó với lệnh tìm kiếm lịch sử vi-mode, để việc gõ <esc>tiếp theo /thực hiện tương tự với bất kỳ thao tác gõ nào tốc độ. =)

Vì điều này sẽ được coi là hợp âm, nên nó sẽ không có tác dụng khi lần đầu tiên vào chế độ lệnh vi, vì vậy chúng tôi sẽ phải đảm bảo điều đó xảy ra trước. Đầu tiên, bạn cần xác định một hàm; đặt nó ở đâu đó trong của bạn fpathnếu bạn sử dụng nó hoặc đặt nó trong .zshrc của bạn nếu không:

vi-search-fix() {
zle vi-cmd-mode
zle .vi-history-search-backward
}

Phần còn lại đi theo .zshrc của bạn theo một trong hai cách:

autoload vi-search-fix
zle -N vi-search-fix
bindkey -M viins '\e/' vi-search-fix

Nên đi là tốt.

(2). Bạn có thể sửa phím xóa lùi như sau:

`bindkey "^?" backward-delete-char`

Ngoài ra, nếu bạn muốn hành vi tương tự cho các lệnh kiểu vi khác:

bindkey "^W" backward-kill-word 
bindkey "^H" backward-delete-char      # Control-h also deletes the previous char
bindkey "^U" backward-kill-line            

Đó ^[/không phải là \e/, nhưng đó là cả hai cách hợp lệ để nói thoát. Sự thay đổi hoạt động hoàn hảo. Bây giờ tôi đang chơi với nó hoàn toàn hơn, có vẻ như chế độ vi của zsh rất tệ so với bash (hoặc ít nhất là không được cấu hình đầy đủ theo mặc định). Một ví dụ về điều này là việc nó đưa bạn vào chế độ chèn sau lịch sử tìm kiếm. Tôi phải quay lại chế độ lệnh để nhấn n để tìm mục tìm kiếm tiếp theo.
Chas. Owens

1
Chà, tôi không biết nếu bạn có bất kỳ ví dụ nào khác, nhưng cái bạn đề cập là lỗi của tôi chứ không phải của zsh. =) Điều gì đã xảy ra là tôi đã ràng buộc một lệnh biên tập chế độ vi-cmd trong chế độ chèn vi - lệnh này dự kiến ​​trình bao đã ở chế độ cmd và hành xử tương ứng. Chúng ta cần viết một lệnh biên tập trước tiên gọi lệnh "enter cmd mode", sau đó thực thi .vi-history-search-backward. Tôi sẽ viết nó và chỉnh sửa câu trả lời của tôi - kiểm tra lại sau hôm nay.
Marshall Eubanks

OK, tôi đã cập nhật câu trả lời của tôi. Hãy thử nó.
Marshall Eubanks

Liên quan đến (2), khi tôi thực hiện bindkey | grep <searchterm>bất kỳ điều khoản nào, tất cả chúng đều có tiền tố vi-. Tôi có cần thiết lập bindkeycác lệnh không có tiền tố vi-không?
adam_0

1
Cảm ơn bạn. Những hack này (và cả những wjv bên dưới nữa) làm cho chế độ vi của zsh chuyển từ không thể sử dụng thành tuyệt vời. Tôi đã tạo một tài khoản superuser để tôi có thể bình chọn cho bạn. :-)
ctrueden

14

Tôi chỉ đi đến câu hỏi (1).

Vấn đề của bạn là TỪ KHÓA. Tôi trích dẫn từ zshzle (1):

Khi ZLE đang đọc một lệnh từ thiết bị đầu cuối, nó có thể đọc một chuỗi được ràng buộc với một số lệnh và cũng là tiền tố của một chuỗi ràng buộc dài hơn. Trong trường hợp này, ZLE sẽ đợi một thời gian nhất định để xem nếu có nhiều ký tự được nhập và nếu không (hoặc chúng không khớp với bất kỳ chuỗi nào nữa), nó sẽ thực hiện liên kết. Thời gian chờ này được xác định bởi tham số KEYTIMEOUT; mặc định của nó là 0,4 giây. Không có thời gian chờ nếu chuỗi tiền tố không bị ràng buộc với lệnh.

0,4 giây đó là độ trễ bạn gặp phải sau khi nhấn ESC. Cách khắc phục là đặt KEYTIMEOUT xuống 0,01s trong một trong các tệp khởi động shell:

export KEYTIMEOUT=1

Thật không may, điều này có tác dụng kích thích: Những thứ khác bắt đầu sai

Đầu tiên, bây giờ có một vấn đề trong chế độ lệnh vi: Nhập ESC làm cho con trỏ bị treo, và sau đó bất kỳ ký tự nào bạn nhập tiếp theo sẽ bị nuốt. Điều này là do ESC không bị ràng buộc với bất cứ điều gì theo mặc định trong chế độ lệnh vi, tuy nhiên vẫn có các widget đa ký tự bắt đầu bằng ESC (phím con trỏ!). Vì vậy, khi bạn nhấn ESC, ZLE đợi nhân vật tiếp theo và sau đó tiêu thụ nó.

Cách khắc phục là liên kết ESC với một cái gì đó trong chế độ lệnh, do đó đảm bảo rằng thứ gì đó được chuyển đến ZLE sau $ KEYTIMEOUT centiseconds. Bây giờ chúng ta có thể giữ các ràng buộc bắt đầu với ESC trong chế độ lệnh mà không có các hiệu ứng xấu này. Tôi liên kết ESC với ký tự chuông mà tôi thấy thậm chí ít xâm phạm hơn so với tự chèn (và vỏ của tôi bị tắt tiếng):

bindkey -sM vicmd '^[' '^G'

Cập nhật 2017:

Kể từ đó, tôi đã tìm thấy một giải pháp tốt hơn để ràng buộc ESC - undefined-keywidget. Tôi không chắc liệu tiện ích này có sẵn trong zsh hay không khi tôi viết câu trả lời này.

bindkey -M vicmd '^[' undefined-key

Vấn đề tiếp theo: Theo mặc định, có một số tiện ích hai phím bắt đầu bằng ^ X ở chế độ chèn vi; những thứ này trở nên không sử dụng được nếu $ KEYTIMEOUT được đặt hoàn toàn. Những gì tôi làm là hủy liên kết ^ X ở chế độ chèn vi (theo mặc định là tự chèn); điều này cho phép các vật dụng hai phím đó tiếp tục hoạt động.

bindkey -rM viins '^X'

Bạn mất liên kết để tự chèn, nhưng bạn có thể liên kết nó với một cái gì đó khác tất nhiên. (Tôi không, vì tôi không có sử dụng cho nó.)

Vấn đề cuối cùng (tôi đã tìm thấy cho đến nay): Có một số tổ hợp phím mặc định còn lại mà chúng tôi "mất" do đặt $ KEYTIMEOUT xuống, để wit: những người bắt đầu với ESC ở chế độ chèn vi không phải là phím con trỏ. Cá nhân tôi bắt buộc họ bắt đầu với ^ X thay vào đó:

bindkey -M viins '^X,' _history-complete-newer \
                 '^X/' _history-complete-older \
                 '^X`' _bash_complete-word

Cập nhật 2018:

Hóa ra toàn bộ phần trên (sau Cập nhật 2017 2017) không nhất thiết phải có. Có thể đặt khóa META tương đương với ESC trong ánh xạ bàn phím bằng cách sử dụng:

bindkey -mv

Do đó, không thể hủy liên kết ^ X và truy cập các tổ hợp phím bắt đầu trong ESC bằng cách nhấn META làm người lãnh đạo thay thế (ALT hoặc OPT trên bàn phím hiện đại).

Nếu bạn có quyền truy cập vào cuốn sách Từ Bash đến Z Shell của Kiddle và cộng sự, thì sự tương đương của ESC và META trong các phím bấm được thảo luận trong thanh bên Chương 4 trên trang 78.


Cảm ơn bạn. Những hack này (và cả của marshaul ở trên nữa) làm cho chế độ vi của zsh đi từ không thể sử dụng đến tuyệt vời. Tôi đã tạo một tài khoản superuser để tôi có thể bình chọn cho bạn. :-)
ctrueden

1
Cảm ơn! Tôi thấy hơi lo lắng rằng, sau tất cả thời gian này, chúng ta vẫn cần những gì thực chất là một hack và một cách giải quyết để làm cho một chút cốt lõi của chức năng zsh có thể sử dụng được!
wjv 6/2/2015
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.