(fix)capture: fill-template preserve whitespace content (#2117)

* (fix)capture: fill-template preserve whitespace content

Preserve the whitespace content given in the capture template, by
caching it and then appending it to the output template. For
Org-capture's purposes, we need to separately ensure that a newline is
present. Adds tests to the various helper functions to illustrate changes.

Addresses #2115
This commit is contained in:
Jethro Kuan
2022-03-10 09:46:53 -08:00
committed by GitHub
parent feb9179c9f
commit f6950a9820
5 changed files with 137 additions and 39 deletions

View File

@ -23,6 +23,8 @@
- [#2082](https://github.com/org-roam/org-roam/pull/2082) buffer: don't destroy window if `org-roam-node-toggle` reuses window - [#2082](https://github.com/org-roam/org-roam/pull/2082) buffer: don't destroy window if `org-roam-node-toggle` reuses window
- [#2080](https://github.com/org-roam/org-roam/pull/2080) dailies: prevent multiple "dailies/" subdir expansions - [#2080](https://github.com/org-roam/org-roam/pull/2080) dailies: prevent multiple "dailies/" subdir expansions
- [#2055](https://github.com/org-roam/org-roam/pull/2055) dailies: removed stray f require, which was causing require and compilation errors - [#2055](https://github.com/org-roam/org-roam/pull/2055) dailies: removed stray f require, which was causing require and compilation errors
- [#2117](https://github.com/org-roam/org-roam/pull/2117) capture: preserve trailing whitespace content in capture templates
### Changed ### Changed
- [#2060](https://github.com/org-roam/org-roam/pull/2060) node: added double acute accent normalization for Unicode characters in titles - [#2060](https://github.com/org-roam/org-roam/pull/2060) node: added double acute accent normalization for Unicode characters in titles
- [#2040](https://github.com/org-roam/org-roam/pull/2040) completions: fix completions display-width for Helm users - [#2040](https://github.com/org-roam/org-roam/pull/2040) completions: fix completions display-width for Helm users

View File

@ -505,7 +505,7 @@ Return the ID of the location."
(set-buffer (org-capture-target-buffer path)) (set-buffer (org-capture-target-buffer path))
(when new-file-p (when new-file-p
(org-roam-capture--put :new-file path) (org-roam-capture--put :new-file path)
(insert (org-roam-capture--fill-template head t))) (insert (org-roam-capture--fill-template head 'ensure-newline)))
(widen) (widen)
(setq p (goto-char (point-min)))) (setq p (goto-char (point-min))))
(`(file+head+olp ,path ,head ,olp) (`(file+head+olp ,path ,head ,olp)
@ -515,7 +515,7 @@ Return the ID of the location."
(widen) (widen)
(when new-file-p (when new-file-p
(org-roam-capture--put :new-file path) (org-roam-capture--put :new-file path)
(insert (org-roam-capture--fill-template head t))) (insert (org-roam-capture--fill-template head 'ensure-newline)))
(setq p (point-min)) (setq p (point-min))
(let ((m (org-roam-capture-find-or-create-olp olp))) (let ((m (org-roam-capture-find-or-create-olp olp)))
(goto-char m))) (goto-char m)))
@ -593,7 +593,7 @@ it."
(or (org-roam-node-file org-roam-capture--node) (or (org-roam-node-file org-roam-capture--node)
(thread-first (thread-first
path path
(org-roam-capture--fill-template t) (org-roam-capture--fill-template)
(string-trim) (string-trim)
(expand-file-name org-roam-directory)))) (expand-file-name org-roam-directory))))
@ -618,7 +618,7 @@ you can catch it with `condition-case'."
(org-with-wide-buffer (org-with-wide-buffer
(goto-char start) (goto-char start)
(dolist (heading olp) (dolist (heading olp)
(setq heading (org-roam-capture--fill-template heading t)) (setq heading (org-roam-capture--fill-template heading))
(let ((re (format org-complex-heading-regexp-format (let ((re (format org-complex-heading-regexp-format
(regexp-quote heading))) (regexp-quote heading)))
(cnt 0)) (cnt 0))
@ -752,12 +752,14 @@ This function is to be called in the Org-capture finalization process."
(insert link))))))) (insert link)))))))
;;;; Processing of the capture templates ;;;; Processing of the capture templates
(defun org-roam-capture--fill-template (template &optional org-capture-p newline) (defun org-roam-capture--fill-template (template &optional ensure-newline)
"Expand TEMPLATE and return it. "Expand TEMPLATE and return it.
It expands ${var} occurrences in TEMPLATE. When ORG-CAPTURE-P, It expands ${var} occurrences in TEMPLATE, and then runs
also run Org-capture's template expansion. org-capture's template expansion.
If NEWLINE, ensure that the template returned ends with a newline." When ENSURE-NEWLINE, always ensure there's a newline behind."
(setq template (org-roam-format-template (let ((template-whitespace-content (org-roam-whitespace-content template)))
(setq template
(org-roam-format-template
template template
(lambda (key default-val) (lambda (key default-val)
(let ((fn (intern key)) (let ((fn (intern key))
@ -777,18 +779,13 @@ If NEWLINE, ensure that the template returned ends with a newline."
;; `org-capture-fill-template' fills the template, but post-processes whitespace such that the resultant ;; `org-capture-fill-template' fills the template, but post-processes whitespace such that the resultant
;; template does not start with any whitespace, and only ends with a single newline ;; template does not start with any whitespace, and only ends with a single newline
;; ;;
;; In most cases where we rely on `org-capture-fill-template' to populate non-org-capture-related templates, ;; Instead, we restore the whitespace in the original template.
;; (e.g. in OLPs), we strip the final newline, obtaining a template that seems to be string-trimmed. (setq template (replace-regexp-in-string "\n$" "" (org-capture-fill-template template)))
;; (when (and ensure-newline
;; This means that if the original passed template has newlines, and ORG-CAPTURE-P is true, then the extra (string-equal template-whitespace-content ""))
;; whitespace specified in the template will be ignored. (setq template-whitespace-content "\n"))
(when org-capture-p (setq template (concat template template-whitespace-content))
(setq template template))
(replace-regexp-in-string "\n$" "" (org-capture-fill-template template))))
(when (and newline
(not (string-suffix-p "\n" template)))
(setq template (concat template "\n")))
template)
(defun org-roam-capture--convert-template (template &optional props) (defun org-roam-capture--convert-template (template &optional props)
"Convert TEMPLATE from Org-roam syntax to `org-capture-templates' syntax. "Convert TEMPLATE from Org-roam syntax to `org-capture-templates' syntax.

View File

@ -69,6 +69,15 @@ Like `string-equal', but case-insensitive."
(or (string-equal s1 s2) (or (string-equal s1 s2)
(string-equal (downcase s1) (downcase s2))))) (string-equal (downcase s1) (downcase s2)))))
(defun org-roam-whitespace-content (s)
"Return the whitespace content at the end of S."
(with-temp-buffer
(let ((c 0))
(insert s)
(skip-chars-backward " \t\n")
(buffer-substring-no-properties
(point) (point-max)))))
(defun org-roam-strip-comments (s) (defun org-roam-strip-comments (s)
"Strip Org comments from string S." "Strip Org comments from string S."
(with-temp-buffer (with-temp-buffer

View File

@ -0,0 +1,51 @@
;;; test-org-roam-capture.el --- Tests for Org-roam -*- lexical-binding: t; -*-
;; Copyright (C) 2020 Jethro Kuan
;; Author: Jethro Kuan <jethrokuan95@gmail.com>
;; Package-Requires: ((buttercup))
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
;;; Code:
(require 'buttercup)
(require 'org-roam)
(describe "org-roam-capture--fill-template"
(it "fills template without newline"
(expect
(org-roam-capture--fill-template "foo")
:to-equal "foo"))
(it "fills template ensuring newline"
(expect
(org-roam-capture--fill-template "foo" 'ensure-newline)
:to-equal "foo\n"))
(it "fills template with newline"
(expect
(org-roam-capture--fill-template "foo\n")
:to-equal "foo\n"))
(it "fills template with two newlines"
(expect
(org-roam-capture--fill-template "foo\n\n")
:to-equal "foo\n\n")
(expect
(org-roam-capture--fill-template "foo\n\t\n")
:to-equal "foo\n\t\n")))
(provide 'test-org-roam-capture)

View File

@ -0,0 +1,39 @@
;;; test-org-roam-utils.el --- Tests for Org-roam -*- lexical-binding: t; -*-
;; Copyright (C) 2020 Jethro Kuan
;; Author: Jethro Kuan <jethrokuan95@gmail.com>
;; Package-Requires: ((buttercup))
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
;;; Code:
(require 'buttercup)
(require 'org-roam)
(describe "org-roam-whitespace-content"
(it "extracts whitespace correctly"
(expect
(org-roam-whitespace-content "foo")
:to-equal "")
(expect
(org-roam-whitespace-content "foo\n")
:to-equal "\n")
(expect
(org-roam-whitespace-content "foo\n\t\n")
:to-equal "\n\t\n")))
(provide 'test-org-roam-utils)