Làm thế nào để ràng buộc C- [cho thật?


10

C-[tương đương với phím thoát trên bàn phím tiếng Anh của Hoa Kỳ, do đó, bất kỳ nỗ lực ràng buộc nào cũng sẽ gây rối M-hành vi.

Emacs dường như không gặp khó khăn gì trong việc phân biệt <escape>C-[tách biệt trong các khung GUI. Sau đây hoạt động tốt và các ràng buộc bắt đầu M-vẫn còn hoạt động:

(global-set-key (kbd "<escape>") (lambda () (interactive) (message "<escape>")))

Tuy nhiên, nếu tôi ràng buộc

(global-set-key (kbd "C-[") (lambda () (interactive) (message "C-[")))

đột nhiên emacs phát điên và ràng buộc như M-xphá vỡ. Hơn nữa, nhấn C-[từ chối để kích hoạt lambda bị ràng buộc. Thật thú vị, C-x @ c [(áp dụng điều khiển sửa đổi cho khung mở) vẫn nói C-[ is undefined.

Có cách nào để ràng buộc một cái gì đó C-[mà không phá vỡ emacs?

Câu trả lời:


7

Bạn thực sự không thể thay đổi C-[ràng buộc ở bản đồ cấp người dùng, như bạn sẽ làm với global-set-key. Tuy nhiên, bạn có thể thay đổi nó như một sự kiện bàn phím trước khi nó đạt đến các keymap đó. Bạn có thể nói ví dụ:

(define-key input-decode-map 
    (kbd "C-[") 
    [control-bracketleft])

và sau đó sử dụng [control-bracketleft]trong keymap của bạn. Khá đơn giản phải không?

Giám đốc cắt

Thật không may, nó không đơn giản và giải pháp này đòi hỏi một số điều chỉnh, sẽ có vẻ rất đau đớn. Mày đã được cảnh báo. Nhưng trước tiên hãy xem tại sao bản đồ cấp người dùng không thể trả lời câu hỏi. Trong phần sau đây, tôi tham khảo hướng dẫn sử dụng Emacs Lisp cho emacs 26.1 khi tôi nói "nhìn thấy gì đó" mà không chính xác hơn.

C-[được hiểu ở giai đoạn rất sớm là ký tự điều khiển ASCII ESC(xem 21.7.1 - Sự kiện bàn phím ). Mã này được trải đều tất cả các vị trí khác làm tiền tố cho các chuỗi dài hơn. Có một lý do cho điều đó: ESCthực sự là tiền tố meta (xem meta-prefix-char) và tất cả các ràng buộc đọc M-một cái gì đó sẽ chuyển thành một chuỗi bắt đầu bằng ESC. Do đó, thay đổi bản đồ toàn cầu sẽ không đủ: trước tiên bạn cần thay đổi meta-prefix-char, sau đó sắp xếp lại bản đồ ESCmới của bạn meta-prefix-chartrong mỗi bản đồ sử dụng M-trước khi bạn có thể lập bản đồ một cách an toàn C-[.

Được rồi, tất nhiên: hãy sử dụng input-decode-map. Có một vài bản đồ tương tự mà chúng ta có thể bị cám dỗ để sử dụng (xem phần 21.8.3 và 22,14), nhưng hãy kiên trì với bản đồ này. Và tốt ... điều này hoạt động! Bạn đã xong chưa?

Thật ra, không, câu chuyện không kết thúc ở đây. Điều này hoạt động ... miễn là bạn đang sử dụng một hệ thống cửa sổ. Nếu do xui xẻo, bạn bị bỏ tù trong bảng điều khiển linux trong trạng thái khẩn cấp, bạn sẽ nhận ra tình huống đã trở nên kịch tính như thế nào: các phím mũi tên Home, và tất nhiên là M-các ràng buộc, tất cả đều là rác. Tại sao? Bởi vì khi thiết bị đầu cuối nói ESC(điều này thực hiện khi bạn nhập C-[), nó thực sự có nghĩa ESC và bắt đầu một chuỗi cùng loại mà nó sử dụng để truyền các ký tự không phải ASCII.

Quan sát thảm họa, bạn có thể xem xét nó là khôn ngoan để bảo vệ input-decode-mapsửa đổi ở trên theo cách nó chỉ kích hoạt trong trường hợp hệ thống cửa sổ đang điều khiển bàn phím:

(let ((frame (framep (selected-frame))))
  (or (eq  t  frame)
      (eq 'pc frame)

      (define-key input-decode-map 
                  (kbd "C-[") 
                  [control-bracketleft])
     )))

Thiết bị đầu cuối sau đó hoạt động như trước đây.

Bây giờ, chúng ta có thể đối phó với các C-[thiết bị đầu cuối? Trên thực tế, vâng, chúng tôi có thể, trên bảng điều khiển linux cũng như trên các trình giả lập thiết bị đầu cuối khác mà tôi có thể chơi với. Nhưng điều đó làm cho câu chuyện trở nên khá dài, khi các nhân vật mới bước vào cảnh. Đối với nó không còn là emacs một mình: thiết bị đầu cuối bây giờ có vai trò trung tâm.

Chúng ta hãy lắng nghe những gì giao diện điều khiển linux nói. Nhập C-vtrước một số phím để nghe rõ. C-[ESC; như vậy là Esc. Mũi tên lên có vẻ như ESC [ A, trong khi M-aESC A. Hmm ... Có vẻ như chu vi khóa meta này trong emacs phải không? Dù sao.

Trừ khi chúng ta đã sẵn sàng để chơi một số thủ thuật dựa trên thời gian trôi qua giữa các sự kiện nhân vật (mà bằng cách này sẽ không phân biệt Esctừ C-[), có vẻ như chúng ta đã không có lựa chọn nào khác để nói với giao diện điều khiển những gì chúng ta thực sự không có ý nghĩa ESCkhi chúng ta gõ C-[. Hơn nữa, nó xuất hiện khá sớm C-[không phải là vấn đề duy nhất với mã thiết bị đầu cuối chứng khoán: phần lớn công cụ sửa đổi hầu hết thời gian bị xóa thông tin truyền đi. Chúng ta cần tùy chỉnh thiết bị đầu cuối vì lý do tương tự chúng ta tùy chỉnh emacs: nó sẽ thực tế hơn nhiều nếu chúng ta làm như vậy.

Tại thời điểm này, bạn sẽ dám nhìn sâu vào mắt tài liệu của thiết bị đầu cuối của bạn: trang man loadkeys(1)cho bảng điều khiển linux, cho xterm xterm(1)trong phần Ràng buộc khóa tùy chỉnhbất cứ điều gì tôi không biết cho các thiết bị đầu cuối khác. Trong KDE konsole, bạn có thể xác định bản dịch tùy chỉnh trong Cài đặt / Chỉnh sửa hồ sơ hiện tại ... rồi Bàn phím . Đây là một đoạn trích từ ~/.local/share/konsole/Test.keytab sau khi chơi với hộp thoại sau này:

key [+Ctrl+AnyModifier : "\EO*["

Khi bạn đã gửi thiết bị đầu cuối ESC O 5 [cho C-[(như trong cấu hình trên), bạn có thể quay lại emacs. Tất nhiên, bạn chưa hoàn thành.

Để hướng dẫn emacs phương ngữ mà một thiết bị đầu cuối đã sử dụng, bạn có thể điều chỉnh input-decode-map. Vâng, đây là một cách tình cờ, chính cái mà chúng ta đã sửa đổi ở đầu câu chuyện này, và đây chính là cái term/xterm.elchạm vào khi xterm có liên quan. Một nơi tốt để điều chỉnh là tty-setup-hook(xem phần 40.1.3):

(add-hook 'tty-setup-hook 
   (lambda ()
    (let ((term (getenv "TERM")))
      (cond 
        (;; xterm-function-map not in doc, but in term/xterm.el
         (boundp 'xterm-function-map) 
         (map-my-term-codes xterm-function-map))

        ((equal term "linux")
         (map-my-term-codes input-decode-map))
        )
      )))

Lưu ý rằng móc này chỉ chạy nếu bạn đang ở trong một thiết bị đầu cuối. Vì vậy, bạn không thể chèn vào đây mã khởi tạo hệ thống cửa sổ. Đây là chức năng dịch của chính nó:

(defun map-my-term-codes (map)
      (define-key map (kbd "M-O 5 [") 
                      [control-bracketleft])
      )

Và sau đó bạn có thể nghỉ ngơi: đó là kết thúc của hành trình. Tất nhiên, nếu bạn không quan tâm đến thiết bị đầu cuối, sẽ nhanh chóng vì bạn sẽ bỏ qua tất cả các phần đau đớn. Nhưng bạn sẽ thừa nhận nó cũng không đầy đủ.

Hai lưu ý cuối cùng:

  • Tôi chọn ESC O 5 [C-[. Đây chỉ là một ví dụ: Tôi sẽ không giả vờ rằng đó là một lựa chọn tốt . Chỉ có 5 phần, có nghĩa là C-, dường như tuân theo một số loại quy ước được thiết lập

  • Cấu hình bảng điều khiển linux để lại mùi vị xấu: dường như không thể thực hiện liên kết mà không sử dụng biểu tượng trung gian hiện có và những thứ tôi cần sẽ không tồn tại . Tôi sử dụng các ký hiệu trong phạm vi F21- F246như trong hầu hết các ví dụ trên internet, nhưng nó không thỏa mãn lắm. Nó ổn đối với một vài ràng buộc không liên quan, nhưng nó sẽ không phục vụ một lược đồ có hệ thống.

Biên tập

  • Tôi đã hoàn thành điều này với Esctrường hợp - có tính cách riêng - trong một bài đăng khác: Cách xóa các ràng buộc với khóa tiền tố ESC
  • đây là một phần của cấu hình để cung cấp loadkeyscho. Tôi đặt cái này vào /root/custom.kmap và tải nó khi tôi cần (rất hiếm). Cấu hình thực tế của tôi cũng ánh xạ các mũi tên và các tổ hợp sửa đổi khác nhau, nhưng khá dài, sự lựa chọn các ký hiệu và trình tự là đáng nghi ngờ, và tôi không chắc mã phím cho bàn phím của tôi sẽ khớp với bàn phím của tôi. Vì vậy, hãy giữ nó ở mức đúng hạn: đây không phải là một minh họa.

    keymaps 0-127
    
    # http://tldp.org/HOWTO/Keyboard-and-Console-HOWTO-15.html
    # web+man:keymaps
    # web+man:loadkeys
    
    # escape
    keycode  1  = F100
        alt keycode  1 = Escape # keep the Escape behavior somewhere          
    
    # keycode  26 = bracketleft
        control keycode 26 = F115 # Control_bracketleft does not exist          
    
    string F100     = "\033OO" # map this to [escape] in map-my-term-codes
    string F115     = "\033O5["
    

1
Cảm ơn, đó là một câu trả lời tuyệt vời. Nhưng chắc chắn ngay cả một câu trả lời tuyệt vời như thế này chắc chắn không cần phải được đưa lên đầu trang 34 lần. Mỗi vết sưng có một chi phí nhỏ được cộng đồng chia sẻ: kiểm tra thư rác, xem có nội dung mới thú vị nào không, v.v. Có lẽ bạn có thể nhóm các cải tiến nhỏ lại với nhau không? Hoặc chỉ gắn bó với những gì bạn có. Nói từ kinh nghiệm, không có bài viết nào hoàn hảo, đến một lúc nào đó bạn phải tiếp tục.
Gilles 'SO- ngừng trở nên xấu xa'

@Gilles Hiểu rồi, và xin lỗi vì điều đó. Tôi đã không biết có một số vấn đề điều chỉnh điều này theo ý muốn.
Champignac

0

Giải pháp sau đây là một chút ít, nhưng dường như hoạt động:

Hãy ~/.xbindkeysrcchứa những điều sau đây:

"xvkbd -xsendevent -text '\[Control_L]\[F13]'"
  m:0x14 + c:34

"xvkbd -xsendevent -text '\[Control_L]\[F14]'"
  m:0x14 + c:35

Bây giờ xbindkeyssẽ dịch C-[sang C-<f13>C-]sang C-<f14>, vì vậy chúng có thể được ràng buộc trong emacs một cách tự do. Bạn có thể sẽ muốn liên kết abort-recursive-editvới một cái gì đó khác hơn C-], ví dụ , C-S-g.

Nhược điểm là bây giờ C-[bị hỏng trong mọi ứng dụng ngoại trừ Emacs, có thể được sửa bằng cách thêm một số logic để kiểm tra xem tổ hợp phím có được gửi đến emacs không ...


FWIW, tôi không nghĩ có gì đặc biệt C-].
Malabarba

Vâng, tôi cũng vậy, nhưng vì một số lý do kỳ lạ, C-]ràng buộc của tôi đã ngừng hoạt động sau khi tôi kích hoạt Xbindkeys, vì vậy tôi cũng bật lại cái đó.
Kristóf Marussy
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.