Fix opening custom ID links with percent escaped syntax
[org-mode/org-tableheadings.git] / testing / lisp / test-org-colview.el
blobfd00a2dde13c309c96c6e5c5ed63626821dfb3f6
1 ;;; test-org-colview.el --- Tests for org-colview.el -*- lexical-binding: t; -*-
3 ;; Copyright (C) 2016 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]" . 7)
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 hours.
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 "3:30"
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 (cl-letf (((symbol-function 'current-time)
514 (lambda ()
515 (apply #'encode-time
516 (org-parse-time-string "<2014-03-04 Tue>")))))
517 (org-test-with-temp-text
518 "* H
519 ** S1
520 :PROPERTIES:
521 :A: <2012-03-29 Thu>
522 :END:
523 ** S1
524 :PROPERTIES:
525 :A: <2014-03-04 Tue>
526 :END:"
527 (let ((org-columns-default-format "%A{@min}")) (org-columns))
528 (get-char-property (point) 'org-columns-value-modified)))))
529 (should
530 (equal
531 "2d"
532 (cl-letf (((symbol-function 'current-time)
533 (lambda ()
534 (apply #'encode-time
535 (org-parse-time-string "<2014-03-04 Tue>")))))
536 (org-test-with-temp-text
537 "* H
538 ** S1
539 :PROPERTIES:
540 :A: <2014-03-03 Mon>
541 :END:
542 ** S1
543 :PROPERTIES:
544 :A: <2014-03-02 Sun>
545 :END:"
546 (let ((org-columns-default-format "%A{@max}")) (org-columns))
547 (get-char-property (point) 'org-columns-value-modified)))))
548 (should
549 (equal
550 "1d 12h"
551 (cl-letf (((symbol-function 'current-time)
552 (lambda ()
553 (apply #'encode-time
554 (org-parse-time-string "<2014-03-04 Tue>")))))
555 (org-test-with-temp-text
556 "* H
557 ** S1
558 :PROPERTIES:
559 :A: <2014-03-03 Mon>
560 :END:
561 ** S1
562 :PROPERTIES:
563 :A: <2014-03-02 Sun>
564 :END:"
565 (let ((org-columns-default-format "%A{@mean}")) (org-columns))
566 (get-char-property (point) 'org-columns-value-modified)))))
567 ;; If a time value is expressed as a duration, return a duration.
568 ;; If any of them follows H:MM:SS pattern, use it too. Also handle
569 ;; combinations of duration and H:MM:SS patterns.
570 (should
571 (equal
572 "3d 4:20"
573 (org-test-with-temp-text
574 "* H
575 ** S1
576 :PROPERTIES:
577 :A: 3d 3h
578 :END:
579 ** S1
580 :PROPERTIES:
581 :A: 1:20
582 :END:"
583 (let ((org-columns-default-format "%A{:}")
584 (org-duration-units '(("d" . 1440) ("h" . 60)))
585 (org-duration-format '(("d" . nil) (special . h:mm))))
586 (org-columns))
587 (get-char-property (point) 'org-columns-value-modified))))
588 (should
589 (equal
590 "6:00:10"
591 (org-test-with-temp-text
592 "* H
593 ** S1
594 :PROPERTIES:
595 :A: 4:40:10
596 :END:
597 ** S1
598 :PROPERTIES:
599 :A: 1:20
600 :END:"
601 (let ((org-columns-default-format "%A{:}")) (org-columns))
602 (get-char-property (point) 'org-columns-value-modified))))
603 (should
604 (equal
605 "3d 4:20"
606 (org-test-with-temp-text
607 "* H
608 ** S1
609 :PROPERTIES:
610 :A: 3d 3h
611 :END:
612 ** S1
613 :PROPERTIES:
614 :A: 0d 1:20
615 :END:"
616 (let ((org-columns-default-format "%A{:}")
617 (org-duration-units '(("d" . 1440) ("h" . 60)))
618 (org-duration-format '(("d" . nil) (special . h:mm))))
619 (org-columns))
620 (get-char-property (point) 'org-columns-value-modified))))
621 ;; @min, @max and @mean also accept regular duration.
622 (should
623 (equal
624 "1d 10h"
625 (org-test-with-temp-text
626 "* H
627 ** S1
628 :PROPERTIES:
629 :A: 1d 10h 0min
630 :END:
631 ** S1
632 :PROPERTIES:
633 :A: 5d 3h
634 :END:"
635 (let ((org-columns-default-format "%A{@min}")) (org-columns))
636 (get-char-property (point) 'org-columns-value-modified))))
637 ;; {est+} gives a low-high estimate using mean and standard
638 ;; deviation.
639 (should
640 (equal
641 "3-17"
642 (org-test-with-temp-text
643 "* H
644 ** S1
645 :PROPERTIES:
646 :A: 0-10
647 :END:
648 ** S1
649 :PROPERTIES:
650 :A: 0-10
651 :END:"
652 (let ((org-columns-default-format "%A{est+}")) (org-columns))
653 (get-char-property (point) 'org-columns-value-modified))))
654 ;; When using {est+} summary, a single number is understood as
655 ;; a degenerate range.
656 (should
657 (equal
658 "4-4"
659 (org-test-with-temp-text
660 "* H
661 ** S1
662 :PROPERTIES:
663 :A: 4
664 :END:
666 (let ((org-columns-default-format "%A{est+}")) (org-columns))
667 (get-char-property (point) 'org-columns-value-modified))))
668 ;; Allow custom summary types.
669 (should
670 (equal
671 "1|2"
672 (org-test-with-temp-text
673 "* H
674 ** S1
675 :PROPERTIES:
676 :A: 1
677 :END:
678 ** S1
679 :PROPERTIES:
680 :A: 2
681 :END:"
682 (let ((org-columns-summary-types
683 '(("custom" . (lambda (s _) (mapconcat #'identity s "|")))))
684 (org-columns-default-format "%A{custom}")) (org-columns))
685 (get-char-property (point) 'org-columns-value-modified))))
686 ;; Allow custom _collect_ for summary types.
687 (should
688 (equal
690 (org-test-with-temp-text
691 "* H
692 ** S1
693 :PROPERTIES:
694 :A: 1
695 :END:
696 ** S1
697 :PROPERTIES:
698 :A: 2
699 :A-OK: 1
700 :END:"
701 (let ((org-columns-summary-types
702 '(("custom" org-columns--summary-sum
703 (lambda (p)
704 (if (equal "1" (org-entry-get nil (format "%s-OK" p)))
705 (org-entry-get nil p)
706 "")))))
707 (org-columns-default-format "%A{custom}")) (org-columns))
708 (get-char-property (point) 'org-columns-value-modified))))
709 ;; Allow custom collect function to be used for different columns
710 (should
711 (equal
712 '("2" "1")
713 (org-test-with-temp-text
714 "* H
715 ** S1
716 :PROPERTIES:
717 :A: 1
718 :B: 1
719 :B-OK: 1
720 :END:
721 ** S1
722 :PROPERTIES:
723 :A: 2
724 :B: 2
725 :A-OK: 1
726 :END:"
727 (let ((org-columns-summary-types
728 '(("custom" org-columns--summary-sum
729 (lambda (p)
730 (if (equal "1" (org-entry-get nil (format "%s-OK" p)))
731 (org-entry-get nil p)
732 "")))))
733 (org-columns-default-format "%A{custom} %B{custom}")) (org-columns))
734 (list (get-char-property (point) 'org-columns-value-modified)
735 (get-char-property (1+ (point)) 'org-columns-value-modified)))))
736 ;; Allow multiple summary types applied to the same property.
737 (should
738 (equal
739 '("42" "99")
740 (org-test-with-temp-text
741 "* H
742 ** S1
743 :PROPERTIES:
744 :A: 99
745 :END:
746 ** S1
747 :PROPERTIES:
748 :A: 42
749 :END:"
750 (let ((org-columns-default-format "%A{min} %A{max}")) (org-columns))
751 (list (get-char-property (point) 'org-columns-value-modified)
752 (get-char-property (1+ (point)) 'org-columns-value-modified)))))
753 ;; Allow mixing both summarized and non-summarized columns for
754 ;; a property. However, the first column takes precedence and
755 ;; updates the value.
756 (should
757 (equal
758 '("1000" "42")
759 (org-test-with-temp-text
760 "* H
761 :PROPERTIES:
762 :A: 1000
763 :END:
764 ** S1
765 :PROPERTIES:
766 :A: 99
767 :END:
768 ** S1
769 :PROPERTIES:
770 :A: 42
771 :END:"
772 (let ((org-columns-default-format "%A %A{min}")) (org-columns))
773 (list (get-char-property (point) 'org-columns-value-modified)
774 (get-char-property (1+ (point)) 'org-columns-value-modified)))))
775 (should
776 (equal
777 '("42" "42")
778 (org-test-with-temp-text
779 "* H
780 :PROPERTIES:
781 :A: 1000
782 :END:
783 ** S1
784 :PROPERTIES:
785 :A: 99
786 :END:
787 ** S1
788 :PROPERTIES:
789 :A: 42
790 :END:"
791 (let ((org-columns-default-format "%A{min} %A")) (org-columns))
792 (list (get-char-property (point) 'org-columns-value-modified)
793 (get-char-property (1+ (point)) 'org-columns-value-modified))))))
795 (ert-deftest test-org-colview/columns-new ()
796 "Test `org-columns-new' specifications."
797 ;; Insert new column at the left of the current one.
798 (should
799 (equal '("FOO" "ITEM")
800 (org-test-with-temp-text "* H"
801 (let ((org-columns-default-format "%ITEM")) (org-columns))
802 (org-columns-new nil "FOO" "FOO" nil nil nil)
803 (list (get-char-property (point) 'org-columns-key)
804 (get-char-property (1+ (point)) 'org-columns-key)))))
805 (should
806 (equal '("ITEM" "FOO" "BAR")
807 (org-test-with-temp-text "* H"
808 (let ((org-columns-default-format "%ITEM %BAR")) (org-columns))
809 (forward-char)
810 (org-columns-new nil "FOO" "FOO" nil nil nil)
811 (list (get-char-property (1- (point)) 'org-columns-key)
812 (get-char-property (point) 'org-columns-key)
813 (get-char-property (1+ (point)) 'org-columns-key)))))
814 ;; Update #+COLUMNS keyword if needed.
815 (should
816 (equal "#+COLUMNS: %FOO %ITEM"
817 (org-test-with-temp-text "#+COLUMNS: %ITEM\n<point>* H"
818 (let ((org-columns-default-format "%ITEM")) (org-columns))
819 (org-columns-new nil "FOO" "FOO" nil nil nil)
820 (goto-char (point-min))
821 (buffer-substring-no-properties (point) (line-end-position)))))
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 ;; Mind case when updating #+COLUMNS.
831 (should
832 (equal "#+COLUMNS: %ITEM %Foo %BAR"
833 (org-test-with-temp-text "#+COLUMNS: %ITEM %BAR\n<point>* H"
834 (let ((org-columns-default-format "%ITEM %BAR")) (org-columns))
835 (forward-char)
836 (org-columns-new nil "Foo" "Foo" nil nil nil)
837 (goto-char (point-min))
838 (buffer-substring-no-properties (point) (line-end-position)))))
839 (should
840 (equal "#+columns: %ITEM %Foo %BAR"
841 (org-test-with-temp-text "#+columns: %ITEM %BAR\n<point>* H"
842 (let ((org-columns-default-format "%ITEM %BAR")) (org-columns))
843 (forward-char)
844 (org-columns-new nil "Foo" "Foo" nil nil nil)
845 (goto-char (point-min))
846 (buffer-substring-no-properties (point) (line-end-position)))))
847 ;; Also update :COLUMNS: properties.
848 (should
849 (equal "%FOO %ITEM"
850 (org-test-with-temp-text "* H\n:PROPERTIES:\n:COLUMNS: %ITEM\n:END:"
851 (let ((org-columns-default-format "%ITEM")) (org-columns))
852 (org-columns-new nil "FOO" "FOO" nil nil nil)
853 (org-entry-get nil "COLUMNS"))))
854 ;; If no keyword nor any property is available, insert one.
855 (should
856 (string-match-p (regexp-quote "#+COLUMNS: %FOO %ITEM")
857 (org-test-with-temp-text "* H"
858 (let ((org-columns-default-format "%ITEM")) (org-columns))
859 (org-columns-new nil "FOO" "FOO" nil nil nil)
860 (buffer-string)))))
862 (ert-deftest test-org-colview/columns-update ()
863 "Test `org-columns-update' specifications."
864 ;; Update display.
865 (should
866 (equal
867 "12 |"
868 (org-test-with-temp-text
869 "* H
870 :PROPERTIES:
871 :A: 1
872 :END:
874 (let ((org-columns-default-format "%5A")) (org-columns))
875 (search-forward "1")
876 (insert "2")
877 (org-columns-update "A")
878 (get-char-property (point-min) 'display))))
879 ;; Update is case-insensitive.
880 (should
881 (equal
882 "12 |"
883 (org-test-with-temp-text
884 "* H
885 :PROPERTIES:
886 :A: 1
887 :END:
889 (let ((org-columns-default-format "%5A")) (org-columns))
890 (search-forward "1")
891 (insert "2")
892 (org-columns-update "a")
893 (get-char-property (point-min) 'display))))
894 ;; Update stored values.
895 (should
896 (equal
897 '("12" "12")
898 (org-test-with-temp-text
899 "* H
900 :PROPERTIES:
901 :A: 1
902 :END:
904 (let ((org-columns-default-format "%5A")) (org-columns))
905 (search-forward "1")
906 (insert "2")
907 (org-columns-update "A")
908 (list (get-char-property (point-min) 'org-columns-value)
909 (get-char-property (point-min) 'org-columns-value-modified)))))
910 ;; When multiple columns are using the same property, value is
911 ;; updated according to the specifications of the first one.
912 (should
913 (equal
915 (org-test-with-temp-text
916 "* H
917 :PROPERTIES:
918 :A: 1
919 :END:
920 ** S
921 :PROPERTIES:
922 :A: 2
923 :END:"
924 (let ((org-columns-default-format "%A{min} %A")) (org-columns))
925 (org-columns-update "A")
926 (org-entry-get nil "A"))))
927 (should
928 (equal
930 (org-test-with-temp-text
931 "* H
932 :PROPERTIES:
933 :A: 1
934 :END:
935 ** S
936 :PROPERTIES:
937 :A: 2
938 :END:"
939 (let ((org-columns-default-format "%A %A{min}")) (org-columns))
940 (org-columns-update "A")
941 (org-entry-get nil "A"))))
942 ;; Ensure modifications propagate in upper levels even when multiple
943 ;; summary types apply to the same property.
944 (should
945 (equal
946 '("1" "22")
947 (org-test-with-temp-text
948 "* H
949 ** S1
950 :PROPERTIES:
951 :A: 1
952 :END:
953 ** S2
954 :PROPERTIES:
955 :A: <point>2
956 :END:"
957 (save-excursion
958 (goto-char (point-min))
959 (let ((org-columns-default-format "%A{min} %A{max}")) (org-columns)))
960 (insert "2")
961 (org-columns-update "A")
962 (list (get-char-property 1 'org-columns-value)
963 (get-char-property 2 'org-columns-value-modified)))))
964 ;; Ensure additional processing is done (e.g., ellipses, special
965 ;; keywords fontification...).
966 (should
967 (equal
968 "ve.. |"
969 (org-test-with-temp-text
970 "* H
971 :PROPERTIES:
972 :A: text
973 :END:
975 (let ((org-columns-default-format "%4A")
976 (org-columns-ellipses ".."))
977 (org-columns))
978 (search-forward ":A: ")
979 (insert "very long ")
980 (org-columns-update "A")
981 (get-char-property (point-min) 'display))))
982 ;; Values obtained from inline tasks are at the same level as those
983 ;; obtained from children of the current node.
984 (when (featurep 'org-inlinetask)
985 (should
986 (equal
988 (org-test-with-temp-text
989 "* H
990 *************** Inline task
991 :PROPERTIES:
992 :A: 2
993 :END:
994 *************** END
995 ** Children
996 :PROPERTIES:
997 :A: 3
998 :END:
1000 (let ((org-columns-default-format "%A{min}")
1001 (org-columns-ellipses "..")
1002 (org-inlinetask-min-level 15))
1003 (org-columns))
1004 (get-char-property (point-min) 'org-columns-value)))))
1005 ;; Handle `org-columns-modify-value-for-display-function', even with
1006 ;; multiple titles for the same property.
1007 (should
1008 (equal '("foo" "bar")
1009 (org-test-with-temp-text "* H"
1010 (let ((org-columns-default-format "%ITEM %ITEM(Name)")
1011 (org-columns-modify-value-for-display-function
1012 (lambda (title value)
1013 (pcase title ("ITEM" "foo") ("Name" "bar") (_ "baz")))))
1014 (org-columns))
1015 (list (get-char-property 1 'org-columns-value-modified)
1016 (get-char-property 2 'org-columns-value-modified))))))
1018 (ert-deftest test-org-colview/columns-move-left ()
1019 "Test `org-columns-move-left' specifications."
1020 ;; Error when trying to move the left-most column.
1021 (should-error
1022 (org-test-with-temp-text "* H"
1023 (let ((org-columns-default-format "%ITEM")) (org-columns))
1024 (org-columns-move-left)))
1025 ;; Otherwise, move column to left and update display.
1026 (should
1027 (equal '("2" "1")
1028 (org-test-with-temp-text "* H\n:PROPERTIES:\n:A: 1\n:B: 2\n:END:"
1029 (let ((org-columns-default-format "%A %B")) (org-columns))
1030 (forward-char)
1031 (org-columns-move-left)
1032 (list (get-char-property (point) 'org-columns-value)
1033 (get-char-property (1+ (point)) 'org-columns-value)))))
1034 ;; Handle multiple columns with the same property.
1035 (should
1036 (equal '("2" "1")
1037 (org-test-with-temp-text
1038 "* H
1039 ** S1
1040 :PROPERTIES:
1041 :A: 1
1042 :END:
1043 ** S1
1044 :PROPERTIES:
1045 :A: 2
1046 :END:"
1047 (let ((org-columns-default-format "%ITEM %A{min} %A{max}"))
1048 (org-columns))
1049 (forward-char 2)
1050 (org-columns-move-left)
1051 (list (get-char-property (point) 'org-columns-value)
1052 (get-char-property (1+ (point)) 'org-columns-value)))))
1053 ;; Special case: do not update values even if move entails changing
1054 ;; them.
1055 (should
1056 (equal "1"
1057 (org-test-with-temp-text
1058 "* H
1059 :PROPERTIES:
1060 :A: 1
1061 :END:
1062 ** S1
1063 :PROPERTIES:
1064 :A: 99
1065 :END:"
1066 (let ((org-columns-default-format "%A %A{max}"))
1067 (org-columns))
1068 (forward-char)
1069 (org-columns-move-left)
1070 ;; Since the first column matching a given property
1071 ;; determines how a value is computed, the following
1072 ;; should return "99" instead. However, this behavior is
1073 ;; in practice surprising so we just ignore the value
1074 ;; change. It can be computed later.
1075 (org-entry-get (point) "A")))))
1077 (ert-deftest test-org-colview/columns-move-right ()
1078 "Test `org-columns-move-right' specifications."
1079 ;; Error when trying to move the right-most column.
1080 (should-error
1081 (org-test-with-temp-text "* H"
1082 (let ((org-columns-default-format "%ITEM")) (org-columns))
1083 (org-columns-move-right)))
1084 ;; Otherwise, move column to left and update display.
1085 (should
1086 (equal '("2" "1")
1087 (org-test-with-temp-text "* H\n:PROPERTIES:\n:A: 1\n:B: 2\n:END:"
1088 (let ((org-columns-default-format "%A %B")) (org-columns))
1089 (org-columns-move-right)
1090 (list (get-char-property (1- (point)) 'org-columns-value)
1091 (get-char-property (point) 'org-columns-value)))))
1092 ;; Handle multiple columns with the same property.
1093 (should
1094 (equal '("2" "1")
1095 (org-test-with-temp-text
1096 "* H
1097 ** S1
1098 :PROPERTIES:
1099 :A: 1
1100 :END:
1101 ** S1
1102 :PROPERTIES:
1103 :A: 2
1104 :END:"
1105 (let ((org-columns-default-format "%ITEM %A{min} %A{max}"))
1106 (org-columns))
1107 (forward-char)
1108 (org-columns-move-right)
1109 (list (get-char-property (1- (point)) 'org-columns-value)
1110 (get-char-property (point) 'org-columns-value)))))
1111 ;; Special case: do not update values even if move entails changing
1112 ;; them.
1113 (should
1114 (equal "1"
1115 (org-test-with-temp-text
1116 "* H
1117 :PROPERTIES:
1118 :A: 1
1119 :END:
1120 ** S1
1121 :PROPERTIES:
1122 :A: 99
1123 :END:"
1124 (let ((org-columns-default-format "%A %A{max}"))
1125 (org-columns))
1126 (org-columns-move-right)
1127 ;; See `test-org-colview/columns-move-left' for an
1128 ;; explanation.
1129 (org-entry-get (point) "A")))))
1131 (ert-deftest test-org-colview/columns-next-allowed-value ()
1132 "Test `org-columns-next-allowed-value' specifications."
1133 ;; Cannot shift "ITEM" property.
1134 (should-error
1135 (org-test-with-temp-text "* H"
1136 (let ((org-columns-default-format "%ITEM")) (org-columns))
1137 (org-columns-next-allowed-value)))
1138 ;; Throw an error when allowed values are not defined.
1139 (should-error
1140 (org-test-with-temp-text "* H\n:PROPERTIES:\n:A: 1\n:END:"
1141 (let ((org-columns-default-format "%A")) (org-columns))
1142 (org-columns-next-allowed-value)))
1143 ;; Throw an error when there's only one value to select.
1144 (should-error
1145 (org-test-with-temp-text "* H\n:PROPERTIES:\n:A: 1\n:A_ALL: 1\n:END:"
1146 (let ((org-columns-default-format "%A")) (org-columns))
1147 (org-columns-next-allowed-value)))
1148 ;; By default select the next allowed value. Where there is no more
1149 ;; value, start again from first possible one.
1150 (should
1151 (equal "2"
1152 (org-test-with-temp-text
1153 "* H\n:PROPERTIES:\n:A: 1\n:A_ALL: 1 2 3\n:END:"
1154 (let ((org-columns-default-format "%A")) (org-columns))
1155 (org-columns-next-allowed-value)
1156 (org-entry-get (point) "A"))))
1157 (should
1158 (equal "3"
1159 (org-test-with-temp-text
1160 "* H\n:PROPERTIES:\n:A: 2\n:A_ALL: 1 2 3\n:END:"
1161 (let ((org-columns-default-format "%A")) (org-columns))
1162 (org-columns-next-allowed-value)
1163 (org-entry-get (point) "A"))))
1164 (should
1165 (equal "1"
1166 (org-test-with-temp-text
1167 "* H\n:PROPERTIES:\n:A: 3\n:A_ALL: 1 2 3\n:END:"
1168 (let ((org-columns-default-format "%A")) (org-columns))
1169 (org-columns-next-allowed-value)
1170 (org-entry-get (point) "A"))))
1171 ;; PREVIOUS argument moves backward.
1172 (should
1173 (equal "1"
1174 (org-test-with-temp-text
1175 "* H\n:PROPERTIES:\n:A: 2\n:A_ALL: 1 2 3\n:END:"
1176 (let ((org-columns-default-format "%A")) (org-columns))
1177 (org-columns-next-allowed-value 'previous)
1178 (org-entry-get (point) "A"))))
1179 (should
1180 (equal "2"
1181 (org-test-with-temp-text
1182 "* H\n:PROPERTIES:\n:A: 3\n:A_ALL: 1 2 3\n:END:"
1183 (let ((org-columns-default-format "%A")) (org-columns))
1184 (org-columns-next-allowed-value 'previous)
1185 (org-entry-get (point) "A"))))
1186 (should
1187 (equal "3"
1188 (org-test-with-temp-text
1189 "* H\n:PROPERTIES:\n:A: 1\n:A_ALL: 1 2 3\n:END:"
1190 (let ((org-columns-default-format "%A")) (org-columns))
1191 (org-columns-next-allowed-value 'previous)
1192 (org-entry-get (point) "A"))))
1193 ;; Select Nth element with optional argument NTH.
1194 (should
1195 (equal "1"
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 1)
1200 (org-entry-get (point) "A"))))
1201 ;; If NTH is negative, go backwards, 0 being the last one and -1 the
1202 ;; penultimate.
1203 (should
1204 (equal "3"
1205 (org-test-with-temp-text
1206 "* H\n:PROPERTIES:\n:A: 2\n:A_ALL: 1 2 3\n:END:"
1207 (let ((org-columns-default-format "%A")) (org-columns))
1208 (org-columns-next-allowed-value nil 0)
1209 (org-entry-get (point) "A"))))
1210 (should
1211 (equal "2"
1212 (org-test-with-temp-text
1213 "* H\n:PROPERTIES:\n:A: 2\n:A_ALL: 1 2 3\n:END:"
1214 (let ((org-columns-default-format "%A")) (org-columns))
1215 (org-columns-next-allowed-value nil -1)
1216 (org-entry-get (point) "A"))))
1217 ;; Throw an error if NTH is greater than the number of allowed
1218 ;; values.
1219 (should-error
1220 (org-test-with-temp-text
1221 "* H\n:PROPERTIES:\n:A: 2\n:A_ALL: 1 2 3\n:END:"
1222 (let ((org-columns-default-format "%A")) (org-columns))
1223 (org-columns-next-allowed-value nil 4)
1224 (org-entry-get (point) "A")))
1225 ;; Pathological case: when shifting the value alters the current
1226 ;; heading, make sure all columns are still at their correct
1227 ;; location.
1228 (should
1229 (equal '("H" "" "" "" "TODO")
1230 (let ((org-todo-keywords '((sequence "TODO" "DONE"))))
1231 (org-test-with-temp-text "* H"
1232 (let ((org-columns-default-format "%ITEM %A %B %C %TODO"))
1233 (org-columns)
1234 (forward-char 4)
1235 (org-columns-next-allowed-value)
1236 (list (get-char-property (- (point) 4) 'org-columns-value)
1237 (get-char-property (- (point) 3) 'org-columns-value)
1238 (get-char-property (- (point) 2) 'org-columns-value)
1239 (get-char-property (- (point) 1) 'org-columns-value)
1240 (get-char-property (point) 'org-columns-value)))))))
1241 (should
1242 (equal '("H" "VERYLONGTODO")
1243 (let ((org-todo-keywords '((sequence "TODO" "VERYLONGTODO"))))
1244 (org-test-with-temp-text "* TODO H"
1245 (let ((org-columns-default-format "%ITEM %TODO"))
1246 (org-columns)
1247 (forward-char)
1248 (org-columns-next-allowed-value)
1249 (list (get-char-property (- (point) 1) 'org-columns-value)
1250 (get-char-property (point) 'org-columns-value))))))))
1254 ;;; Dynamic block
1256 (ert-deftest test-org-colview/dblock ()
1257 "Test the column view table."
1258 (should
1259 (equal
1260 "#+BEGIN: columnview
1261 | ITEM |
1262 |------|
1263 | H |
1264 #+END:"
1265 (org-test-with-temp-text
1266 "* H\n<point>#+BEGIN: columnview\n#+END:"
1267 (let ((org-columns-default-format "%ITEM")) (org-update-dblock))
1268 (buffer-substring-no-properties (point) (point-max)))))
1269 (should
1270 (equal
1271 "#+BEGIN: columnview
1272 | ITEM | A |
1273 |------+---|
1274 | H | 1 |
1275 #+END:"
1276 (org-test-with-temp-text
1277 "* H\n:PROPERTIES:\n:A: 1\n:END:\n<point>#+BEGIN: columnview\n#+END:"
1278 (let ((org-columns-default-format "%ITEM %A")) (org-update-dblock))
1279 (buffer-substring-no-properties (point) (point-max)))))
1280 ;; Properties are case insensitive.
1281 (should
1282 (equal
1283 "#+BEGIN: columnview
1284 | a |
1285 |---|
1286 | 1 |
1287 #+END:"
1288 (org-test-with-temp-text
1289 "* H\n:PROPERTIES:\n:A: 1\n:END:\n<point>#+BEGIN: columnview\n#+END:"
1290 (let ((org-columns-default-format "%a")) (org-update-dblock))
1291 (buffer-substring-no-properties (point) (point-max)))))
1292 ;; Test titles given to columns.
1293 (should
1294 (equal
1295 "#+BEGIN: columnview
1296 | Name | Prop |
1297 |------+------|
1298 | H | 1 |
1299 #+END:"
1300 (org-test-with-temp-text
1301 "* H\n:PROPERTIES:\n:A: 1\n:END:\n<point>#+BEGIN: columnview\n#+END:"
1302 (let ((org-columns-default-format "%ITEM(Name) %A(Prop)"))
1303 (org-update-dblock))
1304 (buffer-substring-no-properties (point) (point-max)))))
1305 ;; Test `:id' parameter
1306 (should
1307 (equal
1308 "#+BEGIN: columnview :id local
1309 | ITEM |
1310 |------|
1311 | H1 |
1312 | H1.1 |
1313 #+END:
1315 (org-test-with-temp-text
1316 "* H1\n<point>#+BEGIN: columnview :id local\n#+END:\n** H1.1\n* H2"
1317 (let ((org-columns-default-format "%ITEM")) (org-update-dblock))
1318 (buffer-substring-no-properties (point) (outline-next-heading)))))
1319 (should
1320 (equal
1321 "#+BEGIN: columnview :id global
1322 | ITEM |
1323 |------|
1324 | H1 |
1325 | H1.1 |
1326 | H2 |
1327 #+END:
1329 (org-test-with-temp-text
1330 "\n* H1\n<point>#+BEGIN: columnview :id global\n#+END:\n** H1.1\n* H2"
1331 (let ((org-columns-default-format "%ITEM")) (org-update-dblock))
1332 (buffer-substring-no-properties (point) (outline-next-heading)))))
1333 ;; Test `:hlines' parameter.
1334 (should
1335 (equal
1336 "#+BEGIN: columnview :hlines t :id global
1337 | ITEM |
1338 |------|
1339 | H |
1340 |------|
1341 | H2 |
1342 |------|
1343 | H2.1 |
1344 #+END:\n"
1345 (org-test-with-temp-text
1348 <point>#+BEGIN: columnview :hlines t :id global
1349 #+END:
1350 * H2
1351 ** H2.1"
1352 (let ((org-columns-default-format "%ITEM")) (org-update-dblock))
1353 (buffer-substring-no-properties (point) (outline-next-heading)))))
1354 (should
1355 (equal
1356 "#+BEGIN: columnview :hlines 1 :id global
1357 | ITEM |
1358 |------|
1359 | H |
1360 |------|
1361 | H2 |
1362 | H2.1 |
1363 #+END:\n"
1364 (org-test-with-temp-text
1367 <point>#+BEGIN: columnview :hlines 1 :id global
1368 #+END:
1369 * H2
1370 ** H2.1"
1371 (let ((org-columns-default-format "%ITEM")) (org-update-dblock))
1372 (buffer-substring-no-properties (point) (outline-next-heading)))))
1373 (should
1374 (equal
1375 "#+BEGIN: columnview :hlines 1 :id \"id\"
1376 | ITEM |
1377 |------|
1378 | H2 |
1379 | H2.1 |
1380 #+END:
1382 (org-test-with-temp-text
1385 <point>#+BEGIN: columnview :hlines 1 :id \"id\"
1386 #+END:
1387 * H2
1388 :PROPERTIES:
1389 :ID: id
1390 :END:
1391 ** H2.1"
1392 (let ((org-columns-default-format "%ITEM")) (org-update-dblock))
1393 (buffer-substring-no-properties (point) (outline-next-heading)))))
1394 (should
1395 (equal
1396 "#+BEGIN: columnview :hlines 1 :id id
1397 | ITEM |
1398 |------|
1399 | H2 |
1400 | H2.1 |
1401 #+END:
1403 (org-test-with-temp-text
1406 <point>#+BEGIN: columnview :hlines 1 :id id
1407 #+END:
1408 * H2
1409 :PROPERTIES:
1410 :ID: id
1411 :END:
1412 ** H2.1"
1413 (let ((org-columns-default-format "%ITEM")) (org-update-dblock))
1414 (buffer-substring-no-properties (point) (outline-next-heading)))))
1415 ;; Test `:indent' parameter.
1416 (should
1417 (equal
1418 "#+BEGIN: columnview :indent t
1419 | ITEM |
1420 |----------|
1421 | H1 |
1422 | \\_ H1.1 |
1423 #+END:
1425 (org-test-with-temp-text
1426 "* H1\n<point>#+BEGIN: columnview :indent t\n#+END:\n** H1.1"
1427 (let ((org-columns-default-format "%ITEM")) (org-update-dblock))
1428 (buffer-substring-no-properties (point) (outline-next-heading)))))
1429 (should
1430 (equal
1431 "#+BEGIN: columnview :indent t
1432 | Prop | Name |
1433 |------+----------|
1434 | | H1 |
1435 | | \\_ H1.1 |
1436 #+END:
1438 (org-test-with-temp-text
1439 "* H1\n<point>#+BEGIN: columnview :indent t\n#+END:\n** H1.1"
1440 (let ((org-columns-default-format "%A(Prop) %ITEM(Name)"))
1441 (org-update-dblock))
1442 (buffer-substring-no-properties (point) (outline-next-heading)))))
1443 ;; Test `:vlines' parameter.
1444 (should
1445 (equal
1446 "#+BEGIN: columnview :vlines t
1447 | | ITEM | A |
1448 |---+------+----|
1449 | | H | 1 |
1450 | / | <> | <> |
1451 #+END:"
1452 (org-test-with-temp-text
1453 "* H\n:PROPERTIES:\n:A: 1\n:END:\n<point>#+BEGIN: columnview :vlines t\n#+END:"
1454 (let ((org-columns-default-format "%ITEM %A")) (org-update-dblock))
1455 (buffer-substring-no-properties (point) (point-max)))))
1456 ;; Test `:skip-empty-rows' parameter.
1457 (should
1458 (equal
1459 "#+BEGIN: columnview :skip-empty-rows t
1460 | ITEM | A |
1461 |------+---|
1462 | H1.1 | 1 |
1463 #+END:
1465 (org-test-with-temp-text
1467 * H1
1468 <point>#+BEGIN: columnview :skip-empty-rows t
1469 #+END:
1470 ** H1.1
1471 :PROPERTIES:
1472 :A: 1
1473 :END:"
1474 (let ((org-columns-default-format "%ITEM %A")) (org-update-dblock))
1475 (buffer-substring-no-properties (point) (outline-next-heading)))))
1476 ;; Test `:format' parameter.
1477 (should
1478 (equal
1479 "#+BEGIN: columnview :format \"%ITEM(Name)\"
1480 | Name |
1481 |------|
1482 | H |
1483 #+END:"
1484 (org-test-with-temp-text
1485 "* H\n<point>#+BEGIN: columnview :format \"%ITEM(Name)\"\n#+END:"
1486 (let ((org-columns-default-format "%ITEM")) (org-update-dblock))
1487 (buffer-substring-no-properties (point) (point-max)))))
1488 ;; When inserting ITEM values, make sure to clean sensitive
1489 ;; contents, like unique targets or forbidden inline src-blocks.
1490 (should
1491 (equal
1492 "#+BEGIN: columnview
1493 | ITEM |
1494 |------|
1495 | H 1 |
1496 #+END:"
1497 (org-test-with-temp-text
1498 "* H <<target>> 1\n<point>#+BEGIN: columnview\n#+END:"
1499 (let ((org-columns-default-format "%ITEM")) (org-update-dblock))
1500 (buffer-substring-no-properties (point) (point-max)))))
1501 (should
1502 (equal
1503 "#+BEGIN: columnview
1504 | ITEM |
1505 |------|
1506 | H 1 |
1507 #+END:"
1508 (org-test-with-temp-text
1509 "* H src_emacs-lisp{(+ 1 1)} 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))))))
1513 (provide 'test-org-colview)
1514 ;;; test-org-colview.el ends here