จะผูก C- [จริงได้อย่างไร?


10

C-[เทียบเท่ากับปุ่มลัดบนแป้นพิมพ์ภาษาอังกฤษแบบสหรัฐอเมริกาดังนั้นความพยายามใด ๆ ที่จะผูกมันจะทำให้M-พฤติกรรมยุ่งเหยิง

Emacs ดูเหมือนจะไม่มีปัญหาในการบอก<escape>และC-[แยกในเฟรม GUI งานต่อไปนี้ทำงานได้ดีและมีผลผูกพันเริ่มต้นด้วยM-ยังคงทำงาน:

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

อย่างไรก็ตามถ้าฉันผูก

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

ทันใดนั้น emacs ก็บ้าคลั่งและมีผลผูกพันเหมือนM-xหยุดพัก ยิ่งไปกว่านั้นการกดC-[ปฏิเสธที่จะเหนี่ยวไกแลมบ์ดาที่ถูกผูกไว้ ที่น่าสนใจพอC-x @ c [(ใช้ควบคุมการปรับแต่งเพื่อวงเล็บเปิด) C-[ is undefinedยังกล่าวว่า

มีวิธีผูกมัดบางอย่างกับC-[โดยไม่ทำลาย emacs หรือไม่?

คำตอบ:


7

คุณไม่สามารถจริงๆเปลี่ยนผูกพันแผนที่ที่ผู้ใช้ระดับที่คุณจะทำอย่างไรกับC-[ global-set-keyอย่างไรก็ตามคุณสามารถเปลี่ยนเป็นเหตุการณ์แป้นพิมพ์ก่อนที่จะถึงปุ่มกดเหล่านั้น คุณสามารถพูดเช่น:

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

จากนั้นใช้[control-bracketleft]ในคีย์แมปของคุณ ค่อนข้างง่ายใช่มั้ย

ผู้อำนวยการคัต

น่าเสียดายที่มันไม่ง่ายอย่างนั้นและการแก้ปัญหานี้ต้องการการปรับแต่งบางอย่างซึ่งจะเจ็บปวดมาก คุณได้รับการเตือน แต่มาดูกันก่อนว่าทำไมแผนที่ระดับผู้ใช้ไม่สามารถตอบคำถามได้ ในต่อไปนี้ฉันดูคู่มือ Emacs Lisp สำหรับ emacs 26.1 เมื่อฉันพูดว่า "เห็นบางอย่าง" โดยไม่มีความแม่นยำมากขึ้น

C-[ถูกตีความตั้งแต่เริ่มแรกในฐานะตัวควบคุม ASCII ESC(ดู 21.7.1 - เหตุการณ์แป้นพิมพ์ ) รหัสนี้จะกระจายออกไปสถานที่อื่น ๆ ทั้งหมดเป็นคำนำหน้าสำหรับลำดับที่ยาวขึ้น มีเหตุผลที่เป็น: ESCเป็นจริงคำนำหน้าเมตา (ดูmeta-prefix-char) และผูกทุกสิ่งที่อ่าน M-สิ่งที่ESCจะแปลลำดับที่เริ่มต้นด้วย ดังนั้นการเปลี่ยนแผนที่โลกจะไม่พอ: คุณจำเป็นต้องมีการเปลี่ยนแปลงครั้งแรกmeta-prefix-charจากนั้นก็ให้ทำการแมปESCใหม่ของคุณmeta-prefix-charในแต่ละคนและทุกแผนที่ที่ใช้M-ก่อนที่คุณจะสามารถ C-[map

ตกลงแล้วแน่นอน: มาใช้input-decode-mapกัน มีแผนที่ที่คล้ายกันสองสามแบบที่เราอาจถูกล่อลวงให้ใช้ (ดูหัวข้อ 21.8.3 และ 22.14) แต่มาติดกับแผนที่นี้กัน และ ... งานนี้! เสร็จแล้วใช่ไหม

จริงๆแล้วไม่เรื่องไม่ได้จบที่นี่ มันใช้งานได้ ... ตราบใดที่คุณใช้ระบบหน้าต่าง หากโชคร้ายที่คุณถูกจำคุกในคอนโซลลินุกซ์ในสถานการณ์ฉุกเฉินคุณตระหนักดีว่าสถานการณ์เป็นอย่างไร: ปุ่มลูกศรHomeและการM-ผูกแน่นอนเป็นขยะทั้งหมด ทำไม? เพราะเมื่อเทอร์มินัลบอกว่าESC(ซึ่งจะทำเมื่อคุณพิมพ์C-[) มันหมายถึง ESCและเริ่มต้นลำดับเดียวกันกับที่ใช้ในการส่งอักขระที่ไม่ใช่ ASCII

จากการสังเกตการณ์ภัยพิบัติคุณอาจคิดว่าควรป้องกันการinput-decode-mapแก้ไขดังกล่าวข้างต้นในลักษณะที่มันเปิดใช้งานเฉพาะในกรณีที่ระบบหน้าต่างควบคุมคีย์บอร์ด:

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

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

เทอร์มินัลก็ทำงานตามที่เคยเป็น

ตอนนี้เราสามารถจัดการกับC-[เทอร์มินัลได้หรือไม่? ที่จริงแล้วใช่แล้วเราสามารถทำได้บนคอนโซลลินุกซ์เช่นเดียวกับเทอร์มินัลอีมูเลเตอร์อื่นที่ฉันสามารถเล่นได้ แต่นั่นทำให้เรื่องนี้ยาวไปหน่อยหนึ่งเนื่องจากตัวละครใหม่เข้ามาในฉาก สำหรับมันไม่ได้เป็น emacs เพียงอย่างเดียว: เทอร์มินัลตอนนี้มีบทบาทสำคัญ

ลองฟังสิ่งที่คอนโซล linux พูด พิมพ์C-vก่อนปุ่มบางปุ่มเพื่อฟังแบบธรรมดา C-[คือESC; Escเพื่อให้เป็น ลูกศรขึ้นเสียงเหมือนESC [ Aในขณะที่มีM-a ESC Aอืม ... ดูเหมือนว่าเมตาคีย์ของการหลีกเลี่ยงข้อผิดพลาดใน emacs ไม่ใช่หรือ อย่างไรก็ตาม.

ถ้าเราไม่พร้อมที่จะเล่นกลตามเวลาที่ผ่านไประหว่างเหตุการณ์ของตัวละคร (ซึ่งจะไม่แยกความแตกต่าง EscจากC-[) ดูเหมือนว่าเราไม่มีทางเลือก แต่บอกคอนโซลว่าสิ่งที่เราไม่ได้หมายถึงจริงเมื่อเราพิมพ์ESC C-[ยิ่งไปกว่านั้นดูเหมือนว่าในไม่ช้าC-[มันก็จะไม่เกิดปัญหาเฉพาะกับรหัสเทอร์มินัลหุ้น: ตัวดัดแปลงส่วนใหญ่จะลบข้อมูลที่ส่งออกไป เราจำเป็นต้องปรับแต่งเทอร์มินัลด้วยเหตุผลเดียวกันกับที่เราปรับแต่ง emacs: มันจะมีประโยชน์มากกว่าถ้าเราทำ

ณ จุดนี้คุณจะกล้ามองลึกลงไปในดวงตาเอกสารของเทอร์มินัลของคุณ: หน้าคนloadkeys(1)สำหรับคอนโซล linux สำหรับ xterm xterm(1)ในส่วนCustom Key Bindingsและสิ่งที่ฉันไม่ทราบสำหรับอาคารอื่น ๆ ในKDE konsoleคุณสามารถกำหนดคำแปลที่กำหนดเองในการตั้งค่า / แก้ไขโปรไฟล์ปัจจุบัน ... แล้วแป้นพิมพ์ นี่คือข้อความที่ตัดตอนมาจาก~/.local/share/konsole/Test.keytab หลังจากเล่นกับกล่องโต้ตอบหลังนี้:

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

เมื่อคุณมีการส่งขั้วESC O 5 [สำหรับ C-[(ในขณะที่การตั้งค่าดังกล่าวข้างต้น), คุณสามารถกลับไป emacs แน่นอนว่าคุณยังไม่ได้ทำ

ในการสั่งให้ emacs ภาษาถิ่นใดที่เทอร์มินัลที่ระบุใช้คุณสามารถปรับinput-decode-mapได้ ใช่นี่เป็นโชคดีที่เราได้ปรับเปลี่ยนตอนต้นของเรื่องนี้และนี่เป็นสิ่งที่ term/xterm.elสัมผัสได้เมื่อ xterm เกี่ยวข้อง สถานที่ที่ดีสำหรับการปรับคือtty-setup-hook(ดูหัวข้อ 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))
        )
      )))

ระวังฮุคนี้จะทำงานก็ต่อเมื่อคุณอยู่ในเทอร์มินัล ดังนั้นคุณไม่สามารถแทรกรหัสสำหรับการเริ่มต้นระบบหน้าต่างได้ที่นี่ นี่คือฟังก์ชั่นการแปลด้วยตัวมันเอง:

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

และจากนั้นคุณสามารถพักผ่อนได้: มันคือจุดสิ้นสุดของการเดินทาง แน่นอนถ้าคุณไม่สนใจอาคารผู้โดยสารมันรวดเร็วเพราะคุณจะข้ามส่วนที่เจ็บปวดไปทั้งหมด แต่คุณจะยอมรับว่ามันค่อนข้างไม่สมบูรณ์เช่นกัน

หมายเหตุสองประการสุดท้าย:

  • ฉันเลือกรหัสESC O 5 [ C-[นี่เป็นเพียงตัวอย่าง: ฉันจะไม่แกล้งทำเป็นว่ามันเป็นทางเลือกที่ดี เฉพาะ5 ส่วนซึ่งหมายความว่าC-ดูเหมือนว่าจะปฏิบัติตามชนิดของการประชุมจัดตั้งขึ้นบางส่วน

  • การกำหนดค่าลินุกซ์คอนโซลใบรสชาติดี: มันไม่น่าเป็นไปได้ที่จะทำผลผูกพันโดยไม่ต้องใช้เป็นสื่อกลางที่มีอยู่สัญลักษณ์และผู้ที่ฉันจะต้อง ไม่อยู่ ฉันใช้สัญลักษณ์ในช่วงF21- F246ในตัวอย่างอินเทอร์เน็ตส่วนใหญ่ แต่ก็ไม่ค่อยพอใจเท่าไหร่ ไม่เป็นไรสำหรับการผูกที่ไม่เกี่ยวข้องสองสามครั้ง แต่จะไม่ให้บริการสคีมาอย่างเป็นระบบ

แก้ไข

  • ฉันได้ทำสิ่งนี้กับEscเคสแล้ว - ซึ่งมีบุคลิกของตัวเอง - ในโพสต์อื่น: วิธีลบการเชื่อมโยงไปยังคีย์คำนำหน้า ESC
  • นี่คือส่วนของการกำหนดค่าที่จะเลี้ยงloadkeysด้วย ฉันใส่สิ่งนี้ใน /root/custom.kmap และโหลดเมื่อฉันต้องการ (ซึ่งหายาก) การกำหนดค่าจริงของฉันยังทำแผนที่ลูกศรและชุดค่าผสมที่แตกต่างกัน แต่ค่อนข้างนานการเลือกสัญลักษณ์และลำดับเป็นที่น่าสงสัยและฉันไม่แน่ใจว่ารหัสสำหรับแป้นพิมพ์ของฉันจะตรงกับของคุณหรือไม่ ดังนั้นให้มันอยู่ในระดับที่เหมาะสม: นี่คืออะไรนอกจากภาพประกอบ

    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
ขอบคุณนั่นเป็นคำตอบที่ดี แต่แน่นอนว่าคำตอบที่ยอดเยี่ยมเช่นนี้ก็ไม่จำเป็นต้องชนไปที่ด้านบนของหน้า 34 ครั้ง การชนแต่ละครั้งมีค่าใช้จ่ายเล็กน้อยซึ่งชุมชนแบ่งปัน: การตรวจสอบสแปมดูว่ามีเนื้อหาใหม่ที่น่าสนใจ ฯลฯ คุณอาจจัดกลุ่มการปรับปรุงเล็กน้อยด้วยกันไหม หรือเพียงแค่ยึดติดกับสิ่งที่คุณมี เมื่อพูดถึงประสบการณ์แล้วไม่มีสิ่งใดที่เป็นโพสต์ที่สมบูรณ์แบบในบางจุดที่คุณต้องก้าวต่อไป
Gilles 'หยุดความชั่วร้าย' ใน

@Gilles เข้าใจแล้วและขอโทษสำหรับสิ่งนั้น ฉันไม่ทราบว่ามีปัญหาในการปรับบางอย่างตามที่ต้องการ
Champignac

0

วิธีแก้ปัญหาต่อไปนี้เป็นบิต kludky แต่ดูเหมือนว่าจะทำงาน:

อนุญาตให้~/.xbindkeysrcมีต่อไปนี้:

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

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

ตอนนี้xbindkeysจะแปลC-[ไปC-<f13>และC-]เพื่อC-<f14>ให้พวกเขาสามารถจะผูกพันใน emacs ได้อย่างอิสระ คุณอาจจะต้องการที่จะผูกabort-recursive-editอย่างอื่นที่ไม่ใช่ตัวอย่างเช่นC-]C-S-g

ข้อเสียคือตอนนี้C-[แตกในทุกแอปพลิเคชั่นยกเว้น Emacs ซึ่งสามารถแก้ไขได้โดยการเพิ่มตรรกะเพื่อทดสอบว่ามีการส่งคีย์ผสมไปยัง emacs หรือไม่ ...


FWIW C-]ผมไม่คิดว่ามีอะไรเป็นพิเศษเกี่ยวกับ
Malabarba

ใช่ฉันไม่ แต่ด้วยเหตุผลแปลก ๆ ที่ฉันC-]ผูกพันหยุดทำงานหลังจากที่ฉันยิง Xbindkeys ขึ้นดังนั้นฉันจึงเด้งกลับมาเช่นกัน
Kristóf Marussy
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.