From mboxrd@z Thu Jan 1 00:00:00 1970 From: Bastien Subject: Re: Best way to implement project specific captures Date: Thu, 23 Aug 2012 17:08:30 +0200 Message-ID: <87ipc91w9d.fsf@altern.org> References: <878vd79en7.fsf@altern.org> <874nnv9ekc.fsf@altern.org> <87a9xmyns1.fsf@altern.org> <84119130-9EE5-4516-B230-AB578DF615FB@gmail.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Return-path: Received: from eggs.gnu.org ([208.118.235.92]:44646) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1T4Z16-0004lb-H2 for emacs-orgmode@gnu.org; Thu, 23 Aug 2012 11:08:21 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1T4Z14-0007Cs-IQ for emacs-orgmode@gnu.org; Thu, 23 Aug 2012 11:08:16 -0400 Received: from mail-wg0-f41.google.com ([74.125.82.41]:34695) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1T4Z14-0007Ck-8f for emacs-orgmode@gnu.org; Thu, 23 Aug 2012 11:08:14 -0400 Received: by wgbds1 with SMTP id ds1so378484wgb.0 for ; Thu, 23 Aug 2012 08:08:12 -0700 (PDT) In-Reply-To: <84119130-9EE5-4516-B230-AB578DF615FB@gmail.com> (Carsten Dominik's message of "Thu, 23 Aug 2012 12:36:06 +0200") List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org Sender: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org To: Carsten Dominik Cc: Sylvain Rousseau , emacs-orgmode@gnu.org --=-=-= Content-Type: text/plain Hi Carsten, Carsten Dominik writes: > I am wondering if the following feature would be useful as well: Context > sensitivity sounds most interesting to me if the same key would do > different things in different contexts. I am not sure if this is possible > with the current implementation? For example, I might want to have a bug > recording key which creates an entry in a bug tracker file, but the file is > different for different source files, and also the template and target type > definitions might be different in different contexts. > > That would require a setup which defines a selection letter, and then an a > list of (sets of) conditions and the corresponding template > definition. I implemented this, relying on the existing contexts options. Please have a go with the attached patch. I copy the comment from the commit log: In the setup below, X is not a real capture template, it is just an alias to templates A and B in .txt and .el files. A and B are deactivated by default in all files. (setq org-capture-templates '(("X" "Nothing but an alias") ("A" "AAAA" entry (file+headline [...])) ("B" "BBBB" entry (file+headline [...])))) (setq org-capture-templates-contexts '(("A" "A" ((not-in-file . ".*"))) ("B" "B" ((not-in-file . ".*"))) ("X" "A" ((in-file . "\\.txt"))) ("X" "B" ((in-file . "\\.el"))))) I find this quite handy... let me know what you think! --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0001-Implement-key-replacement-depending-on-the-contexts.patch >From c191d48aa1f2eb6c28fe2503b6b039265fb1da1e Mon Sep 17 00:00:00 2001 From: Bastien Guerry Date: Thu, 23 Aug 2012 17:04:43 +0200 Subject: [PATCH] Implement key replacement depending on the contexts. * org.el (org-contextualize-agenda-or-capture): Handle key replacement depending on the contexts. * org-capture.el (org-capture-templates-contexts): Allow to use the context as a way to replace one capture template by another one. * org-agenda.el (org-agenda-custom-commands-contexts): Allow to use the context as a way to replace one agenda custom command by another one. * org.texi (Templates in contexts): Document the new structure of the variables `org-agenda-custom-commands-contexts' and `org-capture-templates-contexts'. In the setup below, X is not a real capture template, it is just an alias to templates A and B in .txt and .el files. A and B are deactivated by default in all files. (setq org-capture-templates '(("X" "Nothing but an alias") ("A" "AAAA" entry (file+headline [...])) ("B" "BBBB" entry (file+headline [...])))) (setq org-capture-templates-contexts '(("A" "A" ((not-in-file . ".*"))) ("B" "B" ((not-in-file . ".*"))) ("X" "A" ((in-file . "\\.txt"))) ("X" "B" ((in-file . "\\.el"))))) Thanks to Carsten for suggesting this "key-replacement" idea! --- doc/org.texi | 16 +++++++++++++--- lisp/org-agenda.el | 20 +++++++++++++++++--- lisp/org-capture.el | 22 ++++++++++++++++++---- lisp/org.el | 40 +++++++++++++++++++++++++++++++--------- 4 files changed, 79 insertions(+), 19 deletions(-) diff --git a/doc/org.texi b/doc/org.texi index 897115c..3ec72b3 100644 --- a/doc/org.texi +++ b/doc/org.texi @@ -6863,10 +6863,14 @@ for example that you have a capture template @code{"p"} for storing Gnus emails containing patches. Then you would configure this option like this: @example -(setq org-capture-templates-contexts '(("p" (in-mode . "message-mode")))) +(setq org-capture-templates-contexts + '(("p" "p" (in-mode . "message-mode")))) @end example -See the docstring of the variable for more information. +The second @code{"p"} tells what template to really call in the specified +context. You can set this to another capture template, so that @code{p} will +transparently fall back on it. See the docstring of the variable for more +information. @node Attachments, RSS Feeds, Capture, Capture - Refile - Archive @section Attachments @@ -8778,9 +8782,15 @@ that you only need when reading emails. Then you would configure this option like this: @example -(setq org-agenda-custom-commands-contexts '(("o" (in-mode . "message-mode")))) +(setq org-agenda-custom-commands-contexts + '(("o" "o" (in-mode . "message-mode")))) @end example +The second @code{"o"} tells what command to really call in the specified +context. You can set this to another agenda custom command, so that @code{o} +will transparently fall back on it. See the docstring of the variable for +more information. + See the docstring of the variable for more information. @node Exporting Agenda Views, Agenda column view, Custom agenda views, Agenda Views diff --git a/lisp/org-agenda.el b/lisp/org-agenda.el index 9c7f29b..563ed3f 100644 --- a/lisp/org-agenda.el +++ b/lisp/org-agenda.el @@ -2341,9 +2341,22 @@ For example, if you have a custom agenda command \"p\" and you want this command to be accessible only from plain text files, use this: - '((\"p\" (in-file . \"\\.txt\"))) + '((\"p\" \"p\" (in-file . \"\\.txt\"))) -Here are the available checks: +If you replace the second \"p\" by another key (say \"q\"), then +the \"p\" key will be associated with the \"q\" command in the +valid contexts. This is useful if you want to use the same key +to reach multiple commands depending on the context: + + '((\"p\" \"q\" (in-file . \"\\.txt\")) + (\"p\" \"r\" (in-file . \"\\.el\")) + (\"p\" \"s\" (in-file . \"\\.c\"))) + +Here, the \"p\" key will be accessible from buffers visiting +.txt, .el and .c files, and it will be a synonym for \"q\", \"r\" +and \"s\" respectively. + +Here are the available contexts definition: in-file: command displayed only in matching files in-mode: command displayed only in matching modes @@ -2354,8 +2367,9 @@ If you define several checks, the agenda command will be accessible if there is at least one valid check." ;; :version "24.3" :group 'org-agenda-custom-commands - :type '(repeat (cons :tag "Rule" + :type '(repeat (list :tag "Rule" (string :tag "Agenda key") + (string :tag "Replace by command") (repeat :tag "Available when" (cons :tag "Condition" (choice diff --git a/lisp/org-capture.el b/lisp/org-capture.el index 782e027..368894e 100644 --- a/lisp/org-capture.el +++ b/lisp/org-capture.el @@ -442,12 +442,25 @@ for a capture buffer.") "Bind capture keys with rules on where to display them. For example, if you have a capture template \"c\" and you want -this template to be accessible only from message-mode buffers, +this template to be accessible only from `message-mode' buffers, use this: - '((\"c\" (in-mode . \"message-mode\"))) + '((\"c\" \"c\" (in-mode . \"message-mode\"))) -Here are the available checks: +If you replace the second \"c\" by another key (say \"d\"), then +the \"c\" key will be associated with the \"d\" template in the +valid contexts. This is useful if you want to use the same key +for different templates depending on the context: + + '((\"c\" \"d\" (in-file . \"\\.txt\")) + (\"c\" \"e\" (in-file . \"\\.el\")) + (\"c\" \"f\" (in-file . \"\\.c\"))) + +Here, the \"c\" key will be accessible from buffers visiting +.txt, .el and .c files, and it will be a synonym for \"d\", \"e\" +and \"f\" respectively. + +Here are the available contexts definition: in-file: template displayed only in matching files in-mode: template displayed only in matching modes @@ -458,8 +471,9 @@ If you define several checks, the capture template will be accessible if there is at least one valid check." ;; :version "24.3" :group 'org-capture - :type '(repeat (cons :tag "Rule" + :type '(repeat (list :tag "Rule" (string :tag "Capture key") + (string :tag "Replace by template") (repeat :tag "Available when" (cons :tag "Condition" (choice diff --git a/lisp/org.el b/lisp/org.el index 96b5584..c8b6c54 100644 --- a/lisp/org.el +++ b/lisp/org.el @@ -8623,15 +8623,37 @@ to execute outside of tables." "Return a subset of elements in ALIST depending on CONTEXTS. ALIST can be either `org-agenda-custom-commands' or `org-capture-templates'." - (let ((a alist) c r) - (while (setq c (pop a)) - (when (or (not (assoc (car c) contexts)) - (and (assoc (car c) contexts) - (org-rule-validate - (cdr (assoc (car c) contexts))))) - (push c r))) - ;; Return the limited ALIST - r)) + (let ((a alist) c r s val repl) + (while (setq c (pop a)) ; loop over commands or templates + (cond ((not (assoc (car c) contexts)) + (push c r)) + ((and (assoc (car c) contexts) + (let (rr) + (setq val + (org-rule-validate + (and (mapc ; check all contexts associations + (lambda (rl) + (when (equal (car rl) (car c)) + (setq rr (delq nil (append rr (car (last rl))))))) + contexts) + rr))))) + (setq repl + (car (delq nil + (mapcar (lambda(cnt) + (when (and (member (car val) (caddr cnt)) + (equal (car c) (car cnt))) cnt)) + contexts)))) + (unless (equal (car c) (cadr repl)) + (push (cadr repl) s)) + (push (cons (car c) (cdr (assoc (cadr repl) alist))) r)))) + ;; Return limited ALIST, possibly with keys modified, and deduplicated + (delq nil + (mapcar (lambda(x) + (let ((tpl (car x))) + (when (not (delq nil + (mapcar (lambda(y) + (equal y tpl)) s))) x))) + r)))) (defun org-rule-validate (rules) "Check if one of RULES is valid in this buffer." -- 1.7.10.2 --=-=-= Content-Type: text/plain -- Bastien --=-=-=--