Merge branch 'master' of code.orgmode.org:bzg/org-mode
This commit is contained in:
commit
f979ce47ca
|
@ -3026,14 +3026,17 @@ or alternatively
|
|||
|
||||
: [[LINK]]
|
||||
|
||||
Once a link in the buffer is complete (all brackets present), Org
|
||||
Once a link in the buffer is complete---all brackets present---, Org
|
||||
changes the display so that =DESCRIPTION= is displayed instead of
|
||||
=[[LINK][DESCRIPTION]]= and =LINK= is displayed instead of =[[LINK]]=. Links are be
|
||||
highlighted in the face ~org-link~, which by default is an underlined
|
||||
face. You can directly edit the visible part of a link. Note that
|
||||
this can be either the LINK part, if there is no description, or the
|
||||
{{{var(DESCRIPTION)}}} part. To edit also the invisible
|
||||
{{{var(LINK)}}} part, use {{{kbd(C-c C-l)}}} with point on the link.
|
||||
=[[LINK][DESCRIPTION]]= and =LINK= is displayed instead of =[[LINK]]=.
|
||||
Links are highlighted in the ~org-link~ face, which, by default, is an
|
||||
underlined face.
|
||||
|
||||
You can directly edit the visible part of a link. This can be either
|
||||
the {{{var(LINK)}}} part, if there is no description, or the
|
||||
{{{var(DESCRIPTION)}}} part otherwise. To also edit the invisible
|
||||
{{{var(LINK)}}} part, use {{{kbd(C-c C-l)}}} with point on the link
|
||||
(see [[*Handling Links]]).
|
||||
|
||||
If you place point at the beginning or just behind the end of the
|
||||
displayed text and press {{{kbd(BS)}}}, you remove
|
||||
|
@ -11089,7 +11092,7 @@ Org only loads back-ends for the following formats by default: ASCII,
|
|||
HTML, iCalendar, LaTeX, and ODT. Additional back-ends can be loaded
|
||||
in either of two ways: by configuring the ~org-export-backends~
|
||||
variable, or by requiring libraries in the Emacs init file. For
|
||||
example, to load the markdown back-end, add this to your Emacs config:
|
||||
example, to load the Markdown back-end, add this to your Emacs config:
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(require 'ox-md)
|
||||
|
@ -15235,6 +15238,16 @@ regions. A convenient feature of this in-place conversion is that the
|
|||
exported output replaces the original source. Here are such
|
||||
functions:
|
||||
|
||||
- ~org-ascii-convert-region-to-ascii~ ::
|
||||
|
||||
#+findex: org-ascii-convert-region-to-ascii
|
||||
Convert the selected region into ASCII.
|
||||
|
||||
- ~org-ascii-convert-region-to-utf8~ ::
|
||||
|
||||
#+findex: org-ascii-convert-region-to-utf8
|
||||
Convert the selected region into UTF-8.
|
||||
|
||||
- ~org-html-convert-region-to-html~ ::
|
||||
|
||||
#+findex: org-html-convert-region-to-html
|
||||
|
@ -19279,10 +19292,10 @@ locally just set the variable to point to that directory:
|
|||
|
||||
Alternatively, by using TRAMP (see [[info:tramp][TRAMP User Manual]]),
|
||||
~org-mobile-directory~ may point to a remote directory accessible
|
||||
through, for example, SSH and SCP:
|
||||
through, for example, SSH, SCP, or DAVS:
|
||||
|
||||
#+begin_src emacs-lisp
|
||||
(setq org-mobile-directory "/scpc:user@remote.host:org/webdav/")
|
||||
(setq org-mobile-directory "/davs:user@remote.host:/org/webdav/")
|
||||
#+end_src
|
||||
|
||||
#+vindex: org-mobile-encryption
|
||||
|
|
|
@ -1111,8 +1111,10 @@ may have been stored before."
|
|||
|
||||
(defun org-capture-place-entry ()
|
||||
"Place the template as a new Org entry."
|
||||
(let ((reversed? (org-capture-get :prepend))
|
||||
(let ((template (org-capture-get :template))
|
||||
(reversed? (org-capture-get :prepend))
|
||||
(level 1))
|
||||
(org-capture-verify-tree template)
|
||||
(when (org-capture-get :exact-position)
|
||||
(goto-char (org-capture-get :exact-position)))
|
||||
(cond
|
||||
|
@ -1128,81 +1130,126 @@ may have been stored before."
|
|||
(unless (org-at-heading-p) (outline-next-heading)))
|
||||
;; Otherwise, insert as a top-level entry at the end of the file.
|
||||
(t (goto-char (point-max))))
|
||||
(unless (bolp) (insert "\n"))
|
||||
(org-capture-empty-lines-before)
|
||||
(let ((beg (point))
|
||||
(template (org-capture-get :template)))
|
||||
(org-capture-verify-tree template)
|
||||
(org-paste-subtree level template 'for-yank)
|
||||
(org-capture-empty-lines-after)
|
||||
(org-capture-position-for-last-stored beg)
|
||||
(unless (org-at-heading-p) (outline-next-heading))
|
||||
(let ((end (point)))
|
||||
(org-capture-mark-kill-region beg end)
|
||||
(org-capture-narrow beg end)
|
||||
(when (or (re-search-backward "%\\?" beg t)
|
||||
(re-search-forward "%\\?" end t))
|
||||
(replace-match ""))))))
|
||||
(let ((origin (point)))
|
||||
(unless (bolp) (insert "\n"))
|
||||
(org-capture-empty-lines-before)
|
||||
(org-capture-position-for-last-stored (point))
|
||||
(let ((beg (point)))
|
||||
(org-paste-subtree level template 'for-yank)
|
||||
(let ((end (if (org-at-heading-p) (line-end-position 0) (point))))
|
||||
(org-capture-empty-lines-after)
|
||||
(unless (org-at-heading-p) (outline-next-heading))
|
||||
(org-capture-mark-kill-region origin (point))
|
||||
(org-capture-narrow beg end)
|
||||
(when (or (search-backward "%?" beg t)
|
||||
(search-forward "%?" end t))
|
||||
(replace-match "")))))))
|
||||
|
||||
(defun org-capture-place-item ()
|
||||
"Place the template as a new plain list item."
|
||||
(let* ((txt (org-capture-get :template))
|
||||
(target-entry-p (org-capture-get :target-entry-p))
|
||||
(ind 0)
|
||||
beg end)
|
||||
(if (org-capture-get :exact-position)
|
||||
(goto-char (org-capture-get :exact-position))
|
||||
(cond
|
||||
((not target-entry-p)
|
||||
;; Insert as top-level entry, either at beginning or at end of file
|
||||
(setq beg (point-min) end (point-max)))
|
||||
(t
|
||||
(setq beg (1+ (point-at-eol))
|
||||
end (save-excursion (outline-next-heading) (point)))))
|
||||
(setq ind nil)
|
||||
(if (org-capture-get :prepend)
|
||||
(progn
|
||||
(goto-char beg)
|
||||
(when (org-list-search-forward (org-item-beginning-re) end t)
|
||||
(goto-char (match-beginning 0))
|
||||
(setq ind (current-indentation))))
|
||||
(goto-char end)
|
||||
(when (org-list-search-backward (org-item-beginning-re) beg t)
|
||||
(setq ind (current-indentation))
|
||||
(org-end-of-item)))
|
||||
(unless ind (goto-char end)))
|
||||
;; Remove common indentation
|
||||
(setq txt (org-remove-indentation txt))
|
||||
;; Make sure this is indeed an item
|
||||
(unless (string-match (concat "\\`" (org-item-re)) txt)
|
||||
(setq txt (concat "- "
|
||||
(mapconcat 'identity (split-string txt "\n")
|
||||
"\n "))))
|
||||
;; Prepare surrounding empty lines.
|
||||
(unless (bolp) (insert "\n"))
|
||||
(org-capture-empty-lines-before)
|
||||
(setq beg (point))
|
||||
(unless (eolp) (save-excursion (insert "\n")))
|
||||
(unless ind
|
||||
(org-indent-line)
|
||||
(setq ind (current-indentation))
|
||||
(delete-region beg (point)))
|
||||
;; Set the correct indentation, depending on context
|
||||
(setq ind (make-string ind ?\ ))
|
||||
(setq txt (concat ind
|
||||
(mapconcat 'identity (split-string txt "\n")
|
||||
(concat "\n" ind))
|
||||
"\n"))
|
||||
;; Insert item.
|
||||
(insert txt)
|
||||
(org-capture-empty-lines-after)
|
||||
(org-capture-position-for-last-stored beg)
|
||||
(setq end (point))
|
||||
(org-capture-mark-kill-region beg end)
|
||||
(org-capture-narrow beg end)
|
||||
(when (or (re-search-backward "%\\?" beg t)
|
||||
(re-search-forward "%\\?" end t))
|
||||
(replace-match ""))))
|
||||
(let ((prepend? (org-capture-get :prepend))
|
||||
(template (org-remove-indentation (org-capture-get :template)))
|
||||
item)
|
||||
;; Make template suitable for insertion. In particular, add
|
||||
;; a main bullet if it is missing.
|
||||
(unless (string-match-p (concat "\\`" (org-item-re)) template)
|
||||
(setq template (concat "- " (mapconcat #'identity
|
||||
(split-string template "\n")
|
||||
"\n "))))
|
||||
;; Delimit the area where we should look for a plain list.
|
||||
(pcase-let ((`(,beg . ,end)
|
||||
(cond ((org-capture-get :exact-position)
|
||||
;; User gave a specific position. Start
|
||||
;; looking for lists from here.
|
||||
(cons (save-excursion
|
||||
(goto-char (org-capture-get :exact-position))
|
||||
(line-beginning-position))
|
||||
(org-entry-end-position)))
|
||||
((org-capture-get :target-entry-p)
|
||||
;; At a heading, limit search to its body.
|
||||
(cons (line-beginning-position 2)
|
||||
(org-entry-end-position)))
|
||||
(t
|
||||
;; Table is not necessarily under a heading.
|
||||
;; Search whole buffer.
|
||||
(cons (point-min) (point-max))))))
|
||||
;; Find the first plain list in the delimited area.
|
||||
(goto-char beg)
|
||||
(let ((item-regexp (org-item-beginning-re)))
|
||||
(catch :found
|
||||
(while (re-search-forward item-regexp end t)
|
||||
(when (setq item (org-element-lineage
|
||||
(org-element-at-point) '(plain-list) t))
|
||||
(goto-char (org-element-property (if prepend? :post-affiliated
|
||||
:contents-end)
|
||||
item))
|
||||
(throw :found t)))
|
||||
;; No list found. Move to the location when to insert
|
||||
;; template.
|
||||
(goto-char (if prepend? beg end)))))
|
||||
;; Insert template.
|
||||
(let ((origin (point)))
|
||||
(unless (bolp) (insert "\n"))
|
||||
;; When a new list is created, always obey to `:empty-lines' and
|
||||
;; friends.
|
||||
;;
|
||||
;; When capturing in an existing list, do not change blank lines
|
||||
;; above or below the list; consider it to be a stable
|
||||
;; structure. However, we can control how many blank lines
|
||||
;; separate items. So obey to `:empty-lines' between items as
|
||||
;; long as it does not insert more than one empty line. In the
|
||||
;; specific case of empty lines above, it means we only obey the
|
||||
;; parameter when appending an item.
|
||||
(unless (and item prepend?)
|
||||
(org-capture-empty-lines-before
|
||||
(and item
|
||||
(not prepend?)
|
||||
(min 1 (or (org-capture-get :empty-lines-before)
|
||||
(org-capture-get :empty-lines)
|
||||
0)))))
|
||||
(org-capture-position-for-last-stored (point))
|
||||
(let ((beg (line-beginning-position))
|
||||
(end (progn
|
||||
(insert (org-trim template) "\n")
|
||||
(point-marker))))
|
||||
(when item
|
||||
(let ((i (save-excursion
|
||||
(goto-char (org-element-property :post-affiliated item))
|
||||
(current-indentation))))
|
||||
(save-excursion
|
||||
(goto-char beg)
|
||||
(save-excursion
|
||||
(while (< (point) end)
|
||||
(indent-to i)
|
||||
(forward-line)))
|
||||
;; Pre-pending an item could change the type of the list
|
||||
;; if there is a mismatch. In this situation,
|
||||
;; prioritize the existing list.
|
||||
(when prepend?
|
||||
(let ((ordered? (eq 'ordered (org-element-property :type item))))
|
||||
(when (org-xor ordered?
|
||||
(string-match-p "\\`[A-Za-z0-9]\\([.)]\\)"
|
||||
template))
|
||||
(org-cycle-list-bullet (if ordered? "1." "-")))))
|
||||
;; Eventually repair the list for proper indentation and
|
||||
;; bullets.
|
||||
(org-list-repair))))
|
||||
;; Limit number of empty lines. See above for details.
|
||||
(unless (and item (not prepend?))
|
||||
(org-capture-empty-lines-after
|
||||
(and item
|
||||
prepend?
|
||||
(min 1 (or (org-capture-get :empty-lines-after)
|
||||
(org-capture-get :empty-lines)
|
||||
0)))))
|
||||
(org-capture-mark-kill-region origin (point))
|
||||
;; ITEM always end with a newline character. Make sure we do
|
||||
;; not narrow at the beginning of the next line, possibly
|
||||
;; altering its structure (e.g., when it is a headline).
|
||||
(org-capture-narrow beg (1- end))
|
||||
(when (or (search-backward "%?" beg t)
|
||||
(search-forward "%?" end t))
|
||||
(replace-match ""))))))
|
||||
|
||||
(defun org-capture-place-table-line ()
|
||||
"Place the template as a table line."
|
||||
|
@ -1270,18 +1317,21 @@ may have been stored before."
|
|||
(t
|
||||
(goto-char (org-table-end))))
|
||||
;; Insert text and position point according to template.
|
||||
(unless (bolp) (insert "\n"))
|
||||
(let ((beg (point))
|
||||
(end (save-excursion
|
||||
(insert text)
|
||||
(point))))
|
||||
(org-capture-position-for-last-stored 'table-line)
|
||||
(org-capture-mark-kill-region beg end)
|
||||
(org-capture-narrow beg end)
|
||||
(when (or (re-search-backward "%\\?" beg t)
|
||||
(re-search-forward "%\\?" end t))
|
||||
(replace-match "")))
|
||||
(org-table-align)))
|
||||
(let ((origin (point)))
|
||||
(unless (bolp) (insert "\n"))
|
||||
(let ((beg (point))
|
||||
(end (save-excursion
|
||||
(insert text)
|
||||
(point))))
|
||||
(org-capture-position-for-last-stored 'table-line)
|
||||
(org-capture-mark-kill-region origin end)
|
||||
;; TEXT is guaranteed to end with a newline character. Ignore
|
||||
;; it when narrowing so as to not alter data on the next line.
|
||||
(org-capture-narrow beg (1- end))
|
||||
(when (or (search-backward "%?" beg t)
|
||||
(search-forward "%?" end t))
|
||||
(replace-match "")))
|
||||
(org-table-align))))
|
||||
|
||||
(defun org-capture-place-plain-text ()
|
||||
"Place the template plainly.
|
||||
|
@ -1289,35 +1339,36 @@ If the target locator points at an Org node, place the template into
|
|||
the text of the entry, before the first child. If not, place the
|
||||
template at the beginning or end of the file.
|
||||
Of course, if exact position has been required, just put it there."
|
||||
(let* ((txt (org-capture-get :template))
|
||||
beg end)
|
||||
(cond
|
||||
((org-capture-get :exact-position)
|
||||
(goto-char (org-capture-get :exact-position)))
|
||||
((and (org-capture-get :target-entry-p)
|
||||
(bolp)
|
||||
(looking-at org-outline-regexp))
|
||||
;; we should place the text into this entry
|
||||
(if (org-capture-get :prepend)
|
||||
;; Skip meta data and drawers
|
||||
(org-end-of-meta-data t)
|
||||
;; go to ent of the entry text, before the next headline
|
||||
(outline-next-heading)))
|
||||
(t
|
||||
;; beginning or end of file
|
||||
(goto-char (if (org-capture-get :prepend) (point-min) (point-max)))))
|
||||
(or (bolp) (newline))
|
||||
(cond
|
||||
((org-capture-get :exact-position)
|
||||
(goto-char (org-capture-get :exact-position)))
|
||||
((org-capture-get :target-entry-p)
|
||||
;; Place the text into this entry.
|
||||
(if (org-capture-get :prepend)
|
||||
;; Skip meta data and drawers.
|
||||
(org-end-of-meta-data t)
|
||||
;; Go to end of the entry text, before the next headline.
|
||||
(outline-next-heading)))
|
||||
(t
|
||||
;; Beginning or end of file.
|
||||
(goto-char (if (org-capture-get :prepend) (point-min) (point-max)))))
|
||||
(let ((origin (point)))
|
||||
(unless (bolp) (insert "\n"))
|
||||
(org-capture-empty-lines-before)
|
||||
(setq beg (point))
|
||||
(insert txt)
|
||||
(org-capture-empty-lines-after)
|
||||
(org-capture-position-for-last-stored beg)
|
||||
(setq end (point))
|
||||
(org-capture-mark-kill-region beg (1- end))
|
||||
(org-capture-narrow beg (1- end))
|
||||
(when (or (re-search-backward "%\\?" beg t)
|
||||
(re-search-forward "%\\?" end t))
|
||||
(replace-match ""))))
|
||||
(org-capture-position-for-last-stored (point))
|
||||
(let ((beg (point)))
|
||||
(insert (org-capture-get :template))
|
||||
(unless (bolp) (insert "\n"))
|
||||
;; Ignore the final newline character so as to not alter data
|
||||
;; after inserted text. Yet, if the template is empty, make
|
||||
;; sure END matches BEG instead of pointing before it.
|
||||
(let ((end (max beg (1- (point)))))
|
||||
(org-capture-empty-lines-after)
|
||||
(org-capture-mark-kill-region origin (point))
|
||||
(org-capture-narrow beg end)
|
||||
(when (or (search-backward "%?" beg t)
|
||||
(search-forward "%?" end t))
|
||||
(replace-match ""))))))
|
||||
|
||||
(defun org-capture-mark-kill-region (beg end)
|
||||
"Mark the region that will have to be killed when aborting capture."
|
||||
|
|
|
@ -826,47 +826,70 @@ end of string are ignored."
|
|||
results ;skip trailing separator
|
||||
(cons (substring string i) results)))))))
|
||||
|
||||
(defun org--string-from-props (s property)
|
||||
"Return visible string according to text properties in string S.
|
||||
PROPERTY is either `invisible' or `display'."
|
||||
(let ((len (length s))
|
||||
(new nil)
|
||||
(i 0)
|
||||
(cursor 0))
|
||||
(while (setq i (text-property-not-all i len property nil s))
|
||||
(let* ((end (next-single-property-change i property s len))
|
||||
(props (text-properties-at i s))
|
||||
(defun org--string-from-props (s property beg end)
|
||||
"Return the visible part of string S.
|
||||
Visible part is determined according to text PROPERTY, which is
|
||||
either `invisible' or `display'. BEG and END are 0-indices
|
||||
delimiting S."
|
||||
(let ((width 0)
|
||||
(cursor beg))
|
||||
(while (setq beg (text-property-not-all beg end property nil s))
|
||||
(let* ((next (next-single-property-change beg property s end))
|
||||
(props (text-properties-at beg s))
|
||||
(spec (plist-get props property))
|
||||
(value
|
||||
(if (eq property 'invisible)
|
||||
;; If `invisible' property in PROPS means text is to
|
||||
;; be invisible, return the empty string. Otherwise
|
||||
;; return nil so that the part is skipped.
|
||||
(and (or (eq t buffer-invisibility-spec)
|
||||
(assoc-string (plist-get props 'invisible)
|
||||
buffer-invisibility-spec))
|
||||
"")
|
||||
(let ((display (plist-get props 'display)))
|
||||
(pcase (if (stringp display) display
|
||||
(cl-some #'stringp display))
|
||||
(`nil nil)
|
||||
(pcase property
|
||||
(`invisible
|
||||
;; If `invisible' property in PROPS means text is to
|
||||
;; be invisible, return 0. Otherwise return nil so
|
||||
;; as to resume search.
|
||||
(and (or (eq t buffer-invisibility-spec)
|
||||
(assoc-string spec buffer-invisibility-spec))
|
||||
0))
|
||||
(`display
|
||||
(pcase spec
|
||||
(`nil nil)
|
||||
(`(space . ,props)
|
||||
(let ((width (plist-get props :width)))
|
||||
(and (wholenump width) width)))
|
||||
(`(image . ,_)
|
||||
(ceiling (car (image-size spec))))
|
||||
((pred stringp)
|
||||
;; Displayed string could contain invisible parts,
|
||||
;; but no nested display.
|
||||
(s (org--string-from-props s 'invisible)))))))
|
||||
(org--string-from-props spec 'invisible 0 (length spec)))
|
||||
(_
|
||||
;; Un-handled `display' value. Ignore it.
|
||||
;; Consider the original string instead.
|
||||
nil)))
|
||||
(_ (error "Unknown property: %S" property)))))
|
||||
(when value
|
||||
(setq new (concat new (substring s cursor i) value))
|
||||
(setq cursor end))
|
||||
(setq i end)))
|
||||
(if new (concat new (substring s cursor))
|
||||
;; If PROPERTY was not found, return S as-is.
|
||||
s)))
|
||||
(cl-incf width
|
||||
;; When looking for `display' parts, we still need
|
||||
;; to look for `invisible' property elsewhere.
|
||||
(+ (cond ((eq property 'display)
|
||||
(org--string-from-props s 'invisible cursor beg))
|
||||
((= cursor beg) 0)
|
||||
(t (string-width (substring s cursor beg))))
|
||||
value))
|
||||
(setq cursor next))
|
||||
(setq beg next)))
|
||||
(+ width
|
||||
;; Look for `invisible' property in the last part of the
|
||||
;; string. See above.
|
||||
(cond ((eq property 'display)
|
||||
(org--string-from-props s 'invisible cursor end))
|
||||
((= cursor end) 0)
|
||||
(t (string-width (substring s cursor end)))))))
|
||||
|
||||
(defun org-string-width (string)
|
||||
"Return width of STRING when displayed in the current buffer.
|
||||
Unlike `string-width', this function takes into consideration
|
||||
`invisible' and `display' text properties."
|
||||
(string-width
|
||||
(org--string-from-props (org--string-from-props string 'display)
|
||||
'invisible)))
|
||||
`invisible' and `display' text properties. It supports the
|
||||
latter in a limited way, mostly for combinations used in Org.
|
||||
Results may be off sometimes if it cannot handle a given
|
||||
`display' value."
|
||||
(org--string-from-props string 'display 0 (length string)))
|
||||
|
||||
(defun org-not-nil (v)
|
||||
"If V not nil, and also not the string \"nil\", then return V.
|
||||
|
|
|
@ -2064,6 +2064,20 @@ a communication channel."
|
|||
|
||||
;;; End-user functions
|
||||
|
||||
;;;###autoload
|
||||
(defun org-ascii-convert-region-to-ascii ()
|
||||
"Assume region has Org syntax, and convert it to plain ASCII."
|
||||
(interactive)
|
||||
(let ((org-ascii-charset 'ascii))
|
||||
(org-export-replace-region-by 'ascii)))
|
||||
|
||||
;;;###autoload
|
||||
(defun org-ascii-convert-region-to-utf8 ()
|
||||
"Assume region has Org syntax, and convert it to UTF-8."
|
||||
(interactive)
|
||||
(let ((org-ascii-charset 'utf-8))
|
||||
(org-export-replace-region-by 'ascii)))
|
||||
|
||||
;;;###autoload
|
||||
(defun org-ascii-export-as-ascii
|
||||
(&optional async subtreep visible-only body-only ext-plist)
|
||||
|
|
|
@ -145,8 +145,10 @@
|
|||
(org-capture-refile)
|
||||
(list file1 file2 (buffer-file-name)))))))))
|
||||
|
||||
(ert-deftest test-org-capture/insert-at-end-abort ()
|
||||
"Test that capture can be aborted after inserting at end of capture buffer."
|
||||
(ert-deftest test-org-capture/abort ()
|
||||
"Test aborting a capture process."
|
||||
;; Test that capture can be aborted after inserting at end of
|
||||
;; capture buffer.
|
||||
(should
|
||||
(equal
|
||||
"* A\n* B\n"
|
||||
|
@ -158,6 +160,235 @@
|
|||
(goto-char (point-max))
|
||||
(insert "Capture text")
|
||||
(org-capture-kill))
|
||||
(buffer-string))))
|
||||
(should
|
||||
(equal "- A\n - B"
|
||||
(org-test-with-temp-text-in-file "- A\n - B"
|
||||
(let* ((file (buffer-file-name))
|
||||
(org-capture-templates
|
||||
`(("t" "Item" item (file ,file) "- X"))))
|
||||
(org-capture nil "t")
|
||||
(org-capture-kill))
|
||||
(buffer-string))))
|
||||
(should
|
||||
(equal "| a |\n| b |"
|
||||
(org-test-with-temp-text-in-file "| a |\n| b |"
|
||||
(let* ((file (buffer-file-name))
|
||||
(org-capture-templates
|
||||
`(("t" "Table" table-line (file ,file) "| x |"))))
|
||||
(org-capture nil "t")
|
||||
(org-capture-kill))
|
||||
(buffer-string))))
|
||||
;; Test aborting a capture that split the line.
|
||||
(should
|
||||
(equal
|
||||
"* AB\n"
|
||||
(org-test-with-temp-text-in-file "* AB\n"
|
||||
(let* ((file (buffer-file-name))
|
||||
(org-capture-templates
|
||||
`(("t" "Todo" entry
|
||||
(file+function ,file (lambda () (goto-char 4))) "** H1 %?"))))
|
||||
(org-capture nil "t")
|
||||
(org-capture-kill))
|
||||
(buffer-string)))))
|
||||
|
||||
(ert-deftest test-org-caputre/entry ()
|
||||
"Test `entry' type in capture template."
|
||||
;; Do not break next headline.
|
||||
(should
|
||||
(equal
|
||||
"* A\n** H1 Capture text\n* B\n"
|
||||
(org-test-with-temp-text-in-file "* A\n* B\n"
|
||||
(let* ((file (buffer-file-name))
|
||||
(org-capture-templates
|
||||
`(("t" "Todo" entry (file+headline ,file "A") "** H1 %?"))))
|
||||
(org-capture nil "t")
|
||||
(goto-char (point-max))
|
||||
(insert "Capture text")
|
||||
(org-capture-finalize))
|
||||
(buffer-string)))))
|
||||
|
||||
(ert-deftest test-org-capture/item ()
|
||||
"Test `item' type in capture template."
|
||||
;; Insert item in the first plain list found at the target location.
|
||||
(should
|
||||
(equal
|
||||
"* A\n- list 1\n- X\n\n\n1. list 2"
|
||||
(org-test-with-temp-text-in-file "* A\n- list 1\n\n\n1. list 2"
|
||||
(let* ((file (buffer-file-name))
|
||||
(org-capture-templates
|
||||
`(("t" "Item" item (file+headline ,file "A") "- X"))))
|
||||
(org-capture nil "t")
|
||||
(org-capture-finalize))
|
||||
(buffer-string))))
|
||||
(should
|
||||
(equal
|
||||
"Text\n- list 1\n- X\n\n\n1. list 2"
|
||||
(org-test-with-temp-text-in-file "Text\n- list 1\n\n\n1. list 2"
|
||||
(let* ((file (buffer-file-name))
|
||||
(org-capture-templates
|
||||
`(("t" "Item" item (file ,file) "- X"))))
|
||||
(org-capture nil "t")
|
||||
(org-capture-finalize))
|
||||
(buffer-string))))
|
||||
;; When targeting a specific location, start looking for plain lists
|
||||
;; from there.
|
||||
(should
|
||||
(equal
|
||||
"* A\n- skip\n\n\n1. here\n2. X\n"
|
||||
(org-test-with-temp-text-in-file "* A\n- skip\n\n\n1. here"
|
||||
(let* ((file (buffer-file-name))
|
||||
(org-capture-templates
|
||||
`(("t" "Item" item (file+regexp ,file "here") "1. X"))))
|
||||
(org-capture nil "t")
|
||||
(org-capture-finalize))
|
||||
(buffer-string))))
|
||||
;; If there is no such list, create it.
|
||||
(should
|
||||
(equal
|
||||
"* A\n- X\n"
|
||||
(org-test-with-temp-text-in-file "* A"
|
||||
(let* ((file (buffer-file-name))
|
||||
(org-capture-templates
|
||||
`(("t" "Item" item (file+headline ,file "A") "- X"))))
|
||||
(org-capture nil "t")
|
||||
(org-capture-finalize))
|
||||
(buffer-string))))
|
||||
;; When `:prepend' is non-nil, insert new item as the first item.
|
||||
(should
|
||||
(equal
|
||||
"* A\n- X\n- 1\n- 2"
|
||||
(org-test-with-temp-text-in-file "* A\n- 1\n- 2"
|
||||
(let* ((file (buffer-file-name))
|
||||
(org-capture-templates
|
||||
`(("t" "Item" item (file+headline ,file "A") "- X"
|
||||
:prepend t))))
|
||||
(org-capture nil "t")
|
||||
(org-capture-finalize))
|
||||
(buffer-string))))
|
||||
;; When `:prepend' is nil, insert new item as the last top-level
|
||||
;; item.
|
||||
(should
|
||||
(equal
|
||||
"* A\n- 1\n - 2\n- X\n"
|
||||
(org-test-with-temp-text-in-file "* A\n- 1\n - 2"
|
||||
(let* ((file (buffer-file-name))
|
||||
(org-capture-templates
|
||||
`(("t" "Item" item (file+headline ,file "A") "- X"))))
|
||||
(org-capture nil "t")
|
||||
(org-capture-finalize))
|
||||
(buffer-string))))
|
||||
;; When targeting a specific location, one can insert in a sub-list.
|
||||
(should
|
||||
(equal
|
||||
"* A\n- skip\n - here\n - X\n- skip"
|
||||
(org-test-with-temp-text-in-file "* A\n- skip\n - here\n- skip"
|
||||
(let* ((file (buffer-file-name))
|
||||
(org-capture-templates
|
||||
`(("t" "Item" item (file+regexp ,file "here") "- X"))))
|
||||
(org-capture nil "t")
|
||||
(org-capture-finalize))
|
||||
(buffer-string))))
|
||||
;; Obey `:empty-lines' when creating a new list.
|
||||
(should
|
||||
(equal
|
||||
"\n- X\n\n\n* H"
|
||||
(org-test-with-temp-text-in-file "\n* H"
|
||||
(let* ((file (buffer-file-name))
|
||||
(org-capture-templates
|
||||
`(("t" "Item" item (file ,file) "- X"
|
||||
:empty-lines-before 1 :empty-lines-after 2 :prepend t))))
|
||||
(org-capture nil "t")
|
||||
(org-capture-finalize))
|
||||
(buffer-string))))
|
||||
;; Obey `:empty-lines' in an existing list only between items, and
|
||||
;; only if the value doesn't break the list.
|
||||
(should
|
||||
(equal
|
||||
"- A\n\n- X\nText"
|
||||
(org-test-with-temp-text-in-file "- A\nText"
|
||||
(let* ((file (buffer-file-name))
|
||||
(org-capture-templates
|
||||
`(("t" "Item" item (file ,file) "- X" :empty-lines 1))))
|
||||
(org-capture nil "t")
|
||||
(org-capture-finalize))
|
||||
(buffer-string))))
|
||||
(should
|
||||
(equal
|
||||
"Text\n- X\n\n- A"
|
||||
(org-test-with-temp-text-in-file "Text\n- A"
|
||||
(let* ((file (buffer-file-name))
|
||||
(org-capture-templates
|
||||
`(("t" "Item" item (file ,file) "- X"
|
||||
:prepend t :empty-lines 1))))
|
||||
(org-capture nil "t")
|
||||
(org-capture-finalize))
|
||||
(buffer-string))))
|
||||
(should-not
|
||||
(equal
|
||||
"- A\n\n\n- X"
|
||||
(org-test-with-temp-text-in-file "- A"
|
||||
(let* ((file (buffer-file-name))
|
||||
(org-capture-templates
|
||||
`(("t" "Item" item (file ,file) "- X" :empty-lines 2))))
|
||||
(org-capture nil "t")
|
||||
(org-capture-finalize))
|
||||
(buffer-string))))
|
||||
;; Preserve list type when pre-pending.
|
||||
(should
|
||||
(equal
|
||||
"1. X\n2. A"
|
||||
(org-test-with-temp-text-in-file "1. A"
|
||||
(let* ((file (buffer-file-name))
|
||||
(org-capture-templates
|
||||
`(("t" "Item" item (file ,file) "- X" :prepend t))))
|
||||
(org-capture nil "t")
|
||||
(org-capture-finalize))
|
||||
(buffer-string))))
|
||||
;; Handle indentation. Handle multi-lines templates.
|
||||
(should
|
||||
(equal
|
||||
" - A\n - X\n"
|
||||
(org-test-with-temp-text-in-file " - A"
|
||||
(let* ((file (buffer-file-name))
|
||||
(org-capture-templates
|
||||
`(("t" "Item" item (file ,file) "- X"))))
|
||||
(org-capture nil "t")
|
||||
(org-capture-finalize))
|
||||
(buffer-string))))
|
||||
(should
|
||||
(equal
|
||||
" - A\n - X\n Line 2\n"
|
||||
(org-test-with-temp-text-in-file " - A"
|
||||
(let* ((file (buffer-file-name))
|
||||
(org-capture-templates
|
||||
`(("t" "Item" item (file ,file) "- X\n Line 2"))))
|
||||
(org-capture nil "t")
|
||||
(org-capture-finalize))
|
||||
(buffer-string))))
|
||||
;; Handle incomplete templates.
|
||||
(should
|
||||
(equal
|
||||
"- A\n- X\n"
|
||||
(org-test-with-temp-text-in-file "- A"
|
||||
(let* ((file (buffer-file-name))
|
||||
(org-capture-templates
|
||||
`(("t" "Item" item (file ,file) "X"))))
|
||||
(org-capture nil "t")
|
||||
(org-capture-finalize))
|
||||
(buffer-string))))
|
||||
;; Do not break next headline.
|
||||
(should-not
|
||||
(equal
|
||||
"- A\n- X\nFoo* H"
|
||||
(org-test-with-temp-text-in-file "- A\n* H"
|
||||
(let* ((file (buffer-file-name))
|
||||
(org-capture-templates
|
||||
`(("t" "Item" item (file ,file) "- X"))))
|
||||
(org-capture nil "t")
|
||||
(goto-char (point-max))
|
||||
(insert "Foo")
|
||||
(org-capture-finalize))
|
||||
(buffer-string)))))
|
||||
|
||||
(ert-deftest test-org-capture/table-line ()
|
||||
|
@ -334,6 +565,71 @@
|
|||
(org-capture nil "t")
|
||||
(org-table-get-stored-formulas))))))
|
||||
|
||||
(ert-deftest test-org-capture/plain ()
|
||||
"Test `plain' type in capture template."
|
||||
;; Insert at end of the file, unless `:prepend' is non-nil.
|
||||
(should
|
||||
(equal "Some text.\nFoo\n"
|
||||
(org-test-with-temp-text-in-file "Some text."
|
||||
(let* ((file (buffer-file-name))
|
||||
(org-capture-templates
|
||||
`(("t" "Text" plain (file ,file) "Foo"
|
||||
:immediate-finish t))))
|
||||
(org-capture nil "t")
|
||||
(buffer-string)))))
|
||||
(should
|
||||
(equal "Foo\nSome text."
|
||||
(org-test-with-temp-text-in-file "Some text."
|
||||
(let* ((file (buffer-file-name))
|
||||
(org-capture-templates
|
||||
`(("t" "Text" plain (file ,file) "Foo"
|
||||
:immediate-finish t :prepend t))))
|
||||
(org-capture nil "t")
|
||||
(buffer-string)))))
|
||||
;; When a headline is specified, add it at the beginning of the
|
||||
;; entry, past any meta-data, or at its end, depending on
|
||||
;; `:prepend'.
|
||||
(should
|
||||
(equal "* A\nSCHEDULED: <2012-03-29 Thu>\nSome text.\nFoo\n* B"
|
||||
(org-test-with-temp-text-in-file
|
||||
"* A\nSCHEDULED: <2012-03-29 Thu>\nSome text.\n* B"
|
||||
(let* ((file (buffer-file-name))
|
||||
(org-capture-templates
|
||||
`(("t" "Text" plain (file+headline ,file "A") "Foo"
|
||||
:immediate-finish t))))
|
||||
(org-capture nil "t")
|
||||
(buffer-string)))))
|
||||
(should
|
||||
(equal "* A\nSCHEDULED: <2012-03-29 Thu>\nFoo\nSome text.\n* B"
|
||||
(org-test-with-temp-text-in-file
|
||||
"* A\nSCHEDULED: <2012-03-29 Thu>\nSome text.\n* B"
|
||||
(let* ((file (buffer-file-name))
|
||||
(org-capture-templates
|
||||
`(("t" "Text" plain (file+headline ,file "A") "Foo"
|
||||
:immediate-finish t :prepend t))))
|
||||
(org-capture nil "t")
|
||||
(buffer-string)))))
|
||||
;; At an exact position, in the middle of a line, make sure to
|
||||
;; insert text on a line on its own.
|
||||
(should
|
||||
(equal "A\nX\nB"
|
||||
(org-test-with-temp-text-in-file "AB"
|
||||
(let* ((file (buffer-file-name))
|
||||
(org-capture-templates
|
||||
`(("t" "Text" plain (file+function ,file forward-char) "X"
|
||||
:immediate-finish t))))
|
||||
(org-capture nil "t")
|
||||
(buffer-string)))))
|
||||
;; Pathological case: insert an empty template in an empty file.
|
||||
(should
|
||||
(equal ""
|
||||
(org-test-with-temp-text-in-file ""
|
||||
(let* ((file (buffer-file-name))
|
||||
(org-capture-templates
|
||||
`(("t" "Text" plain (file ,file) ""
|
||||
:immediate-finish t))))
|
||||
(org-capture nil "t")
|
||||
(buffer-string))))))
|
||||
|
||||
(provide 'test-org-capture)
|
||||
;;; test-org-capture.el ends here
|
||||
|
|
|
@ -63,7 +63,9 @@
|
|||
(should (= 5 (org-string-width #("1a3" 1 2 (display "abc")))))
|
||||
;; `display' string can also contain invisible characters.
|
||||
(should (= 4 (org-string-width
|
||||
#("123" 1 2 (display #("abc" 1 2 (invisible t))))))))
|
||||
#("123" 1 2 (display #("abc" 1 2 (invisible t)))))))
|
||||
;; Test `space' property in `display'.
|
||||
(should (= 2 (org-string-width #(" " 0 1 (display (space :width 2)))))))
|
||||
|
||||
|
||||
;;; Regexp
|
||||
|
|
Loading…
Reference in New Issue