From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Tassilo Horn Newsgroups: gmane.emacs.devel Subject: Re: A simple implementation of context-sensitive keys Date: Thu, 11 Sep 2008 09:17:48 +0200 Message-ID: <87r67rjgmb.fsf@thinkpad.tsdh.de> References: <87y72079mg.fsf@thinkpad.tsdh.de> <87d4jbg62j.fsf@thinkpad.tsdh.de> NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: ger.gmane.org 1221117622 8484 80.91.229.12 (11 Sep 2008 07:20:22 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Thu, 11 Sep 2008 07:20:22 +0000 (UTC) Cc: emacs-devel@gnu.org To: Stefan Monnier Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Thu Sep 11 09:21:18 2008 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by lo.gmane.org with esmtp (Exim 4.50) id 1KdgUC-0006AD-0g for ged-emacs-devel@m.gmane.org; Thu, 11 Sep 2008 09:21:04 +0200 Original-Received: from localhost ([127.0.0.1]:55471 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1KdgTB-0004fd-GQ for ged-emacs-devel@m.gmane.org; Thu, 11 Sep 2008 03:20:01 -0400 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1KdgT6-0004cz-E1 for emacs-devel@gnu.org; Thu, 11 Sep 2008 03:19:56 -0400 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1KdgT6-0004cX-0M for emacs-devel@gnu.org; Thu, 11 Sep 2008 03:19:56 -0400 Original-Received: from [199.232.76.173] (port=50652 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1KdgT5-0004cM-PA for emacs-devel@gnu.org; Thu, 11 Sep 2008 03:19:55 -0400 Original-Received: from mx20.gnu.org ([199.232.41.8]:40526) by monty-python.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1KdgT5-0001Mf-8t for emacs-devel@gnu.org; Thu, 11 Sep 2008 03:19:55 -0400 Original-Received: from deliver.uni-koblenz.de ([141.26.64.15]) by mx20.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1KdgT4-0002od-Ix for emacs-devel@gnu.org; Thu, 11 Sep 2008 03:19:54 -0400 Original-Received: from localhost (localhost [127.0.0.1]) by deliver.uni-koblenz.de (Postfix) with ESMTP id 995DD789405F; Thu, 11 Sep 2008 09:19:53 +0200 (CEST) Original-Received: from deliver.uni-koblenz.de ([127.0.0.1]) by localhost (deliver.uni-koblenz.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 05026-10; Thu, 11 Sep 2008 09:19:52 +0200 (CEST) X-CHKRCPT: Envelopesender vrfy tassilo@member.fsf.org Original-Received: from thinkpad.tsdh.de (dhcp188.uni-koblenz.de [141.26.71.188]) by deliver.uni-koblenz.de (Postfix) with ESMTP id 1708778004C0; Thu, 11 Sep 2008 09:19:52 +0200 (CEST) Mail-Copies-To: never Mail-Followup-To: Stefan Monnier , emacs-devel@gnu.org In-Reply-To: (Stefan Monnier's message of "Wed, 10 Sep 2008 21:41:22 -0400") User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.60 (gnu/linux) X-Virus-Scanned: amavisd-new at uni-koblenz.de X-detected-kernel: by mx20.gnu.org: Linux 2.6, seldom 2.4 (older, 4) X-detected-kernel: by monty-python.gnu.org: Genre and OS details not recognized. X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:103798 Archived-At: Stefan Monnier writes: Hi! > I hope we can do better than that, i.e. come up with a way to do > something like what you proposed, but still have where-is, C-h k, > etc... take it into account. But what would C-h k say in that case? TAB is bound to FOO if BAR matches, or to FOO2 if BAR2 matches, else to FOO3. Currently with my approach it says: ,---- | TAB (translated from ) runs the command (lambda nil "Execute | command if eolp matches." (interactive) (if (cond ((user-variable-p | (quote eolp)) eolp) ((functionp (quote eolp)) (funcall (quote eolp))) | (t (eval eolp)))... `---- In my new version (below) I allow arbitrary forms as predicate, so the command really can get long and unreadably. I think it would get much better, if describe-function would pretty-print lambda forms. --8<---------------cut here---------------start------------->8--- (defmacro define-context-key (keymap key predicate command &optional mode) "Bind KEY in KEYMAP to a command which calls COMMAND if PREDICATE is non-nil. If PREDICATE doesn't match and KEY is normally bound in KEYMAP, the corresponding default command will be executed. If KEY isn't normally bound in KEYMAP, MODE (defaulting to s/KEYMAP/-map//) will be disabled temporally (to prevent an infinite recursion) and the function which is then bound to KEY will be called. Here're two examples: ;; TAB on an outline heading toggles visibility (define-context-key outline-minor-mode-map (kbd \"TAB\") ;; This evals to non-nil, if `point' is on a outline-heading (save-excursion (goto-char (line-beginning-position)) (looking-at outline-regexp)) outline-toggle-children) ;; TAB at end of line insert a TAB character (define-context-key outline-minor-mode-map (kbd \"TAB\") eolp self-insert-command) The context key for KEYMAP and KEY which was given as last has precedence, so in this example TAB at the end of a line of an outline heading inserts a TAB and doesn't toggle the visibility." (let* ((mode (or mode (intern (replace-regexp-in-string "-map" "" (symbol-name keymap))))) (default-fun (lookup-key (symbol-value keymap) (eval key)))) `(define-key ,keymap ,key (lambda () ,(concat "Execute " (symbol-name command) " if " (format "%s" predicate) " matches.") (interactive) (if (cond ((user-variable-p (quote ,predicate)) ,predicate) ((functionp (quote ,predicate)) (funcall (quote ,predicate))) (t (eval ,predicate))) (call-interactively (quote ,command)) (if (quote ,default-fun) (call-interactively (quote ,default-fun)) (let (,mode) (call-interactively (key-binding ,key))))))))) --8<---------------cut here---------------end--------------->8--- -- Chuck Norris played Russian Roulette with a fully loaded gun and won.