What are good custom keybindings in emacs?

2019-03-15 14:00发布

Emacs seems to have all the possible keyboard combinations already randomly distributed among it's commands. :p

If I am to define new keyboard shortcuts, where should I put them? Which prefixes should I use?

For instance: I want to define shortcuts for the following functions:

  • indent-buffer (C-c i, after I got the answer)
  • comment-or-uncomment-region (C-c C)
  • rdebug (ruby debugger) (C-c R)
  • rsense-complete (ruby autocomplete) (C-c e)

Where would you put these? Why?

5条回答
来,给爷笑一个
2楼-- · 2019-03-15 14:20

I have an unconventional approach to this that I recommend highly. I have redefined the C-l ('ell') key to be a prefix key, and I use that to prefix my favorite commands. This key is very easy to type and it is bound to a function ('recenter) that isn't used that much.

Well, I don't use 'recenter much, but even if you did, it can be assigned to C-l C-l which is almost as easy to type, and a small price to pay for the possibilities opened up by the Ctrl-L-map . (Actually I prefer 'redraw-display to 'recenter, so I gave that the place of honor.)

I don't remember where I got the magic incantation that makes it work:

(global-unset-key "\C-l")
(defvar ctl-l-map (make-keymap)
     "Keymap for local bindings and functions, prefixed by (^L)")
(define-key global-map "\C-l" 'Control-L-prefix)
(fset 'Control-L-prefix ctl-l-map)

Then you can define keys to your heart's content. C-l is a great place to put bindings for your own commands, as well as functions that are not bound to keys, or are bound to keys you can't remember or find hard to type. Here are some sample bindings to standard functions:

(define-key ctl-l-map "\C-l"  'redraw-display)
(define-key ctl-l-map "l"  'recenter)

(define-key ctl-l-map "g"  'goto-line)
(define-key ctl-l-map "r"  'replace-string)
(define-key ctl-l-map "R"  'replace-regexp)
(define-key ctl-l-map "q"  'query-replace)
(define-key ctl-l-map "Q"  'query-replace-regexp)
(define-key ctl-l-map "o"  'overwrite-mode)
(define-key ctl-l-map "\C-w"  'kill-rectangle)
(define-key ctl-l-map "\C-y"  'yank-rectangle)
(define-key ctl-l-map "h"  'command-history)
(define-key ctl-l-map "w"  'write-region)
(define-key ctl-l-map "r" 'electric-replace-string)
(define-key ctl-l-map "\er" 'replace-string)
(define-key ctl-l-map "T"  'delete-trailing-whitespace)
(define-key ctl-l-map "C"  'describe-char)
(define-key ctl-l-map "W"  'ediff-regions-wordwise)
(define-key ctl-l-map "L"  'ediff-regions-linewise)
(define-key ctl-l-map "\C-f" 'facemenu-remove-all)
(define-key ctl-l-map "\C-c" 'calendar)
(define-key ctl-l-map "m"  'not-modified)   ;; already at M-~
(define-key ctl-l-map "\C-q" 'fill-region)
(define-key ctl-l-map "u" 'set-buffer-file-coding-system)
(define-key ctl-l-map [?\C-2] 'transient-mark-mode)
(define-key ctl-l-map "\C-@"  'transient-mark-mode)
(define-key ctl-l-map "\C-n"  'linum-mode)
(define-key ctl-l-map "\C-s" 'isearch-forward-regexp)
(define-key ctl-l-map "\C-r" 'isearch-backward-regexp)a
(define-key ctl-l-map "U" 'browse-url)
(define-key ctl-l-map "F" 'browse-url-of-file)
(define-key ctl-l-map "\C-u" 'undo-only)
查看更多
Ridiculous、
3楼-- · 2019-03-15 14:29

Emacs actually has a very definite pattern to its bindings, this answer shows some.

As far as where you should define keys, if you take a look at the documentation for conventions, you'll see that C-c a (where a is any lower or upper case character) is reserved for users.

Plus, if you're defining a key that really only makes sense in a particular mode, then you should define it in that keymap.

For example, M-/ is bound to dabbrev-expand, which is a handy way of autocompleting the word you're typing. It might very well make sense to use rsense-complete instead, but only when you're in ruby. In which case, you can do this:

(add-hook 'ruby-mode-hook
     (lambda () (define-key ruby-mode-map (kbd "M-/") 'rsense-complete)))

That will override the binding for M-/ only when you're in ruby-mode, and leave it unchanged (or available) for the rest of the modes.

查看更多
狗以群分
4楼-- · 2019-03-15 14:31

This is mine.

Notice I remapped the movement keys. This was because I use the MS NS4K, which makes those particular key movements very easy.

;;;;;;;; remapping of keys ;;;;;;;;;;;;;;;

(global-set-key "\C-cg" 'goto-line)
;C-c u untabifies...yuck!
(global-set-key "\C-cu" 'untabify)
;Regex replace
(global-set-key "\C-x%" `query-replace-regexp)
;;Backward-kill-line is defined later on in this file.
(global-set-key "\M-k" `backward-kill-line)

(global-set-key "\C-x\C-j" 'eval-print-last-sexp)
;;M-up/down -> start/end of buffer. Yay!
(global-set-key (kbd "M-<up>") 'beginning-of-buffer)
(global-set-key (kbd "M-<down>") 'end-of-buffer)
(global-set-key (kbd "M-[") 'beginning-of-buffer)
(global-set-key (kbd "M-]") 'end-of-buffer)

;;remap movement keys to get rid of emacs pinky
;Jump back and forth by 5.
(global-set-key "\C-n" '(lambda () (interactive) (forward-line 5)))
(global-set-key "\C-p" '(lambda () (interactive) (forward-line -5)))
(global-set-key "\M-a" 'move-beginning-of-line)
(global-set-key "\M-e" 'move-end-of-line)
(global-set-key "\M-n" 'next-line)
(global-set-key "\M-p" 'previous-line)

;bookmark
(global-set-key (kbd "<M-f2>") 'bm-toggle)
(global-set-key (kbd "<f2>")   'bm-next)
(global-set-key (kbd "<f3>") 'bm-previous)
(setq bm-cycle-all-buffers t)

(global-set-key (kbd "<f5>") 'revert-buffer)
(global-set-key (kbd "<f12>") 'delete-trailing-whitespace)
(global-set-key (kbd "<f11>") 'comment-or-uncomment-region)

(global-set-key (kbd "M-RET") 'newline-and-indent)
(global-set-key "\C-m" 'newline-and-indent)

;;Jump "backwards"
(global-set-key "\C-xp" '(lambda () (interactive) (other-window -1)))

;;copy
(global-set-key "\M-y" 'yank)

;;insert line
(global-set-key "\M-o" '(lambda () (interactive) (open-line 1)))

;zap to char backwards
(global-set-key "\C-z" 'minimize)
;;suspend-emacs is the send-to-background command on linux

;simplify register usage
(global-set-key "\M-s" 'copy-to-register)
(global-set-key "\M-i" 'insert-register)

;;autocomplete hacks
(global-set-key [?\M-/] 'hippie-expand)
(global-set-key [?\C-/] 'dabbrev-expand)


(global-set-key [?\C-.] 'find-tag)
;(global-set-key "\C-.\C-s" 'find-tag)
(global-unset-key [?\M-.])

;;this lets us have long lines go off the side of the screen instead of hosing up the ascii art
(global-set-key "\C-t" 'toggle-truncate-lines)

;comment/uncomment region
(global-set-key "\C-c\C-c" 'comment-or-uncomment-region)

;;Buffer-move
(global-set-key (kbd "<C-S-left>")   'buf-move-left)
(global-set-key (kbd "<C-S-right>")  'buf-move-right)
查看更多
甜甜的少女心
5楼-- · 2019-03-15 14:33

By default, C-x h marks the whole buffer, and C-M-\ runs indent-region, so doing those two one after the other will indent the whole buffer.

comment-dwim is already bound by default to M-;, and probably does better than comment-or-uncomment-region. ("DWIM" stands for "do-what-I-mean")

For completion, I recommend setting up auto-complete-mode, which interoperates with rsense. Auto-complete has standard keybindings for all completion.

As for rdebug, I would probably just stick it on one of the F-keys, or else something prefixed by C-c, since that is the sort-of designated "custom" prefix. Maybe C-c d for "Debug". To make sure that the key is not already bound, go to a ruby buffer and press C-h k and then press your key combination, and make sure that Emacs tells you that is is undefined.

查看更多
迷人小祖宗
6楼-- · 2019-03-15 14:42

I generally put global keybindings in a separate file(part of my configuration) and mode specific configuration in the mode-specific configuration files. That way everything is lean, tight and easy to find. Some of the things you've mentioned like comment/uncomment already have keybindings attached. I've implemented indent-buffer with a functions indent-buffer-or-region(part of EDT) that I've bound to the standard C-M-\ indentation key. There are formal rules for what keys should be used by users for their custom keybindings and there is of course common sense. Nothing is written in stone.

Here are some examples from Emacs Prelude:

;; You know, like Readline.
(global-set-key (kbd "C-M-h") 'backward-kill-word)

;; Align your code in a pretty way.
(global-set-key (kbd "C-x \\") 'align-regexp)

;; Perform general cleanup.
(global-set-key (kbd "C-c n") 'cleanup-buffer)

;; Font size
(define-key global-map (kbd "C-+") 'text-scale-increase)
(define-key global-map (kbd "C--") 'text-scale-decrease)

;; Jump to a definition in the current file. (This is awesome.)
(global-set-key (kbd "C-x C-i") 'ido-imenu)

;; File finding
(global-set-key (kbd "C-x M-f") 'ido-find-file-other-window)
(global-set-key (kbd "C-x C-M-f") 'find-file-in-project)
(global-set-key (kbd "C-x f") 'recentf-ido-find-file)
(global-set-key (kbd "C-c r") 'bury-buffer)
(global-set-key (kbd "M-`") 'file-cache-minibuffer-complete)

;; Window switching. (C-x o goes to the next window)
(global-set-key (kbd "C-x O") (lambda ()
                                (interactive)
                                (other-window -1))) ;; back one

;; Indentation help
(global-set-key (kbd "C-x ^") 'join-line)
(global-set-key (kbd "C-M-\\") 'indent-region-or-buffer)

;; Start proced in a similar manner to dired
(global-set-key (kbd "C-x p") 'proced)

;; Start eshell or switch to it if it's active.
(global-set-key (kbd "C-x m") 'eshell)

;; Start a new eshell even if one is active.
(global-set-key (kbd "C-x M") (lambda () (interactive) (eshell t)))

;; Start a regular shell if you prefer that.
(global-set-key (kbd "C-x M-m") 'shell)

;; If you want to be able to M-x without meta
(global-set-key (kbd "C-x C-m") 'execute-extended-command)

;; Fetch the contents at a URL, display it raw.
(global-set-key (kbd "C-x C-h") 'view-url)

;; Help should search more than just commands
(global-set-key (kbd "C-h a") 'apropos)

;; Should be able to eval-and-replace anywhere.
(global-set-key (kbd "C-c e") 'eval-and-replace)

;; Magit rules!
(global-set-key (kbd "C-x g") 'magit-status)

;; Activate occur easily inside isearch
(define-key isearch-mode-map (kbd "C-o")
  (lambda () (interactive)
    (let ((case-fold-search isearch-case-fold-search))
      (occur (if isearch-regexp
                 isearch-string
               (regexp-quote isearch-string))))))

;; cycle through buffers
(global-set-key (kbd "<C-tab>") 'bury-buffer)

;; use hippie-expand instead of dabbrev
(global-set-key (kbd "M-/") 'hippie-expand)

;; spell check Bulgarian text
(global-set-key (kbd "C-c B")
                (lambda()(interactive)
                  (ispell-change-dictionary "bulgarian")
                  (flyspell-buffer)))

;; replace buffer-menu with ibuffer
(global-set-key (kbd "C-x C-b") 'ibuffer)

;; interactive text replacement
(global-set-key (kbd "C-c C-r") 'iedit-mode)

;; swap windows
(global-set-key (kbd "C-c s") 'swap-windows)

;; duplicate the current line or region
(global-set-key (kbd "C-c d") 'duplicate-current-line-or-region)

;; rename buffer & visited file
(global-set-key (kbd "C-c r") 'rename-file-and-buffer)

;; open an ansi-term buffer
(global-set-key (kbd "C-x t") 'visit-term-buffer)

;; toggle input method
(global-set-key (kbd "C-\\") 'toggle-bulgarian-input-method)

;; search with google
(global-set-key (kbd "C-c g") 'google)

;; toggle menu-bar visibility
(global-set-key (kbd "<f12>") (lambda () (interactive) (menu-bar-mode)))
查看更多
登录 后发表回答