Клавиши полуавтоматического редактирования/автоматического префикса

Большинство режимов emacs включают некоторый префикс для активации своих функций. Например, при использовании GUD "next" это "C-c C-n". Из этих режимов многие предоставляют специальные буферы, где можно использовать один ключ для активации некоторой функциональности (просто "n" или "p" для чтения следующей/предыдущей почты в GNUS, например).

Однако не все режимы предоставляют такой буфер, и многократное написание префикса может быть утомительным. Есть ли известный бит elisp, который позволит ad-hoc спецификации префиксных ключей быть перенесены на все входные данные в течение некоторого времени? (Например, до нажатия ESC или какого-либо другого санкционированного ключа)

Ответ 1

Я согласен с Джо Касадонте в том, что путь - это определить свой собственный малый (или основной) режим.

Это, как говорится, ваш вопрос интересен.

Здесь предлагается решение, которое запрашивает последовательность клавиш и принимает префикс нажатия клавиш и продвигает эту раскладку на верхний уровень.

например. Предположим следующую раскладку:

M-g ESC         Prefix Command
M-g g           goto-line
M-g n           next-error
M-g p           previous-error

Когда вы запустите M-x semi-modal-minor-mode, он предложит вам несколько нажатий клавиш. Если вы введете M-g n, тогда будут установлены следующие привязки клавиш:

ESC         Prefix Command   (same as M-g ESC)
g           goto-line
n           next-error
p           previous-error

Итак, теперь n не вставляет самостоятельно, а переходит к следующей ошибке. См. Код ниже.

Примечание: если этот вспомогательный режим включен, <f12> привязан к команде, которая отключает второстепенный режим. Это связано с тем, что привязки клавиш могут очень хорошо отключить ваш Emacs (например, что, если был новый keybinding для M-x).

Отредактировано для добавления этих мыслей: переменная второстепенного режима была первоначально сделана буфером локальным, но это не работает, если вы также не создадите локальный переменный буфер minor-mode-alist (duh). Но вы также (возможно) не хотите эти привязки в минибуфере... Итак, я не собираюсь тестировать его b/c, это действительно зависит от того, что вы хотите, но я добавил комментарий к коду отражая эту мысль.

Без дальнейших церемоний:

(defvar semi-modal-minor-mode-keymap (make-sparse-keymap)
  "keymap holding the prefix key keymapping, not really used")
(defvar semi-modal-minor-mode-disable-key (kbd "<f12>")
  "key to disable the minor mode")
(defun semi-modal-minor-mode-disable ()
  "disable the minor mode"
  (interactive)
  (semi-modal-minor-mode 0))

(define-minor-mode semi-modal-minor-mode
  "local minor mode that prompts for a prefix key and promotes that keymap to the toplevel
e.g. If there are bindings like the following:

M-g ESC         Prefix Command
M-g g           goto-line
M-g n           next-error
M-g p           previous-error

And you enter 'M-g n' when prompted,
then the minor mode keymap has the bindings
  g   ->   goto-line
  n   ->   next-error
  p   ->   previous-error
  ESC ->   Prefix Command (same as M-g ESC)

The variable semi-modal-minor-mode-disable-key is bound to disable the minor mode map.
This is provided because often the mappings make the keyboard unusable.
Use at your own risk."
  nil " Semi" semi-modal-minor-mode-keymap
  (make-local-variable 'semi-modal-minor-mode)
  (make-local-variable 'minor-mode-map-alist)
  (let ((pair-holding-keymap-to-modify (assq 'semi-modal-minor-mode minor-mode-map-alist)))
    (setcdr pair-holding-keymap-to-modify (make-sparse-keymap))
    (if semi-modal-minor-mode
        (let (key
              keymap)
          ;; all but last (b/c we want a prefix
          (setq key (substring (read-key-sequence "Enter a full key combination, the prefix will be used: ") 0 -1))
          (if (and (not (equal "" key))
                   (not (equal (kbd "C-g") key))
                   (let ((semi-modal-minor-mode nil))
                     (keymapp (setq keymap (key-binding key)))))
              (progn
                (setcdr pair-holding-keymap-to-modify (copy-keymap keymap))
                (when semi-modal-minor-mode-disable-key
                  (define-key (cdr pair-holding-keymap-to-modify)
                    semi-modal-minor-mode-disable-key 'semi-modal-minor-mode-disable)))
            (semi-modal-minor-mode 0))))))

Ответ 2

Определенная по модам (модальная?) часть привязок ключей в Emacs реализуется различными локальными картами, которые затмевают универсальную глобальную карту. Большинство основных и второстепенных режимов определяют собственные локальные карты; например, есть карта gud-mode. Связывание клавиш в локальной раскладке будет активироваться только тогда, когда текущий буфер находится в соответствующем режиме. Вы можете настроить специальную ключевую карту с помощью режима. Например, вы можете поместить этот фрагмент в свой файл ~/.emacs

    (add-hook 'gud-mode-hook
      (lambda () 
        (local-set-key (kbd "C-n") 
                       (lookup-key (current-local-map) (kbd "C-c C-n")))))

Подробнее о раскладках можно найти в справочном руководстве Elisp.

Ответ 3

Основная проблема здесь в том, что в настоящее время нет текущей раскладки клавиатуры. Там глобальная раскладка клавиатуры, которая переопределяется основной клавиатурой режима, которая, в свою очередь, переопределяется одним или несколькими малогабаритными ключевыми картами (и они могут наступать друг на друга определенным образом, я уверен). Определение нового основного режима по-прежнему оставит функциональные клавиши второстепенного режима, а определение нового второстепенного режима повлияет только на любые клавиши, которые вы определяете в макете с малым режимом.

Например, вы можете определить малый режим, который будет делать то, что вы хотите, до тех пор, пока активен второстепенный режим. Вы определяете новый второстепенный режим my-gud-mode, который будет иметь свою собственную раскладку. Затем вам нужно будет определить все ваши сопоставления ключей для него (например, n, p и т.д.), И вам также необходимо будет определить все ключи, которые вы не хотите работать, для привязки к функции ignore. Это настоящая боль этого, переназначая все остальные ключи. Однако малый режим легко включать и выключать; что преимущество.

Определение нового основного режима было бы проще при первом румянце, так как это позволит вам отменить более "текущую раскладку" за один снимок. Он должен отметить текущий основной режим в локальной-буферной переменной, чтобы его можно было восстановить позже, когда временный основной режим отключен. Но у вас все еще будут другие второстепенные режимы, вторгающиеся в вашу раскладку, поэтому он не будет "чистым".

То, что я делаю в этой ситуации, - это более простой префикс! Для вещей, которые я использую все время, весь день каждый день, я даю им функциональный ключ самостоятельно (например, у меня есть F1 в качестве ключа jabber-mode). Для менее сразу полезных вещей у меня есть две другие функциональные клавиши, отложенные F3 и F12 (я уверен, что была некоторая причина, по которой я выбрал их давно, но я больше не помню, почему). F3 определяет ключи, которые всегда доступны, независимо от основного режима. F12 определяет ключи, зависящие от основного режима. Некоторые примеры:

Я установил F3-m- в качестве префикса для переключения основных режимов (например, F3-mp переключается в режим cperl) и F3-M- в качестве префикса для второстепенных режимов (например, F3-Mv переключает режим просмотра), Они всегда доступны, поэтому вы можете сделать что-то вроде bind F3-g-, чтобы быть вашим префиксом gud, и ввести F3-g-p для предыдущего и т.д.

Моя клавиша F12 зависит от режима. Итак, в режиме DLC F12-e вызовет dired-nt-open-in-excel в текущем файле, а в emacs- lisp -mode F12-e вызовет elint-current-buffer. Почему-то я никогда не путаю их.

Если вам нужна помощь в определении таких ключевых карт, дайте мне знать.

Ответ 4

Режим Viper позволяет вам отображать команды на клавиши или последовательности клавиш, находясь в визуальном режиме (вводится с помощью клавиши "esc" ). Вернитесь в режим вставки с помощью "i".
Посмотрите viper-in-more-modes.el
Он использует viper-modify- основной режим.
Мне также нравится использовать файл viper-vi-global-user-map: из моего файла .emacs.