1 ;;; test-org-colview.el --- Tests for org-colview.el -*- lexical-binding: t; -*-
3 ;; Copyright (C) 2016, 2019 Nicolas Goaziou
5 ;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
7 ;; This program is free software; you can redistribute it and/or modify
8 ;; it under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation, either version 3 of the License, or
10 ;; (at your option) any later version.
12 ;; This program is distributed in the hope that it will be useful,
13 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ;; GNU General Public License for more details.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
26 (ert-deftest test-org-colview
/get-format
()
27 "Test `org-columns-get-format' specifications."
28 ;; Without any clue, use `org-columns-default-format'.
31 (org-test-with-temp-text "* H"
32 (let ((org-columns-default-format "%A"))
33 (org-columns-get-format)))))
34 ;; If COLUMNS keyword is set, use it.
37 (org-test-with-temp-text "#+COLUMNS: %B\n* H"
38 (let ((org-columns-default-format "%A"))
39 (org-columns-get-format)))))
42 (org-test-with-temp-text "#+columns: %B\n* H"
43 (let ((org-columns-default-format "%A"))
44 (org-columns-get-format)))))
47 (org-test-with-temp-text "* H\n#+COLUMNS: %B"
48 (let ((org-columns-default-format "%A"))
49 (org-columns-get-format)))))
50 ;; When :COLUMNS: property is set somewhere in the tree, use it over
55 (org-test-with-temp-text
56 "#+COLUMNS: %B\n* H\n:PROPERTIES:\n:COLUMNS: %C\n:END:\n** S\n<point>"
57 (let ((org-columns-default-format "%A"))
58 (org-columns-get-format)))))
59 ;; When optional argument is provided, prefer it.
63 (org-test-with-temp-text
64 "#+COLUMNS: %B\n* H\n:PROPERTIES:\n:COLUMNS: %C\n:END:\n** S\n<point>"
65 (let ((org-columns-default-format "%A"))
66 (org-columns-get-format "%D"))))))
68 (ert-deftest test-org-colview
/columns-scope
()
69 "Test `org-columns' scope."
70 ;; Before the first headline, view all document.
74 (org-test-with-temp-text "Top\n* H1\n** H2\n* H3"
75 (let ((org-columns-default-format "%ITEM")) (org-columns))
77 (lambda () (get-char-property (point) 'org-columns-value
))))))
78 ;; When :COLUMNS: is set up in the hierarchy, view tree starting
83 (org-test-with-temp-text
84 "* H1\n** H2\n:PROPERTIES:\n:COLUMNS: %ITEM\n:END:\n*** <point>H3\n* H4"
85 (let ((org-columns-default-format "%ITEM")) (org-columns))
87 (lambda () (get-char-property (point) 'org-columns-value
))))))
88 ;; Otherwise, view tree starting at the current headline.
92 (org-test-with-temp-text "Top\n* H1\n** <point>H2\n*** H3\n* H4"
93 (let ((org-columns-default-format "%ITEM")) (org-columns))
95 (lambda () (get-char-property (point) 'org-columns-value
))))))
96 ;; With a non-nil prefix argument, always view all document.
99 '("H1" "H2" "H3" "H4")
100 (org-test-with-temp-text
101 "* H1\n** H2\n:PROPERTIES:\n:COLUMNS: %ITEM\n:END:\n*** <point>H3\n* H4"
102 (let ((org-columns-default-format "%ITEM")) (org-columns t
))
104 (lambda () (get-char-property (point) 'org-columns-value
))))))
108 (org-test-with-temp-text
109 "Top\n* H1\n** <point>H2\n:PROPERTIES:\n:A: 1\n:END:"
110 (let ((org-columns-default-format "%A{+}")) (org-columns t
))
112 (lambda () (get-char-property (point) 'org-columns-value
)))))))
114 (ert-deftest test-org-colview
/columns-width
()
115 "Test `org-columns' column widths."
116 ;; When a width is specified in the format, use it.
119 (org-test-with-temp-text "* H"
120 (let ((org-columns-default-format "%9ITEM")) (org-columns))
121 (aref org-columns-current-maxwidths
0))))
122 ;; Otherwise, use the width of the largest value in the column.
125 (org-test-with-temp-text
126 "* H\n:PROPERTIES:\n:P: X\n:END:\n** H2\n:PROPERTIES:\n:P: XX\n:END:"
127 (let ((org-columns-default-format "%P")) (org-columns))
128 (aref org-columns-current-maxwidths
0))))
129 ;; If the title is wider than the widest value, use title width
133 (org-test-with-temp-text "* H"
134 (let ((org-columns-default-format "%ITEM")) (org-columns))
135 (aref org-columns-current-maxwidths
0))))
136 ;; Special case: stars do count for ITEM.
139 (org-test-with-temp-text "* Head"
140 (let ((org-columns-default-format "%ITEM")) (org-columns))
141 (aref org-columns-current-maxwidths
0))))
142 ;; Special case: width takes into account link narrowing in ITEM.
146 (org-test-with-temp-text "* [[https://orgmode.org][123]]"
147 (let ((org-columns-default-format "%ITEM")) (org-columns))
148 (cons (get-char-property (point) 'org-columns-value-modified
)
149 (aref org-columns-current-maxwidths
0)))))
150 ;; When a value is too wide for the current column, add ellipses.
151 ;; Take into consideration length of `org-columns-ellipses'.
154 (org-test-with-temp-text "* H\n:PROPERTIES:\n:P: 123456\n:END:"
155 (let ((org-columns-default-format "%5P")
156 (org-columns-ellipses ".."))
158 (org-trim (get-char-property (point) 'display
)))))
161 (org-test-with-temp-text "* H\n:PROPERTIES:\n:P: 123456\n:END:"
162 (let ((org-columns-default-format "%5P")
163 (org-columns-ellipses "…"))
165 (org-trim (get-char-property (point) 'display
))))))
167 (ert-deftest test-org-colview
/columns-summary
()
168 "Test `org-columns' summary types."
169 ;; {+} and {+;format} add numbers.
173 (org-test-with-temp-text
183 (let ((org-columns-default-format "%A{+}")) (org-columns))
184 (get-char-property (point) 'org-columns-value-modified
))))
188 (org-test-with-temp-text
198 (let ((org-columns-default-format "%A{+;%.1f}")) (org-columns))
199 (get-char-property (point) 'org-columns-value-modified
))))
200 ;; {$} is a shortcut for {+;%.2f}.
204 (org-test-with-temp-text
214 (let ((org-columns-default-format "%A{$}")) (org-columns))
215 (get-char-property (point) 'org-columns-value-modified
))))
216 ;; Obey to format string even in leaf values.
220 (org-test-with-temp-text
225 (let ((org-columns-default-format "%A{+;%.1f}")) (org-columns))
226 (get-char-property (point) 'org-columns-value-modified
))))
227 ;; {:} sums times. Plain numbers are minutes.
231 (org-test-with-temp-text
241 (let ((org-columns-default-format "%A{:}")) (org-columns))
242 (get-char-property (point) 'org-columns-value-modified
))))
246 (org-test-with-temp-text
256 (let ((org-columns-default-format "%A{:}")) (org-columns))
257 (get-char-property (point) 'org-columns-value-modified
))))
258 ;; {X}, {X/} and {X%} indicate checkbox status.
262 (org-test-with-temp-text
272 (let ((org-columns-default-format "%A{X}")) (org-columns))
273 (get-char-property (point) 'org-columns-value-modified
))))
277 (org-test-with-temp-text
287 (let ((org-columns-default-format "%A{X}")) (org-columns))
288 (get-char-property (point) 'org-columns-value-modified
))))
292 (org-test-with-temp-text
302 (let ((org-columns-default-format "%A{X}")) (org-columns))
303 (get-char-property (point) 'org-columns-value-modified
))))
307 (org-test-with-temp-text
317 (let ((org-columns-default-format "%A{X/}")) (org-columns))
318 (get-char-property (point) 'org-columns-value-modified
))))
322 (org-test-with-temp-text
332 (let ((org-columns-default-format "%A{X%}")) (org-columns))
333 (get-char-property (point) 'org-columns-value-modified
))))
334 ;; {X/} handles recursive summaries.
338 (org-test-with-temp-text
353 (let ((org-columns-default-format "%A{X/}")) (org-columns))
354 (get-char-property (point) 'org-columns-value-modified
))))
358 (org-test-with-temp-text
373 (let ((org-columns-default-format "%A{X/}")) (org-columns))
374 (get-char-property (point) 'org-columns-value-modified
))))
375 ;; {X%} handles recursive summaries.
379 (org-test-with-temp-text
394 (let ((org-columns-default-format "%A{X%}")) (org-columns))
395 (get-char-property (point) 'org-columns-value-modified
))))
399 (org-test-with-temp-text
414 (let ((org-columns-default-format "%A{X%}")) (org-columns))
415 (get-char-property (point) 'org-columns-value-modified
))))
416 ;; {min} is the smallest number in column, {max} the largest one.
417 ;; {mean} is the arithmetic mean of numbers in column.
421 (org-test-with-temp-text
431 (let ((org-columns-default-format "%A{min}")) (org-columns))
432 (get-char-property (point) 'org-columns-value-modified
))))
436 (org-test-with-temp-text
446 (let ((org-columns-default-format "%A{max}")) (org-columns))
447 (get-char-property (point) 'org-columns-value-modified
))))
451 (org-test-with-temp-text
461 (let ((org-columns-default-format "%A{mean}")) (org-columns))
462 (get-char-property (point) 'org-columns-value-modified
))))
463 ;; {:min}, {:max} and {:mean} apply to time values.
467 (org-test-with-temp-text
477 (let ((org-columns-default-format "%A{:min}")) (org-columns))
478 (get-char-property (point) 'org-columns-value-modified
))))
482 (org-test-with-temp-text
492 (let ((org-columns-default-format "%A{:max}")) (org-columns))
493 (get-char-property (point) 'org-columns-value-modified
))))
497 (org-test-with-temp-text
507 (let ((org-columns-default-format "%A{:mean}")) (org-columns))
508 (get-char-property (point) 'org-columns-value-modified
))))
509 ;; {@min}, {@max} and {@mean} apply to ages.
513 (org-test-at-time "<2014-03-04 Tue>"
514 (org-test-with-temp-text
524 (let ((org-columns-default-format "%A{@min}")) (org-columns))
525 (get-char-property (point) 'org-columns-value-modified
)))))
529 (org-test-at-time "<2014-03-04 Tue>"
530 (org-test-with-temp-text
540 (let ((org-columns-default-format "%A{@max}")) (org-columns))
541 (get-char-property (point) 'org-columns-value-modified
)))))
545 (org-test-at-time "<2014-03-04 Tue>"
546 (org-test-with-temp-text
556 (let ((org-columns-default-format "%A{@mean}")) (org-columns))
557 (get-char-property (point) 'org-columns-value-modified
)))))
558 ;; If a time value is expressed as a duration, return a duration.
559 ;; If any of them follows H:MM:SS pattern, use it too. Also handle
560 ;; combinations of duration and H:MM:SS patterns.
564 (org-test-with-temp-text
574 (let ((org-columns-default-format "%A{:}")
575 (org-duration-units '(("d" .
1440) ("h" .
60)))
576 (org-duration-format '(("d" . nil
) (special . h
:mm
))))
578 (get-char-property (point) 'org-columns-value-modified
))))
582 (org-test-with-temp-text
592 (let ((org-columns-default-format "%A{:}")) (org-columns))
593 (get-char-property (point) 'org-columns-value-modified
))))
597 (org-test-with-temp-text
607 (let ((org-columns-default-format "%A{:}")
608 (org-duration-units '(("d" .
1440) ("h" .
60)))
609 (org-duration-format '(("d" . nil
) (special . h
:mm
))))
611 (get-char-property (point) 'org-columns-value-modified
))))
612 ;; @min, @max and @mean also accept regular duration.
616 (org-test-with-temp-text
626 (let ((org-columns-default-format "%A{@min}")) (org-columns))
627 (get-char-property (point) 'org-columns-value-modified
))))
628 ;; {est+} gives a low-high estimate using mean and standard
633 (org-test-with-temp-text
643 (let ((org-columns-default-format "%A{est+}")) (org-columns))
644 (get-char-property (point) 'org-columns-value-modified
))))
645 ;; When using {est+} summary, a single number is understood as
646 ;; a degenerate range.
650 (org-test-with-temp-text
657 (let ((org-columns-default-format "%A{est+}")) (org-columns))
658 (get-char-property (point) 'org-columns-value-modified
))))
659 ;; Allow custom summary types.
663 (org-test-with-temp-text
673 (let ((org-columns-summary-types
674 '(("custom" .
(lambda (s _
) (mapconcat #'identity s
"|")))))
675 (org-columns-default-format "%A{custom}")) (org-columns))
676 (get-char-property (point) 'org-columns-value-modified
))))
677 ;; Allow custom _collect_ for summary types.
681 (org-test-with-temp-text
692 (let ((org-columns-summary-types
693 '(("custom" org-columns--summary-sum
695 (if (equal "1" (org-entry-get nil
(format "%s-OK" p
)))
696 (org-entry-get nil p
)
698 (org-columns-default-format "%A{custom}")) (org-columns))
699 (get-char-property (point) 'org-columns-value-modified
))))
700 ;; Allow custom collect function to be used for different columns
704 (org-test-with-temp-text
718 (let ((org-columns-summary-types
719 '(("custom" org-columns--summary-sum
721 (if (equal "1" (org-entry-get nil
(format "%s-OK" p
)))
722 (org-entry-get nil p
)
724 (org-columns-default-format "%A{custom} %B{custom}")) (org-columns))
725 (list (get-char-property (point) 'org-columns-value-modified
)
726 (get-char-property (1+ (point)) 'org-columns-value-modified
)))))
727 ;; Allow multiple summary types applied to the same property.
731 (org-test-with-temp-text
741 (let ((org-columns-default-format "%A{min} %A{max}")) (org-columns))
742 (list (get-char-property (point) 'org-columns-value-modified
)
743 (get-char-property (1+ (point)) 'org-columns-value-modified
)))))
744 ;; Allow mixing both summarized and non-summarized columns for
745 ;; a property. However, the first column takes precedence and
746 ;; updates the value.
750 (org-test-with-temp-text
763 (let ((org-columns-default-format "%A %A{min}")) (org-columns))
764 (list (get-char-property (point) 'org-columns-value-modified
)
765 (get-char-property (1+ (point)) 'org-columns-value-modified
)))))
769 (org-test-with-temp-text
782 (let ((org-columns-default-format "%A{min} %A")) (org-columns))
783 (list (get-char-property (point) 'org-columns-value-modified
)
784 (get-char-property (1+ (point)) 'org-columns-value-modified
))))))
786 (ert-deftest test-org-colview
/columns-new
()
787 "Test `org-columns-new' specifications."
788 ;; Insert new column at the left of the current one.
790 (equal '("FOO" "ITEM")
791 (org-test-with-temp-text "* H"
792 (let ((org-columns-default-format "%ITEM")) (org-columns))
793 (org-columns-new nil
"FOO" "FOO" nil nil nil
)
794 (list (get-char-property (point) 'org-columns-key
)
795 (get-char-property (1+ (point)) 'org-columns-key
)))))
797 (equal '("ITEM" "FOO" "BAR")
798 (org-test-with-temp-text "* H"
799 (let ((org-columns-default-format "%ITEM %BAR")) (org-columns))
801 (org-columns-new nil
"FOO" "FOO" nil nil nil
)
802 (list (get-char-property (1- (point)) 'org-columns-key
)
803 (get-char-property (point) 'org-columns-key
)
804 (get-char-property (1+ (point)) 'org-columns-key
)))))
805 ;; Update #+COLUMNS keyword if needed.
807 (equal "#+COLUMNS: %FOO %ITEM"
808 (org-test-with-temp-text "#+COLUMNS: %ITEM\n<point>* H"
809 (let ((org-columns-default-format "%ITEM")) (org-columns))
810 (org-columns-new nil
"FOO" "FOO" nil nil nil
)
811 (goto-char (point-min))
812 (buffer-substring-no-properties (point) (line-end-position)))))
814 (equal "#+COLUMNS: %ITEM %FOO %BAR"
815 (org-test-with-temp-text "#+COLUMNS: %ITEM %BAR\n<point>* H"
816 (let ((org-columns-default-format "%ITEM %BAR")) (org-columns))
818 (org-columns-new nil
"FOO" "FOO" nil nil nil
)
819 (goto-char (point-min))
820 (buffer-substring-no-properties (point) (line-end-position)))))
821 ;; Mind case when updating #+COLUMNS.
823 (equal "#+COLUMNS: %ITEM %Foo %BAR"
824 (org-test-with-temp-text "#+COLUMNS: %ITEM %BAR\n<point>* H"
825 (let ((org-columns-default-format "%ITEM %BAR")) (org-columns))
827 (org-columns-new nil
"Foo" "Foo" nil nil nil
)
828 (goto-char (point-min))
829 (buffer-substring-no-properties (point) (line-end-position)))))
831 (equal "#+columns: %ITEM %Foo %BAR"
832 (org-test-with-temp-text "#+columns: %ITEM %BAR\n<point>* H"
833 (let ((org-columns-default-format "%ITEM %BAR")) (org-columns))
835 (org-columns-new nil
"Foo" "Foo" nil nil nil
)
836 (goto-char (point-min))
837 (buffer-substring-no-properties (point) (line-end-position)))))
838 ;; Also update :COLUMNS: properties.
841 (org-test-with-temp-text "* H\n:PROPERTIES:\n:COLUMNS: %ITEM\n:END:"
842 (let ((org-columns-default-format "%ITEM")) (org-columns))
843 (org-columns-new nil
"FOO" "FOO" nil nil nil
)
844 (org-entry-get nil
"COLUMNS"))))
845 ;; If no keyword nor any property is available, insert one.
847 (string-match-p (regexp-quote "#+COLUMNS: %FOO %ITEM")
848 (org-test-with-temp-text "* H"
849 (let ((org-columns-default-format "%ITEM")) (org-columns))
850 (org-columns-new nil
"FOO" "FOO" nil nil nil
)
853 (ert-deftest test-org-colview
/columns-update
()
854 "Test `org-columns-update' specifications."
859 (org-test-with-temp-text
865 (let ((org-columns-default-format "%5A")) (org-columns))
868 (org-columns-update "A")
869 (get-char-property (point-min) 'display
))))
870 ;; Update is case-insensitive.
874 (org-test-with-temp-text
880 (let ((org-columns-default-format "%5A")) (org-columns))
883 (org-columns-update "a")
884 (get-char-property (point-min) 'display
))))
885 ;; Update stored values.
889 (org-test-with-temp-text
895 (let ((org-columns-default-format "%5A")) (org-columns))
898 (org-columns-update "A")
899 (list (get-char-property (point-min) 'org-columns-value
)
900 (get-char-property (point-min) 'org-columns-value-modified
)))))
901 ;; When multiple columns are using the same property, value is
902 ;; updated according to the specifications of the first one.
906 (org-test-with-temp-text
915 (let ((org-columns-default-format "%A{min} %A")) (org-columns))
916 (org-columns-update "A")
917 (org-entry-get nil
"A"))))
921 (org-test-with-temp-text
930 (let ((org-columns-default-format "%A %A{min}")) (org-columns))
931 (org-columns-update "A")
932 (org-entry-get nil
"A"))))
933 ;; Ensure modifications propagate in upper levels even when multiple
934 ;; summary types apply to the same property.
938 (org-test-with-temp-text
949 (goto-char (point-min))
950 (let ((org-columns-default-format "%A{min} %A{max}")) (org-columns)))
952 (org-columns-update "A")
953 (list (get-char-property 1 'org-columns-value
)
954 (get-char-property 2 'org-columns-value-modified
)))))
955 ;; Ensure additional processing is done (e.g., ellipses, special
956 ;; keywords fontification...).
960 (org-test-with-temp-text
966 (let ((org-columns-default-format "%4A")
967 (org-columns-ellipses ".."))
969 (search-forward ":A: ")
970 (insert "very long ")
971 (org-columns-update "A")
972 (get-char-property (point-min) 'display
))))
973 ;; Values obtained from inline tasks are at the same level as those
974 ;; obtained from children of the current node.
975 (when (featurep 'org-inlinetask
)
979 (org-test-with-temp-text
981 *************** Inline task
991 (let ((org-columns-default-format "%A{min}")
992 (org-columns-ellipses "..")
993 (org-inlinetask-min-level 15))
995 (get-char-property (point-min) 'org-columns-value
)))))
996 ;; Handle `org-columns-modify-value-for-display-function', even with
997 ;; multiple titles for the same property.
999 (equal '("foo" "bar")
1000 (org-test-with-temp-text "* H"
1001 (let ((org-columns-default-format "%ITEM %ITEM(Name)")
1002 (org-columns-modify-value-for-display-function
1003 (lambda (title value
)
1004 (pcase title
("ITEM" "foo") ("Name" "bar") (_ "baz")))))
1006 (list (get-char-property 1 'org-columns-value-modified
)
1007 (get-char-property 2 'org-columns-value-modified
))))))
1009 (ert-deftest test-org-colview
/columns-move-left
()
1010 "Test `org-columns-move-left' specifications."
1011 ;; Error when trying to move the left-most column.
1013 (org-test-with-temp-text "* H"
1014 (let ((org-columns-default-format "%ITEM")) (org-columns))
1015 (org-columns-move-left)))
1016 ;; Otherwise, move column to left and update display.
1019 (org-test-with-temp-text "* H\n:PROPERTIES:\n:A: 1\n:B: 2\n:END:"
1020 (let ((org-columns-default-format "%A %B")) (org-columns))
1022 (org-columns-move-left)
1023 (list (get-char-property (point) 'org-columns-value
)
1024 (get-char-property (1+ (point)) 'org-columns-value
)))))
1025 ;; Handle multiple columns with the same property.
1028 (org-test-with-temp-text
1038 (let ((org-columns-default-format "%ITEM %A{min} %A{max}"))
1041 (org-columns-move-left)
1042 (list (get-char-property (point) 'org-columns-value
)
1043 (get-char-property (1+ (point)) 'org-columns-value
)))))
1044 ;; Special case: do not update values even if move entails changing
1048 (org-test-with-temp-text
1057 (let ((org-columns-default-format "%A %A{max}"))
1060 (org-columns-move-left)
1061 ;; Since the first column matching a given property
1062 ;; determines how a value is computed, the following
1063 ;; should return "99" instead. However, this behavior is
1064 ;; in practice surprising so we just ignore the value
1065 ;; change. It can be computed later.
1066 (org-entry-get (point) "A")))))
1068 (ert-deftest test-org-colview
/columns-move-right
()
1069 "Test `org-columns-move-right' specifications."
1070 ;; Error when trying to move the right-most column.
1072 (org-test-with-temp-text "* H"
1073 (let ((org-columns-default-format "%ITEM")) (org-columns))
1074 (org-columns-move-right)))
1075 ;; Otherwise, move column to left and update display.
1078 (org-test-with-temp-text "* H\n:PROPERTIES:\n:A: 1\n:B: 2\n:END:"
1079 (let ((org-columns-default-format "%A %B")) (org-columns))
1080 (org-columns-move-right)
1081 (list (get-char-property (1- (point)) 'org-columns-value
)
1082 (get-char-property (point) 'org-columns-value
)))))
1083 ;; Handle multiple columns with the same property.
1086 (org-test-with-temp-text
1096 (let ((org-columns-default-format "%ITEM %A{min} %A{max}"))
1099 (org-columns-move-right)
1100 (list (get-char-property (1- (point)) 'org-columns-value
)
1101 (get-char-property (point) 'org-columns-value
)))))
1102 ;; Special case: do not update values even if move entails changing
1106 (org-test-with-temp-text
1115 (let ((org-columns-default-format "%A %A{max}"))
1117 (org-columns-move-right)
1118 ;; See `test-org-colview/columns-move-left' for an
1120 (org-entry-get (point) "A")))))
1122 (ert-deftest test-org-colview
/columns-next-allowed-value
()
1123 "Test `org-columns-next-allowed-value' specifications."
1124 ;; Cannot shift "ITEM" property.
1126 (org-test-with-temp-text "* H"
1127 (let ((org-columns-default-format "%ITEM")) (org-columns))
1128 (org-columns-next-allowed-value)))
1129 ;; Throw an error when allowed values are not defined.
1131 (org-test-with-temp-text "* H\n:PROPERTIES:\n:A: 1\n:END:"
1132 (let ((org-columns-default-format "%A")) (org-columns))
1133 (org-columns-next-allowed-value)))
1134 ;; Throw an error when there's only one value to select.
1136 (org-test-with-temp-text "* H\n:PROPERTIES:\n:A: 1\n:A_ALL: 1\n:END:"
1137 (let ((org-columns-default-format "%A")) (org-columns))
1138 (org-columns-next-allowed-value)))
1139 ;; By default select the next allowed value. Where there is no more
1140 ;; value, start again from first possible one.
1143 (org-test-with-temp-text
1144 "* H\n:PROPERTIES:\n:A: 1\n:A_ALL: 1 2 3\n:END:"
1145 (let ((org-columns-default-format "%A")) (org-columns))
1146 (org-columns-next-allowed-value)
1147 (org-entry-get (point) "A"))))
1150 (org-test-with-temp-text
1151 "* H\n:PROPERTIES:\n:A: 2\n:A_ALL: 1 2 3\n:END:"
1152 (let ((org-columns-default-format "%A")) (org-columns))
1153 (org-columns-next-allowed-value)
1154 (org-entry-get (point) "A"))))
1157 (org-test-with-temp-text
1158 "* H\n:PROPERTIES:\n:A: 3\n:A_ALL: 1 2 3\n:END:"
1159 (let ((org-columns-default-format "%A")) (org-columns))
1160 (org-columns-next-allowed-value)
1161 (org-entry-get (point) "A"))))
1162 ;; PREVIOUS argument moves backward.
1165 (org-test-with-temp-text
1166 "* H\n:PROPERTIES:\n:A: 2\n:A_ALL: 1 2 3\n:END:"
1167 (let ((org-columns-default-format "%A")) (org-columns))
1168 (org-columns-next-allowed-value 'previous
)
1169 (org-entry-get (point) "A"))))
1172 (org-test-with-temp-text
1173 "* H\n:PROPERTIES:\n:A: 3\n:A_ALL: 1 2 3\n:END:"
1174 (let ((org-columns-default-format "%A")) (org-columns))
1175 (org-columns-next-allowed-value 'previous
)
1176 (org-entry-get (point) "A"))))
1179 (org-test-with-temp-text
1180 "* H\n:PROPERTIES:\n:A: 1\n:A_ALL: 1 2 3\n:END:"
1181 (let ((org-columns-default-format "%A")) (org-columns))
1182 (org-columns-next-allowed-value 'previous
)
1183 (org-entry-get (point) "A"))))
1184 ;; Select Nth element with optional argument NTH.
1187 (org-test-with-temp-text
1188 "* H\n:PROPERTIES:\n:A: 2\n:A_ALL: 1 2 3\n:END:"
1189 (let ((org-columns-default-format "%A")) (org-columns))
1190 (org-columns-next-allowed-value nil
1)
1191 (org-entry-get (point) "A"))))
1192 ;; If NTH is negative, go backwards, 0 being the last one and -1 the
1196 (org-test-with-temp-text
1197 "* H\n:PROPERTIES:\n:A: 2\n:A_ALL: 1 2 3\n:END:"
1198 (let ((org-columns-default-format "%A")) (org-columns))
1199 (org-columns-next-allowed-value nil
0)
1200 (org-entry-get (point) "A"))))
1203 (org-test-with-temp-text
1204 "* H\n:PROPERTIES:\n:A: 2\n:A_ALL: 1 2 3\n:END:"
1205 (let ((org-columns-default-format "%A")) (org-columns))
1206 (org-columns-next-allowed-value nil -
1)
1207 (org-entry-get (point) "A"))))
1208 ;; Throw an error if NTH is greater than the number of allowed
1211 (org-test-with-temp-text
1212 "* H\n:PROPERTIES:\n:A: 2\n:A_ALL: 1 2 3\n:END:"
1213 (let ((org-columns-default-format "%A")) (org-columns))
1214 (org-columns-next-allowed-value nil
4)
1215 (org-entry-get (point) "A")))
1216 ;; Pathological case: when shifting the value alters the current
1217 ;; heading, make sure all columns are still at their correct
1220 (equal '("H" "" "" "" "TODO")
1221 (let ((org-todo-keywords '((sequence "TODO" "DONE"))))
1222 (org-test-with-temp-text "* H"
1223 (let ((org-columns-default-format "%ITEM %A %B %C %TODO"))
1226 (org-columns-next-allowed-value)
1227 (list (get-char-property (- (point) 4) 'org-columns-value
)
1228 (get-char-property (- (point) 3) 'org-columns-value
)
1229 (get-char-property (- (point) 2) 'org-columns-value
)
1230 (get-char-property (- (point) 1) 'org-columns-value
)
1231 (get-char-property (point) 'org-columns-value
)))))))
1233 (equal '("H" "VERYLONGTODO")
1234 (let ((org-todo-keywords '((sequence "TODO" "VERYLONGTODO"))))
1235 (org-test-with-temp-text "* TODO H"
1236 (let ((org-columns-default-format "%ITEM %TODO"))
1239 (org-columns-next-allowed-value)
1240 (list (get-char-property (- (point) 1) 'org-columns-value
)
1241 (get-char-property (point) 'org-columns-value
))))))))
1247 (ert-deftest test-org-colview
/dblock
()
1248 "Test the column view table."
1251 "#+BEGIN: columnview
1256 (org-test-with-temp-text
1257 "* H\n<point>#+BEGIN: columnview\n#+END:"
1258 (let ((org-columns-default-format "%ITEM")) (org-update-dblock))
1259 (buffer-substring-no-properties (point) (point-max)))))
1262 "#+BEGIN: columnview
1267 (org-test-with-temp-text
1268 "* H\n:PROPERTIES:\n:A: 1\n:END:\n<point>#+BEGIN: columnview\n#+END:"
1269 (let ((org-columns-default-format "%ITEM %A")) (org-update-dblock))
1270 (buffer-substring-no-properties (point) (point-max)))))
1271 ;; Properties are case insensitive.
1274 "#+BEGIN: columnview
1279 (org-test-with-temp-text
1280 "* H\n:PROPERTIES:\n:A: 1\n:END:\n<point>#+BEGIN: columnview\n#+END:"
1281 (let ((org-columns-default-format "%a")) (org-update-dblock))
1282 (buffer-substring-no-properties (point) (point-max)))))
1283 ;; Test titles given to columns.
1286 "#+BEGIN: columnview
1291 (org-test-with-temp-text
1292 "* H\n:PROPERTIES:\n:A: 1\n:END:\n<point>#+BEGIN: columnview\n#+END:"
1293 (let ((org-columns-default-format "%ITEM(Name) %A(Prop)"))
1294 (org-update-dblock))
1295 (buffer-substring-no-properties (point) (point-max)))))
1296 ;; Test `:id' parameter
1299 "#+BEGIN: columnview :id local
1306 (org-test-with-temp-text
1307 "* H1\n<point>#+BEGIN: columnview :id local\n#+END:\n** H1.1\n* H2"
1308 (let ((org-columns-default-format "%ITEM")) (org-update-dblock))
1309 (buffer-substring-no-properties (point) (outline-next-heading)))))
1312 "#+BEGIN: columnview :id global
1320 (org-test-with-temp-text
1321 "\n* H1\n<point>#+BEGIN: columnview :id global\n#+END:\n** H1.1\n* H2"
1322 (let ((org-columns-default-format "%ITEM")) (org-update-dblock))
1323 (buffer-substring-no-properties (point) (outline-next-heading)))))
1324 ;; Test `:hlines' parameter.
1327 "#+BEGIN: columnview :hlines t :id global
1336 (org-test-with-temp-text
1339 <point>#+BEGIN: columnview :hlines t :id global
1343 (let ((org-columns-default-format "%ITEM")) (org-update-dblock))
1344 (buffer-substring-no-properties (point) (outline-next-heading)))))
1347 "#+BEGIN: columnview :hlines 1 :id global
1355 (org-test-with-temp-text
1358 <point>#+BEGIN: columnview :hlines 1 :id global
1362 (let ((org-columns-default-format "%ITEM")) (org-update-dblock))
1363 (buffer-substring-no-properties (point) (outline-next-heading)))))
1366 "#+BEGIN: columnview :hlines 1 :id \"id\"
1373 (org-test-with-temp-text
1376 <point>#+BEGIN: columnview :hlines 1 :id \"id\"
1383 (let ((org-columns-default-format "%ITEM")) (org-update-dblock))
1384 (buffer-substring-no-properties (point) (outline-next-heading)))))
1387 "#+BEGIN: columnview :hlines 1 :id id
1394 (org-test-with-temp-text
1397 <point>#+BEGIN: columnview :hlines 1 :id id
1404 (let ((org-columns-default-format "%ITEM")) (org-update-dblock))
1405 (buffer-substring-no-properties (point) (outline-next-heading)))))
1406 ;; Test `:indent' parameter.
1409 "#+BEGIN: columnview :indent t
1416 (org-test-with-temp-text
1417 "* H1\n<point>#+BEGIN: columnview :indent t\n#+END:\n** H1.1"
1418 (let ((org-columns-default-format "%ITEM")) (org-update-dblock))
1419 (buffer-substring-no-properties (point) (outline-next-heading)))))
1422 "#+BEGIN: columnview :indent t
1429 (org-test-with-temp-text
1430 "* H1\n<point>#+BEGIN: columnview :indent t\n#+END:\n** H1.1"
1431 (let ((org-columns-default-format "%A(Prop) %ITEM(Name)"))
1432 (org-update-dblock))
1433 (buffer-substring-no-properties (point) (outline-next-heading)))))
1434 ;; Test `:vlines' parameter.
1437 "#+BEGIN: columnview :vlines t
1443 (org-test-with-temp-text
1444 "* H\n:PROPERTIES:\n:A: 1\n:END:\n<point>#+BEGIN: columnview :vlines t\n#+END:"
1445 (let ((org-columns-default-format "%ITEM %A")) (org-update-dblock))
1446 (buffer-substring-no-properties (point) (point-max)))))
1447 ;; Test `:skip-empty-rows' parameter.
1450 "#+BEGIN: columnview :skip-empty-rows t
1456 (org-test-with-temp-text
1459 <point>#+BEGIN: columnview :skip-empty-rows t
1465 (let ((org-columns-default-format "%ITEM %A")) (org-update-dblock))
1466 (buffer-substring-no-properties (point) (outline-next-heading)))))
1467 ;; Test `:exclude-tags' parameter.
1470 "#+BEGIN: columnview :exclude-tags (\"excludeme\")
1476 (org-test-with-temp-text
1479 <point>#+BEGIN: columnview :exclude-tags (\"excludeme\")
1485 (let ((org-columns-default-format "%ITEM %A")) (org-update-dblock))
1486 (buffer-substring-no-properties (point) (outline-next-heading)))))
1487 ;; Test `:format' parameter.
1490 "#+BEGIN: columnview :format \"%ITEM(Name)\"
1495 (org-test-with-temp-text
1496 "* H\n<point>#+BEGIN: columnview :format \"%ITEM(Name)\"\n#+END:"
1497 (let ((org-columns-default-format "%ITEM")) (org-update-dblock))
1498 (buffer-substring-no-properties (point) (point-max)))))
1499 ;; When inserting ITEM values, make sure to clean sensitive
1500 ;; contents, like unique targets or forbidden inline src-blocks.
1503 "#+BEGIN: columnview
1508 (org-test-with-temp-text
1509 "* H <<target>> 1\n<point>#+BEGIN: columnview\n#+END:"
1510 (let ((org-columns-default-format "%ITEM")) (org-update-dblock))
1511 (buffer-substring-no-properties (point) (point-max)))))
1514 "#+BEGIN: columnview
1519 (org-test-with-temp-text
1520 "* H src_emacs-lisp{(+ 1 1)} 1\n<point>#+BEGIN: columnview\n#+END:"
1521 (let ((org-columns-default-format "%ITEM")) (org-update-dblock))
1522 (buffer-substring-no-properties (point) (point-max))))))
1524 (provide 'test-org-colview
)
1525 ;;; test-org-colview.el ends here