emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
From: Bastien <bzg@altern.org>
To: Carsten Dominik <carsten.dominik@gmail.com>
Cc: Sylvain Rousseau <thisirs@gmail.com>, emacs-orgmode@gnu.org
Subject: Re: Best way to implement project specific captures
Date: Thu, 23 Aug 2012 17:08:30 +0200	[thread overview]
Message-ID: <87ipc91w9d.fsf@altern.org> (raw)
In-Reply-To: <84119130-9EE5-4516-B230-AB578DF615FB@gmail.com> (Carsten Dominik's message of "Thu, 23 Aug 2012 12:36:06 +0200")

[-- Attachment #1: Type: text/plain, Size: 1438 bytes --]

Hi Carsten,

Carsten Dominik <carsten.dominik@gmail.com> 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!


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Implement-key-replacement-depending-on-the-contexts.patch --]
[-- Type: text/x-patch, Size: 8097 bytes --]

From c191d48aa1f2eb6c28fe2503b6b039265fb1da1e Mon Sep 17 00:00:00 2001
From: Bastien Guerry <bzg@altern.org>
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


[-- Attachment #3: Type: text/plain, Size: 14 bytes --]


-- 
 Bastien

  parent reply	other threads:[~2012-08-23 15:08 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-08-22  3:00 Best way to implement project specific captures Richard Riley
2012-08-22 11:48 ` Sylvain Rousseau
2012-08-22 14:37   ` Bastien
2012-08-22 14:38     ` Bastien
2012-08-22 18:04       ` Sylvain Rousseau
2012-08-23  9:13         ` Bastien
2012-08-23 10:36           ` Carsten Dominik
2012-08-23 11:09             ` Jambunathan K
2012-08-23 15:08             ` Bastien [this message]
2012-08-23 17:16             ` Sylvain Rousseau
2012-08-22 21:12   ` Richard Riley
2012-08-22 22:04   ` Richard Riley
2012-08-22 22:54     ` Richard Riley
2012-08-23  8:52       ` Sylvain Rousseau
2012-08-23 17:52         ` Richard Riley
2012-08-24 12:25           ` Bastien
2012-08-24 19:38             ` Richard Riley
2012-08-24 20:00               ` Bastien
2012-08-24 20:01               ` Bastien
2012-08-26  6:18                 ` Richard Riley

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.orgmode.org/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87ipc91w9d.fsf@altern.org \
    --to=bzg@altern.org \
    --cc=carsten.dominik@gmail.com \
    --cc=emacs-orgmode@gnu.org \
    --cc=thisirs@gmail.com \
    /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/org-mode.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).