lisp/org-table.el: fix table alignment
[org-mode/org-tableheadings.git] / testing / lisp / test-org-colview.el
blobed75090df9d94a5a00766fc8bd0c5be1085f95e9
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/>.
20 ;;; Code:
22 ;;; Column view
24 (require 'cl-lib)
26 (ert-deftest test-org-colview/get-format ()
27 "Test `org-columns-get-format' specifications."
28 ;; Without any clue, use `org-columns-default-format'.
29 (should
30 (equal "%A"
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.
35 (should
36 (equal "%B"
37 (org-test-with-temp-text "#+COLUMNS: %B\n* H"
38 (let ((org-columns-default-format "%A"))
39 (org-columns-get-format)))))
40 (should
41 (equal "%B"
42 (org-test-with-temp-text "#+columns: %B\n* H"
43 (let ((org-columns-default-format "%A"))
44 (org-columns-get-format)))))
45 (should
46 (equal "%B"
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
51 ;; the previous ways.
52 (should
53 (equal
54 "%C"
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.
60 (should
61 (equal
62 "%D"
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.
71 (should
72 (equal
73 '("H1" "H2" "H3")
74 (org-test-with-temp-text "Top\n* H1\n** H2\n* H3"
75 (let ((org-columns-default-format "%ITEM")) (org-columns))
76 (org-map-entries
77 (lambda () (get-char-property (point) 'org-columns-value))))))
78 ;; When :COLUMNS: is set up in the hierarchy, view tree starting
79 ;; there.
80 (should
81 (equal
82 '(nil "H2" "H3" nil)
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))
86 (org-map-entries
87 (lambda () (get-char-property (point) 'org-columns-value))))))
88 ;; Otherwise, view tree starting at the current headline.
89 (should
90 (equal
91 '(nil "H2" "H3" nil)
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))
94 (org-map-entries
95 (lambda () (get-char-property (point) 'org-columns-value))))))
96 ;; With a non-nil prefix argument, always view all document.
97 (should
98 (equal
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))
103 (org-map-entries
104 (lambda () (get-char-property (point) 'org-columns-value))))))
105 (should
106 (equal
107 '("1" "1")
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))
111 (org-map-entries
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.
117 (should
118 (= 9
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.
123 (should
124 (= 2
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
130 ;; instead.
131 (should
132 (= 4
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.
137 (should
138 (= 6
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.
143 (should
144 (equal
145 '("* 123" . 5)
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'.
152 (should
153 (equal "123.. |"
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 ".."))
157 (org-columns))
158 (org-trim (get-char-property (point) 'display)))))
159 (should
160 (equal "1234… |"
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 "…"))
164 (org-columns))
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.
170 (should
171 (equal
173 (org-test-with-temp-text
174 "* H
175 ** S1
176 :PROPERTIES:
177 :A: 1
178 :END:
179 ** S1
180 :PROPERTIES:
181 :A: 2
182 :END:"
183 (let ((org-columns-default-format "%A{+}")) (org-columns))
184 (get-char-property (point) 'org-columns-value-modified))))
185 (should
186 (equal
187 "3.0"
188 (org-test-with-temp-text
189 "* H
190 ** S1
191 :PROPERTIES:
192 :A: 1
193 :END:
194 ** S1
195 :PROPERTIES:
196 :A: 2
197 :END:"
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}.
201 (should
202 (equal
203 "3.60"
204 (org-test-with-temp-text
205 "* H
206 ** S1
207 :PROPERTIES:
208 :A: 1.50
209 :END:
210 ** S1
211 :PROPERTIES:
212 :A: 2.10
213 :END:"
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.
217 (should
218 (equal
219 "1.0"
220 (org-test-with-temp-text
221 "* H
222 :PROPERTIES:
223 :A: 1
224 :END:"
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.
228 (should
229 (equal
230 "4:10"
231 (org-test-with-temp-text
232 "* H
233 ** S1
234 :PROPERTIES:
235 :A: 1:30
236 :END:
237 ** S1
238 :PROPERTIES:
239 :A: 2:40
240 :END:"
241 (let ((org-columns-default-format "%A{:}")) (org-columns))
242 (get-char-property (point) 'org-columns-value-modified))))
243 (should
244 (equal
245 "1:32"
246 (org-test-with-temp-text
247 "* H
248 ** S1
249 :PROPERTIES:
250 :A: 1:30
251 :END:
252 ** S1
253 :PROPERTIES:
254 :A: 2
255 :END:"
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.
259 (should
260 (equal
261 "[ ]"
262 (org-test-with-temp-text
263 "* H
264 ** S1
265 :PROPERTIES:
266 :A: [ ]
267 :END:
268 ** S1
269 :PROPERTIES:
270 :A: [ ]
271 :END:"
272 (let ((org-columns-default-format "%A{X}")) (org-columns))
273 (get-char-property (point) 'org-columns-value-modified))))
274 (should
275 (equal
276 "[-]"
277 (org-test-with-temp-text
278 "* H
279 ** S1
280 :PROPERTIES:
281 :A: [ ]
282 :END:
283 ** S1
284 :PROPERTIES:
285 :A: [X]
286 :END:"
287 (let ((org-columns-default-format "%A{X}")) (org-columns))
288 (get-char-property (point) 'org-columns-value-modified))))
289 (should
290 (equal
291 "[X]"
292 (org-test-with-temp-text
293 "* H
294 ** S1
295 :PROPERTIES:
296 :A: [X]
297 :END:
298 ** S1
299 :PROPERTIES:
300 :A: [X]
301 :END:"
302 (let ((org-columns-default-format "%A{X}")) (org-columns))
303 (get-char-property (point) 'org-columns-value-modified))))
304 (should
305 (equal
306 "[1/2]"
307 (org-test-with-temp-text
308 "* H
309 ** S1
310 :PROPERTIES:
311 :A: [ ]
312 :END:
313 ** S1
314 :PROPERTIES:
315 :A: [X]
316 :END:"
317 (let ((org-columns-default-format "%A{X/}")) (org-columns))
318 (get-char-property (point) 'org-columns-value-modified))))
319 (should
320 (equal
321 "[50%]"
322 (org-test-with-temp-text
323 "* H
324 ** S1
325 :PROPERTIES:
326 :A: [ ]
327 :END:
328 ** S1
329 :PROPERTIES:
330 :A: [X]
331 :END:"
332 (let ((org-columns-default-format "%A{X%}")) (org-columns))
333 (get-char-property (point) 'org-columns-value-modified))))
334 ;; {X/} handles recursive summaries.
335 (should
336 (equal
337 "[1/2]"
338 (org-test-with-temp-text
339 "* H
340 ** S1
341 :PROPERTIES:
342 :A: [ ]
343 :END:
344 ** S2
345 *** S21
346 :PROPERTIES:
347 :A: [X]
348 :END:
349 *** S22
350 :PROPERTIES:
351 :A: [X]
352 :END:"
353 (let ((org-columns-default-format "%A{X/}")) (org-columns))
354 (get-char-property (point) 'org-columns-value-modified))))
355 (should
356 (equal
357 "[1/2]"
358 (org-test-with-temp-text
359 "* H
360 ** S1
361 :PROPERTIES:
362 :A: [X]
363 :END:
364 ** S2
365 *** S21
366 :PROPERTIES:
367 :A: [ ]
368 :END:
369 *** S22
370 :PROPERTIES:
371 :A: [ ]
372 :END:"
373 (let ((org-columns-default-format "%A{X/}")) (org-columns))
374 (get-char-property (point) 'org-columns-value-modified))))
375 ;; {X%} handles recursive summaries.
376 (should
377 (equal
378 "[50%]"
379 (org-test-with-temp-text
380 "* H
381 ** S1
382 :PROPERTIES:
383 :A: [ ]
384 :END:
385 ** S2
386 *** S21
387 :PROPERTIES:
388 :A: [X]
389 :END:
390 *** S22
391 :PROPERTIES:
392 :A: [X]
393 :END:"
394 (let ((org-columns-default-format "%A{X%}")) (org-columns))
395 (get-char-property (point) 'org-columns-value-modified))))
396 (should
397 (equal
398 "[50%]"
399 (org-test-with-temp-text
400 "* H
401 ** S1
402 :PROPERTIES:
403 :A: [X]
404 :END:
405 ** S2
406 *** S21
407 :PROPERTIES:
408 :A: [ ]
409 :END:
410 *** S22
411 :PROPERTIES:
412 :A: [ ]
413 :END:"
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.
418 (should
419 (equal
420 "42"
421 (org-test-with-temp-text
422 "* H
423 ** S1
424 :PROPERTIES:
425 :A: 99
426 :END:
427 ** S1
428 :PROPERTIES:
429 :A: 42
430 :END:"
431 (let ((org-columns-default-format "%A{min}")) (org-columns))
432 (get-char-property (point) 'org-columns-value-modified))))
433 (should
434 (equal
435 "99"
436 (org-test-with-temp-text
437 "* H
438 ** S1
439 :PROPERTIES:
440 :A: 99
441 :END:
442 ** S1
443 :PROPERTIES:
444 :A: 42
445 :END:"
446 (let ((org-columns-default-format "%A{max}")) (org-columns))
447 (get-char-property (point) 'org-columns-value-modified))))
448 (should
449 (equal
450 "51.0"
451 (org-test-with-temp-text
452 "* H
453 ** S1
454 :PROPERTIES:
455 :A: 60
456 :END:
457 ** S1
458 :PROPERTIES:
459 :A: 42
460 :END:"
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.
464 (should
465 (equal
466 "1:20"
467 (org-test-with-temp-text
468 "* H
469 ** S1
470 :PROPERTIES:
471 :A: 4:40
472 :END:
473 ** S1
474 :PROPERTIES:
475 :A: 1:20
476 :END:"
477 (let ((org-columns-default-format "%A{:min}")) (org-columns))
478 (get-char-property (point) 'org-columns-value-modified))))
479 (should
480 (equal
481 "4:40"
482 (org-test-with-temp-text
483 "* H
484 ** S1
485 :PROPERTIES:
486 :A: 4:40
487 :END:
488 ** S1
489 :PROPERTIES:
490 :A: 1:20
491 :END:"
492 (let ((org-columns-default-format "%A{:max}")) (org-columns))
493 (get-char-property (point) 'org-columns-value-modified))))
494 (should
495 (equal
496 "3:00"
497 (org-test-with-temp-text
498 "* H
499 ** S1
500 :PROPERTIES:
501 :A: 4:40
502 :END:
503 ** S1
504 :PROPERTIES:
505 :A: 1:20
506 :END:"
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.
510 (should
511 (equal
512 "0min"
513 (org-test-at-time "<2014-03-04 Tue>"
514 (org-test-with-temp-text
515 "* H
516 ** S1
517 :PROPERTIES:
518 :A: <2012-03-29 Thu>
519 :END:
520 ** S1
521 :PROPERTIES:
522 :A: <2014-03-04 Tue>
523 :END:"
524 (let ((org-columns-default-format "%A{@min}")) (org-columns))
525 (get-char-property (point) 'org-columns-value-modified)))))
526 (should
527 (equal
528 "2d"
529 (org-test-at-time "<2014-03-04 Tue>"
530 (org-test-with-temp-text
531 "* H
532 ** S1
533 :PROPERTIES:
534 :A: <2014-03-03 Mon>
535 :END:
536 ** S1
537 :PROPERTIES:
538 :A: <2014-03-02 Sun>
539 :END:"
540 (let ((org-columns-default-format "%A{@max}")) (org-columns))
541 (get-char-property (point) 'org-columns-value-modified)))))
542 (should
543 (equal
544 "1d 12h"
545 (org-test-at-time "<2014-03-04 Tue>"
546 (org-test-with-temp-text
547 "* H
548 ** S1
549 :PROPERTIES:
550 :A: <2014-03-03 Mon>
551 :END:
552 ** S1
553 :PROPERTIES:
554 :A: <2014-03-02 Sun>
555 :END:"
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.
561 (should
562 (equal
563 "3d 4:20"
564 (org-test-with-temp-text
565 "* H
566 ** S1
567 :PROPERTIES:
568 :A: 3d 3h
569 :END:
570 ** S1
571 :PROPERTIES:
572 :A: 1:20
573 :END:"
574 (let ((org-columns-default-format "%A{:}")
575 (org-duration-units '(("d" . 1440) ("h" . 60)))
576 (org-duration-format '(("d" . nil) (special . h:mm))))
577 (org-columns))
578 (get-char-property (point) 'org-columns-value-modified))))
579 (should
580 (equal
581 "6:00:10"
582 (org-test-with-temp-text
583 "* H
584 ** S1
585 :PROPERTIES:
586 :A: 4:40:10
587 :END:
588 ** S1
589 :PROPERTIES:
590 :A: 1:20
591 :END:"
592 (let ((org-columns-default-format "%A{:}")) (org-columns))
593 (get-char-property (point) 'org-columns-value-modified))))
594 (should
595 (equal
596 "3d 4:20"
597 (org-test-with-temp-text
598 "* H
599 ** S1
600 :PROPERTIES:
601 :A: 3d 3h
602 :END:
603 ** S1
604 :PROPERTIES:
605 :A: 0d 1:20
606 :END:"
607 (let ((org-columns-default-format "%A{:}")
608 (org-duration-units '(("d" . 1440) ("h" . 60)))
609 (org-duration-format '(("d" . nil) (special . h:mm))))
610 (org-columns))
611 (get-char-property (point) 'org-columns-value-modified))))
612 ;; @min, @max and @mean also accept regular duration.
613 (should
614 (equal
615 "1d 10h"
616 (org-test-with-temp-text
617 "* H
618 ** S1
619 :PROPERTIES:
620 :A: 1d 10h 0min
621 :END:
622 ** S1
623 :PROPERTIES:
624 :A: 5d 3h
625 :END:"
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
629 ;; deviation.
630 (should
631 (equal
632 "3-17"
633 (org-test-with-temp-text
634 "* H
635 ** S1
636 :PROPERTIES:
637 :A: 0-10
638 :END:
639 ** S1
640 :PROPERTIES:
641 :A: 0-10
642 :END:"
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.
647 (should
648 (equal
649 "4-4"
650 (org-test-with-temp-text
651 "* H
652 ** S1
653 :PROPERTIES:
654 :A: 4
655 :END:
657 (let ((org-columns-default-format "%A{est+}")) (org-columns))
658 (get-char-property (point) 'org-columns-value-modified))))
659 ;; Allow custom summary types.
660 (should
661 (equal
662 "1|2"
663 (org-test-with-temp-text
664 "* H
665 ** S1
666 :PROPERTIES:
667 :A: 1
668 :END:
669 ** S1
670 :PROPERTIES:
671 :A: 2
672 :END:"
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.
678 (should
679 (equal
681 (org-test-with-temp-text
682 "* H
683 ** S1
684 :PROPERTIES:
685 :A: 1
686 :END:
687 ** S1
688 :PROPERTIES:
689 :A: 2
690 :A-OK: 1
691 :END:"
692 (let ((org-columns-summary-types
693 '(("custom" org-columns--summary-sum
694 (lambda (p)
695 (if (equal "1" (org-entry-get nil (format "%s-OK" p)))
696 (org-entry-get nil p)
697 "")))))
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
701 (should
702 (equal
703 '("2" "1")
704 (org-test-with-temp-text
705 "* H
706 ** S1
707 :PROPERTIES:
708 :A: 1
709 :B: 1
710 :B-OK: 1
711 :END:
712 ** S1
713 :PROPERTIES:
714 :A: 2
715 :B: 2
716 :A-OK: 1
717 :END:"
718 (let ((org-columns-summary-types
719 '(("custom" org-columns--summary-sum
720 (lambda (p)
721 (if (equal "1" (org-entry-get nil (format "%s-OK" p)))
722 (org-entry-get nil p)
723 "")))))
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.
728 (should
729 (equal
730 '("42" "99")
731 (org-test-with-temp-text
732 "* H
733 ** S1
734 :PROPERTIES:
735 :A: 99
736 :END:
737 ** S1
738 :PROPERTIES:
739 :A: 42
740 :END:"
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.
747 (should
748 (equal
749 '("1000" "42")
750 (org-test-with-temp-text
751 "* H
752 :PROPERTIES:
753 :A: 1000
754 :END:
755 ** S1
756 :PROPERTIES:
757 :A: 99
758 :END:
759 ** S1
760 :PROPERTIES:
761 :A: 42
762 :END:"
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)))))
766 (should
767 (equal
768 '("42" "42")
769 (org-test-with-temp-text
770 "* H
771 :PROPERTIES:
772 :A: 1000
773 :END:
774 ** S1
775 :PROPERTIES:
776 :A: 99
777 :END:
778 ** S1
779 :PROPERTIES:
780 :A: 42
781 :END:"
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.
789 (should
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)))))
796 (should
797 (equal '("ITEM" "FOO" "BAR")
798 (org-test-with-temp-text "* H"
799 (let ((org-columns-default-format "%ITEM %BAR")) (org-columns))
800 (forward-char)
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.
806 (should
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)))))
813 (should
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))
817 (forward-char)
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.
822 (should
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))
826 (forward-char)
827 (org-columns-new nil "Foo" "Foo" nil nil nil)
828 (goto-char (point-min))
829 (buffer-substring-no-properties (point) (line-end-position)))))
830 (should
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))
834 (forward-char)
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.
839 (should
840 (equal "%FOO %ITEM"
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.
846 (should
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)
851 (buffer-string)))))
853 (ert-deftest test-org-colview/columns-update ()
854 "Test `org-columns-update' specifications."
855 ;; Update display.
856 (should
857 (equal
858 "12 |"
859 (org-test-with-temp-text
860 "* H
861 :PROPERTIES:
862 :A: 1
863 :END:
865 (let ((org-columns-default-format "%5A")) (org-columns))
866 (search-forward "1")
867 (insert "2")
868 (org-columns-update "A")
869 (get-char-property (point-min) 'display))))
870 ;; Update is case-insensitive.
871 (should
872 (equal
873 "12 |"
874 (org-test-with-temp-text
875 "* H
876 :PROPERTIES:
877 :A: 1
878 :END:
880 (let ((org-columns-default-format "%5A")) (org-columns))
881 (search-forward "1")
882 (insert "2")
883 (org-columns-update "a")
884 (get-char-property (point-min) 'display))))
885 ;; Update stored values.
886 (should
887 (equal
888 '("12" "12")
889 (org-test-with-temp-text
890 "* H
891 :PROPERTIES:
892 :A: 1
893 :END:
895 (let ((org-columns-default-format "%5A")) (org-columns))
896 (search-forward "1")
897 (insert "2")
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.
903 (should
904 (equal
906 (org-test-with-temp-text
907 "* H
908 :PROPERTIES:
909 :A: 1
910 :END:
911 ** S
912 :PROPERTIES:
913 :A: 2
914 :END:"
915 (let ((org-columns-default-format "%A{min} %A")) (org-columns))
916 (org-columns-update "A")
917 (org-entry-get nil "A"))))
918 (should
919 (equal
921 (org-test-with-temp-text
922 "* H
923 :PROPERTIES:
924 :A: 1
925 :END:
926 ** S
927 :PROPERTIES:
928 :A: 2
929 :END:"
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.
935 (should
936 (equal
937 '("1" "22")
938 (org-test-with-temp-text
939 "* H
940 ** S1
941 :PROPERTIES:
942 :A: 1
943 :END:
944 ** S2
945 :PROPERTIES:
946 :A: <point>2
947 :END:"
948 (save-excursion
949 (goto-char (point-min))
950 (let ((org-columns-default-format "%A{min} %A{max}")) (org-columns)))
951 (insert "2")
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...).
957 (should
958 (equal
959 "ve.. |"
960 (org-test-with-temp-text
961 "* H
962 :PROPERTIES:
963 :A: text
964 :END:
966 (let ((org-columns-default-format "%4A")
967 (org-columns-ellipses ".."))
968 (org-columns))
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)
976 (should
977 (equal
979 (org-test-with-temp-text
980 "* H
981 *************** Inline task
982 :PROPERTIES:
983 :A: 2
984 :END:
985 *************** END
986 ** Children
987 :PROPERTIES:
988 :A: 3
989 :END:
991 (let ((org-columns-default-format "%A{min}")
992 (org-columns-ellipses "..")
993 (org-inlinetask-min-level 15))
994 (org-columns))
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.
998 (should
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")))))
1005 (org-columns))
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.
1012 (should-error
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.
1017 (should
1018 (equal '("2" "1")
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))
1021 (forward-char)
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.
1026 (should
1027 (equal '("2" "1")
1028 (org-test-with-temp-text
1029 "* H
1030 ** S1
1031 :PROPERTIES:
1032 :A: 1
1033 :END:
1034 ** S1
1035 :PROPERTIES:
1036 :A: 2
1037 :END:"
1038 (let ((org-columns-default-format "%ITEM %A{min} %A{max}"))
1039 (org-columns))
1040 (forward-char 2)
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
1045 ;; them.
1046 (should
1047 (equal "1"
1048 (org-test-with-temp-text
1049 "* H
1050 :PROPERTIES:
1051 :A: 1
1052 :END:
1053 ** S1
1054 :PROPERTIES:
1055 :A: 99
1056 :END:"
1057 (let ((org-columns-default-format "%A %A{max}"))
1058 (org-columns))
1059 (forward-char)
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.
1071 (should-error
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.
1076 (should
1077 (equal '("2" "1")
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.
1084 (should
1085 (equal '("2" "1")
1086 (org-test-with-temp-text
1087 "* H
1088 ** S1
1089 :PROPERTIES:
1090 :A: 1
1091 :END:
1092 ** S1
1093 :PROPERTIES:
1094 :A: 2
1095 :END:"
1096 (let ((org-columns-default-format "%ITEM %A{min} %A{max}"))
1097 (org-columns))
1098 (forward-char)
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
1103 ;; them.
1104 (should
1105 (equal "1"
1106 (org-test-with-temp-text
1107 "* H
1108 :PROPERTIES:
1109 :A: 1
1110 :END:
1111 ** S1
1112 :PROPERTIES:
1113 :A: 99
1114 :END:"
1115 (let ((org-columns-default-format "%A %A{max}"))
1116 (org-columns))
1117 (org-columns-move-right)
1118 ;; See `test-org-colview/columns-move-left' for an
1119 ;; explanation.
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.
1125 (should-error
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.
1130 (should-error
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.
1135 (should-error
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.
1141 (should
1142 (equal "2"
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"))))
1148 (should
1149 (equal "3"
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"))))
1155 (should
1156 (equal "1"
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.
1163 (should
1164 (equal "1"
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"))))
1170 (should
1171 (equal "2"
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"))))
1177 (should
1178 (equal "3"
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.
1185 (should
1186 (equal "1"
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
1193 ;; penultimate.
1194 (should
1195 (equal "3"
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"))))
1201 (should
1202 (equal "2"
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
1209 ;; values.
1210 (should-error
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
1218 ;; location.
1219 (should
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"))
1224 (org-columns)
1225 (forward-char 4)
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)))))))
1232 (should
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"))
1237 (org-columns)
1238 (forward-char)
1239 (org-columns-next-allowed-value)
1240 (list (get-char-property (- (point) 1) 'org-columns-value)
1241 (get-char-property (point) 'org-columns-value))))))))
1245 ;;; Dynamic block
1247 (ert-deftest test-org-colview/dblock ()
1248 "Test the column view table."
1249 (should
1250 (equal
1251 "#+BEGIN: columnview
1252 | ITEM |
1253 |------|
1254 | H |
1255 #+END:"
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)))))
1260 (should
1261 (equal
1262 "#+BEGIN: columnview
1263 | ITEM | A |
1264 |------+---|
1265 | H | 1 |
1266 #+END:"
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.
1272 (should
1273 (equal
1274 "#+BEGIN: columnview
1275 | a |
1276 |---|
1277 | 1 |
1278 #+END:"
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.
1284 (should
1285 (equal
1286 "#+BEGIN: columnview
1287 | Name | Prop |
1288 |------+------|
1289 | H | 1 |
1290 #+END:"
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
1297 (should
1298 (equal
1299 "#+BEGIN: columnview :id local
1300 | ITEM |
1301 |------|
1302 | H1 |
1303 | H1.1 |
1304 #+END:
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)))))
1310 (should
1311 (equal
1312 "#+BEGIN: columnview :id global
1313 | ITEM |
1314 |------|
1315 | H1 |
1316 | H1.1 |
1317 | H2 |
1318 #+END:
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.
1325 (should
1326 (equal
1327 "#+BEGIN: columnview :hlines t :id global
1328 | ITEM |
1329 |------|
1330 | H |
1331 |------|
1332 | H2 |
1333 |------|
1334 | H2.1 |
1335 #+END:\n"
1336 (org-test-with-temp-text
1339 <point>#+BEGIN: columnview :hlines t :id global
1340 #+END:
1341 * H2
1342 ** H2.1"
1343 (let ((org-columns-default-format "%ITEM")) (org-update-dblock))
1344 (buffer-substring-no-properties (point) (outline-next-heading)))))
1345 (should
1346 (equal
1347 "#+BEGIN: columnview :hlines 1 :id global
1348 | ITEM |
1349 |------|
1350 | H |
1351 |------|
1352 | H2 |
1353 | H2.1 |
1354 #+END:\n"
1355 (org-test-with-temp-text
1358 <point>#+BEGIN: columnview :hlines 1 :id global
1359 #+END:
1360 * H2
1361 ** H2.1"
1362 (let ((org-columns-default-format "%ITEM")) (org-update-dblock))
1363 (buffer-substring-no-properties (point) (outline-next-heading)))))
1364 (should
1365 (equal
1366 "#+BEGIN: columnview :hlines 1 :id \"id\"
1367 | ITEM |
1368 |------|
1369 | H2 |
1370 | H2.1 |
1371 #+END:
1373 (org-test-with-temp-text
1376 <point>#+BEGIN: columnview :hlines 1 :id \"id\"
1377 #+END:
1378 * H2
1379 :PROPERTIES:
1380 :ID: id
1381 :END:
1382 ** H2.1"
1383 (let ((org-columns-default-format "%ITEM")) (org-update-dblock))
1384 (buffer-substring-no-properties (point) (outline-next-heading)))))
1385 (should
1386 (equal
1387 "#+BEGIN: columnview :hlines 1 :id id
1388 | ITEM |
1389 |------|
1390 | H2 |
1391 | H2.1 |
1392 #+END:
1394 (org-test-with-temp-text
1397 <point>#+BEGIN: columnview :hlines 1 :id id
1398 #+END:
1399 * H2
1400 :PROPERTIES:
1401 :ID: id
1402 :END:
1403 ** H2.1"
1404 (let ((org-columns-default-format "%ITEM")) (org-update-dblock))
1405 (buffer-substring-no-properties (point) (outline-next-heading)))))
1406 ;; Test `:indent' parameter.
1407 (should
1408 (equal
1409 "#+BEGIN: columnview :indent t
1410 | ITEM |
1411 |----------|
1412 | H1 |
1413 | \\_ H1.1 |
1414 #+END:
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)))))
1420 (should
1421 (equal
1422 "#+BEGIN: columnview :indent t
1423 | Prop | Name |
1424 |------+----------|
1425 | | H1 |
1426 | | \\_ H1.1 |
1427 #+END:
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.
1435 (should
1436 (equal
1437 "#+BEGIN: columnview :vlines t
1438 | | ITEM | A |
1439 |---+------+----|
1440 | | H | 1 |
1441 | / | <> | <> |
1442 #+END:"
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.
1448 (should
1449 (equal
1450 "#+BEGIN: columnview :skip-empty-rows t
1451 | ITEM | A |
1452 |------+---|
1453 | H1.1 | 1 |
1454 #+END:
1456 (org-test-with-temp-text
1458 * H1
1459 <point>#+BEGIN: columnview :skip-empty-rows t
1460 #+END:
1461 ** H1.1
1462 :PROPERTIES:
1463 :A: 1
1464 :END:"
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.
1468 (should
1469 (equal
1470 "#+BEGIN: columnview :exclude-tags (\"excludeme\")
1471 | ITEM | A |
1472 |------+---|
1473 | H1 | |
1474 #+END:
1476 (org-test-with-temp-text
1478 * H1
1479 <point>#+BEGIN: columnview :exclude-tags (\"excludeme\")
1480 #+END:
1481 ** H1.1 :excludeme:
1482 :PROPERTIES:
1483 :A: 1
1484 :END:"
1485 (let ((org-columns-default-format "%ITEM %A")) (org-update-dblock))
1486 (buffer-substring-no-properties (point) (outline-next-heading)))))
1487 ;; Test `:format' parameter.
1488 (should
1489 (equal
1490 "#+BEGIN: columnview :format \"%ITEM(Name)\"
1491 | Name |
1492 |------|
1493 | H |
1494 #+END:"
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.
1501 (should
1502 (equal
1503 "#+BEGIN: columnview
1504 | ITEM |
1505 |------|
1506 | H 1 |
1507 #+END:"
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)))))
1512 (should
1513 (equal
1514 "#+BEGIN: columnview
1515 | ITEM |
1516 |------|
1517 | H 1 |
1518 #+END:"
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