Überschreiben von Hauptmodusbindungen

38

Manchmal werden meine globalen Tastenkombinationen von einem Hauptmodus überschrieben. Ein einfaches Beispiel ist die folgende Einstellung in meiner Init-Datei

(global-set-key (kbd "C-j") 'newline-and-indent)

Ärgerlicherweise wird diese Tastenkombination durch den Hauptmodus "Lisp Interaction" (Lisp-Interaktion) ausgeblendet, der der Standardmodus des Arbeitspuffers ist.

Wenn ich mich in einer Situation befinde, in der ein Hauptmodus (oder ein Nebenmodus) meine globale Tastenkombination verbirgt, wie kann ich sie wieder herstellen?

Hinweis: Meine Frage ist nicht : „Wie kann ich binden C-jan newline-and-indent‚? Mode‘in“ Lisp - Interaktion Ich interessiere mich für eine viel allgemeinere Antwort zum Umgang mit zusammenstoßenden Tastenkombinationen oder Benutzertastenkombinationen, die durch einen Dur / Moll-Modus ausgeblendet werden.

Nispio
quelle

Antworten:

39

Es gibt auch einen "Shortcut" -Ansatz für dieselbe Lösung, wenn Sie nicht Ihren eigenen Nebenmodus definieren möchten (über den ich in meiner ersten Antwort spreche).

Sie können das use-packageInstallationspaket zur Verfügung von Melpa und nutzt bind-key*oder bind-keys*Makro , das Teil des ist bind-keyPakets , dass Schiffe mit use-package.

Aus der Dokumentation von bind-key.el:

;; If you want the keybinding to override all minor modes that may also bind
;; the same key, use the `bind-key*' form:
;;
;;   (bind-key* "<C-return>" 'other-window)

;; To bind multiple keys in a `bind-key*' way (to be sure that your bindings
;; will not be overridden by other modes), you may use `bind-keys*' macro:
;;
;;    (bind-keys*
;;     ("C-o" . other-window)
;;     ("C-M-n" . forward-page)
;;     ("C-M-p" . backward-page))
Kaushal Modi
quelle
Falls jemand neugierig ist, beachten Sie, dass dies nur einen Nebenmodus hinter den Kulissen verwendet. Bei Konflikten mit anderen Nebenmodi wird ein anderer Ansatz gewählt, indem emulation-mode-map-alistsVorrang erzwungen wird.
Phils
Ich habe dies aufgrund seiner Einfachheit als Antwort markiert. Es macht im Wesentlichen das Gleiche wie diese Antwort , aber es erledigt die meiste Arbeit für Sie bequem hinter den Kulissen.
Nispio
@nispio Du hast recht. Meiner Erfahrung nach ist der einzige Unterschied die Methode, mit der die Nebenmodusbindungen andere Modi global überschreiben. Der Vorteil des anderen Ansatzes (Ihren eigenen Nebenmodus zu haben) ist jedoch, dass Sie ihn vorübergehend ausschalten können, um die ursprünglichen Emacs-Bindungen auszuprobieren, wenn Sie dies jemals benötigen (ich musste dies einige Male tun).
Kaushal Modi
1
Fügen Sie (bind-key* "C-M-&" 'override-global-mode), um Ihre init, und Sie können in der Regel die Bindungen aus dem Weg schnell bekommen , wenn Sie benötigen. Da override-global-modees sich nicht um einen "globalen" Nebenmodus handelt, müssen Sie ihn dennoch pufferweise deaktivieren. Wenn Sie also häufig feststellen, dass Sie die globalen Überschreibungsschlüssel deaktivieren, ist diese Lösung nicht praktisch.
Nispio
25

Sie können Ihren eigenen Nebenmodus und seine Tastenbelegung definieren und alle anderen Modi (Moll + Dur) überschreiben. Genau deshalb habe ich mich entschieden, meinen eigenen Nebenmodus zu schreiben.

Mit den folgenden Schritten können Sie festlegen, dass Ihre Tastenkombinationen alle Verknüpfungen überschreiben:

  • Definieren Sie Ihren eigenen Nebenmodus und Ihre eigene Tastenbelegung wie unten gezeigt.
  • Aktivieren Sie Ihren Nebenmodus global
  • (define-key my-mode-map (kbd "C-j") #'newline-and-indent)

In ähnlicher Weise überschreiben Ihre anderen in Ihrem Nebenmodus festgelegten Tastenbelegungen die in anderen Modi.

Ich empfehle dringend, den Blog-Beitrag von Christopher Wellons zu lesen, in dem erklärt wird, wie man einen Nebenmodus schreibt. Dieser Blog und das Ärgernis, mehrere Tastenkombinationen nilin mehreren Haupt- und Nebenmodi festlegen zu müssen, haben mich dazu inspiriert, meinen eigenen Nebenmodus zu schreiben.

Der beste Teil dieser Vorgehensweise ist, dass Sie, wenn Sie überprüfen möchten, wie die Tastenkombinationen in der Standardkonfiguration von emacs funktionieren, einfach den Nebenmodus deaktivieren. Sie schalten es dann wieder ein und Sie erhalten Ihre benutzerdefinierten Tastenkombinationen zurück.

;; Main use is to have my key bindings have the highest priority
;; https://github.com/kaushalmodi/.emacs.d/blob/master/elisp/modi-mode.el

(defvar my-mode-map (make-sparse-keymap)
  "Keymap for `my-mode'.")

;;;###autoload
(define-minor-mode my-mode
  "A minor mode so that my key settings override annoying major modes."
  ;; If init-value is not set to t, this mode does not get enabled in
  ;; `fundamental-mode' buffers even after doing \"(global-my-mode 1)\".
  ;; More info: http://emacs.stackexchange.com/q/16693/115
  :init-value t
  :lighter " my-mode"
  :keymap my-mode-map)

;;;###autoload
(define-globalized-minor-mode global-my-mode my-mode my-mode)

;; https://github.com/jwiegley/use-package/blob/master/bind-key.el
;; The keymaps in `emulation-mode-map-alists' take precedence over
;; `minor-mode-map-alist'
(add-to-list 'emulation-mode-map-alists `((my-mode . ,my-mode-map)))

;; Turn off the minor mode in the minibuffer
(defun turn-off-my-mode ()
  "Turn off my-mode."
  (my-mode -1))
(add-hook 'minibuffer-setup-hook #'turn-off-my-mode)

(provide 'my-mode)

;; Minor mode tutorial: http://nullprogram.com/blog/2013/02/06/
Kaushal Modi
quelle
5

Wenn eine globale Bindung eine Hauptmodusbindung überschreiben soll, legen Sie die Bindung einfach nilim Hauptmodus fest:

(define-key my-major-mode-map (kbd "C-j") nil)

Es ist nicht möglich, dass die globale Bindung im Allgemeinen Vorrang vor allen Modi hat (andernfalls macht es keinen Sinn, über Hauptmodi zu verfügen), aber Sie könnten sie umgehen, indem Sie Ihren eigenen Nebenmodus mit den wichtigsten Bindungen erstellen. Dann hätten Sie zumindest Vorrang vor den meisten (wenn auch nicht unbedingt allen) Modi.

Shosti
quelle
Funktioniert dies für einen beliebigen Hauptmodus? Mit anderen Worten, wenn ich einen (define-key foo-mode (kbd "C-j") nil)Hauptmodus namens "foo-mode" installiere, kann ich meine .emacs-Datei einfügen und damit rechnen, dass dies funktioniert?
Nispio
Eigentlich möchten Sie, dass dies so ist foo-mode-map(mein Beispiel in der Antwort war schlecht), aber ja, dadurch wird die Tastaturbindung im Hauptmodus deaktiviert, sodass stattdessen die globale Tastaturbindung verwendet wird (es sei denn, es gibt einen anderen Nebenmodus, der sie verwendet).
Shosti
Ist es ziemlich universell, dass die Keymap für foo-modeaufgerufen wird foo-mode-map?
Nispio
@nispio ja, das gilt für die große Mehrheit der Modi (obwohl es ein paar Schurken gibt).
Shosti
0

Sie können diese Makros verwenden:

(defmacro expose-global-keybinding (binding map)
  `(define-key ,map ,binding (lookup-key (current-global-map) ,binding)))

(defmacro expose-bindings (map bindings)
  `(dolist (bnd ,bindings)
     (expose-global-keybinding (kbd bnd) ,map)))

EDIT :

Überprüfen Sie das Beispiel unten:

Wenn die Keymap X Ihre globale Bindung Y überschreibt, schreiben Sie:

(expose-bindings X '("Y"))

Und dann wird die Außerkraftsetzung rückgängig gemacht.

Renan Ranelli
quelle
Ihr Makro profitieren Sie von der Verwendung des Backquote: (Definieren-Schlüssel, Karte, Bindung (Lookup-Schlüssel (aktuelle-globale-Karte), Bindung))
Sigma
Können Sie kommentieren, was das Makro tut und wie es verwendet wird? Es ist mir aus dem Code nicht klar.
Nispio
Das erste Makro sucht nur den Schlüssel in der globalen Karte und weist das Ergebnis dem zu other map, wodurch die globale Kartenbindung durch den offen gelegt wird other map. Mit der zweiten können Sie nur die erste für eine Liste von Bindungen anwenden.
Renan Ranelli
Es tut mir leid, wenn ich dicht bin, aber ich verstehe die Verwendung immer noch nicht ganz. Muss ich meine eigene spezielle globale Keymap definieren? Muss es zu einem Nebenmodus gehören? Führe ich expose-bindingszuerst aus und binde diese Schlüssel dann global an die gewünschten Befehle? Vielleicht könnten Sie ein Beispiel dafür zeigen, was ich in meine Init-Datei einfügen könnte, damit dies funktioniert.
Nispio
2
Beachten Sie, dass diese Makronamen falsche Bezeichnungen sind. Sie "offenbaren" nicht die globale Bindung, sondern duplizieren die globale Bindung. Wenn sich die reale globale Bindung ändert, werden diese doppelten Kopien nicht.
Phils