mirror of
https://github.com/org-roam/org-roam
synced 2025-08-01 12:17:21 -05:00
(feat): capture: create OLP if does not exist (#1270)
Remove the requirement that the OLP already exists in the captured file. Also, make OLP available beyond dailies functionality.
This commit is contained in:
@ -1,4 +1,12 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
## 1.2.4 (TBD)
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- [#1270](https://github.com/org-roam/org-roam/pull/1270) capture: create OLP if it does not exist. Removes need for OLP setup in `:head`.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
## 1.2.3 (13-11-2020)
|
## 1.2.3 (13-11-2020)
|
||||||
|
|
||||||
|
@ -1123,20 +1123,19 @@ specifying the outline-path to a heading:
|
|||||||
#'org-roam-capture--get-point
|
#'org-roam-capture--get-point
|
||||||
"* %?"
|
"* %?"
|
||||||
:file-name "daily/%<%Y-%m-%d>"
|
:file-name "daily/%<%Y-%m-%d>"
|
||||||
:head "#+title: %<%Y-%m-%d>\n\n* Lab notes\n* Journal"
|
:head "#+title: %<%Y-%m-%d>\n"
|
||||||
:olp ("Journal"))
|
:olp ("Journal"))
|
||||||
|
|
||||||
("j" "journal" entry
|
("j" "journal" entry
|
||||||
#'org-roam-capture--get-point
|
#'org-roam-capture--get-point
|
||||||
"* %?"
|
"* %?"
|
||||||
:file-name "daily/%<%Y-%m-%d>"
|
:file-name "daily/%<%Y-%m-%d>"
|
||||||
:head "#+title: %<%Y-%m-%d>\n\n* Lab notes\n* Journal"
|
:head "#+title: %<%Y-%m-%d>\n"
|
||||||
:olp ("Lab notes"))))
|
:olp ("Lab notes"))))
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
The template ~l~ will put its notes under the heading ‘Lab notes’, and the
|
The template ~l~ will put its notes under the heading ‘Lab notes’, and the
|
||||||
template ~j~ will put its notes under the heading ‘Journal’. When you use
|
template ~j~ will put its notes under the heading ‘Journal’.
|
||||||
~:olp~, make sure that the headings are present in ~:head~.
|
|
||||||
|
|
||||||
** Capturing and finding daily-notes
|
** Capturing and finding daily-notes
|
||||||
|
|
||||||
|
@ -1525,20 +1525,19 @@ specifying the outline-path to a heading:
|
|||||||
#'org-roam-capture--get-point
|
#'org-roam-capture--get-point
|
||||||
"* %?"
|
"* %?"
|
||||||
:file-name "daily/%<%Y-%m-%d>"
|
:file-name "daily/%<%Y-%m-%d>"
|
||||||
:head "#+title: %<%Y-%m-%d>\n\n* Lab notes\n* Journal"
|
:head "#+title: %<%Y-%m-%d>\n"
|
||||||
:olp ("Journal"))
|
:olp ("Journal"))
|
||||||
|
|
||||||
("j" "journal" entry
|
("j" "journal" entry
|
||||||
#'org-roam-capture--get-point
|
#'org-roam-capture--get-point
|
||||||
"* %?"
|
"* %?"
|
||||||
:file-name "daily/%<%Y-%m-%d>"
|
:file-name "daily/%<%Y-%m-%d>"
|
||||||
:head "#+title: %<%Y-%m-%d>\n\n* Lab notes\n* Journal"
|
:head "#+title: %<%Y-%m-%d>\n"
|
||||||
:olp ("Lab notes"))))
|
:olp ("Lab notes"))))
|
||||||
@end lisp
|
@end lisp
|
||||||
|
|
||||||
The template @code{l} will put its notes under the heading ‘Lab notes’, and the
|
The template @code{l} will put its notes under the heading ‘Lab notes’, and the
|
||||||
template @code{j} will put its notes under the heading ‘Journal’. When you use
|
template @code{j} will put its notes under the heading ‘Journal’.
|
||||||
@code{:olp}, make sure that the headings are present in @code{:head}.
|
|
||||||
|
|
||||||
@node Capturing and finding daily-notes
|
@node Capturing and finding daily-notes
|
||||||
@section Capturing and finding daily-notes
|
@section Capturing and finding daily-notes
|
||||||
|
@ -442,6 +442,50 @@ the file if the original value of :no-save is not t and
|
|||||||
(org-capture-put :no-save t))
|
(org-capture-put :no-save t))
|
||||||
file-path))
|
file-path))
|
||||||
|
|
||||||
|
(defun org-roam-capture-find-or-create-olp (olp)
|
||||||
|
"Return a marker pointing to the entry at OLP in the current buffer.
|
||||||
|
If OLP does not exist, create it. If anything goes wrong, throw
|
||||||
|
an error, and if you need to do something based on this error,
|
||||||
|
you can catch it with `condition-case'."
|
||||||
|
(let* ((level 1)
|
||||||
|
(lmin 1)
|
||||||
|
(lmax 1)
|
||||||
|
(start (point-min))
|
||||||
|
(end (point-max))
|
||||||
|
found flevel)
|
||||||
|
(unless (derived-mode-p 'org-mode)
|
||||||
|
(error "Buffer %s needs to be in Org mode" (current-buffer)))
|
||||||
|
(org-with-wide-buffer
|
||||||
|
(goto-char start)
|
||||||
|
(dolist (heading olp)
|
||||||
|
(let ((re (format org-complex-heading-regexp-format
|
||||||
|
(regexp-quote heading)))
|
||||||
|
(cnt 0))
|
||||||
|
(while (re-search-forward re end t)
|
||||||
|
(setq level (- (match-end 1) (match-beginning 1)))
|
||||||
|
(when (and (>= level lmin) (<= level lmax))
|
||||||
|
(setq found (match-beginning 0) flevel level cnt (1+ cnt))))
|
||||||
|
(when (> cnt 1)
|
||||||
|
(error "Heading not unique on level %d: %s" lmax heading))
|
||||||
|
(when (= cnt 0)
|
||||||
|
;; Create heading if it doesn't exist
|
||||||
|
(goto-char end)
|
||||||
|
(unless (bolp) (newline))
|
||||||
|
(org-insert-heading nil nil t)
|
||||||
|
(unless (= lmax 1) (org-do-demote))
|
||||||
|
(insert heading)
|
||||||
|
(setq end (point))
|
||||||
|
(goto-char start)
|
||||||
|
(while (re-search-forward re end t)
|
||||||
|
(setq level (- (match-end 1) (match-beginning 1)))
|
||||||
|
(when (and (>= level lmin) (<= level lmax))
|
||||||
|
(setq found (match-beginning 0) flevel level cnt (1+ cnt))))))
|
||||||
|
(goto-char found)
|
||||||
|
(setq lmin (1+ flevel) lmax (+ lmin (if org-odd-levels-only 1 0)))
|
||||||
|
(setq start found
|
||||||
|
end (save-excursion (org-end-of-subtree t t))))
|
||||||
|
(point-marker))))
|
||||||
|
|
||||||
(defun org-roam-capture--get-point ()
|
(defun org-roam-capture--get-point ()
|
||||||
"Return exact point to file for org-capture-template.
|
"Return exact point to file for org-capture-template.
|
||||||
The file to use is dependent on the context:
|
The file to use is dependent on the context:
|
||||||
@ -485,26 +529,23 @@ This function is used solely in Org-roam's capture templates: see
|
|||||||
(org-roam-capture--put prop val)))
|
(org-roam-capture--put prop val)))
|
||||||
(set-buffer (org-capture-target-buffer file-path))
|
(set-buffer (org-capture-target-buffer file-path))
|
||||||
(widen)
|
(widen)
|
||||||
(if-let* ((olp (when (eq org-roam-capture--context 'dailies)
|
(if-let* ((olp (--> (org-roam-capture--get :olp)
|
||||||
(--> (org-roam-capture--get :olp)
|
(pcase it
|
||||||
(pcase it
|
((pred listp)
|
||||||
((pred stringp)
|
it)
|
||||||
(list it))
|
(wrong-type
|
||||||
((pred listp)
|
(signal 'wrong-type-argument
|
||||||
it)
|
`((stringp listp)
|
||||||
(wrong-type
|
,wrong-type)))))))
|
||||||
(signal 'wrong-type-argument
|
|
||||||
`((stringp listp)
|
|
||||||
,wrong-type))))))))
|
|
||||||
(condition-case err
|
(condition-case err
|
||||||
(when-let ((marker (org-find-olp `(,file-path ,@olp))))
|
(when-let ((marker (org-roam-capture-find-or-create-olp olp)))
|
||||||
(goto-char marker)
|
(goto-char marker)
|
||||||
(set-marker marker nil))
|
(set-marker marker nil))
|
||||||
(error
|
(error
|
||||||
(when (org-roam-capture--get :new-file)
|
(when (org-roam-capture--get :new-file)
|
||||||
(kill-buffer))
|
(kill-buffer))
|
||||||
(signal (car err) (cdr err))))
|
(signal (car err) (cdr err))))
|
||||||
(goto-char (point-min)))))
|
(goto-char (point-max)))))
|
||||||
|
|
||||||
(defun org-roam-capture--convert-template (template)
|
(defun org-roam-capture--convert-template (template)
|
||||||
"Convert TEMPLATE from Org-roam syntax to `org-capture-templates' syntax."
|
"Convert TEMPLATE from Org-roam syntax to `org-capture-templates' syntax."
|
||||||
|
Reference in New Issue
Block a user