cp-org-capture: offer both project-specific and regular templates

The regular templates determined by the variables
`org-capture-templates` and `org-capture-templates-contexts` are now
added to the project-specific templates. If not inside a project, the
project templates are ignored. Thus `counsel-projectile-org-capture`
can now systematically be used instead of `org-capture` or `counsel-org-capture`.
This commit is contained in:
Eric Danan 2018-07-18 17:42:46 +02:00
parent 2bb5aab9e8
commit 6ffcf45767
2 changed files with 63 additions and 44 deletions

View file

@ -72,7 +72,7 @@ New commands:
| :------------------- | :------------------------------- | :-------------------------------------------------- | | :------------------- | :------------------------------- | :-------------------------------------------------- |
| <kbd>C-c p SPC</kbd> | `counsel-projectile` | Jump to a project buffer or file, or switch project | | <kbd>C-c p SPC</kbd> | `counsel-projectile` | Jump to a project buffer or file, or switch project |
| <kbd>C-c p s r</kbd> | `counsel-projectile-rg` | Search project with rg | | <kbd>C-c p s r</kbd> | `counsel-projectile-rg` | Search project with rg |
| <kbd>C-c p O c</kbd> | `counsel-projectile-org-capture` | Org-capture into project | | <kbd>C-c p O c</kbd> | `counsel-projectile-org-capture` | Capture into project |
| <kbd>C-c p O a</kbd> | `counsel-projectile-org-capture` | Open project agenda | | <kbd>C-c p O a</kbd> | `counsel-projectile-org-capture` | Open project agenda |
## The `counsel-projectile` command ## The `counsel-projectile` command
Default key binding: <kbd>C-c p SPC</kbd>. Default key binding: <kbd>C-c p SPC</kbd>.
@ -117,7 +117,8 @@ This command is a replacement for `projectile-switch-project`. It adds the possi
| <kbd>x s</kbd> | Invoke shell from the project root | | <kbd>x s</kbd> | Invoke shell from the project root |
| <kbd>x e</kbd> | Invoke eshell from the project root | | <kbd>x e</kbd> | Invoke eshell from the project root |
| <kbd>x t</kbd> | Invoke term from the project root | | <kbd>x t</kbd> | Invoke term from the project root |
| <kbd>O</kbd> | Org-capture into project: call `counsel-projectile-org-capture` (see below) | | <kbd>O c</kbd> | Capture into project: call `counsel-projectile-org-capture` (see below) |
| <kbd>O a</kbd> | Open project agenda: call `counsel-projectile-org-agenda` (see below) |
## The `counsel-projectile-find-file` command ## The `counsel-projectile-find-file` command
Default key binding: <kbd>C-c p f</kbd>. Default key binding: <kbd>C-c p f</kbd>.
@ -173,7 +174,9 @@ This command is similar to `counsel-projectile-grep` (see above) but uses `rg` (
## The `counsel-projectile-org-capture` command ## The `counsel-projectile-org-capture` command
Default key binding: <kbd>C-c p O c</kbd>. Default key binding: <kbd>C-c p O c</kbd>.
This command lets you capture something (a note, todo item, ...) into the current project using org-mode's `org-capture` (actually `counsel-org-capture`) command. Like `org-capture`, it first lets you select a capture template then file the newly captured information. By default, there is a single template storing the captured information into file `notes.org` in the project root directory, under headline `Tasks`. This command is a replacement for `org-capture` (or `counsel-org-capture`) offering project-specific capture templates, in addition to the regular templates available from `org-capture`. By default, there is a single project template, named `[<project-name>] Tasks`, which stores the captured information under headline `Tasks` in file `<project-root>/notes.org`.
If not inside a project, the project templates are ignored and only the regular ones are offered. So you may want to systematically use `counsel-projectile-org-capture` isntead of `org-capture` or `counsel-org-capture` (you may also want to give it a global key binding, such as `C-c c`).
## The `counsel-projectile-org-agenda` command ## The `counsel-projectile-org-agenda` command
Default key binding: <kbd>C-c p O a</kbd>. Default key binding: <kbd>C-c p O a</kbd>.
@ -217,9 +220,12 @@ Extra actions can be added to these lists or, alternatively, can be set through
- change the index of the default action. - change the index of the default action.
See its docstring for details. See its docstring for details.
## Setting `counsel-projectile-org-capture` templates ## Setting `counsel-projectile-org-capture` templates
The available capture templates for `counsel-projectile-org-capture` are read from the variable `counsel-projectile-org-capture-templates`. This variable has the same format as the variable `org-capture-templates`, except that in all strings of in an entrys target slot, all instances of `${root}` and `${name}` are replaced with the current project root and name, respectively. The project-specific capture templates for `counsel-projectile-org-capture` are read from the variable `counsel-projectile-org-capture-templates`. This variable has the same format as the variable `org-capture-templates`, except that in a template's name or target, the placeholders `${root}` and
`${name}` can be used to stand for the current project root and
name, respectively.
The default value contains a single template, whose target is: The default value contains a single template, whose name is
`[${name}] Task` and whose target is:
```emacs-lisp ```emacs-lisp
(file+headline "${root}/notes.org}" "Tasks") (file+headline "${root}/notes.org}" "Tasks")
@ -227,15 +233,16 @@ The default value contains a single template, whose target is:
This points to headline `Tasks` in file `notes.org` in the project root directory (one file per project). This points to headline `Tasks` in file `notes.org` in the project root directory (one file per project).
Another example of a valid target is: Two other examples of valid targets are:
```emacs-lisp ```emacs-lisp
(file+headline "${root}/${name}.org}" "Tasks")
(file+olp "~/notes.org" "${root}" "Tasks") (file+olp "~/notes.org" "${root}" "Tasks")
``` ```
This points to outline path `<project-root>/Tasks` in file `~/notes.org` (same file for all projects). The first one is similar to the default value's target, except that the file is named after the project name (this can be handy if you use org-mode's agenda since the project name is then displayed as category). The second one points to outline path `<project-root>/Tasks` in file `~/notes.org` (same file for all projects).
Templates contexts are read from the variable `counsel-projectile-org-capture-templates-contexts`, which has the same format as `org-capture-templates-contexts` Project-specific template contexts are read from the variable `counsel-projectile-org-capture-templates-contexts`, which has the same format as `org-capture-templates-contexts`
## Removing the current project or buffer from the list of candidates ## Removing the current project or buffer from the list of candidates
By default, when calling `counsel-projectile-switch-project`, the current project (if any) is included in the candidates list and preselected. Similarly, when calling `counsel-projectile-switch-to-buffer`, the current buffer is included in the candidates list and preselected. If you prefer removing these elements from the candidate lists of these commands, you can set the variables `counsel-projectile-remove-current-project` and `counsel-projectile-remove-current-buffer` accordingly. By default, when calling `counsel-projectile-switch-project`, the current project (if any) is included in the candidates list and preselected. Similarly, when calling `counsel-projectile-switch-to-buffer`, the current buffer is included in the candidates list and preselected. If you prefer removing these elements from the candidate lists of these commands, you can set the variables `counsel-projectile-remove-current-project` and `counsel-projectile-remove-current-buffer` accordingly.
## Initial input for the project search commands ## Initial input for the project search commands

View file

@ -781,16 +781,18 @@ is called with a prefix argument."
(defvar org-capture-templates-contexts) (defvar org-capture-templates-contexts)
(defcustom counsel-projectile-org-capture-templates (defcustom counsel-projectile-org-capture-templates
'(("t" "Task" entry (file+headline "${root}/notes.org" "Tasks") '(("t" "[${name}] Task" entry (file+headline "${root}/notes.org" "Tasks")
"* TODO %?\n %u\n %a")) "* TODO %?\n %u\n %a"))
"Templates for the creation of new entries with `counsel-projectile-org-capture'. "Project-specific templates for the creation of new entries
with `counsel-projectile-org-capture'.
The format is the same as in `org-capture-templates', except that The format is the same as in `org-capture-templates', except that
in all strings of in an entry's target slot, all instances of in a template's name or target, the placeholders \"${root}\" and
\"${root}\" and \"${name}\" are replaced with the current project \"${name}\" can be used to stand for the current project root and
root and name, respectively. name, respectively.
The default value contains a single template, whose target is: The default value contains a single template, whose name is
\"[${name}] Task\" and whose target is:
\(file+headline \"${root}/notes.org}\" \"Tasks\"\) \(file+headline \"${root}/notes.org}\" \"Tasks\"\)
@ -912,44 +914,54 @@ The format is the same as in `org-capture-templates-contexts'."
;;;###autoload ;;;###autoload
(defun counsel-projectile-org-capture (&optional from-buffer) (defun counsel-projectile-org-capture (&optional from-buffer)
"Org-capture into the current project. "Capture into the current project.
The capture templates are read from the variables This command is a replacement for `org-capture' (or
`counsel-projectile-org-capture-templates' and `counsel-org-capture') offering project-specific capture
`counsel-projectile-org-capture-templates-contexts'. templates, in addition to the regular templates available from
`org-capture'. These project templates, which are \"expanded\"
relatively to the current project, are determined by the
variables `counsel-projectile-org-capture-templates' and
`counsel-projectile-org-capture-templates-contexts'. See the
former variable in particular for details.
Optional argument FROM-BUFFER specifies the buffer from which to Optional argument FROM-BUFFER specifies the buffer from which to
capture." capture."
(interactive) (interactive)
(require 'org-capture) (require 'org-capture)
(let* ((root (projectile-project-root)) (let* ((root (ignore-errors (projectile-project-root)))
(name (projectile-project-name)) (name (projectile-project-name))
(org-capture-templates-contexts
(append (when root
counsel-projectile-org-capture-templates-contexts)
org-capture-templates-contexts))
(org-capture-templates (org-capture-templates
(cl-loop (append
for template in counsel-projectile-org-capture-templates (when root
collect (cl-loop (cl-loop
for item in template with replace-fun = `(lambda (string)
if (= (cl-position item template) 3) ;; template's target (replace-regexp-in-string
collect (cl-loop "\\${[^}]+}"
for x in item (lambda (s)
if (stringp x) (pcase s
collect (replace-regexp-in-string ("${root}" ,root)
"\\${[^}]+}" ("${name}" ,name)))
(lambda (s) string))
(pcase s for template in counsel-projectile-org-capture-templates
("${root}" root) collect (cl-loop
("${name}" name))) for item in template
x) if (= (cl-position item template) 1) ;; template's name
else collect (funcall replace-fun item)
collect x) else if (= (cl-position item template) 3) ;; template's target
else collect (cl-loop
collect item))) for x in item
(org-capture-templates-contexts counsel-projectile-org-capture-templates-contexts) if (stringp x)
(ivy--prompts-list ivy--prompts-list)) collect (funcall replace-fun x)
(ivy-set-prompt 'counsel-org-capture else
(lambda () collect x)
(ivy-add-prompt-count else
(projectile-prepend-project-name (ivy-state-prompt ivy-last))))) collect item)))
org-capture-templates)))
(with-current-buffer (or from-buffer (current-buffer)) (with-current-buffer (or from-buffer (current-buffer))
(counsel-org-capture)))) (counsel-org-capture))))