mirror of
https://git.savannah.gnu.org/git/emacs/org-mode.git
synced 2024-12-28 10:56:57 +00:00
Implement context filtering for agenda commands and capture templates.
* org.el (org-contextualize-agenda-or-capture) (org-rule-validate): New functions, implement context filtering for agenda commands and capture templates. * org-agenda.el (org-agenda-custom-commands-contexts): New option. (org-agenda): Use it. * org-capture.el (org-capture-templates-contexts): New option. (org-capture-select-template): Use it. * org.texi (Templates in contexts): Document the new option `org-capture-templates-contexts'. (Storing searches): Document the new option `org-agenda-custom-commands-contexts'. This idea comes from Sylvain Rousseau, who implemented a similar feature with org-context.el: https://github.com/thisirs/org-context This implementation is a bit simpler and more general. Simpler because it relies on existing templates, no need to define other contextual ones. More general because contexts can be defined wrt files and modes. Thanks *very much* to Sylvain for paving the way -- certainly a great addition to Org.
This commit is contained in:
parent
6dedecf806
commit
d378c7b41b
39
doc/org.texi
39
doc/org.texi
@ -1,4 +1,3 @@
|
||||
|
||||
\input texinfo
|
||||
@c %**start of header
|
||||
@setfilename ../../info/org
|
||||
@ -494,6 +493,7 @@ Capture templates
|
||||
|
||||
* Template elements:: What is needed for a complete template entry
|
||||
* Template expansion:: Filling in information about time and context
|
||||
* Templates in contexts:: Only show a template in a specific context
|
||||
|
||||
Archiving
|
||||
|
||||
@ -6631,6 +6631,7 @@ like this:
|
||||
@menu
|
||||
* Template elements:: What is needed for a complete template entry
|
||||
* Template expansion:: Filling in information about time and context
|
||||
* Templates in contexts:: Only show a template in a specific context
|
||||
@end menu
|
||||
|
||||
@node Template elements, Template expansion, Capture templates, Capture templates
|
||||
@ -6774,7 +6775,7 @@ buffer again after capture is completed.
|
||||
@end table
|
||||
@end table
|
||||
|
||||
@node Template expansion, , Template elements, Capture templates
|
||||
@node Template expansion, Templates in contexts, Template elements, Capture templates
|
||||
@subsubsection Template expansion
|
||||
|
||||
In the template itself, special @kbd{%}-escapes@footnote{If you need one of
|
||||
@ -6852,6 +6853,20 @@ To place the cursor after template expansion use:
|
||||
%? @r{After completing the template, position cursor here.}
|
||||
@end smallexample
|
||||
|
||||
@node Templates in contexts, , Template expansion, Capture templates
|
||||
@subsubsection Templates in contexts
|
||||
|
||||
@vindex org-capture-templates-contexts
|
||||
To control whether a capture template should be accessible from a specific
|
||||
context, you can customize @var{org-capture-templates-contexts}. Let's say
|
||||
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"))))
|
||||
@end example
|
||||
|
||||
See the docstring of the variable for more information.
|
||||
|
||||
@node Attachments, RSS Feeds, Capture, Capture - Refile - Archive
|
||||
@section Attachments
|
||||
@ -8590,11 +8605,12 @@ buffer, or a sparse tree (the latter covering of course only the current
|
||||
buffer).
|
||||
@kindex C-c a C
|
||||
@vindex org-agenda-custom-commands
|
||||
|
||||
Custom commands are configured in the variable
|
||||
@code{org-agenda-custom-commands}. You can customize this variable, for
|
||||
example by pressing @kbd{C-c a C}. You can also directly set it with
|
||||
Emacs Lisp in @file{.emacs}. The following example contains all valid
|
||||
search types:
|
||||
example by pressing @kbd{C-c a C}. You can also directly set it with Emacs
|
||||
Lisp in @file{.emacs}. The following example contains all valid search
|
||||
types:
|
||||
|
||||
@lisp
|
||||
@group
|
||||
@ -8754,6 +8770,18 @@ this interface, the @emph{values} are just Lisp expressions. So if the
|
||||
value is a string, you need to add the double-quotes around the value
|
||||
yourself.
|
||||
|
||||
@vindex org-agenda-custom-commands-contexts
|
||||
To control whether an agenda command should be accessible from a specific
|
||||
context, you can customize @var{org-agenda-custom-commands-contexts}. Let's
|
||||
say for example that you have an agenda commands @code{"o"} displaying a view
|
||||
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"))))
|
||||
@end example
|
||||
|
||||
See the docstring of the variable for more information.
|
||||
|
||||
@node Exporting Agenda Views, Agenda column view, Custom agenda views, Agenda Views
|
||||
@section Exporting Agenda Views
|
||||
@ -16819,7 +16847,6 @@ work on a tty.
|
||||
@item
|
||||
@i{Piotr Zielinski} wrote @file{org-mouse.el}, proposed agenda blocks
|
||||
and contributed various ideas and code snippets.
|
||||
@item
|
||||
@end itemize
|
||||
|
||||
|
||||
|
@ -2334,6 +2334,37 @@ that have been changed along."
|
||||
(defvar org-agenda-last-dispatch-buffer nil)
|
||||
(defvar org-agenda-overriding-restriction nil)
|
||||
|
||||
(defcustom org-agenda-custom-commands-contexts nil
|
||||
"Alist of custom agenda commands and valid contexts.
|
||||
|
||||
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\")))
|
||||
|
||||
Here are the available checks:
|
||||
|
||||
in-file: command displayed only in matching files
|
||||
in-mode: command displayed only in matching modes
|
||||
not-in-file: command not displayed in matching files
|
||||
not-in-mode: command not displayed in matching modes
|
||||
|
||||
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"
|
||||
(string :tag "Agenda key")
|
||||
(repeat :tag "Available when"
|
||||
(cons :tag "Condition"
|
||||
(choice
|
||||
(const :tag "In file" in-file)
|
||||
(const :tag "Not in file" not-in-file)
|
||||
(const :tag "In mode" in-mode)
|
||||
(const :tag "Not in mode" not-in-mode))
|
||||
(regexp))))))
|
||||
|
||||
;;;###autoload
|
||||
(defun org-agenda (&optional arg keys restriction)
|
||||
"Dispatch agenda commands to collect entries to the agenda buffer.
|
||||
@ -2389,6 +2420,9 @@ Pressing `<' twice means to restrict to the current subtree or region
|
||||
((not (nth 1 x)) (cons (car x) (cons "" (cddr x))))
|
||||
(t (cons (car x) (cons "" (cdr x))))))
|
||||
org-agenda-custom-commands)))
|
||||
(org-agenda-custom-commands
|
||||
(org-contextualize-agenda-or-capture
|
||||
org-agenda-custom-commands org-agenda-custom-commands-contexts))
|
||||
(buf (current-buffer))
|
||||
(bfn (buffer-file-name (buffer-base-buffer)))
|
||||
entry key type match lprops ans)
|
||||
|
@ -438,6 +438,37 @@ for a capture buffer.")
|
||||
(entry (org-capture-select-template keys)))
|
||||
(org-capture)))
|
||||
|
||||
(defcustom org-capture-templates-contexts nil
|
||||
"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,
|
||||
use this:
|
||||
|
||||
'((\"c\" (in-mode . \"message-mode\")))
|
||||
|
||||
Here are the available checks:
|
||||
|
||||
in-file: template displayed only in matching files
|
||||
in-mode: template displayed only in matching modes
|
||||
not-in-file: template not displayed in matching files
|
||||
not-in-mode: template not displayed in matching modes
|
||||
|
||||
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"
|
||||
(string :tag "Capture key")
|
||||
(repeat :tag "Available when"
|
||||
(cons :tag "Condition"
|
||||
(choice
|
||||
(const :tag "In file" in-file)
|
||||
(const :tag "Not in file" not-in-file)
|
||||
(const :tag "In mode" in-mode)
|
||||
(const :tag "Not in mode" not-in-mode))
|
||||
(regexp))))))
|
||||
|
||||
;;;###autoload
|
||||
(defun org-capture (&optional goto keys)
|
||||
"Capture something.
|
||||
@ -1282,7 +1313,8 @@ Use PREFIX as a prefix for the name of the indirect buffer."
|
||||
"Select a capture template.
|
||||
Lisp programs can force the template by setting KEYS to a string."
|
||||
(let ((org-capture-templates
|
||||
(or org-capture-templates
|
||||
(or (org-contextualize-agenda-or-capture
|
||||
org-capture-templates org-capture-templates-contexts)
|
||||
'(("t" "Task" entry (file+headline "" "Tasks")
|
||||
"* TODO %?\n %u\n %a")))))
|
||||
(if keys
|
||||
|
31
lisp/org.el
31
lisp/org.el
@ -8619,6 +8619,37 @@ to execute outside of tables."
|
||||
keys)
|
||||
'('orgstruct-error))))))))
|
||||
|
||||
(defun org-contextualize-agenda-or-capture (alist contexts)
|
||||
"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))
|
||||
|
||||
(defun org-rule-validate (rules)
|
||||
"Check if one of RULES is valid in this buffer."
|
||||
(let (r res)
|
||||
(while (setq r (pop rules))
|
||||
(when (or (and (eq (car r) 'in-file)
|
||||
(buffer-file-name)
|
||||
(string-match (cdr r) (buffer-file-name)))
|
||||
(and (eq (car r) 'in-mode)
|
||||
(string-match (cdr r) (symbol-name major-mode)))
|
||||
(when (and (eq (car r) 'not-in-file)
|
||||
(buffer-file-name))
|
||||
(not (string-match (cdr r) (buffer-file-name))))
|
||||
(when (eq (car r) 'not-in-mode)
|
||||
(not (string-match (cdr r) (symbol-name major-mode)))))
|
||||
(push r res)))
|
||||
(delq nil res)))
|
||||
|
||||
(defun org-context-p (&rest contexts)
|
||||
"Check if local context is any of CONTEXTS.
|
||||
Possible values in the list of contexts are `table', `headline', and `item'."
|
||||
|
Loading…
Reference in New Issue
Block a user