Come legare C- [per davvero?


10

C-[equivale al tasto Esc delle tastiere inglesi statunitensi, quindi qualsiasi tentativo di vincolarlo comprometterà il M-comportamento.

Emacs sembra non avere problemi a distinguerlo <escape>e a C-[parte nei frame della GUI. Funzionano bene e i binding che iniziano con M-rimangono funzionanti:

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

Tuttavia, se mi lego

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

improvvisamente emacs impazzisce e si lega come una M-xpausa. Inoltre, premendo si C-[rifiuta di innescare la lambda legata. È interessante notare che C-x @ c [(applica il controllo modificatore alla parentesi aperta) dice ancora C-[ is undefined.

Esiste un modo per legare qualcosa C-[senza rompere gli emacs?

Risposte:


7

Non puoi davvero cambiare l' C-[associazione a mappe a livello di utente, come faresti con global-set-key. Tuttavia, è possibile modificarlo come evento da tastiera prima che raggiunga quelle mappe dei tasti. Puoi dire per esempio:

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

e poi [control-bracketleft]usalo nelle tue keymap. Abbastanza semplice no?

Scene extra

Sfortunatamente, non è così semplice e questa soluzione richiede alcuni aggiustamenti, che sembreranno molto dolorosi. Sei stato avvisato. Ma vediamo innanzitutto perché le mappe a livello di utente non possono rispondere alla domanda. Di seguito, mi riferisco al manuale di Emacs Lisp per emacs 26.1 quando dico "vedere qualcosa" senza più precisione.

C-[viene interpretato molto presto come il carattere di controllo ASCII ESC(vedi 21.7.1 - Eventi tastiera ). Questo codice viene distribuito in tutte le altre posizioni come prefisso per sequenze più lunghe. C'è una ragione per questo: in ESCrealtà è il meta prefisso (vedi meta-prefix-char), e tutti i binding che leggono M-qualcosa si tradurranno in una sequenza che inizia con ESC. Pertanto, cambiare la mappa globale non sarà sufficiente: devi prima cambiare meta-prefix-char, quindi rimappare ESCal tuo nuovo meta-prefix-charin ogni mappa che usi M-prima di poter mappare in sicurezza C-[.

OK allora, ovviamente: usiamo input-decode-map. Esistono un paio di mappe simili che potremmo essere tentati di usare (vedere le sezioni 21.8.3 e 22.14), ma atteniamoci a questa. E bene ... questo funziona! Hai finito, vero?

In realtà no, la storia non finisce qui. Funziona ... fintanto che stai usando un sistema a finestre. Se per sfortuna sei imprigionato nella console di Linux in uno stato di emergenza, ti rendi conto di quanto sia drammatica la situazione: i tasti freccia Homee, ovviamente M-, i collegamenti, sono tutti spazzatura. Perché? Perché quando dice il terminale ESC(cosa che fa quando si digita C-[), significa davvero ESC, e inizia una sequenza dello stesso tipo che usa per trasmettere caratteri non ASCII.

Osservando il disastro, potresti considerare saggio proteggere la input-decode-mapmodifica di cui sopra in modo tale che si attivi solo nel caso in cui un sistema a finestre stia controllando la tastiera:

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

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

I terminali quindi funzionano come prima.

Ora, possiamo occuparci dei C-[terminali? In realtà, sì, possiamo, sia sulla console Linux che sugli altri emulatori di terminali con cui posso giocare. Ma questo rende la storia piuttosto lunga, poiché nuovi personaggi entrano nella scena. Perché non è più solo emacs: il terminale ha ora il ruolo centrale.

Diamo un'occhiata a ciò che la console linux ha da dire. Digita C-vprima di un tasto per ascoltarlo chiaramente. C-[è ESC; così è Esc. La freccia su suona come ESC [ A, mentre lo M-aè ESC A. Hmm ... Sembra che questa meta-circonvoluzione in emacs non sia vero? Comunque.

A meno che non siamo pronti a giocare alcuni trucchi in base al tempo trascorso tra gli eventi del personaggio (che tra l'altro non si distinguerà Escda C-[), sembra che non abbiamo altra scelta che dire alla console ciò che in realtà non intendiamo ESCquando digitiamo C-[. Inoltre, sembra abbastanza presto che C-[non sia l'unico problema con i codici terminali di serie: i modificatori vengono spesso cancellati dalle informazioni trasmesse. Dobbiamo personalizzare il terminale per lo stesso motivo per cui personalizziamo emacs: sarebbe molto più pratico se lo facessimo.

A questo punto, avrai il coraggio di dare uno sguardo approfondito agli occhi della documentazione del tuo terminale: pagine man loadkeys(1)per la console linux, per xterm xterm(1)nella sezione Associazioni chiave personalizzate e tutto ciò che non so per altri terminali. In KDE konsole, puoi definire traduzioni personalizzate in Impostazioni / Modifica profilo corrente ... quindi Tastiera . Ecco un estratto da ~/.local/share/konsole/Test.keytab dopo aver giocato con quest'ultima finestra di dialogo:

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

Una volta che avete l'invio del terminale ESC O 5 [per C-[(come nella configurazione di cui sopra), si può tornare a emacs. Ovviamente, non hai ancora finito.

Per indicare a emacs quale dialetto utilizza un determinato terminale, è possibile regolare input-decode-map. Sì, questo è casualmente quello che abbiamo modificato all'inizio di questa storia, e questo è quello che term/xterm.eltocca quando è coinvolto xterm. Un buon posto per la regolazione è tty-setup-hook(vedere la sezione 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))
        )
      )))

Ricorda che questo hook funziona solo se ti trovi in ​​un terminale. Pertanto, non è possibile inserire qui il codice per l'inizializzazione del sistema di finestre. Ecco la funzione di traduzione da sola:

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

E poi puoi riposarti: è la fine del viaggio. Naturalmente, se non ti interessano i terminali, è veloce poiché salterai tutta la parte dolorosa. Ma riconoscerai che è anche piuttosto incompleto.

Due note finali:

  • Ho scelto ESC O 5 [di codificare C-[. Questo è solo un esempio: non pretendo che sia una buona scelta. Solo la 5 parte, il che significa C-, sembra obbedire a una sorta di convenzione stabilita

  • la configurazione della console linux lascia un cattivo gusto: non sembra possibile fare il binding senza usare un simbolo intermedio esistente , e quelli di cui avrei bisogno non esistono . Uso i simboli nell'intervallo F21- F246come nella maggior parte degli esempi di Internet, ma non è molto soddisfacente. Va bene per alcuni collegamenti non correlati, ma non servirà uno schema sistematico.

modificare

  • Ho completato questo con il Esccaso - che ha una sua personalità - in un altro post: Come rimuovere i collegamenti alla chiave del prefisso ESC
  • ecco un frammento di una configurazione con cui nutrirsi loadkeys. L'ho inserito in /root/custom.kmap e lo carico quando necessario (cosa rara). La mia configurazione attuale mappa anche le frecce e le diverse combinazioni di modificatori, ma è piuttosto lunga, la scelta dei simboli e delle sequenze è discutibile e non sono sicuro che i codici chiave per la mia tastiera corrisponderanno ai tuoi. Quindi manteniamolo al suo giusto livello: questo non è altro che un'illustrazione.

    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
Grazie, è un'ottima risposta. Ma sicuramente anche una grande risposta come questa sicuramente non ha bisogno di essere sbattuta in cima alla prima pagina 34 volte. Ogni bump ha un piccolo costo che viene condiviso dalla community: controllare lo spam, cercare nuovi contenuti interessanti, ecc. Forse potresti raggruppare piccoli miglioramenti insieme? O semplicemente attenersi a ciò che hai. Parlando per esperienza, non esiste il post perfetto, ad un certo punto non resta che andare avanti.
Gilles 'SO- smetti di essere malvagio' il

@Gilles Capito, e scusa per quello. Non sapevo che ci fosse qualche problema ad aggiustarlo a piacimento.
Champignac,

0

La seguente soluzione è un po 'kludky, ma sembra funzionare:

Lasciate ~/.xbindkeysrccontenere quanto segue:

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

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

Ora xbindkeyssi tradurrà C-[in C-<f13>e C-]in C-<f14>, in modo che possano essere liberamente associati in emacs. Probabilmente vorrai associarti abort-recursive-edita qualcosa di diverso C-], ad esempio C-S-g.

Il rovescio della medaglia è che ora C-[è rotto in ogni applicazione tranne Emacs, che potrebbe essere risolto aggiungendo una logica per testare se la combinazione di tasti viene inviata a emacs ...


FWIW, non credo ci sia niente di speciale in questo C-].
Malabarba,

Sì, neanche io, ma per qualche strana ragione la mia C-]rilegatura ha smesso di funzionare dopo aver acceso Xbindkeys, quindi ho rimbalzato anche quello.
Kristóf Marussy,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.