[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
bug#18729: [PATCH] subr.el (set-key): New macro making creating new bind
From: |
Michal Nazarewicz |
Subject: |
bug#18729: [PATCH] subr.el (set-key): New macro making creating new bindings more concise. |
Date: |
Wed, 15 Oct 2014 09:48:49 +0200 |
User-agent: |
Notmuch/0.17+15~gb65ca8e (http://notmuchmail.org) Emacs/24.4.50.1 (x86_64-unknown-linux-gnu) |
---
lisp/ChangeLog | 6 +++++
lisp/subr.el | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 79 insertions(+)
I found this macro very convenient for my configuration file, so
perhaps it's a good match for inclusion in Emacs? It handles the
majority of uses of
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 6916143..a5c4632 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,9 @@
+2014-10-15 Michal Nazarewicz <mina86@mina86.com>
+
+ * subr.el (set-key): New macro making creating new bindings more
+ concise and thus somehow easier/faster to type in user
+ configuration file.
+
2014-10-15 Eli Zaretskii <eliz@gnu.org>
* emacs-lisp/tabulated-list.el (tabulated-list-mode): Force
diff --git a/lisp/subr.el b/lisp/subr.el
index 585f936..9b1ceb3 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -836,6 +836,79 @@ cases is shared with all other buffers in the same major
mode."
(signal 'wrong-type-argument (list 'arrayp key)))
(define-key map key command)))
+(defun set-key--current-local-map ()
+ "Return current local map creating one if not set yet."
+ (or (current-local-map)
+ (let ((map (make-sparse-keymap)))
+ (use-local-map map)
+ map)))
+
+(defmacro set-key (keymap key &rest def)
+ "(set-key [KEYMAP] KEY . DEF)
+
+In KEYMAP, define key sequence KEY as DEF.
+
+KEYMAP can be :global (to mean global keymap, the default), :local (to mean
+the local keymap) or an unquoted symbol (to mean a keymap in given variable).
+
+KEY is anything `define-key' accepts as a key except that if KEYMAP was not
+given, KEY cannot be an unquoted symbol, i.e.:
+ (let ((key \"a\"))
+ (set-key key self-insert-command) ; will *not* work
+ (set-key :global key self-insert-command)) ; will work
+
+If DEF is a single unquoted symbol it will be quoted, otherwise if it is
+a single non-cons value it will not be quoted, otherwise it will be processed
+as a lambda (see below). Thus the following do what one might expect:
+ (set-key \"a\" self-insert-command)
+ ;; same as (global-set-key \"a\" 'self-insert-command)
+ (set-key \"\\C-h\" [(backspace)])
+ ;; same as (global-set-key \"\\C-h\" [(backspace)])
+ (set-key \"\\C-d\" ())
+ ;; same as (global-set-key \"\\C-h\" ())
+However, the following will not work:
+ (let ((callback 'self-insert-command))
+ (set-key \"a\" callback))
+ ;; same as (global-set-key \"a\" 'callback)
+
+If DEF is a cons value its format is:
+ ([:args ARGS INTERACTIVE] . BODY)
+and results in the following lambda:
+ (lambda ARGS (interactive INTERACTIVE) . BODY)
+or if :args is not given (at which point DEF == BODY):
+ (lambda () (interactive) . BODY)
+For example:
+ (set-key \"\\C-B\" (goto-char (- (point) 2)))
+ ;; same as (global-set-key \"\\C-B\"
+ ;; (lambda () (interactive) (goto-char (- (point) 2))))
+ (set-key \"\\C-B\" :args (n) \"P\" (goto-char (- (point) (* 2 n))))
+ ;; same as (global-set-key \"\\C-B\"
+ ;; (lambda (n) (interactive \"P\")
+ ;; (goto-char (- (point) (* 2 n)))))
+
+This macro is not a replacement for `define-key', `global-set-key' or
+`local-set-key', since it is not capable of dealing with some forms of DEFs
+that those functions accept. Instead it is meant as a helper to use in user
+configuration file to make setting up bindings more concise especially when
+lambdas are used."
+ (setq keymap (cond ((eq :local keymap) '(set-key--current-local-map))
+ ((eq :global keymap) '(current-global-map))
+ ((symbolp keymap) keymap)
+ (t
+ (setq def (cons key def) key keymap) ; shift args
+ '(current-global-map))))
+ (unless def
+ (error "DEF argument missing"))
+ (list
+ 'define-key keymap key
+ (cond ((or (cdr def) (consp (car def)))
+ (let ((args (if (eq :args (car def)) (cadr def)))
+ (interactive (if (eq :args (car def)) (list (car (cddr def)))))
+ (body (if (eq :args (car def)) (cdr (cddr def)) def)))
+ `(function (lambda ,args (interactive . ,interactive) ,@body))))
+ ((symbolp (car def)) (list 'quote (car def)))
+ ((car def)))))
+
(defun global-unset-key (key)
"Remove global binding of KEY.
KEY is a string or vector representing a sequence of keystrokes."
- bug#18729: [PATCH] subr.el (set-key): New macro making creating new bindings more concise.,
Michal Nazarewicz <=