From: Michal Nazarewicz <mina86@mina86.com>
To: 18729@debbugs.gnu.org
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 [thread overview]
Message-ID: <xa1tiojln57i.fsf@mina86.com> (raw)
---
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."
next reply other threads:[~2014-10-15 7:48 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-10-15 7:48 Michal Nazarewicz [this message]
2014-10-15 14:20 ` bug#18729: [PATCH] subr.el (set-key): New macro making creating new bindings more concise Stefan Monnier
2014-10-16 12:39 ` Michal Nazarewicz
2014-10-16 14:50 ` Stefan Monnier
2014-10-27 17:52 ` Michal Nazarewicz
2015-01-19 15:40 ` Michal Nazarewicz
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/emacs/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=xa1tiojln57i.fsf@mina86.com \
--to=mina86@mina86.com \
--cc=18729@debbugs.gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).