2009-02-17 10 views
12

EDIT: Ich verstehe, dass es Tastatur-beenden (die normalerweise an C-g gebunden ist); aber ich bin mehr daran interessiert zu wissen, wie man mit Bearbeitungsfunktionen arbeitet, die mit Emacs kommen (wie in diesem Fall). Ich stoße von Zeit zu Zeit auf diese Art von Situationen, wenn ich nur ein paar eingebaute Funktionen ändern möchte.in Emacs, was ist der beste Weg für Keyboard-Escape-Quit nicht andere Fenster zu zerstören?

In Emacs, wenn Sie M-ESC ESC (oder ESC drei Mal) drücken, können Sie aus einer Vielzahl von Situationen wie transient-Mark, etc. kommen. Aber ich habe gewöhnlich die Escape-Taste gedrückt ein einzelner Treffer der Escape-Taste) mehr als ich beabsichtigt hatte, und das endet mit dem Töten meiner Windows-Konfiguration, was ziemlich nervig ist. Die Funktionstastatur-escape-quit in simple.el definiert:

(defun keyboard-escape-quit() 
    "Exit the current \"mode\" (in a generalized sense of the word). 
This command can exit an interactive command such as `query-replace', 
can clear out a prefix argument or a region, 
can get out of the minibuffer or other recursive edit, 
cancel the use of the current buffer (for special-purpose buffers), 
or go back to just one window (by deleting all but the selected window)." 
    (interactive) 
    (cond ((eq last-command 'mode-exited) nil) 
    ((> (minibuffer-depth) 0) 
    (abort-recursive-edit)) 
    (current-prefix-arg 
    nil) 
    ((and transient-mark-mode mark-active) 
    (deactivate-mark)) 
    ((> (recursion-depth) 0) 
    (exit-recursive-edit)) 
    (buffer-quit-function 
    (funcall buffer-quit-function)) 
    ((not (one-window-p t)) 
    (delete-other-windows)) 
    ((string-match "^ \\*" (buffer-name (current-buffer))) 
    (bury-buffer)))) 

Und ich kann sehen, dass ich will nicht die Zeilen:

((not (one-window-p t)) 
    (delete-other-windows)) 

Aber was ist der beste Weg, dies zu ändern Funktion? Ich kann nur zwei Möglichkeiten sehen: 1) modifiziere simple.el 2) kopiere diese Funktion in meine .emacs Datei und führe dort die Änderungen durch. Beide Wege sind nicht wirklich gut; Idealerweise würde ich gerne etwas auf der Linie des Defadvice sehen, aber ich kann nicht sehen, wie ich es in diesem Fall schaffen kann.

Antwort

14

Sie um Rat verwenden könnte und die beanstandete Funktion neu definieren zu tun, was Sie wollen (dh ein Fenster-p immer t zurückkehren sollte):

(defadvice keyboard-escape-quit (around my-keyboard-escape-quit activate) 
    (let (orig-one-window-p) 
    (fset 'orig-one-window-p (symbol-function 'one-window-p)) 
    (fset 'one-window-p (lambda (&optional nomini all-frames) t)) 
    (unwind-protect 
     ad-do-it 
     (fset 'one-window-p (symbol-function 'orig-one-window-p))))) 

Diese Art von Handlungen wie ein (lassen Sie ...), muss aber komplizierter sein, weil Sie eine Funktion für einen begrenzten Bereich anstelle einer Variable außer Kraft setzen müssen.

+4

Eine bessere Einzeiler Version mit flet (dh die Funktion Version let): (defadvice Tastatur-escape-quit (um meine-Tastatur-escape-quit activate) (flet ((one-window-p (& optionale nomini all-frames) t)) ad-do-it)) – polyglot

+0

Die cl-Erweiterung wird benötigt, damit flet funktioniert. – Alan

+0

Sie müssen möglicherweise auch 'flet' in' cl-flet' ändern. – Alan

7

Ich finde normalerweise, dass Tastatur-beenden (C-g) funktioniert, um aus all diesen Situationen herauszukommen.

Wenn Sie jedoch wirklich eine Variante dieser Funktion haben möchten, denke ich, dass das Kopieren in Ihre .emacs-Datei (und das Umbenennen, ich benutze normalerweise ein Präfix von bp) und die Bearbeitung dort wahrscheinlich die beste Option ist.

BEARBEITEN, als Antwort auf edit: Im Allgemeinen, wann immer ich eine bearbeitete Version einer Emacs-Funktion möchte, schreibe ich sie entweder selbst, oder kopiere sie in meine .emacs, benenne sie in bp-whotever um und führe entsprechende Bearbeitungen durch.

Der Nachteil ist, dass meine .emacs ist RIESIG, und wahrscheinlich extracratty mit alten Funktionen, die nicht mehr verwendet werden ... der Vorteil ist, dass, wenn ich etwas neues schreiben muss, habe ich Tonnen Probe Code zu sehen ...

0

Ein einmaliges Drücken der Escape-Taste dient standardmäßig als Meta-Präfix-Taste; das heißt, eine Tastenkombination, die den Meta-Schlüssel beinhaltet.

Wenn Sie die Escape-Taste dreimal drücken, wird keyboard-escape-quit ausgeführt. Dies ist wie ein Tastatur-Beenden, aber mit mehr "tue, was ich meine" Verhalten.

Dieser Code kann bei Ihrem Anwendungsfall hilfreich sein.Sie können in Ihrem Emacs init-Datei verwenden, um dies:

;;; esc always quits 
(define-key minibuffer-local-map [escape] 'minibuffer-keyboard-quit) 
(define-key minibuffer-local-ns-map [escape] 'minibuffer-keyboard-quit) 
(define-key minibuffer-local-completion-map [escape] 'minibuffer-keyboard-quit) 
(define-key minibuffer-local-must-match-map [escape] 'minibuffer-keyboard-quit) 
(define-key minibuffer-local-isearch-map [escape] 'minibuffer-keyboard-quit) 
(global-set-key [escape] 'keyboard-quit) 
1

Hier ist eine andere, einfachere Ratschlag, den Vorteil der Tatsache Rechnung, dass keyboard-escape-quit Anrufe buffer-quit-function vor dem Schließen Fenster:

(defadvice keyboard-escape-quit 
    (around keyboard-escape-quit-dont-close-windows activate) 
    (let ((buffer-quit-function (lambda()()))) 
    ad-do-it)) 

Arbeiten mit Emacs 25.1. (I ursprünglich @ scottfrazer Rat verwendet, aber es ist unglücklich in 25.1. Haben Sie nicht das Debuggen noch gestört.)

1

Ich bin mehr daran interessiert zu wissen, wie man sich mit Bearbeitungsfunktionen, die mit Emacs kommen (wie in diesem Fall). Ich stoße von Zeit zu Zeit auf diese Art von Situationen, wenn ich nur ein paar eingebaute Funktionen ändern möchte.

Dies ist genau der Zweck, für den ich die Bibliothek el-patch erstellt. Sie würden dies in Ihrer init-Datei setzen:

(el-patch-defun keyboard-escape-quit() 
    "Exit the current \"mode\" (in a generalized sense of the word). 
This command can exit an interactive command such as `query-replace', 
can clear out a prefix argument or a region, 
can get out of the minibuffer or other recursive edit, 
cancel the use of the current buffer (for special-purpose buffers), 
or go back to just one window (by deleting all but the selected window)." 
    (interactive) 
    (cond ((eq last-command 'mode-exited) nil) 
    ((> (minibuffer-depth) 0) 
    (abort-recursive-edit)) 
    (current-prefix-arg 
    nil) 
    ((and transient-mark-mode mark-active) 
    (deactivate-mark)) 
    ((> (recursion-depth) 0) 
    (exit-recursive-edit)) 
    (buffer-quit-function 
    (funcall buffer-quit-function)) 
    (el-patch-remove 
     ((not (one-window-p t)) 
     (delete-other-windows))) 
    ((string-match "^ \\*" (buffer-name (current-buffer))) 
    (bury-buffer))))