From mboxrd@z Thu Jan 1 00:00:00 1970 Path: main.gmane.org!not-for-mail From: storm@cua.dk (Kim F. Storm) Newsgroups: gmane.emacs.devel Subject: Suggestion: Simple way to make conditional key bindings. Date: 23 Aug 2002 14:05:13 +0200 Sender: emacs-devel-admin@gnu.org Message-ID: <5x4rdlbx1i.fsf@kfs2.cua.dk> NNTP-Posting-Host: localhost.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: main.gmane.org 1030100691 21929 127.0.0.1 (23 Aug 2002 11:04:51 GMT) X-Complaints-To: usenet@main.gmane.org NNTP-Posting-Date: Fri, 23 Aug 2002 11:04:51 +0000 (UTC) Return-path: Original-Received: from quimby.gnus.org ([80.91.224.244]) by main.gmane.org with esmtp (Exim 3.35 #1 (Debian)) id 17iCFG-0005ha-00 for ; Fri, 23 Aug 2002 13:04:50 +0200 Original-Received: from monty-python.gnu.org ([199.232.76.173]) by quimby.gnus.org with esmtp (Exim 3.12 #1 (Debian)) id 17iCia-0008Oy-00 for ; Fri, 23 Aug 2002 13:35:08 +0200 Original-Received: from localhost ([127.0.0.1] helo=monty-python.gnu.org) by monty-python.gnu.org with esmtp (Exim 4.10) id 17iCGQ-00029L-00; Fri, 23 Aug 2002 07:06:02 -0400 Original-Received: from list by monty-python.gnu.org with tmda-scanned (Exim 4.10) id 17iCFH-0001vq-00 for emacs-devel@gnu.org; Fri, 23 Aug 2002 07:04:51 -0400 Original-Received: from mail by monty-python.gnu.org with spam-scanned (Exim 4.10) id 17iCFE-0001vJ-00 for emacs-devel@gnu.org; Fri, 23 Aug 2002 07:04:50 -0400 Original-Received: from mail.filanet.dk ([195.215.206.179]) by monty-python.gnu.org with esmtp (Exim 4.10) id 17iCFE-0001v5-00 for emacs-devel@gnu.org; Fri, 23 Aug 2002 07:04:48 -0400 Original-Received: from kfs2.cua.dk.cua.dk (kfs2.local.filanet.dk [192.168.1.182]) by mail.filanet.dk (Postfix) with SMTP id 4444F7C016 for ; Fri, 23 Aug 2002 11:04:47 +0000 (GMT) Original-To: emacs-devel@gnu.org Original-Lines: 122 User-Agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.3.50 Errors-To: emacs-devel-admin@gnu.org X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.0.11 Precedence: bulk List-Help: List-Post: List-Subscribe: , List-Id: Emacs development discussions. List-Unsubscribe: , List-Archive: Xref: main.gmane.org gmane.emacs.devel:6787 X-Report-Spam: http://spam.gmane.org/gmane.emacs.devel:6787 Sometimes you would like a specific key binding to be controlled by some global or local state, but you really don't want to mess with minor-mode keymaps etc. The following method - illustrated by example - is simple, yet very powerful and flexible. The basic idea is to interpret a '(cond ...) binding "the natural way": (setq a nil b nil c nil) (global-set-key [f11] '(cond (a delete-char) (b find-file) (c nil) (t (keymap (?a . "abc") (?b . "bcd"))))) [f11 a] => "abc" [f11 b] => "bcd" [f11 c] => undefined (setq c t) [f11] => undefined (setq b t) [f11] => find-char (setq a t) [f11] => delete-char Here is a patch [against a fairly old keymap.c] to implement this feature. The simplicity of the approach is proven by the size of the patch :-) One use would be to bind C-y to `yank' except when the first element in the kill-ring is a table, in which case we want to run `yank-with-properties': (global-set-key "\C-y" '(cond ((and kill-ring (table-recognize-table (car kill-ring))) yank-with-properties) (t yank))) One advantage (IMO) is that C-h k C-y will report yank or yank-with-properties depending on the actual function taken if you hit C-y. WDYT ? Index: keymap.c =================================================================== RCS file: /cvs/emacs/src/keymap.c,v retrieving revision 1.260 diff -c -r1.260 keymap.c *** keymap.c 10 May 2002 23:57:14 -0000 1.260 --- keymap.c 13 May 2002 10:08:23 -0000 *************** *** 93,98 **** --- 93,99 ---- Lisp_Object Vdefine_key_rebound_commands; Lisp_Object Qkeymapp, Qkeymap, Qnon_ascii, Qmenu_item, Qremap; + Lisp_Object Qcond; /* Alist of elements like (DEL . "\d"). */ static Lisp_Object exclude_keys; *************** *** 690,695 **** --- 691,718 ---- return object; } + /* If the keymap contents looks like (cond (COND DEFN)...) + then find first non-nil COND and use its DEFN.*/ + + else if (EQ (XCAR (object), Qcond)) + { + register Lisp_Object args = XCDR (object); + object = Qnil; + for ( ; CONSP (args); args = XCDR (args)) + { + register Lisp_Object clause, val; + clause = XCAR (args); + if (!CONSP (clause) || !CONSP (XCDR (clause))) + continue; + val = menu_item_eval_property (XCAR (clause)); + if (!NILP (val)) + { + object = XCAR (XCDR (clause)); + break; + } + } + } + /* If the keymap contents looks like (STRING . DEFN), use DEFN. Keymap alist elements like (CHAR MENUSTRING . DEFN) will be used by HierarKey menus. */ *************** *** 3650,3655 **** --- 3673,3681 ---- Qremap = intern ("remap"); staticpro (&Qremap); + + Qcond = intern ("cond"); + staticpro (&Qcond); remap_command_vector = Fmake_vector (make_number (2), Qremap); staticpro (&remap_command_vector); -- Kim F. Storm http://www.cua.dk