в Emacs, как лучше всего, чтобы клавиша-escape-quit не уничтожала другие окна?

РЕДАКТИРОВАТЬ: Я понимаю, что есть клавиатурный выход (который обычно привязан к C-g); но мне больше интересно узнать, как можно работать с функциями редактирования, которые поставляются с Emacs (как в этом случае). Время от времени я сталкиваюсь с подобными ситуациями, когда хочу немного изменить некоторые встроенные функции.

В emacs, когда вы нажимаете M-ESC ESC (или ESC три раза), вы можете выйти из множества ситуаций, таких как переходная метка и т. Д. Но я обычно нажимаю клавишу выхода (я фактически переназначаю это на одно нажатие клавиша выхода) больше, чем я предполагал, и это в конечном итоге убивает мою конфигурацию Windows, что довольно раздражает. Функция keyboard-escape-quit определена в simple.el:

(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))))

И я вижу, что мне не нужны строки:

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

Но как лучше всего изменить эту функцию? Я вижу только два пути: 1) изменить simple.el 2) скопировать эту функцию в мой файл .emacs и внести там изменения. Оба способа не очень хороши; в идеале я хотел бы увидеть что-нибудь в строке defadvice, но я не понимаю, как я могу это сделать в этом случае.


person polyglot    schedule 17.02.2009    source источник


Ответы (5)


Вы можете использовать around advice и переопределить вызывающую ошибку функцию, чтобы она делала то, что вы хотите (т.е. one-window-p всегда должен возвращать t):

(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)))))

Этот вид действует как (let ...), но должен быть более сложным, потому что вам нужно переопределить функцию для ограниченной области вместо переменной.

person scottfrazer    schedule 17.02.2009
comment
Лучшая однострочная версия с использованием flet (т.е. функциональная версия let): (defadvice keyboard-escape-quit (around my-keyboard-escape-quit activate) (flet ((one-window-p (& optional nomini all-frames) ) т)) ad-do-it)) - person polyglot; 20.06.2009
comment
Вам также может потребоваться изменить flet на cl-flet. - person Alan; 24.01.2016

Обычно я нахожу, что «выход с клавиатуры» (C-g) помогает выбраться из всех этих ситуаций.

Однако, если вы действительно хотите иметь вариант этой функции, я думаю, что копирование в ваш файл .emacs (и переименование, я обычно использую префикс bp) и внесение там изменений, вероятно, лучший вариант.

РЕДАКТИРОВАТЬ в ответ на редактирование: В общем, всякий раз, когда мне нужна отредактированная версия функции emacs, я либо пишу ее сам, либо копирую в свой .emacs, переименовывая ее в bp-whotever, а затем вношу соответствующие изменения.

Обратной стороной этого является то, что мой .emacs ОГРОМНЫЙ и, вероятно, излишне замкнутый с древними функциями, которые больше не используются ... Плюс в том, что всякий раз, когда мне нужно написать что-то новое, у меня есть тонны образцов кода, на которые можно посмотреть ...

person Brian Postow    schedule 17.02.2009

Вот еще один, более простой совет, в котором используется тот факт, что keyboard-escape-quit вызывает buffer-quit-function перед закрытием окон:

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

Работает с Emacs 25.1. (Первоначально я использовал совет @scottfrazer, но в 25.1 он не понравился. Пока не занимался отладкой.)

person ryan    schedule 02.11.2016
comment
Идеально. Спасибо ‹3 - person Ole; 16.08.2018

Однократное нажатие клавиши Escape по умолчанию действует как префиксная клавиша Meta; то есть привязка клавиш, которая включает в себя мета-ключ.

Трехкратное нажатие клавиши Escape запустит keyboard-escape-quit, что похоже на keyboard-quit, но с поведением «делай то, что я имею в виду».

Этот код может помочь в вашем случае использования. Вы можете использовать это в своем файле инициализации Emacs:

;;; 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)
person gsl    schedule 25.07.2015

Мне больше интересно узнать, как можно работать с функциями редактирования, которые поставляются с Emacs (как в этом случае). Время от времени я сталкиваюсь с подобными ситуациями, когда хочу немного изменить некоторые встроенные функции.

Именно для этой цели я создал библиотеку el-patch. Вы должны поместить это в свой файл инициализации:

(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))))
person Radon Rosborough    schedule 08.03.2017