diff --git a/README.md b/README.md
index 52efbf9..51e9515 100644
--- a/README.md
+++ b/README.md
@@ -72,7 +72,7 @@ New commands:
| :------------------- | :------------------------------- | :-------------------------------------------------- |
| C-c p SPC | `counsel-projectile` | Jump to a project buffer or file, or switch project |
| C-c p s r | `counsel-projectile-rg` | Search project with rg |
-| C-c p O c | `counsel-projectile-org-capture` | Org-capture into project |
+| C-c p O c | `counsel-projectile-org-capture` | Capture into project |
| C-c p O a | `counsel-projectile-org-capture` | Open project agenda |
## The `counsel-projectile` command
Default key binding: C-c p SPC.
@@ -117,7 +117,8 @@ This command is a replacement for `projectile-switch-project`. It adds the possi
| x s | Invoke shell from the project root |
| x e | Invoke eshell from the project root |
| x t | Invoke term from the project root |
-| O | Org-capture into project: call `counsel-projectile-org-capture` (see below) |
+| O c | Capture into project: call `counsel-projectile-org-capture` (see below) |
+| O a | Open project agenda: call `counsel-projectile-org-agenda` (see below) |
## The `counsel-projectile-find-file` command
Default key binding: C-c p f.
@@ -173,7 +174,9 @@ This command is similar to `counsel-projectile-grep` (see above) but uses `rg` (
## The `counsel-projectile-org-capture` command
Default key binding: C-c p O c.
-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 `[] Tasks`, which stores the captured information under headline `Tasks` in file `/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
Default key binding: C-c p O a.
@@ -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.
See its docstring for details.
## 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 entry’s 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
(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).
-Another example of a valid target is:
+Two other examples of valid targets are:
```emacs-lisp
+(file+headline "${root}/${name}.org}" "Tasks")
(file+olp "~/notes.org" "${root}" "Tasks")
```
-This points to outline path `/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 `/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
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
diff --git a/counsel-projectile.el b/counsel-projectile.el
index fb60326..b99a5e3 100644
--- a/counsel-projectile.el
+++ b/counsel-projectile.el
@@ -781,16 +781,18 @@ is called with a prefix argument."
(defvar org-capture-templates-contexts)
(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"))
- "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
-in all strings of in an entry's target slot, all instances of
-\"${root}\" and \"${name}\" are replaced with the current project
-root and name, respectively.
+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:
\(file+headline \"${root}/notes.org}\" \"Tasks\"\)
@@ -912,44 +914,54 @@ The format is the same as in `org-capture-templates-contexts'."
;;;###autoload
(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
-`counsel-projectile-org-capture-templates' and
-`counsel-projectile-org-capture-templates-contexts'.
+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'. 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
capture."
(interactive)
(require 'org-capture)
- (let* ((root (projectile-project-root))
+ (let* ((root (ignore-errors (projectile-project-root)))
(name (projectile-project-name))
+ (org-capture-templates-contexts
+ (append (when root
+ counsel-projectile-org-capture-templates-contexts)
+ org-capture-templates-contexts))
(org-capture-templates
- (cl-loop
- for template in counsel-projectile-org-capture-templates
- collect (cl-loop
- for item in template
- if (= (cl-position item template) 3) ;; template's target
- collect (cl-loop
- for x in item
- if (stringp x)
- collect (replace-regexp-in-string
- "\\${[^}]+}"
- (lambda (s)
- (pcase s
- ("${root}" root)
- ("${name}" name)))
- x)
- else
- collect x)
- else
- collect item)))
- (org-capture-templates-contexts counsel-projectile-org-capture-templates-contexts)
- (ivy--prompts-list ivy--prompts-list))
- (ivy-set-prompt 'counsel-org-capture
- (lambda ()
- (ivy-add-prompt-count
- (projectile-prepend-project-name (ivy-state-prompt ivy-last)))))
+ (append
+ (when root
+ (cl-loop
+ with replace-fun = `(lambda (string)
+ (replace-regexp-in-string
+ "\\${[^}]+}"
+ (lambda (s)
+ (pcase s
+ ("${root}" ,root)
+ ("${name}" ,name)))
+ string))
+ for template in counsel-projectile-org-capture-templates
+ collect (cl-loop
+ for item in template
+ if (= (cl-position item template) 1) ;; template's name
+ collect (funcall replace-fun item)
+ else if (= (cl-position item template) 3) ;; template's target
+ collect (cl-loop
+ for x in item
+ if (stringp x)
+ collect (funcall replace-fun x)
+ else
+ collect x)
+ else
+ collect item)))
+ org-capture-templates)))
(with-current-buffer (or from-buffer (current-buffer))
(counsel-org-capture))))