test-org-colview.el 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546
  1. ;;; test-org-colview.el --- Tests for org-colview.el -*- lexical-binding: t; -*-
  2. ;; Copyright (C) 2016, 2019 Nicolas Goaziou
  3. ;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
  4. ;; This program is free software; you can redistribute it and/or modify
  5. ;; it under the terms of the GNU General Public License as published by
  6. ;; the Free Software Foundation, either version 3 of the License, or
  7. ;; (at your option) any later version.
  8. ;; This program is distributed in the hope that it will be useful,
  9. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. ;; GNU General Public License for more details.
  12. ;; You should have received a copy of the GNU General Public License
  13. ;; along with this program. If not, see <https://www.gnu.org/licenses/>.
  14. ;;; Code:
  15. ;;; Column view
  16. (require 'cl-lib)
  17. (require 'org-colview)
  18. (require 'org-duration)
  19. (require 'org-inlinetask)
  20. (ert-deftest test-org-colview/get-format ()
  21. "Test `org-columns-get-format' specifications."
  22. ;; Without any clue, use `org-columns-default-format'.
  23. (should
  24. (equal "%A"
  25. (org-test-with-temp-text "* H"
  26. (let ((org-columns-default-format "%A"))
  27. (org-columns-get-format)))))
  28. ;; If COLUMNS keyword is set, use it.
  29. (should
  30. (equal "%B"
  31. (org-test-with-temp-text "#+COLUMNS: %B\n* H"
  32. (let ((org-columns-default-format "%A"))
  33. (org-columns-get-format)))))
  34. (should
  35. (equal "%B"
  36. (org-test-with-temp-text "#+columns: %B\n* H"
  37. (let ((org-columns-default-format "%A"))
  38. (org-columns-get-format)))))
  39. (should
  40. (equal "%B"
  41. (org-test-with-temp-text "* H\n#+COLUMNS: %B"
  42. (let ((org-columns-default-format "%A"))
  43. (org-columns-get-format)))))
  44. ;; When :COLUMNS: property is set somewhere in the tree, use it over
  45. ;; the previous ways.
  46. (should
  47. (equal
  48. "%C"
  49. (org-test-with-temp-text
  50. "#+COLUMNS: %B\n* H\n:PROPERTIES:\n:COLUMNS: %C\n:END:\n** S\n<point>"
  51. (let ((org-columns-default-format "%A"))
  52. (org-columns-get-format)))))
  53. ;; When optional argument is provided, prefer it.
  54. (should
  55. (equal
  56. "%D"
  57. (org-test-with-temp-text
  58. "#+COLUMNS: %B\n* H\n:PROPERTIES:\n:COLUMNS: %C\n:END:\n** S\n<point>"
  59. (let ((org-columns-default-format "%A"))
  60. (org-columns-get-format "%D"))))))
  61. (ert-deftest test-org-colview/columns-scope ()
  62. "Test `org-columns' scope."
  63. ;; Before the first headline, view all document.
  64. (should
  65. (equal
  66. '("H1" "H2" "H3")
  67. (org-test-with-temp-text "Top\n* H1\n** H2\n* H3"
  68. (let ((org-columns-default-format "%ITEM")) (org-columns))
  69. (org-map-entries
  70. (lambda () (get-char-property (point) 'org-columns-value))))))
  71. ;; When :COLUMNS: is set up in the hierarchy, view tree starting
  72. ;; there.
  73. (should
  74. (equal
  75. '(nil "H2" "H3" nil)
  76. (org-test-with-temp-text
  77. "* H1\n** H2\n:PROPERTIES:\n:COLUMNS: %ITEM\n:END:\n*** <point>H3\n* H4"
  78. (let ((org-columns-default-format "%ITEM")) (org-columns))
  79. (org-map-entries
  80. (lambda () (get-char-property (point) 'org-columns-value))))))
  81. ;; Otherwise, view tree starting at the current headline.
  82. (should
  83. (equal
  84. '(nil "H2" "H3" nil)
  85. (org-test-with-temp-text "Top\n* H1\n** <point>H2\n*** H3\n* H4"
  86. (let ((org-columns-default-format "%ITEM")) (org-columns))
  87. (org-map-entries
  88. (lambda () (get-char-property (point) 'org-columns-value))))))
  89. ;; With a non-nil prefix argument, always view all document.
  90. (should
  91. (equal
  92. '("H1" "H2" "H3" "H4")
  93. (org-test-with-temp-text
  94. "* H1\n** H2\n:PROPERTIES:\n:COLUMNS: %ITEM\n:END:\n*** <point>H3\n* H4"
  95. (let ((org-columns-default-format "%ITEM")) (org-columns t))
  96. (org-map-entries
  97. (lambda () (get-char-property (point) 'org-columns-value))))))
  98. (should
  99. (equal
  100. '("1" "1")
  101. (org-test-with-temp-text
  102. "Top\n* H1\n** <point>H2\n:PROPERTIES:\n:A: 1\n:END:"
  103. (let ((org-columns-default-format "%A{+}")) (org-columns t))
  104. (org-map-entries
  105. (lambda () (get-char-property (point) 'org-columns-value)))))))
  106. (ert-deftest test-org-colview/columns-width ()
  107. "Test `org-columns' column widths."
  108. ;; When a width is specified in the format, use it.
  109. (should
  110. (= 9
  111. (org-test-with-temp-text "* H"
  112. (let ((org-columns-default-format "%9ITEM")) (org-columns))
  113. (aref org-columns-current-maxwidths 0))))
  114. ;; Otherwise, use the width of the largest value in the column.
  115. (should
  116. (= 2
  117. (org-test-with-temp-text
  118. "* H\n:PROPERTIES:\n:P: X\n:END:\n** H2\n:PROPERTIES:\n:P: XX\n:END:"
  119. (let ((org-columns-default-format "%P")) (org-columns))
  120. (aref org-columns-current-maxwidths 0))))
  121. ;; If the title is wider than the widest value, use title width
  122. ;; instead.
  123. (should
  124. (= 4
  125. (org-test-with-temp-text "* H"
  126. (let ((org-columns-default-format "%ITEM")) (org-columns))
  127. (aref org-columns-current-maxwidths 0))))
  128. ;; Special case: stars do count for ITEM.
  129. (should
  130. (= 6
  131. (org-test-with-temp-text "* Head"
  132. (let ((org-columns-default-format "%ITEM")) (org-columns))
  133. (aref org-columns-current-maxwidths 0))))
  134. ;; Special case: width takes into account link narrowing in ITEM.
  135. (should
  136. (equal
  137. '("* 123" . 5)
  138. (org-test-with-temp-text "* [[https://orgmode.org][123]]"
  139. (let ((org-columns-default-format "%ITEM")) (org-columns))
  140. (cons (get-char-property (point) 'org-columns-value-modified)
  141. (aref org-columns-current-maxwidths 0)))))
  142. ;; When a value is too wide for the current column, add ellipses.
  143. ;; Take into consideration length of `org-columns-ellipses'.
  144. (should
  145. (equal "123.. |"
  146. (org-test-with-temp-text "* H\n:PROPERTIES:\n:P: 123456\n:END:"
  147. (let ((org-columns-default-format "%5P")
  148. (org-columns-ellipses ".."))
  149. (org-columns))
  150. (org-trim (get-char-property (point) 'display)))))
  151. (should
  152. (equal "1234… |"
  153. (org-test-with-temp-text "* H\n:PROPERTIES:\n:P: 123456\n:END:"
  154. (let ((org-columns-default-format "%5P")
  155. (org-columns-ellipses "…"))
  156. (org-columns))
  157. (org-trim (get-char-property (point) 'display))))))
  158. (ert-deftest test-org-colview/columns-summary ()
  159. "Test `org-columns' summary types."
  160. ;; {+} and {+;format} add numbers.
  161. (should
  162. (equal
  163. "3"
  164. (org-test-with-temp-text
  165. "* H
  166. ** S1
  167. :PROPERTIES:
  168. :A: 1
  169. :END:
  170. ** S1
  171. :PROPERTIES:
  172. :A: 2
  173. :END:"
  174. (let ((org-columns-default-format "%A{+}")) (org-columns))
  175. (get-char-property (point) 'org-columns-value-modified))))
  176. (should
  177. (equal
  178. "3.0"
  179. (org-test-with-temp-text
  180. "* H
  181. ** S1
  182. :PROPERTIES:
  183. :A: 1
  184. :END:
  185. ** S1
  186. :PROPERTIES:
  187. :A: 2
  188. :END:"
  189. (let ((org-columns-default-format "%A{+;%.1f}")) (org-columns))
  190. (get-char-property (point) 'org-columns-value-modified))))
  191. ;; {$} is a shortcut for {+;%.2f}.
  192. (should
  193. (equal
  194. "3.60"
  195. (org-test-with-temp-text
  196. "* H
  197. ** S1
  198. :PROPERTIES:
  199. :A: 1.50
  200. :END:
  201. ** S1
  202. :PROPERTIES:
  203. :A: 2.10
  204. :END:"
  205. (let ((org-columns-default-format "%A{$}")) (org-columns))
  206. (get-char-property (point) 'org-columns-value-modified))))
  207. ;; Obey to format string even in leaf values.
  208. (should
  209. (equal
  210. "1.0"
  211. (org-test-with-temp-text
  212. "* H
  213. :PROPERTIES:
  214. :A: 1
  215. :END:"
  216. (let ((org-columns-default-format "%A{+;%.1f}")) (org-columns))
  217. (get-char-property (point) 'org-columns-value-modified))))
  218. ;; {:} sums times. Plain numbers are minutes.
  219. (should
  220. (equal
  221. "4:10"
  222. (org-test-with-temp-text
  223. "* H
  224. ** S1
  225. :PROPERTIES:
  226. :A: 1:30
  227. :END:
  228. ** S1
  229. :PROPERTIES:
  230. :A: 2:40
  231. :END:"
  232. (let ((org-columns-default-format "%A{:}")) (org-columns))
  233. (get-char-property (point) 'org-columns-value-modified))))
  234. (should
  235. (equal
  236. "1:32"
  237. (org-test-with-temp-text
  238. "* H
  239. ** S1
  240. :PROPERTIES:
  241. :A: 1:30
  242. :END:
  243. ** S1
  244. :PROPERTIES:
  245. :A: 2
  246. :END:"
  247. (let ((org-columns-default-format "%A{:}")) (org-columns))
  248. (get-char-property (point) 'org-columns-value-modified))))
  249. ;; {X}, {X/} and {X%} indicate checkbox status.
  250. (should
  251. (equal
  252. "[ ]"
  253. (org-test-with-temp-text
  254. "* H
  255. ** S1
  256. :PROPERTIES:
  257. :A: [ ]
  258. :END:
  259. ** S1
  260. :PROPERTIES:
  261. :A: [ ]
  262. :END:"
  263. (let ((org-columns-default-format "%A{X}")) (org-columns))
  264. (get-char-property (point) 'org-columns-value-modified))))
  265. (should
  266. (equal
  267. "[-]"
  268. (org-test-with-temp-text
  269. "* H
  270. ** S1
  271. :PROPERTIES:
  272. :A: [ ]
  273. :END:
  274. ** S1
  275. :PROPERTIES:
  276. :A: [X]
  277. :END:"
  278. (let ((org-columns-default-format "%A{X}")) (org-columns))
  279. (get-char-property (point) 'org-columns-value-modified))))
  280. (should
  281. (equal
  282. "[X]"
  283. (org-test-with-temp-text
  284. "* H
  285. ** S1
  286. :PROPERTIES:
  287. :A: [X]
  288. :END:
  289. ** S1
  290. :PROPERTIES:
  291. :A: [X]
  292. :END:"
  293. (let ((org-columns-default-format "%A{X}")) (org-columns))
  294. (get-char-property (point) 'org-columns-value-modified))))
  295. (should
  296. (equal
  297. "[1/2]"
  298. (org-test-with-temp-text
  299. "* H
  300. ** S1
  301. :PROPERTIES:
  302. :A: [ ]
  303. :END:
  304. ** S1
  305. :PROPERTIES:
  306. :A: [X]
  307. :END:"
  308. (let ((org-columns-default-format "%A{X/}")) (org-columns))
  309. (get-char-property (point) 'org-columns-value-modified))))
  310. (should
  311. (equal
  312. "[50%]"
  313. (org-test-with-temp-text
  314. "* H
  315. ** S1
  316. :PROPERTIES:
  317. :A: [ ]
  318. :END:
  319. ** S1
  320. :PROPERTIES:
  321. :A: [X]
  322. :END:"
  323. (let ((org-columns-default-format "%A{X%}")) (org-columns))
  324. (get-char-property (point) 'org-columns-value-modified))))
  325. ;; {X/} handles recursive summaries.
  326. (should
  327. (equal
  328. "[1/2]"
  329. (org-test-with-temp-text
  330. "* H
  331. ** S1
  332. :PROPERTIES:
  333. :A: [ ]
  334. :END:
  335. ** S2
  336. *** S21
  337. :PROPERTIES:
  338. :A: [X]
  339. :END:
  340. *** S22
  341. :PROPERTIES:
  342. :A: [X]
  343. :END:"
  344. (let ((org-columns-default-format "%A{X/}")) (org-columns))
  345. (get-char-property (point) 'org-columns-value-modified))))
  346. (should
  347. (equal
  348. "[1/2]"
  349. (org-test-with-temp-text
  350. "* H
  351. ** S1
  352. :PROPERTIES:
  353. :A: [X]
  354. :END:
  355. ** S2
  356. *** S21
  357. :PROPERTIES:
  358. :A: [ ]
  359. :END:
  360. *** S22
  361. :PROPERTIES:
  362. :A: [ ]
  363. :END:"
  364. (let ((org-columns-default-format "%A{X/}")) (org-columns))
  365. (get-char-property (point) 'org-columns-value-modified))))
  366. ;; {X%} handles recursive summaries.
  367. (should
  368. (equal
  369. "[50%]"
  370. (org-test-with-temp-text
  371. "* H
  372. ** S1
  373. :PROPERTIES:
  374. :A: [ ]
  375. :END:
  376. ** S2
  377. *** S21
  378. :PROPERTIES:
  379. :A: [X]
  380. :END:
  381. *** S22
  382. :PROPERTIES:
  383. :A: [X]
  384. :END:"
  385. (let ((org-columns-default-format "%A{X%}")) (org-columns))
  386. (get-char-property (point) 'org-columns-value-modified))))
  387. (should
  388. (equal
  389. "[50%]"
  390. (org-test-with-temp-text
  391. "* H
  392. ** S1
  393. :PROPERTIES:
  394. :A: [X]
  395. :END:
  396. ** S2
  397. *** S21
  398. :PROPERTIES:
  399. :A: [ ]
  400. :END:
  401. *** S22
  402. :PROPERTIES:
  403. :A: [ ]
  404. :END:"
  405. (let ((org-columns-default-format "%A{X%}")) (org-columns))
  406. (get-char-property (point) 'org-columns-value-modified))))
  407. ;; {min} is the smallest number in column, {max} the largest one.
  408. ;; {mean} is the arithmetic mean of numbers in column.
  409. (should
  410. (equal
  411. "42"
  412. (org-test-with-temp-text
  413. "* H
  414. ** S1
  415. :PROPERTIES:
  416. :A: 99
  417. :END:
  418. ** S1
  419. :PROPERTIES:
  420. :A: 42
  421. :END:"
  422. (let ((org-columns-default-format "%A{min}")) (org-columns))
  423. (get-char-property (point) 'org-columns-value-modified))))
  424. (should
  425. (equal
  426. "99"
  427. (org-test-with-temp-text
  428. "* H
  429. ** S1
  430. :PROPERTIES:
  431. :A: 99
  432. :END:
  433. ** S1
  434. :PROPERTIES:
  435. :A: 42
  436. :END:"
  437. (let ((org-columns-default-format "%A{max}")) (org-columns))
  438. (get-char-property (point) 'org-columns-value-modified))))
  439. (should
  440. (equal
  441. "51.0"
  442. (org-test-with-temp-text
  443. "* H
  444. ** S1
  445. :PROPERTIES:
  446. :A: 60
  447. :END:
  448. ** S1
  449. :PROPERTIES:
  450. :A: 42
  451. :END:"
  452. (let ((org-columns-default-format "%A{mean}")) (org-columns))
  453. (get-char-property (point) 'org-columns-value-modified))))
  454. ;; {:min}, {:max} and {:mean} apply to time values.
  455. (should
  456. (equal
  457. "1:20"
  458. (org-test-with-temp-text
  459. "* H
  460. ** S1
  461. :PROPERTIES:
  462. :A: 4:40
  463. :END:
  464. ** S1
  465. :PROPERTIES:
  466. :A: 1:20
  467. :END:"
  468. (let ((org-columns-default-format "%A{:min}")) (org-columns))
  469. (get-char-property (point) 'org-columns-value-modified))))
  470. (should
  471. (equal
  472. "4:40"
  473. (org-test-with-temp-text
  474. "* H
  475. ** S1
  476. :PROPERTIES:
  477. :A: 4:40
  478. :END:
  479. ** S1
  480. :PROPERTIES:
  481. :A: 1:20
  482. :END:"
  483. (let ((org-columns-default-format "%A{:max}")) (org-columns))
  484. (get-char-property (point) 'org-columns-value-modified))))
  485. (should
  486. (equal
  487. "3:00"
  488. (org-test-with-temp-text
  489. "* H
  490. ** S1
  491. :PROPERTIES:
  492. :A: 4:40
  493. :END:
  494. ** S1
  495. :PROPERTIES:
  496. :A: 1:20
  497. :END:"
  498. (let ((org-columns-default-format "%A{:mean}")) (org-columns))
  499. (get-char-property (point) 'org-columns-value-modified))))
  500. ;; {@min}, {@max} and {@mean} apply to ages.
  501. (should
  502. (equal
  503. "0min"
  504. (org-test-at-time "<2014-03-04 Tue>"
  505. (org-test-with-temp-text
  506. "* H
  507. ** S1
  508. :PROPERTIES:
  509. :A: <2012-03-29 Thu>
  510. :END:
  511. ** S1
  512. :PROPERTIES:
  513. :A: <2014-03-04 Tue>
  514. :END:"
  515. (let ((org-columns-default-format "%A{@min}")) (org-columns))
  516. (get-char-property (point) 'org-columns-value-modified)))))
  517. (should
  518. (equal
  519. "2d"
  520. (org-test-at-time "<2014-03-04 Tue>"
  521. (org-test-with-temp-text
  522. "* H
  523. ** S1
  524. :PROPERTIES:
  525. :A: <2014-03-03 Mon>
  526. :END:
  527. ** S1
  528. :PROPERTIES:
  529. :A: <2014-03-02 Sun>
  530. :END:"
  531. (let ((org-columns-default-format "%A{@max}")) (org-columns))
  532. (get-char-property (point) 'org-columns-value-modified)))))
  533. (should
  534. (equal
  535. "1d 12h"
  536. (org-test-at-time "<2014-03-04 Tue>"
  537. (org-test-with-temp-text
  538. "* H
  539. ** S1
  540. :PROPERTIES:
  541. :A: <2014-03-03 Mon>
  542. :END:
  543. ** S1
  544. :PROPERTIES:
  545. :A: <2014-03-02 Sun>
  546. :END:"
  547. (let ((org-columns-default-format "%A{@mean}")) (org-columns))
  548. (get-char-property (point) 'org-columns-value-modified)))))
  549. ;; If a time value is expressed as a duration, return a duration.
  550. ;; If any of them follows H:MM:SS pattern, use it too. Also handle
  551. ;; combinations of duration and H:MM:SS patterns.
  552. (should
  553. (equal
  554. "3d 4:20"
  555. (org-test-with-temp-text
  556. "* H
  557. ** S1
  558. :PROPERTIES:
  559. :A: 3d 3h
  560. :END:
  561. ** S1
  562. :PROPERTIES:
  563. :A: 1:20
  564. :END:"
  565. (let ((org-columns-default-format "%A{:}")
  566. (org-duration-units '(("d" . 1440) ("h" . 60)))
  567. (org-duration-format '(("d" . nil) (special . h:mm))))
  568. (org-columns))
  569. (get-char-property (point) 'org-columns-value-modified))))
  570. (should
  571. (equal
  572. "6:00:10"
  573. (org-test-with-temp-text
  574. "* H
  575. ** S1
  576. :PROPERTIES:
  577. :A: 4:40:10
  578. :END:
  579. ** S1
  580. :PROPERTIES:
  581. :A: 1:20
  582. :END:"
  583. (let ((org-columns-default-format "%A{:}")) (org-columns))
  584. (get-char-property (point) 'org-columns-value-modified))))
  585. (should
  586. (equal
  587. "3d 4:20"
  588. (org-test-with-temp-text
  589. "* H
  590. ** S1
  591. :PROPERTIES:
  592. :A: 3d 3h
  593. :END:
  594. ** S1
  595. :PROPERTIES:
  596. :A: 0d 1:20
  597. :END:"
  598. (let ((org-columns-default-format "%A{:}")
  599. (org-duration-units '(("d" . 1440) ("h" . 60)))
  600. (org-duration-format '(("d" . nil) (special . h:mm))))
  601. (org-columns))
  602. (get-char-property (point) 'org-columns-value-modified))))
  603. ;; @min, @max and @mean also accept regular duration.
  604. (should
  605. (equal
  606. "1d 10h"
  607. (org-test-with-temp-text
  608. "* H
  609. ** S1
  610. :PROPERTIES:
  611. :A: 1d 10h 0min
  612. :END:
  613. ** S1
  614. :PROPERTIES:
  615. :A: 5d 3h
  616. :END:"
  617. (let ((org-columns-default-format "%A{@min}")) (org-columns))
  618. (get-char-property (point) 'org-columns-value-modified))))
  619. ;; {est+} gives a low-high estimate using mean and standard
  620. ;; deviation.
  621. (should
  622. (equal
  623. "3-17"
  624. (org-test-with-temp-text
  625. "* H
  626. ** S1
  627. :PROPERTIES:
  628. :A: 0-10
  629. :END:
  630. ** S1
  631. :PROPERTIES:
  632. :A: 0-10
  633. :END:"
  634. (let ((org-columns-default-format "%A{est+}")) (org-columns))
  635. (get-char-property (point) 'org-columns-value-modified))))
  636. ;; When using {est+} summary, a single number is understood as
  637. ;; a degenerate range.
  638. (should
  639. (equal
  640. "4-4"
  641. (org-test-with-temp-text
  642. "* H
  643. ** S1
  644. :PROPERTIES:
  645. :A: 4
  646. :END:
  647. "
  648. (let ((org-columns-default-format "%A{est+}")) (org-columns))
  649. (get-char-property (point) 'org-columns-value-modified))))
  650. ;; Allow custom summary types.
  651. (should
  652. (equal
  653. "1|2"
  654. (org-test-with-temp-text
  655. "* H
  656. ** S1
  657. :PROPERTIES:
  658. :A: 1
  659. :END:
  660. ** S1
  661. :PROPERTIES:
  662. :A: 2
  663. :END:"
  664. (let ((org-columns-summary-types
  665. '(("custom" . (lambda (s _) (mapconcat #'identity s "|")))))
  666. (org-columns-default-format "%A{custom}")) (org-columns))
  667. (get-char-property (point) 'org-columns-value-modified))))
  668. ;; Allow custom _collect_ for summary types.
  669. (should
  670. (equal
  671. "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. :A-OK: 1
  682. :END:"
  683. (let ((org-columns-summary-types
  684. '(("custom" org-columns--summary-sum
  685. (lambda (p)
  686. (if (equal "1" (org-entry-get nil (format "%s-OK" p)))
  687. (org-entry-get nil p)
  688. "")))))
  689. (org-columns-default-format "%A{custom}")) (org-columns))
  690. (get-char-property (point) 'org-columns-value-modified))))
  691. ;; Allow custom collect function to be used for different columns
  692. (should
  693. (equal
  694. '("2" "1")
  695. (org-test-with-temp-text
  696. "* H
  697. ** S1
  698. :PROPERTIES:
  699. :A: 1
  700. :B: 1
  701. :B-OK: 1
  702. :END:
  703. ** S1
  704. :PROPERTIES:
  705. :A: 2
  706. :B: 2
  707. :A-OK: 1
  708. :END:"
  709. (let ((org-columns-summary-types
  710. '(("custom" org-columns--summary-sum
  711. (lambda (p)
  712. (if (equal "1" (org-entry-get nil (format "%s-OK" p)))
  713. (org-entry-get nil p)
  714. "")))))
  715. (org-columns-default-format "%A{custom} %B{custom}")) (org-columns))
  716. (list (get-char-property (point) 'org-columns-value-modified)
  717. (get-char-property (1+ (point)) 'org-columns-value-modified)))))
  718. ;; Allow multiple summary types applied to the same property.
  719. (should
  720. (equal
  721. '("42" "99")
  722. (org-test-with-temp-text
  723. "* H
  724. ** S1
  725. :PROPERTIES:
  726. :A: 99
  727. :END:
  728. ** S1
  729. :PROPERTIES:
  730. :A: 42
  731. :END:"
  732. (let ((org-columns-default-format "%A{min} %A{max}")) (org-columns))
  733. (list (get-char-property (point) 'org-columns-value-modified)
  734. (get-char-property (1+ (point)) 'org-columns-value-modified)))))
  735. ;; Allow mixing both summarized and non-summarized columns for
  736. ;; a property. However, the first column takes precedence and
  737. ;; updates the value.
  738. (should
  739. (equal
  740. '("1000" "42")
  741. (org-test-with-temp-text
  742. "* H
  743. :PROPERTIES:
  744. :A: 1000
  745. :END:
  746. ** S1
  747. :PROPERTIES:
  748. :A: 99
  749. :END:
  750. ** S1
  751. :PROPERTIES:
  752. :A: 42
  753. :END:"
  754. (let ((org-columns-default-format "%A %A{min}")) (org-columns))
  755. (list (get-char-property (point) 'org-columns-value-modified)
  756. (get-char-property (1+ (point)) 'org-columns-value-modified)))))
  757. (should
  758. (equal
  759. '("42" "42")
  760. (org-test-with-temp-text
  761. "* H
  762. :PROPERTIES:
  763. :A: 1000
  764. :END:
  765. ** S1
  766. :PROPERTIES:
  767. :A: 99
  768. :END:
  769. ** S1
  770. :PROPERTIES:
  771. :A: 42
  772. :END:"
  773. (let ((org-columns-default-format "%A{min} %A")) (org-columns))
  774. (list (get-char-property (point) 'org-columns-value-modified)
  775. (get-char-property (1+ (point)) 'org-columns-value-modified))))))
  776. (ert-deftest test-org-colview/columns-new ()
  777. "Test `org-columns-new' specifications."
  778. ;; Insert new column at the left of the current one.
  779. (should
  780. (equal '("FOO" "ITEM")
  781. (org-test-with-temp-text "* H"
  782. (let ((org-columns-default-format "%ITEM")) (org-columns))
  783. (org-columns-new nil "FOO" "FOO" nil nil nil)
  784. (list (get-char-property (point) 'org-columns-key)
  785. (get-char-property (1+ (point)) 'org-columns-key)))))
  786. (should
  787. (equal '("ITEM" "FOO" "BAR")
  788. (org-test-with-temp-text "* H"
  789. (let ((org-columns-default-format "%ITEM %BAR")) (org-columns))
  790. (forward-char)
  791. (org-columns-new nil "FOO" "FOO" nil nil nil)
  792. (list (get-char-property (1- (point)) 'org-columns-key)
  793. (get-char-property (point) 'org-columns-key)
  794. (get-char-property (1+ (point)) 'org-columns-key)))))
  795. ;; Update #+COLUMNS keyword if needed.
  796. (should
  797. (equal "#+COLUMNS: %FOO %ITEM"
  798. (org-test-with-temp-text "#+COLUMNS: %ITEM\n<point>* H"
  799. (let ((org-columns-default-format "%ITEM")) (org-columns))
  800. (org-columns-new nil "FOO" "FOO" nil nil nil)
  801. (goto-char (point-min))
  802. (buffer-substring-no-properties (point) (line-end-position)))))
  803. (should
  804. (equal "#+COLUMNS: %ITEM %FOO %BAR"
  805. (org-test-with-temp-text "#+COLUMNS: %ITEM %BAR\n<point>* H"
  806. (let ((org-columns-default-format "%ITEM %BAR")) (org-columns))
  807. (forward-char)
  808. (org-columns-new nil "FOO" "FOO" nil nil nil)
  809. (goto-char (point-min))
  810. (buffer-substring-no-properties (point) (line-end-position)))))
  811. ;; Mind case when updating #+COLUMNS.
  812. (should
  813. (equal "#+COLUMNS: %ITEM %Foo %BAR"
  814. (org-test-with-temp-text "#+COLUMNS: %ITEM %BAR\n<point>* H"
  815. (let ((org-columns-default-format "%ITEM %BAR")) (org-columns))
  816. (forward-char)
  817. (org-columns-new nil "Foo" "Foo" nil nil nil)
  818. (goto-char (point-min))
  819. (buffer-substring-no-properties (point) (line-end-position)))))
  820. (should
  821. (equal "#+columns: %ITEM %Foo %BAR"
  822. (org-test-with-temp-text "#+columns: %ITEM %BAR\n<point>* H"
  823. (let ((org-columns-default-format "%ITEM %BAR")) (org-columns))
  824. (forward-char)
  825. (org-columns-new nil "Foo" "Foo" nil nil nil)
  826. (goto-char (point-min))
  827. (buffer-substring-no-properties (point) (line-end-position)))))
  828. ;; Also update :COLUMNS: properties.
  829. (should
  830. (equal "%FOO %ITEM"
  831. (org-test-with-temp-text "* H\n:PROPERTIES:\n:COLUMNS: %ITEM\n:END:"
  832. (let ((org-columns-default-format "%ITEM")) (org-columns))
  833. (org-columns-new nil "FOO" "FOO" nil nil nil)
  834. (org-entry-get nil "COLUMNS"))))
  835. ;; If no keyword nor any property is available, insert one.
  836. (should
  837. (string-match-p (regexp-quote "#+COLUMNS: %FOO %ITEM")
  838. (org-test-with-temp-text "* H"
  839. (let ((org-columns-default-format "%ITEM")) (org-columns))
  840. (org-columns-new nil "FOO" "FOO" nil nil nil)
  841. (buffer-string)))))
  842. (ert-deftest test-org-colview/columns-update ()
  843. "Test `org-columns-update' specifications."
  844. ;; Update display.
  845. (should
  846. (equal
  847. "12 |"
  848. (org-test-with-temp-text
  849. "* H
  850. :PROPERTIES:
  851. :A: 1
  852. :END:
  853. "
  854. (let ((org-columns-default-format "%5A")) (org-columns))
  855. (search-forward "1")
  856. (insert "2")
  857. (org-columns-update "A")
  858. (get-char-property (point-min) 'display))))
  859. ;; Update is case-insensitive.
  860. (should
  861. (equal
  862. "12 |"
  863. (org-test-with-temp-text
  864. "* H
  865. :PROPERTIES:
  866. :A: 1
  867. :END:
  868. "
  869. (let ((org-columns-default-format "%5A")) (org-columns))
  870. (search-forward "1")
  871. (insert "2")
  872. (org-columns-update "a")
  873. (get-char-property (point-min) 'display))))
  874. ;; Update stored values.
  875. (should
  876. (equal
  877. '("12" "12")
  878. (org-test-with-temp-text
  879. "* H
  880. :PROPERTIES:
  881. :A: 1
  882. :END:
  883. "
  884. (let ((org-columns-default-format "%5A")) (org-columns))
  885. (search-forward "1")
  886. (insert "2")
  887. (org-columns-update "A")
  888. (list (get-char-property (point-min) 'org-columns-value)
  889. (get-char-property (point-min) 'org-columns-value-modified)))))
  890. ;; When multiple columns are using the same property, value is
  891. ;; updated according to the specifications of the first one.
  892. (should
  893. (equal
  894. "2"
  895. (org-test-with-temp-text
  896. "* H
  897. :PROPERTIES:
  898. :A: 1
  899. :END:
  900. ** S
  901. :PROPERTIES:
  902. :A: 2
  903. :END:"
  904. (let ((org-columns-default-format "%A{min} %A")) (org-columns))
  905. (org-columns-update "A")
  906. (org-entry-get nil "A"))))
  907. (should
  908. (equal
  909. "1"
  910. (org-test-with-temp-text
  911. "* H
  912. :PROPERTIES:
  913. :A: 1
  914. :END:
  915. ** S
  916. :PROPERTIES:
  917. :A: 2
  918. :END:"
  919. (let ((org-columns-default-format "%A %A{min}")) (org-columns))
  920. (org-columns-update "A")
  921. (org-entry-get nil "A"))))
  922. ;; Ensure modifications propagate in upper levels even when multiple
  923. ;; summary types apply to the same property.
  924. (should
  925. (equal
  926. '("1" "22")
  927. (org-test-with-temp-text
  928. "* H
  929. ** S1
  930. :PROPERTIES:
  931. :A: 1
  932. :END:
  933. ** S2
  934. :PROPERTIES:
  935. :A: <point>2
  936. :END:"
  937. (save-excursion
  938. (goto-char (point-min))
  939. (let ((org-columns-default-format "%A{min} %A{max}")) (org-columns)))
  940. (insert "2")
  941. (org-columns-update "A")
  942. (list (get-char-property 1 'org-columns-value)
  943. (get-char-property 2 'org-columns-value-modified)))))
  944. ;; Ensure additional processing is done (e.g., ellipses, special
  945. ;; keywords fontification...).
  946. (should
  947. (equal
  948. "ve.. |"
  949. (org-test-with-temp-text
  950. "* H
  951. :PROPERTIES:
  952. :A: text
  953. :END:
  954. "
  955. (let ((org-columns-default-format "%4A")
  956. (org-columns-ellipses ".."))
  957. (org-columns))
  958. (search-forward ":A: ")
  959. (insert "very long ")
  960. (org-columns-update "A")
  961. (get-char-property (point-min) 'display))))
  962. ;; Values obtained from inline tasks are at the same level as those
  963. ;; obtained from children of the current node.
  964. (when (featurep 'org-inlinetask)
  965. (should
  966. (equal
  967. "2"
  968. (org-test-with-temp-text
  969. "* H
  970. *************** Inline task
  971. :PROPERTIES:
  972. :A: 2
  973. :END:
  974. *************** END
  975. ** Children
  976. :PROPERTIES:
  977. :A: 3
  978. :END:
  979. "
  980. (let ((org-columns-default-format "%A{min}")
  981. (org-columns-ellipses "..")
  982. (org-inlinetask-min-level 15))
  983. (org-element-update-syntax)
  984. (org-columns))
  985. (get-char-property (point-min) 'org-columns-value)))))
  986. ;; Handle `org-columns-modify-value-for-display-function', even with
  987. ;; multiple titles for the same property.
  988. (should
  989. (equal '("foo" "bar")
  990. (org-test-with-temp-text "* H"
  991. (let ((org-columns-default-format "%ITEM %ITEM(Name)")
  992. (org-columns-modify-value-for-display-function
  993. (lambda (title _value)
  994. (pcase title ("ITEM" "foo") ("Name" "bar") (_ "baz")))))
  995. (org-columns))
  996. (list (get-char-property 1 'org-columns-value-modified)
  997. (get-char-property 2 'org-columns-value-modified))))))
  998. (ert-deftest test-org-colview/columns-move-left ()
  999. "Test `org-columns-move-left' specifications."
  1000. ;; Error when trying to move the left-most column.
  1001. (should-error
  1002. (org-test-with-temp-text "* H"
  1003. (let ((org-columns-default-format "%ITEM")) (org-columns))
  1004. (org-columns-move-left)))
  1005. ;; Otherwise, move column to left and update display.
  1006. (should
  1007. (equal '("2" "1")
  1008. (org-test-with-temp-text "* H\n:PROPERTIES:\n:A: 1\n:B: 2\n:END:"
  1009. (let ((org-columns-default-format "%A %B")) (org-columns))
  1010. (forward-char)
  1011. (org-columns-move-left)
  1012. (list (get-char-property (point) 'org-columns-value)
  1013. (get-char-property (1+ (point)) 'org-columns-value)))))
  1014. ;; Handle multiple columns with the same property.
  1015. (should
  1016. (equal '("2" "1")
  1017. (org-test-with-temp-text
  1018. "* H
  1019. ** S1
  1020. :PROPERTIES:
  1021. :A: 1
  1022. :END:
  1023. ** S1
  1024. :PROPERTIES:
  1025. :A: 2
  1026. :END:"
  1027. (let ((org-columns-default-format "%ITEM %A{min} %A{max}"))
  1028. (org-columns))
  1029. (forward-char 2)
  1030. (org-columns-move-left)
  1031. (list (get-char-property (point) 'org-columns-value)
  1032. (get-char-property (1+ (point)) 'org-columns-value)))))
  1033. ;; Special case: do not update values even if move entails changing
  1034. ;; them.
  1035. (should
  1036. (equal "1"
  1037. (org-test-with-temp-text
  1038. "* H
  1039. :PROPERTIES:
  1040. :A: 1
  1041. :END:
  1042. ** S1
  1043. :PROPERTIES:
  1044. :A: 99
  1045. :END:"
  1046. (let ((org-columns-default-format "%A %A{max}"))
  1047. (org-columns))
  1048. (forward-char)
  1049. (org-columns-move-left)
  1050. ;; Since the first column matching a given property
  1051. ;; determines how a value is computed, the following
  1052. ;; should return "99" instead. However, this behavior is
  1053. ;; in practice surprising so we just ignore the value
  1054. ;; change. It can be computed later.
  1055. (org-entry-get (point) "A")))))
  1056. (ert-deftest test-org-colview/columns-move-right ()
  1057. "Test `org-columns-move-right' specifications."
  1058. ;; Error when trying to move the right-most column.
  1059. (should-error
  1060. (org-test-with-temp-text "* H"
  1061. (let ((org-columns-default-format "%ITEM")) (org-columns))
  1062. (org-columns-move-right)))
  1063. ;; Otherwise, move column to left and update display.
  1064. (should
  1065. (equal '("2" "1")
  1066. (org-test-with-temp-text "* H\n:PROPERTIES:\n:A: 1\n:B: 2\n:END:"
  1067. (let ((org-columns-default-format "%A %B")) (org-columns))
  1068. (org-columns-move-right)
  1069. (list (get-char-property (1- (point)) 'org-columns-value)
  1070. (get-char-property (point) 'org-columns-value)))))
  1071. ;; Handle multiple columns with the same property.
  1072. (should
  1073. (equal '("2" "1")
  1074. (org-test-with-temp-text
  1075. "* H
  1076. ** S1
  1077. :PROPERTIES:
  1078. :A: 1
  1079. :END:
  1080. ** S1
  1081. :PROPERTIES:
  1082. :A: 2
  1083. :END:"
  1084. (let ((org-columns-default-format "%ITEM %A{min} %A{max}"))
  1085. (org-columns))
  1086. (forward-char)
  1087. (org-columns-move-right)
  1088. (list (get-char-property (1- (point)) 'org-columns-value)
  1089. (get-char-property (point) 'org-columns-value)))))
  1090. ;; Special case: do not update values even if move entails changing
  1091. ;; them.
  1092. (should
  1093. (equal "1"
  1094. (org-test-with-temp-text
  1095. "* H
  1096. :PROPERTIES:
  1097. :A: 1
  1098. :END:
  1099. ** S1
  1100. :PROPERTIES:
  1101. :A: 99
  1102. :END:"
  1103. (let ((org-columns-default-format "%A %A{max}"))
  1104. (org-columns))
  1105. (org-columns-move-right)
  1106. ;; See `test-org-colview/columns-move-left' for an
  1107. ;; explanation.
  1108. (org-entry-get (point) "A")))))
  1109. (ert-deftest test-org-colview/columns-next-allowed-value ()
  1110. "Test `org-columns-next-allowed-value' specifications."
  1111. ;; Cannot shift "ITEM" property.
  1112. (should-error
  1113. (org-test-with-temp-text "* H"
  1114. (let ((org-columns-default-format "%ITEM")) (org-columns))
  1115. (org-columns-next-allowed-value)))
  1116. ;; Throw an error when allowed values are not defined.
  1117. (should-error
  1118. (org-test-with-temp-text "* H\n:PROPERTIES:\n:A: 1\n:END:"
  1119. (let ((org-columns-default-format "%A")) (org-columns))
  1120. (org-columns-next-allowed-value)))
  1121. ;; Throw an error when there's only one value to select.
  1122. (should-error
  1123. (org-test-with-temp-text "* H\n:PROPERTIES:\n:A: 1\n:A_ALL: 1\n:END:"
  1124. (let ((org-columns-default-format "%A")) (org-columns))
  1125. (org-columns-next-allowed-value)))
  1126. ;; By default select the next allowed value. Where there is no more
  1127. ;; value, start again from first possible one.
  1128. (should
  1129. (equal "2"
  1130. (org-test-with-temp-text
  1131. "* H\n:PROPERTIES:\n:A: 1\n:A_ALL: 1 2 3\n:END:"
  1132. (let ((org-columns-default-format "%A")) (org-columns))
  1133. (org-columns-next-allowed-value)
  1134. (org-entry-get (point) "A"))))
  1135. (should
  1136. (equal "3"
  1137. (org-test-with-temp-text
  1138. "* H\n:PROPERTIES:\n:A: 2\n:A_ALL: 1 2 3\n:END:"
  1139. (let ((org-columns-default-format "%A")) (org-columns))
  1140. (org-columns-next-allowed-value)
  1141. (org-entry-get (point) "A"))))
  1142. (should
  1143. (equal "1"
  1144. (org-test-with-temp-text
  1145. "* H\n:PROPERTIES:\n:A: 3\n:A_ALL: 1 2 3\n:END:"
  1146. (let ((org-columns-default-format "%A")) (org-columns))
  1147. (org-columns-next-allowed-value)
  1148. (org-entry-get (point) "A"))))
  1149. ;; PREVIOUS argument moves backward.
  1150. (should
  1151. (equal "1"
  1152. (org-test-with-temp-text
  1153. "* H\n:PROPERTIES:\n:A: 2\n:A_ALL: 1 2 3\n:END:"
  1154. (let ((org-columns-default-format "%A")) (org-columns))
  1155. (org-columns-next-allowed-value 'previous)
  1156. (org-entry-get (point) "A"))))
  1157. (should
  1158. (equal "2"
  1159. (org-test-with-temp-text
  1160. "* H\n:PROPERTIES:\n:A: 3\n:A_ALL: 1 2 3\n:END:"
  1161. (let ((org-columns-default-format "%A")) (org-columns))
  1162. (org-columns-next-allowed-value 'previous)
  1163. (org-entry-get (point) "A"))))
  1164. (should
  1165. (equal "3"
  1166. (org-test-with-temp-text
  1167. "* H\n:PROPERTIES:\n:A: 1\n:A_ALL: 1 2 3\n:END:"
  1168. (let ((org-columns-default-format "%A")) (org-columns))
  1169. (org-columns-next-allowed-value 'previous)
  1170. (org-entry-get (point) "A"))))
  1171. ;; Select Nth element with optional argument NTH.
  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 nil 1)
  1178. (org-entry-get (point) "A"))))
  1179. ;; If NTH is negative, go backwards, 0 being the last one and -1 the
  1180. ;; penultimate.
  1181. (should
  1182. (equal "3"
  1183. (org-test-with-temp-text
  1184. "* H\n:PROPERTIES:\n:A: 2\n:A_ALL: 1 2 3\n:END:"
  1185. (let ((org-columns-default-format "%A")) (org-columns))
  1186. (org-columns-next-allowed-value nil 0)
  1187. (org-entry-get (point) "A"))))
  1188. (should
  1189. (equal "2"
  1190. (org-test-with-temp-text
  1191. "* H\n:PROPERTIES:\n:A: 2\n:A_ALL: 1 2 3\n:END:"
  1192. (let ((org-columns-default-format "%A")) (org-columns))
  1193. (org-columns-next-allowed-value nil -1)
  1194. (org-entry-get (point) "A"))))
  1195. ;; Throw an error if NTH is greater than the number of allowed
  1196. ;; values.
  1197. (should-error
  1198. (org-test-with-temp-text
  1199. "* H\n:PROPERTIES:\n:A: 2\n:A_ALL: 1 2 3\n:END:"
  1200. (let ((org-columns-default-format "%A")) (org-columns))
  1201. (org-columns-next-allowed-value nil 4)
  1202. (org-entry-get (point) "A")))
  1203. ;; Pathological case: when shifting the value alters the current
  1204. ;; heading, make sure all columns are still at their correct
  1205. ;; location.
  1206. (should
  1207. (equal '("H" "" "" "" "TODO")
  1208. (let ((org-todo-keywords '((sequence "TODO" "DONE"))))
  1209. (org-test-with-temp-text "* H"
  1210. (let ((org-columns-default-format "%ITEM %A %B %C %TODO"))
  1211. (org-columns)
  1212. (forward-char 4)
  1213. (org-columns-next-allowed-value)
  1214. (list (get-char-property (- (point) 4) 'org-columns-value)
  1215. (get-char-property (- (point) 3) 'org-columns-value)
  1216. (get-char-property (- (point) 2) 'org-columns-value)
  1217. (get-char-property (- (point) 1) 'org-columns-value)
  1218. (get-char-property (point) 'org-columns-value)))))))
  1219. (should
  1220. (equal '("H" "VERYLONGTODO")
  1221. (let ((org-todo-keywords '((sequence "TODO" "VERYLONGTODO"))))
  1222. (org-test-with-temp-text "* TODO H"
  1223. (let ((org-columns-default-format "%ITEM %TODO"))
  1224. (org-columns)
  1225. (forward-char)
  1226. (org-columns-next-allowed-value)
  1227. (list (get-char-property (- (point) 1) 'org-columns-value)
  1228. (get-char-property (point) 'org-columns-value))))))))
  1229. ;;; Dynamic block
  1230. (ert-deftest test-org-colview/dblock ()
  1231. "Test the column view table."
  1232. (should
  1233. (equal
  1234. "#+BEGIN: columnview
  1235. | ITEM |
  1236. |------|
  1237. | H |
  1238. #+END:"
  1239. (org-test-with-temp-text
  1240. "* H\n<point>#+BEGIN: columnview\n#+END:"
  1241. (let ((org-columns-default-format "%ITEM")) (org-update-dblock))
  1242. (buffer-substring-no-properties (point) (point-max)))))
  1243. (should
  1244. (equal
  1245. "#+BEGIN: columnview
  1246. | ITEM | A |
  1247. |------+---|
  1248. | H | 1 |
  1249. #+END:"
  1250. (org-test-with-temp-text
  1251. "* H\n:PROPERTIES:\n:A: 1\n:END:\n<point>#+BEGIN: columnview\n#+END:"
  1252. (let ((org-columns-default-format "%ITEM %A")) (org-update-dblock))
  1253. (buffer-substring-no-properties (point) (point-max)))))
  1254. ;; Properties are case insensitive.
  1255. (should
  1256. (equal
  1257. "#+BEGIN: columnview
  1258. | a |
  1259. |---|
  1260. | 1 |
  1261. #+END:"
  1262. (org-test-with-temp-text
  1263. "* H\n:PROPERTIES:\n:A: 1\n:END:\n<point>#+BEGIN: columnview\n#+END:"
  1264. (let ((org-columns-default-format "%a")) (org-update-dblock))
  1265. (buffer-substring-no-properties (point) (point-max)))))
  1266. ;; Test titles given to columns.
  1267. (should
  1268. (equal
  1269. "#+BEGIN: columnview
  1270. | Name | Prop |
  1271. |------+------|
  1272. | H | 1 |
  1273. #+END:"
  1274. (org-test-with-temp-text
  1275. "* H\n:PROPERTIES:\n:A: 1\n:END:\n<point>#+BEGIN: columnview\n#+END:"
  1276. (let ((org-columns-default-format "%ITEM(Name) %A(Prop)"))
  1277. (org-update-dblock))
  1278. (buffer-substring-no-properties (point) (point-max)))))
  1279. ;; Test `:id' parameter
  1280. (should
  1281. (equal
  1282. "#+BEGIN: columnview :id local
  1283. | ITEM |
  1284. |------|
  1285. | H1 |
  1286. | H1.1 |
  1287. #+END:
  1288. "
  1289. (org-test-with-temp-text
  1290. "* H1\n<point>#+BEGIN: columnview :id local\n#+END:\n** H1.1\n* H2"
  1291. (let ((org-columns-default-format "%ITEM")) (org-update-dblock))
  1292. (buffer-substring-no-properties (point) (outline-next-heading)))))
  1293. (should
  1294. (equal
  1295. "#+BEGIN: columnview :id global
  1296. | ITEM |
  1297. |------|
  1298. | H1 |
  1299. | H1.1 |
  1300. | H2 |
  1301. #+END:
  1302. "
  1303. (org-test-with-temp-text
  1304. "\n* H1\n<point>#+BEGIN: columnview :id global\n#+END:\n** H1.1\n* H2"
  1305. (let ((org-columns-default-format "%ITEM")) (org-update-dblock))
  1306. (buffer-substring-no-properties (point) (outline-next-heading)))))
  1307. ;; Test `:hlines' parameter.
  1308. (should
  1309. (equal
  1310. "#+BEGIN: columnview :hlines t :id global
  1311. | ITEM |
  1312. |------|
  1313. | H |
  1314. |------|
  1315. | H2 |
  1316. |------|
  1317. | H2.1 |
  1318. #+END:\n"
  1319. (org-test-with-temp-text
  1320. "
  1321. * H
  1322. <point>#+BEGIN: columnview :hlines t :id global
  1323. #+END:
  1324. * H2
  1325. ** H2.1"
  1326. (let ((org-columns-default-format "%ITEM")) (org-update-dblock))
  1327. (buffer-substring-no-properties (point) (outline-next-heading)))))
  1328. (should
  1329. (equal
  1330. "#+BEGIN: columnview :hlines 1 :id global
  1331. | ITEM |
  1332. |------|
  1333. | H |
  1334. |------|
  1335. | H2 |
  1336. | H2.1 |
  1337. #+END:\n"
  1338. (org-test-with-temp-text
  1339. "
  1340. * H
  1341. <point>#+BEGIN: columnview :hlines 1 :id global
  1342. #+END:
  1343. * H2
  1344. ** H2.1"
  1345. (let ((org-columns-default-format "%ITEM")) (org-update-dblock))
  1346. (buffer-substring-no-properties (point) (outline-next-heading)))))
  1347. (should
  1348. (equal
  1349. "#+BEGIN: columnview :hlines 1 :id \"id\"
  1350. | ITEM |
  1351. |------|
  1352. | H2 |
  1353. | H2.1 |
  1354. #+END:
  1355. "
  1356. (org-test-with-temp-text
  1357. "
  1358. * H
  1359. <point>#+BEGIN: columnview :hlines 1 :id \"id\"
  1360. #+END:
  1361. * H2
  1362. :PROPERTIES:
  1363. :ID: id
  1364. :END:
  1365. ** H2.1"
  1366. (let ((org-columns-default-format "%ITEM")) (org-update-dblock))
  1367. (buffer-substring-no-properties (point) (outline-next-heading)))))
  1368. (should
  1369. (equal
  1370. "#+BEGIN: columnview :hlines 1 :id id
  1371. | ITEM |
  1372. |------|
  1373. | H2 |
  1374. | H2.1 |
  1375. #+END:
  1376. "
  1377. (org-test-with-temp-text
  1378. "
  1379. * H
  1380. <point>#+BEGIN: columnview :hlines 1 :id id
  1381. #+END:
  1382. * H2
  1383. :PROPERTIES:
  1384. :ID: id
  1385. :END:
  1386. ** H2.1"
  1387. (let ((org-columns-default-format "%ITEM")) (org-update-dblock))
  1388. (buffer-substring-no-properties (point) (outline-next-heading)))))
  1389. ;; Test `:indent' parameter.
  1390. (should
  1391. (equal
  1392. "#+BEGIN: columnview :indent t
  1393. | ITEM |
  1394. |----------|
  1395. | H1 |
  1396. | \\_ H1.1 |
  1397. #+END:
  1398. "
  1399. (org-test-with-temp-text
  1400. "* H1\n<point>#+BEGIN: columnview :indent t\n#+END:\n** H1.1"
  1401. (let ((org-columns-default-format "%ITEM")) (org-update-dblock))
  1402. (buffer-substring-no-properties (point) (outline-next-heading)))))
  1403. (should
  1404. (equal
  1405. "#+BEGIN: columnview :indent t
  1406. | Prop | Name |
  1407. |------+----------|
  1408. | | H1 |
  1409. | | \\_ H1.1 |
  1410. #+END:
  1411. "
  1412. (org-test-with-temp-text
  1413. "* H1\n<point>#+BEGIN: columnview :indent t\n#+END:\n** H1.1"
  1414. (let ((org-columns-default-format "%A(Prop) %ITEM(Name)"))
  1415. (org-update-dblock))
  1416. (buffer-substring-no-properties (point) (outline-next-heading)))))
  1417. ;; Test `:vlines' parameter.
  1418. (should
  1419. (equal
  1420. "#+BEGIN: columnview :vlines t
  1421. | | ITEM | A |
  1422. |---+------+----|
  1423. | | H | 1 |
  1424. | / | <> | <> |
  1425. #+END:"
  1426. (org-test-with-temp-text
  1427. "* H\n:PROPERTIES:\n:A: 1\n:END:\n<point>#+BEGIN: columnview :vlines t\n#+END:"
  1428. (let ((org-columns-default-format "%ITEM %A")) (org-update-dblock))
  1429. (buffer-substring-no-properties (point) (point-max)))))
  1430. ;; Test `:skip-empty-rows' parameter.
  1431. (should
  1432. (equal
  1433. "#+BEGIN: columnview :skip-empty-rows t
  1434. | ITEM | A |
  1435. |------+---|
  1436. | H1.1 | 1 |
  1437. #+END:
  1438. "
  1439. (org-test-with-temp-text
  1440. "
  1441. * H1
  1442. <point>#+BEGIN: columnview :skip-empty-rows t
  1443. #+END:
  1444. ** H1.1
  1445. :PROPERTIES:
  1446. :A: 1
  1447. :END:"
  1448. (let ((org-columns-default-format "%ITEM %A")) (org-update-dblock))
  1449. (buffer-substring-no-properties (point) (outline-next-heading)))))
  1450. ;; Test `:exclude-tags' parameter.
  1451. (should
  1452. (equal
  1453. "#+BEGIN: columnview :exclude-tags (\"excludeme\")
  1454. | ITEM | A |
  1455. |------+---|
  1456. | H1 | |
  1457. #+END:
  1458. "
  1459. (org-test-with-temp-text
  1460. "
  1461. * H1
  1462. <point>#+BEGIN: columnview :exclude-tags (\"excludeme\")
  1463. #+END:
  1464. ** H1.1 :excludeme:
  1465. :PROPERTIES:
  1466. :A: 1
  1467. :END:"
  1468. (let ((org-columns-default-format "%ITEM %A")) (org-update-dblock))
  1469. (buffer-substring-no-properties (point) (outline-next-heading)))))
  1470. ;; Test `:format' parameter.
  1471. (should
  1472. (equal
  1473. "#+BEGIN: columnview :format \"%ITEM(Name)\"
  1474. | Name |
  1475. |------|
  1476. | H |
  1477. #+END:"
  1478. (org-test-with-temp-text
  1479. "* H\n<point>#+BEGIN: columnview :format \"%ITEM(Name)\"\n#+END:"
  1480. (let ((org-columns-default-format "%ITEM")) (org-update-dblock))
  1481. (buffer-substring-no-properties (point) (point-max)))))
  1482. ;; When inserting ITEM values, make sure to clean sensitive
  1483. ;; contents, like unique targets or forbidden inline src-blocks.
  1484. (should
  1485. (equal
  1486. "#+BEGIN: columnview
  1487. | ITEM |
  1488. |------|
  1489. | H 1 |
  1490. #+END:"
  1491. (org-test-with-temp-text
  1492. "* H <<target>> 1\n<point>#+BEGIN: columnview\n#+END:"
  1493. (let ((org-columns-default-format "%ITEM")) (org-update-dblock))
  1494. (buffer-substring-no-properties (point) (point-max)))))
  1495. (should
  1496. (equal
  1497. "#+BEGIN: columnview
  1498. | ITEM |
  1499. |------|
  1500. | H 1 |
  1501. #+END:"
  1502. (org-test-with-temp-text
  1503. "* H src_emacs-lisp{(+ 1 1)} 1\n<point>#+BEGIN: columnview\n#+END:"
  1504. (let ((org-columns-default-format "%ITEM")) (org-update-dblock))
  1505. (buffer-substring-no-properties (point) (point-max)))))
  1506. ;; Active time stamps are displayed as inactive.
  1507. (should
  1508. (equal
  1509. "#+BEGIN: columnview
  1510. | ITEM | d | s | t |
  1511. |------+------------------+------------------+------------------|
  1512. | H | [2020-05-14 Thu] | [2020-05-11 Mon] | [2020-06-10 Wed] |
  1513. #+END:"
  1514. (org-test-with-temp-text
  1515. "* H
  1516. SCHEDULED: <2020-05-11 Mon> DEADLINE: <2020-05-14 Thu>
  1517. <2020-06-10 Wed>
  1518. <point>#+BEGIN: columnview\n#+END:"
  1519. (let ((org-columns-default-format
  1520. "%ITEM %DEADLINE(d) %SCHEDULED(s) %TIMESTAMP(t)"))
  1521. (org-update-dblock))
  1522. (buffer-substring-no-properties (point) (point-max))))))
  1523. (provide 'test-org-colview)
  1524. ;;; test-org-colview.el ends here