Sync with Org git commit 374c56b.
[bpt/emacs.git] / lisp / org / org-list.el
CommitLineData
47ffc456
CD
1;;; org-list.el --- Plain lists for Org-mode
2;;
b73f1974 3;; Copyright (C) 2004-2012 Free Software Foundation, Inc.
47ffc456
CD
4;;
5;; Author: Carsten Dominik <carsten at orgmode dot org>
e66ba1df 6;; Bastien Guerry <bzg AT gnu DOT org>
47ffc456
CD
7;; Keywords: outlines, hypermedia, calendar, wp
8;; Homepage: http://orgmode.org
47ffc456
CD
9;;
10;; This file is part of GNU Emacs.
11;;
12;; GNU Emacs is free software: you can redistribute it and/or modify
13;; it under the terms of the GNU General Public License as published by
14;; the Free Software Foundation, either version 3 of the License, or
15;; (at your option) any later version.
16
17;; GNU Emacs is distributed in the hope that it will be useful,
18;; but WITHOUT ANY WARRANTY; without even the implied warranty of
33306645 19;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
47ffc456
CD
20;; GNU General Public License for more details.
21
22;; You should have received a copy of the GNU General Public License
23;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
25;;
26;;; Commentary:
27
28;; This file contains the code dealing with plain lists in Org-mode.
29
e66ba1df
BG
30;; The core concept behind lists is their structure. A structure is
31;; a snapshot of the list, in the shape of a data tree (see
32;; `org-list-struct').
3ab2c837
BG
33
34;; Once the list structure is stored, it is possible to make changes
e66ba1df
BG
35;; on it that will be mirrored to the real list or to get information
36;; about the list, using accessors and methods provided in the
37;; library. Most of them require the use of one or two helper
38;; functions, namely `org-list-parents-alist' and
39;; `org-list-prevs-alist'.
3ab2c837
BG
40
41;; Structure is eventually applied to the buffer with
42;; `org-list-write-struct'. This function repairs (bullets,
e66ba1df
BG
43;; indentation, checkboxes) the list in the process. It should be
44;; called near the end of any function working on structures.
3ab2c837
BG
45
46;; Thus, a function applying to lists should usually follow this
47;; template:
48
49;; 1. Verify point is in a list and grab item beginning (with the same
50;; function `org-in-item-p'). If the function requires the cursor
e66ba1df
BG
51;; to be at item's bullet, `org-at-item-p' is more selective. It
52;; is also possible to move point to the closest item with
53;; `org-list-search-backward', or `org-list-search-forward',
54;; applied to the function `org-item-beginning-re'.
3ab2c837
BG
55
56;; 2. Get list structure with `org-list-struct'.
57
58;; 3. Compute one, or both, helper functions,
59;; (`org-list-parents-alist', `org-list-prevs-alist') depending on
60;; needed accessors.
61
62;; 4. Proceed with the modifications, using methods and accessors.
63
64;; 5. Verify and apply structure to buffer, using
e66ba1df 65;; `org-list-write-struct'.
3ab2c837 66
e66ba1df
BG
67;; 6. If changes made to the list might have modified check-boxes,
68;; call `org-update-checkbox-count-maybe'.
69
70;; Computing a structure can be a costly operation on huge lists (a
71;; few thousand lines long). Thus, code should follow the rule:
c80e3b4a 72;; "collect once, use many". As a corollary, it is usually a bad idea
3ab2c837 73;; to use directly an interactive function inside the code, as those,
27e428e7 74;; being independent entities, read the whole list structure another
3ab2c837
BG
75;; time.
76
47ffc456
CD
77;;; Code:
78
40a8bdf6 79(eval-when-compile
86fbb8ca 80 (require 'cl))
47ffc456
CD
81(require 'org-macs)
82(require 'org-compat)
83
47ffc456 84(defvar org-M-RET-may-split-line)
3ab2c837
BG
85(defvar org-auto-align-tags)
86(defvar org-blank-before-new-entry)
87(defvar org-clock-string)
88(defvar org-closed-string)
89(defvar org-deadline-string)
90(defvar org-description-max-indent)
91(defvar org-drawers)
c8d0cf5c 92(defvar org-odd-levels-only)
3ab2c837 93(defvar org-scheduled-string)
afe98dfa
CD
94(defvar org-ts-regexp)
95(defvar org-ts-regexp-both)
47ffc456 96
3ab2c837
BG
97(declare-function org-at-heading-p "org" (&optional ignored))
98(declare-function org-before-first-heading-p "org" ())
3ab2c837 99(declare-function org-back-to-heading "org" (&optional invisible-ok))
0bd48b37 100(declare-function org-combine-plists "org" (&rest plists))
3ab2c837
BG
101(declare-function org-count "org" (cl-item cl-seq))
102(declare-function org-current-level "org" ())
f1eee0b6
GM
103(declare-function org-entry-get "org"
104 (pom property &optional inherit literal-nil))
3ab2c837
BG
105(declare-function org-fix-tags-on-the-fly "org" ())
106(declare-function org-get-indentation "org" (&optional line))
107(declare-function org-icompleting-read "org" (&rest args))
108(declare-function org-in-block-p "org" (names))
109(declare-function org-in-regexp "org" (re &optional nlines visually))
110(declare-function org-inlinetask-goto-beginning "org-inlinetask" ())
111(declare-function org-inlinetask-goto-end "org-inlinetask" ())
112(declare-function org-inlinetask-in-task-p "org-inlinetask" ())
113(declare-function org-inlinetask-outline-regexp "org-inlinetask" ())
114(declare-function org-level-increment "org" ())
c8d0cf5c 115(declare-function org-narrow-to-subtree "org" ())
e66ba1df 116(declare-function org-at-heading-p "org" (&optional invisible-ok))
3ab2c837
BG
117(declare-function org-previous-line-empty-p "org" ())
118(declare-function org-remove-if "org" (predicate seq))
119(declare-function org-reduced-level "org" (L))
c8d0cf5c 120(declare-function org-show-subtree "org" ())
afe98dfa 121(declare-function org-time-string-to-seconds "org" (s))
3ab2c837
BG
122(declare-function org-timer-hms-to-secs "org-timer" (hms))
123(declare-function org-timer-item "org-timer" (&optional arg))
124(declare-function org-trim "org" (s))
125(declare-function org-uniquify "org" (list))
126(declare-function outline-invisible-p "outline" (&optional pos))
127(declare-function outline-flag-region "outline" (from to flag))
128(declare-function outline-next-heading "outline" ())
129(declare-function outline-previous-heading "outline" ())
130
e66ba1df
BG
131
132\f
3ab2c837 133;;; Configuration variables
47ffc456
CD
134
135(defgroup org-plain-lists nil
136 "Options concerning plain lists in Org-mode."
137 :tag "Org Plain lists"
138 :group 'org-structure)
139
c8d0cf5c
CD
140(defcustom org-cycle-include-plain-lists t
141 "When t, make TAB cycle visibility on plain list items.
c8d0cf5c
CD
142Cycling plain lists works only when the cursor is on a plain list
143item. When the cursor is on an outline heading, plain lists are
144treated as text. This is the most stable way of handling this,
145which is why it is the default.
146
147When this is the symbol `integrate', then during cycling, plain
148list items will *temporarily* be interpreted as outline headlines
149with a level given by 1000+i where i is the indentation of the
150bullet. This setting can lead to strange effects when switching
151visibility to `children', because the first \"child\" in a
152subtree decides what children should be listed. If that first
153\"child\" is a plain list item with an implied large level
154number, all true children and grand children of the outline
155heading will be exposed in a children' view."
47ffc456 156 :group 'org-plain-lists
c8d0cf5c
CD
157 :type '(choice
158 (const :tag "Never" nil)
159 (const :tag "With cursor in plain list (recommended)" t)
160 (const :tag "As children of outline headings" integrate)))
161
162(defcustom org-list-demote-modify-bullet nil
163 "Default bullet type installed when demoting an item.
164This is an association list, for each bullet type, this alist will point
86fbb8ca
CD
165to the bullet that should be used when this item is demoted.
166For example,
167
168 (setq org-list-demote-modify-bullet
169 '((\"+\" . \"-\") (\"-\" . \"+\") (\"*\" . \"+\")))
170
171will make
172
173 + Movies
174 + Silence of the Lambs
175 + My Cousin Vinny
176 + Books
177 + The Hunt for Red October
178 + The Road to Omaha
179
180into
181
182 + Movies
183 - Silence of the Lambs
184 - My Cousin Vinny
185 + Books
186 - The Hunt for Red October
187 - The Road to Omaha"
c8d0cf5c
CD
188 :group 'org-plain-lists
189 :type '(repeat
190 (cons
191 (choice :tag "If the current bullet is "
192 (const "-")
193 (const "+")
194 (const "*")
195 (const "1.")
196 (const "1)"))
197 (choice :tag "demotion will change it to"
198 (const "-")
199 (const "+")
200 (const "*")
201 (const "1.")
202 (const "1)")))))
47ffc456
CD
203
204(defcustom org-plain-list-ordered-item-terminator t
205 "The character that makes a line with leading number an ordered list item.
3ab2c837 206Valid values are ?. and ?\). To get both terminators, use t."
47ffc456
CD
207 :group 'org-plain-lists
208 :type '(choice (const :tag "dot like in \"2.\"" ?.)
209 (const :tag "paren like in \"2)\"" ?\))
153ae947 210 (const :tag "both" t)))
47ffc456 211
3ab2c837
BG
212(defcustom org-alphabetical-lists nil
213 "Non-nil means single character alphabetical bullets are allowed.
214Both uppercase and lowercase are handled. Lists with more than
21526 items will fallback to standard numbering. Alphabetical
216counters like \"[@c]\" will be recognized."
217 :group 'org-plain-lists
372d7b21 218 :version "24.1"
3ab2c837
BG
219 :type 'boolean)
220
ce4fdcb9
CD
221(defcustom org-list-two-spaces-after-bullet-regexp nil
222 "A regular expression matching bullets that should have 2 spaces after them.
3ab2c837
BG
223When nil, no bullet will have two spaces after them. When
224a string, it will be used as a regular expression. When the
afe98dfa 225bullet type of a list is changed, the new bullet type will be
3ab2c837 226matched against this regexp. If it matches, there will be two
afe98dfa 227spaces instead of one after the bullet in each item of the list."
86fbb8ca 228 :group 'org-plain-lists
ce4fdcb9
CD
229 :type '(choice
230 (const :tag "never" nil)
231 (regexp)))
232
afe98dfa
CD
233(defcustom org-empty-line-terminates-plain-lists nil
234 "Non-nil means an empty line ends all plain list levels.
153ae947 235Otherwise, two of them will be necessary."
47ffc456
CD
236 :group 'org-plain-lists
237 :type 'boolean)
238
afe98dfa
CD
239(defcustom org-list-automatic-rules '((bullet . t)
240 (checkbox . t)
3ab2c837 241 (indent . t))
afe98dfa
CD
242 "Non-nil means apply set of rules when acting on lists.
243By default, automatic actions are taken when using
244 \\[org-meta-return], \\[org-metaright], \\[org-metaleft],
245 \\[org-shiftmetaright], \\[org-shiftmetaleft],
246 \\[org-ctrl-c-minus], \\[org-toggle-checkbox] or
e66ba1df 247 \\[org-insert-todo-heading]. You can disable individually these
3ab2c837 248 rules by setting them to nil. Valid rules are:
afe98dfa
CD
249
250bullet when non-nil, cycling bullet do not allow lists at
251 column 0 to have * as a bullet and descriptions lists
252 to be numbered.
253checkbox when non-nil, checkbox statistics is updated each time
254 you either insert a new checkbox or toggle a checkbox.
255 It also prevents from inserting a checkbox in a
256 description item.
257indent when non-nil, indenting or outdenting list top-item
258 with its subtree will move the whole list and
259 outdenting a list whose bullet is * to column 0 will
3ab2c837 260 change that bullet to \"-\"."
afe98dfa 261 :group 'org-plain-lists
372d7b21 262 :version "24.1"
afe98dfa
CD
263 :type '(alist :tag "Sets of rules"
264 :key-type
265 (choice
266 (const :tag "Bullet" bullet)
267 (const :tag "Checkbox" checkbox)
3ab2c837 268 (const :tag "Indent" indent))
afe98dfa
CD
269 :value-type
270 (boolean :tag "Activate" :value t)))
c8d0cf5c 271
3ab2c837
BG
272(defcustom org-list-use-circular-motion nil
273 "Non-nil means commands implying motion in lists should be cyclic.
274
275In that case, the item following the last item is the first one,
276and the item preceding the first item is the last one.
277
278This affects the behavior of \\[org-move-item-up],
279 \\[org-move-item-down], \\[org-next-item] and
280 \\[org-previous-item]."
281 :group 'org-plain-lists
372d7b21 282 :version "24.1"
3ab2c837
BG
283 :type 'boolean)
284
285(defvar org-checkbox-statistics-hook nil
286 "Hook that is run whenever Org thinks checkbox statistics should be updated.
287This hook runs even if checkbox rule in
288`org-list-automatic-rules' does not apply, so it can be used to
289implement alternative ways of collecting statistics
290information.")
291
c8d0cf5c 292(defcustom org-hierarchical-checkbox-statistics t
ed21c5c8 293 "Non-nil means checkbox statistics counts only the state of direct children.
54a0dee5 294When nil, all boxes below the cookie are counted.
8bfe682a 295This can be set to nil on a per-node basis using a COOKIE_DATA property
54a0dee5 296with the word \"recursive\" in the value."
47ffc456
CD
297 :group 'org-plain-lists
298 :type 'boolean)
299
300(defcustom org-description-max-indent 20
301 "Maximum indentation for the second line of a description list.
302When the indentation would be larger than this, it will become
3035 characters instead."
304 :group 'org-plain-lists
305 :type 'integer)
306
3ab2c837
BG
307(defcustom org-list-indent-offset 0
308 "Additional indentation for sub-items in a list.
309By setting this to a small number, usually 1 or 2, one can more
310clearly distinguish sub-items in a list."
311 :group 'org-plain-lists
372d7b21 312 :version "24.1"
3ab2c837
BG
313 :type 'integer)
314
47ffc456
CD
315(defcustom org-list-radio-list-templates
316 '((latex-mode "% BEGIN RECEIVE ORGLST %n
317% END RECEIVE ORGLST %n
318\\begin{comment}
319#+ORGLST: SEND %n org-list-to-latex
86fbb8ca 320-
47ffc456
CD
321\\end{comment}\n")
322 (texinfo-mode "@c BEGIN RECEIVE ORGLST %n
323@c END RECEIVE ORGLST %n
324@ignore
325#+ORGLST: SEND %n org-list-to-texinfo
86fbb8ca 326-
47ffc456
CD
327@end ignore\n")
328 (html-mode "<!-- BEGIN RECEIVE ORGLST %n -->
329<!-- END RECEIVE ORGLST %n -->
330<!--
331#+ORGLST: SEND %n org-list-to-html
86fbb8ca 332-
47ffc456
CD
333-->\n"))
334 "Templates for radio lists in different major modes.
335All occurrences of %n in a template will be replaced with the name of the
336list, obtained by prompting the user."
337 :group 'org-plain-lists
338 :type '(repeat
339 (list (symbol :tag "Major mode")
340 (string :tag "Format"))))
341
3ab2c837
BG
342(defvar org-list-forbidden-blocks '("example" "verse" "src" "ascii" "beamer"
343 "docbook" "html" "latex" "odt")
344 "Names of blocks where lists are not allowed.
345Names must be in lower case.")
346
347(defvar org-list-export-context '(block inlinetask)
348 "Context types where lists will be interpreted during export.
349
350Valid types are `drawer', `inlinetask' and `block'. More
351specifically, type `block' is determined by the variable
352`org-list-forbidden-blocks'.")
353
354
e66ba1df 355\f
3ab2c837
BG
356;;; Predicates and regexps
357
153ae947
BG
358(defconst org-list-end-re (if org-empty-line-terminates-plain-lists "^[ \t]*\n"
359 "^[ \t]*\n[ \t]*\n")
3ab2c837
BG
360 "Regex corresponding to the end of a list.
361It depends on `org-empty-line-terminates-plain-lists'.")
362
363(defconst org-list-full-item-re
e66ba1df 364 (concat "^[ \t]*\\(\\(?:[-+*]\\|\\(?:[0-9]+\\|[A-Za-z]\\)[.)]\\)\\(?:[ \t]+\\|$\\)\\)"
3ab2c837 365 "\\(?:\\[@\\(?:start:\\)?\\([0-9]+\\|[A-Za-z]\\)\\][ \t]*\\)?"
e66ba1df 366 "\\(?:\\(\\[[ X-]\\]\\)\\(?:[ \t]+\\|$\\)\\)?"
3ab2c837
BG
367 "\\(?:\\(.*\\)[ \t]+::\\(?:[ \t]+\\|$\\)\\)?")
368 "Matches a list item and puts everything into groups:
369group 1: bullet
370group 2: counter
371group 3: checkbox
372group 4: description tag")
373
374(defun org-item-re ()
375 "Return the correct regular expression for plain lists."
376 (let ((term (cond
377 ((eq org-plain-list-ordered-item-terminator t) "[.)]")
378 ((= org-plain-list-ordered-item-terminator ?\)) ")")
379 ((= org-plain-list-ordered-item-terminator ?.) "\\.")
380 (t "[.)]")))
381 (alpha (if org-alphabetical-lists "\\|[A-Za-z]" "")))
382 (concat "\\([ \t]*\\([-+]\\|\\(\\([0-9]+" alpha "\\)" term
383 "\\)\\)\\|[ \t]+\\*\\)\\([ \t]+\\|$\\)")))
384
385(defsubst org-item-beginning-re ()
386 "Regexp matching the beginning of a plain list item."
387 (concat "^" (org-item-re)))
afe98dfa
CD
388
389(defun org-list-at-regexp-after-bullet-p (regexp)
390 "Is point at a list item with REGEXP after bullet?"
391 (and (org-at-item-p)
392 (save-excursion
393 (goto-char (match-end 0))
3ab2c837
BG
394 (let ((counter-re (concat "\\(?:\\[@\\(?:start:\\)?"
395 (if org-alphabetical-lists
396 "\\([0-9]+\\|[A-Za-z]\\)"
397 "[0-9]+")
398 "\\][ \t]*\\)")))
399 ;; Ignore counter if any
400 (when (looking-at counter-re) (goto-char (match-end 0))))
afe98dfa
CD
401 (looking-at regexp))))
402
3ab2c837
BG
403(defun org-list-in-valid-context-p ()
404 "Is point in a context where lists are allowed?"
405 (not (org-in-block-p org-list-forbidden-blocks)))
afe98dfa
CD
406
407(defun org-in-item-p ()
153ae947 408 "Return item beginning position when in a plain list, nil otherwise."
afe98dfa
CD
409 (save-excursion
410 (beginning-of-line)
3ab2c837
BG
411 (let* ((case-fold-search t)
412 (context (org-list-context))
413 (lim-up (car context))
414 (drawers-re (concat "^[ \t]*:\\("
415 (mapconcat 'regexp-quote org-drawers "\\|")
416 "\\):[ \t]*$"))
417 (inlinetask-re (and (featurep 'org-inlinetask)
418 (org-inlinetask-outline-regexp)))
419 (item-re (org-item-re))
420 ;; Indentation isn't meaningful when point starts at an empty
421 ;; line or an inline task.
422 (ind-ref (if (or (looking-at "^[ \t]*$")
423 (and inlinetask-re (looking-at inlinetask-re)))
424 10000
425 (org-get-indentation))))
426 (cond
427 ((eq (nth 2 context) 'invalid) nil)
428 ((looking-at item-re) (point))
429 (t
430 ;; Detect if cursor in amidst `org-list-end-re'. First, count
431 ;; number HL of hard lines it takes, then call `org-in-regexp'
432 ;; to compute its boundaries END-BOUNDS. When point is
433 ;; in-between, move cursor before regexp beginning.
434 (let ((hl 0) (i -1) end-bounds)
153ae947 435 (when (and (progn
3ab2c837
BG
436 (while (setq i (string-match
437 "[\r\n]" org-list-end-re (1+ i)))
438 (setq hl (1+ hl)))
439 (setq end-bounds (org-in-regexp org-list-end-re hl)))
440 (>= (point) (car end-bounds))
441 (< (point) (cdr end-bounds)))
442 (goto-char (car end-bounds))
443 (forward-line -1)))
153ae947 444 ;; Look for an item, less indented that reference line.
3ab2c837
BG
445 (catch 'exit
446 (while t
447 (let ((ind (org-get-indentation)))
448 (cond
449 ;; This is exactly what we want.
153ae947 450 ((and (looking-at item-re) (< ind ind-ref))
3ab2c837
BG
451 (throw 'exit (point)))
452 ;; At upper bound of search or looking at the end of a
453 ;; previous list: search is over.
454 ((<= (point) lim-up) (throw 'exit nil))
153ae947 455 ((looking-at org-list-end-re) (throw 'exit nil))
3ab2c837
BG
456 ;; Skip blocks, drawers, inline-tasks, blank lines
457 ((and (looking-at "^[ \t]*#\\+end_")
458 (re-search-backward "^[ \t]*#\\+begin_" lim-up t)))
459 ((and (looking-at "^[ \t]*:END:")
460 (re-search-backward drawers-re lim-up t))
461 (beginning-of-line))
462 ((and inlinetask-re (looking-at inlinetask-re))
463 (org-inlinetask-goto-beginning)
464 (forward-line -1))
465 ((looking-at "^[ \t]*$") (forward-line -1))
466 ;; Text at column 0 cannot belong to a list: stop.
467 ((zerop ind) (throw 'exit nil))
468 ;; Normal text less indented than reference line, take
469 ;; it as new reference.
470 ((< ind ind-ref)
471 (setq ind-ref ind)
472 (forward-line -1))
473 (t (forward-line -1)))))))))))
afe98dfa 474
47ffc456
CD
475(defun org-at-item-p ()
476 "Is point in a line starting a hand-formatted item?"
86fbb8ca 477 (save-excursion
3ab2c837
BG
478 (beginning-of-line)
479 (and (looking-at (org-item-re)) (org-list-in-valid-context-p))))
47ffc456 480
65c439fd
CD
481(defun org-at-item-bullet-p ()
482 "Is point at the bullet of a plain list item?"
483 (and (org-at-item-p)
484 (not (member (char-after) '(?\ ?\t)))
485 (< (point) (match-end 0))))
486
afe98dfa
CD
487(defun org-at-item-timer-p ()
488 "Is point at a line starting a plain list item with a timer?"
489 (org-list-at-regexp-after-bullet-p
490 "\\([0-9]+:[0-9]+:[0-9]+\\)[ \t]+::[ \t]+"))
47ffc456 491
afe98dfa
CD
492(defun org-at-item-description-p ()
493 "Is point at a description list item?"
494 (org-list-at-regexp-after-bullet-p "\\(\\S-.+\\)[ \t]+::[ \t]+"))
47ffc456
CD
495
496(defun org-at-item-checkbox-p ()
497 "Is point at a line starting a plain-list item with a checklet?"
afe98dfa 498 (org-list-at-regexp-after-bullet-p "\\(\\[[- X]\\]\\)[ \t]+"))
c8d0cf5c 499
3ab2c837
BG
500(defun org-at-item-counter-p ()
501 "Is point at a line starting a plain-list item with a counter?"
502 (and (org-at-item-p)
503 (looking-at org-list-full-item-re)
504 (match-string 2)))
c8d0cf5c 505
c8d0cf5c 506
e66ba1df 507\f
3ab2c837 508;;; Structures and helper functions
c8d0cf5c 509
3ab2c837
BG
510(defun org-list-context ()
511 "Determine context, and its boundaries, around point.
47ffc456 512
3ab2c837
BG
513Context will be a cell like (MIN MAX CONTEXT) where MIN and MAX
514are boundaries and CONTEXT is a symbol among `drawer', `block',
515`invalid', `inlinetask' and nil.
47ffc456 516
3ab2c837
BG
517Contexts `block' and `invalid' refer to `org-list-forbidden-blocks'."
518 (save-match-data
519 (save-excursion
520 (org-with-limited-levels
521 (beginning-of-line)
522 (let ((case-fold-search t) (pos (point)) beg end context-type
523 ;; Get positions of surrounding headings. This is the
524 ;; default context.
525 (lim-up (or (save-excursion (and (ignore-errors (org-back-to-heading t))
526 (point)))
527 (point-min)))
528 (lim-down (or (save-excursion (outline-next-heading)) (point-max))))
529 ;; Is point inside a drawer?
530 (let ((end-re "^[ \t]*:END:")
531 ;; Can't use org-drawers-regexp as this function might
532 ;; be called in buffers not in Org mode.
533 (beg-re (concat "^[ \t]*:\\("
534 (mapconcat 'regexp-quote org-drawers "\\|")
535 "\\):[ \t]*$")))
536 (when (save-excursion
537 (and (not (looking-at beg-re))
538 (not (looking-at end-re))
539 (setq beg (and (re-search-backward beg-re lim-up t)
540 (1+ (point-at-eol))))
541 (setq end (or (and (re-search-forward end-re lim-down t)
542 (1- (match-beginning 0)))
543 lim-down))
544 (>= end pos)))
545 (setq lim-up beg lim-down end context-type 'drawer)))
546 ;; Is point strictly in a block, and of which type?
547 (let ((block-re "^[ \t]*#\\+\\(begin\\|end\\)_") type)
548 (when (save-excursion
549 (and (not (looking-at block-re))
550 (setq beg (and (re-search-backward block-re lim-up t)
551 (1+ (point-at-eol))))
552 (looking-at "^[ \t]*#\\+begin_\\(\\S-+\\)")
553 (setq type (downcase (match-string 1)))
554 (goto-char beg)
555 (setq end (or (and (re-search-forward block-re lim-down t)
556 (1- (point-at-bol)))
557 lim-down))
558 (>= end pos)
559 (equal (downcase (match-string 1)) "end")))
560 (setq lim-up beg lim-down end
561 context-type (if (member type org-list-forbidden-blocks)
562 'invalid 'block))))
563 ;; Is point in an inlinetask?
564 (when (and (featurep 'org-inlinetask)
565 (save-excursion
566 (let* ((beg-re (org-inlinetask-outline-regexp))
567 (end-re (concat beg-re "END[ \t]*$")))
568 (and (not (looking-at "^\\*+"))
569 (setq beg (and (re-search-backward beg-re lim-up t)
570 (1+ (point-at-eol))))
571 (not (looking-at end-re))
572 (setq end (and (re-search-forward end-re lim-down t)
573 (1- (match-beginning 0))))
574 (> (point) pos)))))
575 (setq lim-up beg lim-down end context-type 'inlinetask))
576 ;; Return context boundaries and type.
577 (list lim-up lim-down context-type))))))
578
579(defun org-list-struct ()
580 "Return structure of list at point.
581
582A list structure is an alist where key is point at item, and
583values are:
5841. indentation,
5852. bullet with trailing whitespace,
5863. bullet counter, if any,
5874. checkbox, if any,
5885. description tag, if any,
5896. position at item end.
590
591Thus the following list, where numbers in parens are
592point-at-bol:
593
594- [X] first item (1)
595 1. sub-item 1 (18)
596 5. [@5] sub-item 2 (34)
597 some other text belonging to first item (55)
598- last item (97)
599 + tag :: description (109)
600 (131)
601
602will get the following structure:
603
604\(\(1 0 \"- \" nil \"[X]\" nil 97\)
605 \(18 2 \"1. \" nil nil nil 34\)
606 \(34 2 \"5. \" \"5\" nil nil 55\)
607 \(97 0 \"- \" nil nil nil 131\)
608 \(109 2 \"+ \" nil nil \"tag\" 131\)
609
610Assume point is at an item."
afe98dfa 611 (save-excursion
3ab2c837
BG
612 (beginning-of-line)
613 (let* ((case-fold-search t)
614 (context (org-list-context))
615 (lim-up (car context))
616 (lim-down (nth 1 context))
617 (text-min-ind 10000)
618 (item-re (org-item-re))
619 (drawers-re (concat "^[ \t]*:\\("
620 (mapconcat 'regexp-quote org-drawers "\\|")
621 "\\):[ \t]*$"))
622 (inlinetask-re (and (featurep 'org-inlinetask)
623 (org-inlinetask-outline-regexp)))
624 (beg-cell (cons (point) (org-get-indentation)))
625 ind itm-lst itm-lst-2 end-lst end-lst-2 struct
626 (assoc-at-point
627 (function
628 ;; Return association at point.
629 (lambda (ind)
630 (looking-at org-list-full-item-re)
631 (list (point)
632 ind
633 (match-string-no-properties 1) ; bullet
634 (match-string-no-properties 2) ; counter
635 (match-string-no-properties 3) ; checkbox
636 (match-string-no-properties 4))))) ; description tag
637 (end-before-blank
638 (function
639 ;; Ensure list ends at the first blank line.
640 (lambda ()
641 (skip-chars-backward " \r\t\n")
642 (min (1+ (point-at-eol)) lim-down)))))
643 ;; 1. Read list from starting item to its beginning, and save
644 ;; top item position and indentation in BEG-CELL. Also store
645 ;; ending position of items in END-LST.
646 (save-excursion
647 (catch 'exit
648 (while t
649 (let ((ind (+ (or (get-text-property (point) 'original-indentation) 0)
650 (org-get-indentation))))
651 (cond
652 ((<= (point) lim-up)
653 ;; At upward limit: if we ended at an item, store it,
27e428e7 654 ;; else dismiss useless data recorded above BEG-CELL.
3ab2c837
BG
655 ;; Jump to part 2.
656 (throw 'exit
657 (setq itm-lst
658 (if (or (not (looking-at item-re))
659 (get-text-property (point) 'org-example))
660 (memq (assq (car beg-cell) itm-lst) itm-lst)
661 (setq beg-cell (cons (point) ind))
662 (cons (funcall assoc-at-point ind) itm-lst)))))
663 ;; At a verbatim block, go before its beginning. Move
664 ;; from eol to ensure `previous-single-property-change'
665 ;; will return a value.
666 ((get-text-property (point) 'org-example)
667 (goto-char (previous-single-property-change
668 (point-at-eol) 'org-example nil lim-up))
669 (forward-line -1))
670 ;; Looking at a list ending regexp. Dismiss useless
671 ;; data recorded above BEG-CELL. Jump to part 2.
153ae947 672 ((looking-at org-list-end-re)
3ab2c837
BG
673 (throw 'exit
674 (setq itm-lst
675 (memq (assq (car beg-cell) itm-lst) itm-lst))))
676 ;; Point is at an item. Add data to ITM-LST. It may
677 ;; also end a previous item: save it in END-LST. If
678 ;; ind is less or equal than BEG-CELL and there is no
679 ;; end at this ind or lesser, this item becomes the new
680 ;; BEG-CELL.
681 ((looking-at item-re)
682 (push (funcall assoc-at-point ind) itm-lst)
683 (push (cons ind (point)) end-lst)
153ae947 684 (when (< ind text-min-ind) (setq beg-cell (cons (point) ind)))
3ab2c837
BG
685 (forward-line -1))
686 ;; Skip blocks, drawers, inline tasks, blank lines.
687 ((and (looking-at "^[ \t]*#\\+end_")
688 (re-search-backward "^[ \t]*#\\+begin_" lim-up t)))
689 ((and (looking-at "^[ \t]*:END:")
690 (re-search-backward drawers-re lim-up t))
691 (beginning-of-line))
692 ((and inlinetask-re (looking-at inlinetask-re))
693 (org-inlinetask-goto-beginning)
694 (forward-line -1))
695 ((looking-at "^[ \t]*$")
696 (forward-line -1))
153ae947
BG
697 ;; From there, point is not at an item. Interpret
698 ;; line's indentation:
3ab2c837
BG
699 ;; - text at column 0 is necessarily out of any list.
700 ;; Dismiss data recorded above BEG-CELL. Jump to
701 ;; part 2.
702 ;; - any other case may be an ending position for an
703 ;; hypothetical item above. Store it and proceed.
3ab2c837
BG
704 ((zerop ind)
705 (throw 'exit
706 (setq itm-lst
707 (memq (assq (car beg-cell) itm-lst) itm-lst))))
708 (t
709 (when (< ind text-min-ind) (setq text-min-ind ind))
710 (push (cons ind (point)) end-lst)
711 (forward-line -1)))))))
712 ;; 2. Read list from starting point to its end, that is until we
713 ;; get out of context, or that a non-item line is less or
714 ;; equally indented than BEG-CELL's cdr. Also, store ending
715 ;; position of items in END-LST-2.
716 (catch 'exit
717 (while t
718 (let ((ind (+ (or (get-text-property (point) 'original-indentation) 0)
719 (org-get-indentation))))
720 (cond
721 ((>= (point) lim-down)
722 ;; At downward limit: this is de facto the end of the
723 ;; list. Save point as an ending position, and jump to
724 ;; part 3.
725 (throw 'exit
726 (push (cons 0 (funcall end-before-blank)) end-lst-2)))
727 ;; At a verbatim block, move to its end. Point is at bol
728 ;; and 'org-example property is set by whole lines:
729 ;; `next-single-property-change' always return a value.
730 ((get-text-property (point) 'org-example)
731 (goto-char
732 (next-single-property-change (point) 'org-example nil lim-down)))
733 ;; Looking at a list ending regexp. Save point as an
734 ;; ending position and jump to part 3.
153ae947 735 ((looking-at org-list-end-re)
3ab2c837
BG
736 (throw 'exit (push (cons 0 (point)) end-lst-2)))
737 ((looking-at item-re)
738 ;; Point is at an item. Add data to ITM-LST-2. It may
739 ;; also end a previous item, so save it in END-LST-2.
740 (push (funcall assoc-at-point ind) itm-lst-2)
741 (push (cons ind (point)) end-lst-2)
742 (forward-line 1))
743 ;; Skip inline tasks and blank lines along the way
744 ((and inlinetask-re (looking-at inlinetask-re))
745 (org-inlinetask-goto-end))
746 ((looking-at "^[ \t]*$")
747 (forward-line 1))
748 ;; Ind is lesser or equal than BEG-CELL's. The list is
749 ;; over: store point as an ending position and jump to
750 ;; part 3.
153ae947 751 ((<= ind (cdr beg-cell))
3ab2c837
BG
752 (throw 'exit
753 (push (cons 0 (funcall end-before-blank)) end-lst-2)))
754 ;; Else, if ind is lesser or equal than previous item's,
755 ;; this is an ending position: store it. In any case,
756 ;; skip block or drawer at point, and move to next line.
757 (t
153ae947 758 (when (<= ind (nth 1 (car itm-lst-2)))
3ab2c837
BG
759 (push (cons ind (point)) end-lst-2))
760 (cond
761 ((and (looking-at "^[ \t]*#\\+begin_")
762 (re-search-forward "^[ \t]*#\\+end_" lim-down t)))
763 ((and (looking-at drawers-re)
764 (re-search-forward "^[ \t]*:END:" lim-down t))))
765 (forward-line 1))))))
766 (setq struct (append itm-lst (cdr (nreverse itm-lst-2)))
767 end-lst (append end-lst (cdr (nreverse end-lst-2))))
e66ba1df 768 ;; 3. Associate each item to its end position.
3ab2c837 769 (org-list-struct-assoc-end struct end-lst)
e66ba1df 770 ;; 4. Return STRUCT
3ab2c837
BG
771 struct)))
772
773(defun org-list-struct-assoc-end (struct end-list)
774 "Associate proper ending point to items in STRUCT.
775
776END-LIST is a pseudo-alist where car is indentation and cdr is
777ending position.
47ffc456 778
3ab2c837
BG
779This function modifies STRUCT."
780 (let ((endings end-list))
781 (mapc
782 (lambda (elt)
783 (let ((pos (car elt))
784 (ind (nth 1 elt)))
785 ;; Remove end candidates behind current item.
786 (while (or (<= (cdar endings) pos))
787 (pop endings))
788 ;; Add end position to item assoc.
789 (let ((old-end (nthcdr 6 elt))
790 (new-end (assoc-default ind endings '<=)))
791 (if old-end
792 (setcar old-end new-end)
793 (setcdr elt (append (cdr elt) (list new-end)))))))
794 struct)))
795
796(defun org-list-prevs-alist (struct)
797 "Return alist between item and previous item in STRUCT."
798 (let ((item-end-alist (mapcar (lambda (e) (cons (car e) (nth 6 e)))
799 struct)))
800 (mapcar (lambda (e)
801 (let ((prev (car (rassq (car e) item-end-alist))))
802 (cons (car e) prev)))
803 struct)))
804
805(defun org-list-parents-alist (struct)
806 "Return alist between item and parent in STRUCT."
e66ba1df
BG
807 (let* ((ind-to-ori (list (list (nth 1 (car struct)))))
808 (top-item (org-list-get-top-point struct))
809 (prev-pos (list top-item)))
3ab2c837
BG
810 (cons prev-pos
811 (mapcar (lambda (item)
812 (let ((pos (car item))
813 (ind (nth 1 item))
814 (prev-ind (caar ind-to-ori)))
815 (push pos prev-pos)
816 (cond
817 ((> prev-ind ind)
e66ba1df
BG
818 ;; A sub-list is over. Find the associated
819 ;; origin in IND-TO-ORI. If it cannot be
820 ;; found (ill-formed list), set its parent as
821 ;; the first item less indented. If there is
822 ;; none, make it a top-level item.
3ab2c837 823 (setq ind-to-ori
e66ba1df
BG
824 (or (member (assq ind ind-to-ori) ind-to-ori)
825 (catch 'exit
826 (mapc
827 (lambda (e)
828 (when (< (car e) ind)
829 (throw 'exit (member e ind-to-ori))))
830 ind-to-ori)
831 (list (list ind)))))
3ab2c837 832 (cons pos (cdar ind-to-ori)))
e66ba1df
BG
833 ;; A sub-list starts. Every item at IND will
834 ;; have previous item as its parent.
3ab2c837
BG
835 ((< prev-ind ind)
836 (let ((origin (nth 1 prev-pos)))
837 (push (cons ind origin) ind-to-ori)
838 (cons pos origin)))
e66ba1df
BG
839 ;; Another item in the same sub-list: it shares
840 ;; the same parent as the previous item.
3ab2c837
BG
841 (t (cons pos (cdar ind-to-ori))))))
842 (cdr struct)))))
843
844
e66ba1df 845\f
3ab2c837
BG
846;;; Accessors
847
848(defsubst org-list-get-nth (n key struct)
849 "Return the Nth value of KEY in STRUCT."
850 (nth n (assq key struct)))
851
852(defun org-list-set-nth (n key struct new)
853 "Set the Nth value of KEY in STRUCT to NEW.
854\nThis function modifies STRUCT."
855 (setcar (nthcdr n (assq key struct)) new))
856
857(defsubst org-list-get-ind (item struct)
858 "Return indentation of ITEM in STRUCT."
859 (org-list-get-nth 1 item struct))
860
861(defun org-list-set-ind (item struct ind)
862 "Set indentation of ITEM in STRUCT to IND.
863\nThis function modifies STRUCT."
864 (org-list-set-nth 1 item struct ind))
865
866(defsubst org-list-get-bullet (item struct)
867 "Return bullet of ITEM in STRUCT."
868 (org-list-get-nth 2 item struct))
869
870(defun org-list-set-bullet (item struct bullet)
871 "Set bullet of ITEM in STRUCT to BULLET.
872\nThis function modifies STRUCT."
873 (org-list-set-nth 2 item struct bullet))
874
875(defsubst org-list-get-counter (item struct)
876 "Return counter of ITEM in STRUCT."
877 (org-list-get-nth 3 item struct))
878
879(defsubst org-list-get-checkbox (item struct)
880 "Return checkbox of ITEM in STRUCT or nil."
881 (org-list-get-nth 4 item struct))
882
883(defun org-list-set-checkbox (item struct checkbox)
884 "Set checkbox of ITEM in STRUCT to CHECKBOX.
885\nThis function modifies STRUCT."
886 (org-list-set-nth 4 item struct checkbox))
887
888(defsubst org-list-get-tag (item struct)
889 "Return end position of ITEM in STRUCT."
890 (org-list-get-nth 5 item struct))
891
892(defun org-list-get-item-end (item struct)
893 "Return end position of ITEM in STRUCT."
894 (org-list-get-nth 6 item struct))
895
896(defun org-list-get-item-end-before-blank (item struct)
897 "Return point at end of ITEM in STRUCT, before any blank line.
898Point returned is at end of line."
afe98dfa 899 (save-excursion
3ab2c837 900 (goto-char (org-list-get-item-end item struct))
afe98dfa
CD
901 (skip-chars-backward " \r\t\n")
902 (point-at-eol)))
903
3ab2c837
BG
904(defun org-list-get-parent (item struct parents)
905 "Return parent of ITEM or nil.
906STRUCT is the list structure. PARENTS is the alist of parents,
907as returned by `org-list-parents-alist'."
908 (let ((parents (or parents (org-list-parents-alist struct))))
909 (cdr (assq item parents))))
910
911(defun org-list-has-child-p (item struct)
912 "Non-nil if ITEM has a child.
913
914STRUCT is the list structure.
915
916Value returned is the position of the first child of ITEM."
917 (let ((ind (org-list-get-ind item struct))
918 (child-maybe (car (nth 1 (member (assq item struct) struct)))))
919 (when (and child-maybe
920 (< ind (org-list-get-ind child-maybe struct)))
921 child-maybe)))
922
923(defun org-list-get-next-item (item struct prevs)
924 "Return next item in same sub-list as ITEM, or nil.
925STRUCT is the list structure. PREVS is the alist of previous
926items, as returned by `org-list-prevs-alist'."
927 (car (rassq item prevs)))
928
929(defun org-list-get-prev-item (item struct prevs)
930 "Return previous item in same sub-list as ITEM, or nil.
931STRUCT is the list structure. PREVS is the alist of previous
932items, as returned by `org-list-prevs-alist'."
933 (cdr (assq item prevs)))
934
935(defun org-list-get-subtree (item struct)
936 "List all items having ITEM as a common ancestor, or nil.
937STRUCT is the list structure."
938 (let* ((item-end (org-list-get-item-end item struct))
939 (sub-struct (cdr (member (assq item struct) struct)))
940 subtree)
941 (catch 'exit
942 (mapc (lambda (e)
943 (let ((pos (car e)))
944 (if (< pos item-end) (push pos subtree) (throw 'exit nil))))
945 sub-struct))
946 (nreverse subtree)))
947
948(defun org-list-get-all-items (item struct prevs)
949 "List all items in the same sub-list as ITEM.
950STRUCT is the list structure. PREVS is the alist of previous
951items, as returned by `org-list-prevs-alist'."
952 (let ((prev-item item)
953 (next-item item)
954 before-item after-item)
955 (while (setq prev-item (org-list-get-prev-item prev-item struct prevs))
956 (push prev-item before-item))
957 (while (setq next-item (org-list-get-next-item next-item struct prevs))
958 (push next-item after-item))
959 (append before-item (list item) (nreverse after-item))))
960
961(defun org-list-get-children (item struct parents)
962 "List all children of ITEM, or nil.
e66ba1df
BG
963STRUCT is the list structure. PARENTS is the alist of parents,
964as returned by `org-list-parents-alist'."
3ab2c837
BG
965 (let (all child)
966 (while (setq child (car (rassq item parents)))
967 (setq parents (cdr (member (assq child parents) parents)))
968 (push child all))
969 (nreverse all)))
970
971(defun org-list-get-top-point (struct)
972 "Return point at beginning of list.
973STRUCT is the list structure."
974 (caar struct))
975
976(defun org-list-get-bottom-point (struct)
977 "Return point at bottom of list.
978STRUCT is the list structure."
979 (apply 'max
980 (mapcar (lambda (e) (org-list-get-item-end (car e) struct)) struct)))
981
982(defun org-list-get-list-begin (item struct prevs)
983 "Return point at beginning of sub-list ITEM belongs.
984STRUCT is the list structure. PREVS is the alist of previous
985items, as returned by `org-list-prevs-alist'."
986 (let ((first-item item) prev-item)
987 (while (setq prev-item (org-list-get-prev-item first-item struct prevs))
988 (setq first-item prev-item))
989 first-item))
990
991(defalias 'org-list-get-first-item 'org-list-get-list-begin)
992
993(defun org-list-get-last-item (item struct prevs)
994 "Return point at last item of sub-list ITEM belongs.
995STRUCT is the list structure. PREVS is the alist of previous
996items, as returned by `org-list-prevs-alist'."
997 (let ((last-item item) next-item)
998 (while (setq next-item (org-list-get-next-item last-item struct prevs))
999 (setq last-item next-item))
1000 last-item))
1001
1002(defun org-list-get-list-end (item struct prevs)
1003 "Return point at end of sub-list ITEM belongs.
1004STRUCT is the list structure. PREVS is the alist of previous
1005items, as returned by `org-list-prevs-alist'."
1006 (org-list-get-item-end (org-list-get-last-item item struct prevs) struct))
1007
1008(defun org-list-get-list-type (item struct prevs)
1009 "Return the type of the list containing ITEM, as a symbol.
1010
1011STRUCT is the list structure. PREVS is the alist of previous
1012items, as returned by `org-list-prevs-alist'.
1013
1014Possible types are `descriptive', `ordered' and `unordered'. The
1015type is determined by the first item of the list."
1016 (let ((first (org-list-get-list-begin item struct prevs)))
1017 (cond
1018 ((org-list-get-tag first struct) 'descriptive)
1019 ((string-match "[[:alnum:]]" (org-list-get-bullet first struct)) 'ordered)
1020 (t 'unordered))))
47ffc456 1021
afe98dfa 1022
e66ba1df 1023\f
3ab2c837
BG
1024;;; Searching
1025
1026(defun org-list-search-generic (search re bound noerr)
1027 "Search a string in valid contexts for lists.
1028Arguments SEARCH, RE, BOUND and NOERR are similar to those used
1029in `re-search-forward'."
1030 (catch 'exit
1031 (let ((origin (point)))
1032 (while t
1033 ;; 1. No match: return to origin or bound, depending on NOERR.
1034 (unless (funcall search re bound noerr)
1035 (throw 'exit (and (goto-char (if (memq noerr '(t nil)) origin bound))
1036 nil)))
1037 ;; 2. Match in valid context: return point. Else, continue
1038 ;; searching.
1039 (when (org-list-in-valid-context-p) (throw 'exit (point)))))))
1040
1041(defun org-list-search-backward (regexp &optional bound noerror)
1042 "Like `re-search-backward' but stop only where lists are recognized.
1043Arguments REGEXP, BOUND and NOERROR are similar to those used in
1044`re-search-backward'."
1045 (org-list-search-generic #'re-search-backward
1046 regexp (or bound (point-min)) noerror))
1047
1048(defun org-list-search-forward (regexp &optional bound noerror)
1049 "Like `re-search-forward' but stop only where lists are recognized.
1050Arguments REGEXP, BOUND and NOERROR are similar to those used in
1051`re-search-forward'."
1052 (org-list-search-generic #'re-search-forward
1053 regexp (or bound (point-max)) noerror))
afe98dfa 1054
afe98dfa 1055
e66ba1df 1056\f
3ab2c837 1057;;; Methods on structures
afe98dfa 1058
3ab2c837
BG
1059(defsubst org-list-bullet-string (bullet)
1060 "Return BULLET with the correct number of whitespaces.
1061It determines the number of whitespaces to append by looking at
1062`org-list-two-spaces-after-bullet-regexp'."
1063 (save-match-data
1064 (let ((spaces (if (and org-list-two-spaces-after-bullet-regexp
1065 (string-match
1066 org-list-two-spaces-after-bullet-regexp bullet))
1067 " "
1068 " ")))
1069 (string-match "\\S-+\\([ \t]*\\)" bullet)
1070 (replace-match spaces nil nil bullet 1))))
1071
1072(defun org-list-swap-items (beg-A beg-B struct)
1073 "Swap item starting at BEG-A with item starting at BEG-B in STRUCT.
1074Blank lines at the end of items are left in place. Return the
1075new structure after the changes.
1076
1077Assume BEG-A is lesser than BEG-B and that BEG-A and BEG-B belong
1078to the same sub-list.
afe98dfa 1079
3ab2c837 1080This function modifies STRUCT."
c8d0cf5c 1081 (save-excursion
3ab2c837
BG
1082 (let* ((end-A-no-blank (org-list-get-item-end-before-blank beg-A struct))
1083 (end-B-no-blank (org-list-get-item-end-before-blank beg-B struct))
1084 (end-A (org-list-get-item-end beg-A struct))
1085 (end-B (org-list-get-item-end beg-B struct))
1086 (size-A (- end-A-no-blank beg-A))
1087 (size-B (- end-B-no-blank beg-B))
afe98dfa
CD
1088 (body-A (buffer-substring beg-A end-A-no-blank))
1089 (body-B (buffer-substring beg-B end-B-no-blank))
3ab2c837
BG
1090 (between-A-no-blank-and-B (buffer-substring end-A-no-blank beg-B))
1091 (sub-A (cons beg-A (org-list-get-subtree beg-A struct)))
1092 (sub-B (cons beg-B (org-list-get-subtree beg-B struct))))
1093 ;; 1. Move effectively items in buffer.
afe98dfa
CD
1094 (goto-char beg-A)
1095 (delete-region beg-A end-B-no-blank)
3ab2c837
BG
1096 (insert (concat body-B between-A-no-blank-and-B body-A))
1097 ;; 2. Now modify struct. No need to re-read the list, the
1098 ;; transformation is just a shift of positions. Some special
1099 ;; attention is required for items ending at END-A and END-B
1100 ;; as empty spaces are not moved there. In others words,
1101 ;; item BEG-A will end with whitespaces that were at the end
1102 ;; of BEG-B and the same applies to BEG-B.
1103 (mapc (lambda (e)
1104 (let ((pos (car e)))
1105 (cond
1106 ((< pos beg-A))
1107 ((memq pos sub-A)
1108 (let ((end-e (nth 6 e)))
1109 (setcar e (+ pos (- end-B-no-blank end-A-no-blank)))
1110 (setcar (nthcdr 6 e)
1111 (+ end-e (- end-B-no-blank end-A-no-blank)))
1112 (when (= end-e end-A) (setcar (nthcdr 6 e) end-B))))
1113 ((memq pos sub-B)
1114 (let ((end-e (nth 6 e)))
1115 (setcar e (- (+ pos beg-A) beg-B))
1116 (setcar (nthcdr 6 e) (+ end-e (- beg-A beg-B)))
1117 (when (= end-e end-B)
1118 (setcar (nthcdr 6 e)
1119 (+ beg-A size-B (- end-A end-A-no-blank))))))
1120 ((< pos beg-B)
1121 (let ((end-e (nth 6 e)))
1122 (setcar e (+ pos (- size-B size-A)))
1123 (setcar (nthcdr 6 e) (+ end-e (- size-B size-A))))))))
1124 struct)
1125 (sort struct (lambda (e1 e2) (< (car e1) (car e2)))))))
1126
1127(defun org-list-separating-blank-lines-number (pos struct prevs)
1128 "Return number of blank lines that should separate items in list.
47ffc456 1129
3ab2c837 1130POS is the position of point where `org-list-insert-item' was called.
afe98dfa 1131
3ab2c837
BG
1132STRUCT is the list structure. PREVS is the alist of previous
1133items, as returned by `org-list-prevs-alist'.
47ffc456 1134
3ab2c837
BG
1135Assume point is at item's beginning. If the item is alone, apply
1136some heuristics to guess the result."
1137 (save-excursion
1138 (let ((item (point))
1139 (insert-blank-p
1140 (cdr (assq 'plain-list-item org-blank-before-new-entry)))
e66ba1df
BG
1141 usr-blank
1142 (count-blanks
1143 (function
1144 (lambda ()
1145 ;; Count blank lines above beginning of line.
1146 (save-excursion
1147 (count-lines (goto-char (point-at-bol))
1148 (progn (skip-chars-backward " \r\t\n")
1149 (forward-line)
1150 (point))))))))
3ab2c837
BG
1151 (cond
1152 ;; Trivial cases where there should be none.
153ae947 1153 ((or org-empty-line-terminates-plain-lists (not insert-blank-p)) 0)
3ab2c837
BG
1154 ;; When `org-blank-before-new-entry' says so, it is 1.
1155 ((eq insert-blank-p t) 1)
1156 ;; `plain-list-item' is 'auto. Count blank lines separating
e66ba1df 1157 ;; neighbours items in list.
3ab2c837
BG
1158 (t (let ((next-p (org-list-get-next-item item struct prevs)))
1159 (cond
1160 ;; Is there a next item?
1161 (next-p (goto-char next-p)
e66ba1df 1162 (funcall count-blanks))
3ab2c837
BG
1163 ;; Is there a previous item?
1164 ((org-list-get-prev-item item struct prevs)
e66ba1df 1165 (funcall count-blanks))
3ab2c837
BG
1166 ;; User inserted blank lines, trust him.
1167 ((and (> pos (org-list-get-item-end-before-blank item struct))
e66ba1df
BG
1168 (> (save-excursion (goto-char pos)
1169 (setq usr-blank (funcall count-blanks)))
1170 0))
3ab2c837
BG
1171 usr-blank)
1172 ;; Are there blank lines inside the list so far?
1173 ((save-excursion
1174 (goto-char (org-list-get-top-point struct))
1175 (org-list-search-forward
1176 "^[ \t]*$" (org-list-get-item-end-before-blank item struct) t))
1177 1)
1178 ;; Default choice: no blank line.
1179 (t 0))))))))
47ffc456 1180
3ab2c837
BG
1181(defun org-list-insert-item (pos struct prevs &optional checkbox after-bullet)
1182 "Insert a new list item at POS and return the new structure.
1183If POS is before first character after bullet of the item, the
1184new item will be created before the current one.
47ffc456 1185
e66ba1df 1186STRUCT is the list structure. PREVS is the the alist of previous
3ab2c837 1187items, as returned by `org-list-prevs-alist'.
afe98dfa 1188
3ab2c837
BG
1189Insert a checkbox if CHECKBOX is non-nil, and string AFTER-BULLET
1190after the bullet. Cursor will be after this text once the
1191function ends.
afe98dfa
CD
1192
1193This function modifies STRUCT."
3ab2c837
BG
1194 (let ((case-fold-search t))
1195 ;; 1. Get information about list: position of point with regards
1196 ;; to item start (BEFOREP), blank lines number separating items
1197 ;; (BLANK-NB), if we're allowed to (SPLIT-LINE-P).
1198 (let* ((item (progn (goto-char pos) (goto-char (org-list-get-item-begin))))
1199 (item-end (org-list-get-item-end item struct))
1200 (item-end-no-blank (org-list-get-item-end-before-blank item struct))
1201 (beforep (and (looking-at org-list-full-item-re)
1202 (<= pos (match-end 0))))
1203 (split-line-p (org-get-alist-option org-M-RET-may-split-line 'item))
1204 (blank-nb (org-list-separating-blank-lines-number
1205 pos struct prevs))
1206 ;; 2. Build the new item to be created. Concatenate same
1207 ;; bullet as item, checkbox, text AFTER-BULLET if
1208 ;; provided, and text cut from point to end of item
1209 ;; (TEXT-CUT) to form item's BODY. TEXT-CUT depends on
1210 ;; BEFOREP and SPLIT-LINE-P. The difference of size
1211 ;; between what was cut and what was inserted in buffer
1212 ;; is stored in SIZE-OFFSET.
1213 (ind (org-list-get-ind item struct))
1214 (ind-size (if indent-tabs-mode
1215 (+ (/ ind tab-width) (mod ind tab-width))
1216 ind))
1217 (bullet (org-list-bullet-string (org-list-get-bullet item struct)))
1218 (box (when checkbox "[ ]"))
1219 (text-cut
1220 (and (not beforep) split-line-p
1221 (progn
1222 (goto-char pos)
1223 ;; If POS is greater than ITEM-END, then point is
1224 ;; in some white lines after the end of the list.
1225 ;; Those must be removed, or they will be left,
1226 ;; stacking up after the list.
1227 (when (< item-end pos)
1228 (delete-region (1- item-end) (point-at-eol)))
1229 (skip-chars-backward " \r\t\n")
1230 (setq pos (point))
1231 (delete-and-extract-region pos item-end-no-blank))))
1232 (body (concat bullet (when box (concat box " ")) after-bullet
1233 (and text-cut
1234 (if (string-match "\\`[ \t]+" text-cut)
1235 (replace-match "" t t text-cut)
1236 text-cut))))
1237 (item-sep (make-string (1+ blank-nb) ?\n))
1238 (item-size (+ ind-size (length body) (length item-sep)))
1239 (size-offset (- item-size (length text-cut))))
1240 ;; 4. Insert effectively item into buffer.
1241 (goto-char item)
1242 (org-indent-to-column ind)
1243 (insert body item-sep)
1244 ;; 5. Add new item to STRUCT.
1245 (mapc (lambda (e)
1246 (let ((p (car e))
1247 (end (nth 6 e)))
1248 (cond
1249 ;; Before inserted item, positions don't change but
1250 ;; an item ending after insertion has its end shifted
1251 ;; by SIZE-OFFSET.
1252 ((< p item)
1253 (when (> end item) (setcar (nthcdr 6 e) (+ end size-offset))))
1254 ;; Trivial cases where current item isn't split in
1255 ;; two. Just shift every item after new one by
1256 ;; ITEM-SIZE.
1257 ((or beforep (not split-line-p))
1258 (setcar e (+ p item-size))
1259 (setcar (nthcdr 6 e) (+ end item-size)))
1260 ;; Item is split in two: elements before POS are just
1261 ;; shifted by ITEM-SIZE. In the case item would end
1262 ;; after split POS, ending is only shifted by
1263 ;; SIZE-OFFSET.
1264 ((< p pos)
1265 (setcar e (+ p item-size))
1266 (if (< end pos)
1267 (setcar (nthcdr 6 e) (+ end item-size))
1268 (setcar (nthcdr 6 e) (+ end size-offset))))
1269 ;; Elements after POS are moved into new item.
1270 ;; Length of ITEM-SEP has to be removed as ITEM-SEP
1271 ;; doesn't appear in buffer yet.
1272 ((< p item-end)
1273 (setcar e (+ p size-offset (- item pos (length item-sep))))
1274 (if (= end item-end)
1275 (setcar (nthcdr 6 e) (+ item item-size))
1276 (setcar (nthcdr 6 e)
1277 (+ end size-offset
1278 (- item pos (length item-sep))))))
1279 ;; Elements at ITEM-END or after are only shifted by
1280 ;; SIZE-OFFSET.
1281 (t (setcar e (+ p size-offset))
1282 (setcar (nthcdr 6 e) (+ end size-offset))))))
1283 struct)
1284 (push (list item ind bullet nil box nil (+ item item-size)) struct)
1285 (setq struct (sort struct (lambda (e1 e2) (< (car e1) (car e2)))))
1286 ;; 6. If not BEFOREP, new item must appear after ITEM, so
1287 ;; exchange ITEM with the next item in list. Position cursor
1288 ;; after bullet, counter, checkbox, and label.
1289 (if beforep
1290 (goto-char item)
1291 (setq struct (org-list-swap-items item (+ item item-size) struct))
1292 (goto-char (org-list-get-next-item
1293 item struct (org-list-prevs-alist struct))))
1294 struct)))
1295
1296(defun org-list-delete-item (item struct)
1297 "Remove ITEM from the list and return the new structure.
1298
1299STRUCT is the list structure."
1300 (let* ((end (org-list-get-item-end item struct))
1301 (beg (if (= (org-list-get-bottom-point struct) end)
1302 ;; If ITEM ends with the list, delete blank lines
1303 ;; before it.
1304 (save-excursion
1305 (goto-char item)
1306 (skip-chars-backward " \r\t\n")
1307 (min (1+ (point-at-eol)) (point-max)))
1308 item)))
1309 ;; Remove item from buffer.
1310 (delete-region beg end)
1311 ;; Remove item from structure and shift others items accordingly.
1312 ;; Don't forget to shift also ending position when appropriate.
1313 (let ((size (- end beg)))
1314 (delq nil (mapcar (lambda (e)
1315 (let ((pos (car e)))
1316 (cond
1317 ((< pos item)
1318 (let ((end-e (nth 6 e)))
1319 (cond
1320 ((< end-e item) e)
1321 ((= end-e item)
1322 (append (butlast e) (list beg)))
1323 (t
1324 (append (butlast e) (list (- end-e size)))))))
1325 ((< pos end) nil)
1326 (t
1327 (cons (- pos size)
1328 (append (butlast (cdr e))
1329 (list (- (nth 6 e) size))))))))
1330 struct)))))
1331
1332(defun org-list-send-item (item dest struct)
1333 "Send ITEM to destination DEST.
1334
1335STRUCT is the list structure.
1336
1337DEST can have various values.
1338
1339If DEST is a buffer position, the function will assume it points
1340to another item in the same list as ITEM, and will move the
1341latter just before the former.
1342
e66ba1df
BG
1343If DEST is `begin' \(respectively `end'\), ITEM will be moved at
1344the beginning \(respectively end\) of the list it belongs to.
3ab2c837
BG
1345
1346If DEST is a string like \"N\", where N is an integer, ITEM will
1347be moved at the Nth position in the list.
1348
1349If DEST is `kill', ITEM will be deleted and its body will be
1350added to the kill-ring.
1351
1352If DEST is `delete', ITEM will be deleted.
1353
1354This function returns, destructively, the new list structure."
1355 (let* ((prevs (org-list-prevs-alist struct))
1356 (item-end (org-list-get-item-end item struct))
1357 ;; Grab full item body minus its bullet.
1358 (body (org-trim
1359 (buffer-substring
1360 (save-excursion
1361 (goto-char item)
1362 (looking-at
1363 (concat "[ \t]*"
1364 (regexp-quote (org-list-get-bullet item struct))))
1365 (match-end 0))
1366 item-end)))
1367 ;; Change DEST into a buffer position. A trick is needed
1368 ;; when ITEM is meant to be sent at the end of the list.
1369 ;; Indeed, by setting locally `org-M-RET-may-split-line' to
1370 ;; nil and insertion point (INS-POINT) to the first line's
1371 ;; end of the last item, we ensure the new item will be
1372 ;; inserted after the last item, and not after any of its
1373 ;; hypothetical sub-items.
1374 (ins-point (cond
1375 ((or (eq dest 'kill) (eq dest 'delete)))
1376 ((eq dest 'begin)
1377 (setq dest (org-list-get-list-begin item struct prevs)))
1378 ((eq dest 'end)
1379 (setq dest (org-list-get-list-end item struct prevs))
1380 (save-excursion
1381 (goto-char (org-list-get-last-item item struct prevs))
1382 (point-at-eol)))
1383 ((string-match "\\`[0-9]+\\'" dest)
1384 (let* ((all (org-list-get-all-items item struct prevs))
1385 (len (length all))
1386 (index (mod (string-to-number dest) len)))
1387 (if (not (zerop index))
1388 (setq dest (nth (1- index) all))
1389 ;; Send ITEM at the end of the list.
1390 (setq dest (org-list-get-list-end item struct prevs))
1391 (save-excursion
1392 (goto-char
1393 (org-list-get-last-item item struct prevs))
1394 (point-at-eol)))))
1395 (t dest)))
1396 (org-M-RET-may-split-line nil))
1397 (cond
1398 ((eq dest 'delete) (org-list-delete-item item struct))
1399 ((eq dest 'kill)
1400 (kill-new body)
1401 (org-list-delete-item item struct))
1402 ((and (integerp dest) (/= item ins-point))
1403 (setq item (copy-marker item))
1404 (setq struct (org-list-insert-item ins-point struct prevs nil body))
1405 ;; 1. Structure returned by `org-list-insert-item' may not be
1406 ;; accurate, as it cannot see sub-items included in BODY.
1407 ;; Thus, first compute the real structure so far.
1408 (let ((moved-items
1409 (cons (marker-position item)
1410 (org-list-get-subtree (marker-position item) struct)))
1411 (new-end (org-list-get-item-end (point) struct))
1412 (old-end (org-list-get-item-end (marker-position item) struct))
1413 (new-item (point))
1414 (shift (- (point) item)))
1415 ;; 1.1. Remove the item just created in structure.
1416 (setq struct (delete (assq new-item struct) struct))
1417 ;; 1.2. Copy ITEM and any of its sub-items at NEW-ITEM.
f6cba7e0 1418 (setq struct (sort
3ab2c837
BG
1419 (append
1420 struct
1421 (mapcar (lambda (e)
1422 (let* ((cell (assq e struct))
1423 (pos (car cell))
1424 (end (nth 6 cell)))
1425 (cons (+ pos shift)
1426 (append (butlast (cdr cell))
1427 (list (if (= end old-end)
1428 new-end
1429 (+ end shift)))))))
1430 moved-items))
1431 (lambda (e1 e2) (< (car e1) (car e2))))))
1432 ;; 2. Eventually delete extra copy of the item and clean marker.
1433 (prog1
1434 (org-list-delete-item (marker-position item) struct)
1435 (move-marker item nil)))
1436 (t struct))))
1437
1438(defun org-list-struct-outdent (start end struct parents)
1439 "Outdent items between positions START and END.
1440
1441STRUCT is the list structure. PARENTS is the alist of items'
1442parents, as returned by `org-list-parents-alist'.
1443
1444START is included, END excluded."
afe98dfa
CD
1445 (let* (acc
1446 (out (lambda (cell)
1447 (let* ((item (car cell))
1448 (parent (cdr cell)))
1449 (cond
3ab2c837 1450 ;; Item not yet in zone: keep association.
afe98dfa 1451 ((< item start) cell)
3ab2c837 1452 ;; Item out of zone: follow associations in ACC.
afe98dfa 1453 ((>= item end)
3ab2c837 1454 (let ((convert (and parent (assq parent acc))))
afe98dfa
CD
1455 (if convert (cons item (cdr convert)) cell)))
1456 ;; Item has no parent: error
3ab2c837 1457 ((not parent)
afe98dfa 1458 (error "Cannot outdent top-level items"))
3ab2c837 1459 ;; Parent is outdented: keep association.
afe98dfa 1460 ((>= parent start)
3ab2c837 1461 (push (cons parent item) acc) cell)
afe98dfa 1462 (t
3ab2c837
BG
1463 ;; Parent isn't outdented: reparent to grand-parent.
1464 (let ((grand-parent (org-list-get-parent
1465 parent struct parents)))
1466 (push (cons parent item) acc)
afe98dfa 1467 (cons item grand-parent))))))))
3ab2c837
BG
1468 (mapcar out parents)))
1469
1470(defun org-list-struct-indent (start end struct parents prevs)
1471 "Indent items between positions START and END.
afe98dfa 1472
3ab2c837
BG
1473STRUCT is the list structure. PARENTS is the alist of parents
1474and PREVS is the alist of previous items, returned by,
1475respectively, `org-list-parents-alist' and
1476`org-list-prevs-alist'.
afe98dfa 1477
3ab2c837 1478START is included and END excluded.
afe98dfa 1479
3ab2c837
BG
1480STRUCT may be modified if `org-list-demote-modify-bullet' matches
1481bullets between START and END."
afe98dfa 1482 (let* (acc
3ab2c837 1483 (set-assoc (lambda (cell) (push cell acc) cell))
afe98dfa 1484 (change-bullet-maybe
3ab2c837
BG
1485 (function
1486 (lambda (item)
2f885dca
BG
1487 (let ((new-bul-p
1488 (cdr (assoc
1489 ;; Normalize ordered bullets.
1490 (let ((bul (org-trim
1491 (org-list-get-bullet item struct))))
1492 (cond ((string-match "[A-Z]\\." bul) "A.")
1493 ((string-match "[A-Z])" bul) "A)")
1494 ((string-match "[a-z]\\." bul) "a.")
1495 ((string-match "[a-z])" bul) "a)")
1496 ((string-match "[0-9]\\." bul) "1.")
1497 ((string-match "[0-9])" bul) "1)")
1498 (t bul)))
1499 org-list-demote-modify-bullet))))
3ab2c837 1500 (when new-bul-p (org-list-set-bullet item struct new-bul-p))))))
afe98dfa
CD
1501 (ind
1502 (lambda (cell)
1503 (let* ((item (car cell))
1504 (parent (cdr cell)))
1505 (cond
3ab2c837 1506 ;; Item not yet in zone: keep association.
afe98dfa
CD
1507 ((< item start) cell)
1508 ((>= item end)
3ab2c837 1509 ;; Item out of zone: follow associations in ACC.
afe98dfa
CD
1510 (let ((convert (assq parent acc)))
1511 (if convert (cons item (cdr convert)) cell)))
1512 (t
1513 ;; Item is in zone...
3ab2c837
BG
1514 (let ((prev (org-list-get-prev-item item struct prevs)))
1515 ;; Check if bullet needs to be changed.
afe98dfa
CD
1516 (funcall change-bullet-maybe item)
1517 (cond
1518 ;; First item indented but not parent: error
3ab2c837 1519 ((and (not prev) (< parent start))
afe98dfa 1520 (error "Cannot indent the first item of a list"))
3ab2c837
BG
1521 ;; First item and parent indented: keep same
1522 ;; parent.
1523 ((not prev) (funcall set-assoc cell))
1524 ;; Previous item not indented: reparent to it.
1525 ((< prev start) (funcall set-assoc (cons item prev)))
1526 ;; Previous item indented: reparent like it.
afe98dfa 1527 (t
3ab2c837
BG
1528 (funcall set-assoc
1529 (cons item (cdr (assq prev acc)))))))))))))
1530 (mapcar ind parents)))
1531
1532
e66ba1df 1533\f
3ab2c837
BG
1534;;; Repairing structures
1535
1536(defun org-list-use-alpha-bul-p (first struct prevs)
1537 "Non-nil if list starting at FIRST can have alphabetical bullets.
1538
e66ba1df 1539STRUCT is list structure. PREVS is the alist of previous items,
3ab2c837
BG
1540as returned by `org-list-prevs-alist'."
1541 (and org-alphabetical-lists
1542 (catch 'exit
1543 (let ((item first) (ascii 64) (case-fold-search nil))
1544 ;; Pretend that bullets are uppercase and check if alphabet
1545 ;; is sufficient, taking counters into account.
1546 (while item
1547 (let ((bul (org-list-get-bullet item struct))
1548 (count (org-list-get-counter item struct)))
1549 ;; Virtually determine current bullet
1550 (if (and count (string-match "[a-zA-Z]" count))
1551 ;; Counters are not case-sensitive.
1552 (setq ascii (string-to-char (upcase count)))
1553 (setq ascii (1+ ascii)))
1554 ;; Test if bullet would be over z or Z.
1555 (if (> ascii 90)
1556 (throw 'exit nil)
1557 (setq item (org-list-get-next-item item struct prevs)))))
1558 ;; All items checked. All good.
1559 t))))
1560
1561(defun org-list-inc-bullet-maybe (bullet)
1562 "Increment BULLET if applicable."
1563 (let ((case-fold-search nil))
1564 (cond
1565 ;; Num bullet: increment it.
1566 ((string-match "[0-9]+" bullet)
1567 (replace-match
1568 (number-to-string (1+ (string-to-number (match-string 0 bullet))))
1569 nil nil bullet))
1570 ;; Alpha bullet: increment it.
1571 ((string-match "[A-Za-z]" bullet)
1572 (replace-match
1573 (char-to-string (1+ (string-to-char (match-string 0 bullet))))
1574 nil nil bullet))
1575 ;; Unordered bullet: leave it.
1576 (t bullet))))
1577
1578(defun org-list-struct-fix-bul (struct prevs)
1579 "Verify and correct bullets in STRUCT.
1580PREVS is the alist of previous items, as returned by
1581`org-list-prevs-alist'.
1582
1583This function modifies STRUCT."
1584 (let ((case-fold-search nil)
1585 (fix-bul
1586 (function
1587 ;; Set bullet of ITEM in STRUCT, depending on the type of
1588 ;; first item of the list, the previous bullet and counter
1589 ;; if any.
1590 (lambda (item)
1591 (let* ((prev (org-list-get-prev-item item struct prevs))
1592 (prev-bul (and prev (org-list-get-bullet prev struct)))
1593 (counter (org-list-get-counter item struct))
1594 (bullet (org-list-get-bullet item struct))
1595 (alphap (and (not prev)
1596 (org-list-use-alpha-bul-p item struct prevs))))
1597 (org-list-set-bullet
1598 item struct
1599 (org-list-bullet-string
1600 (cond
1601 ;; Alpha counter in alpha list: use counter.
1602 ((and prev counter
1603 (string-match "[a-zA-Z]" counter)
1604 (string-match "[a-zA-Z]" prev-bul))
1605 ;; Use cond to be sure `string-match' is used in
1606 ;; both cases.
1607 (let ((real-count
1608 (cond
1609 ((string-match "[a-z]" prev-bul) (downcase counter))
1610 ((string-match "[A-Z]" prev-bul) (upcase counter)))))
1611 (replace-match real-count nil nil prev-bul)))
1612 ;; Num counter in a num list: use counter.
1613 ((and prev counter
1614 (string-match "[0-9]+" counter)
1615 (string-match "[0-9]+" prev-bul))
1616 (replace-match counter nil nil prev-bul))
1617 ;; No counter: increase, if needed, previous bullet.
1618 (prev
1619 (org-list-inc-bullet-maybe (org-list-get-bullet prev struct)))
1620 ;; Alpha counter at first item: use counter.
1621 ((and counter (org-list-use-alpha-bul-p item struct prevs)
1622 (string-match "[A-Za-z]" counter)
1623 (string-match "[A-Za-z]" bullet))
1624 (let ((real-count
1625 (cond
1626 ((string-match "[a-z]" bullet) (downcase counter))
1627 ((string-match "[A-Z]" bullet) (upcase counter)))))
1628 (replace-match real-count nil nil bullet)))
1629 ;; Num counter at first item: use counter.
1630 ((and counter
1631 (string-match "[0-9]+" counter)
1632 (string-match "[0-9]+" bullet))
1633 (replace-match counter nil nil bullet))
1634 ;; First bullet is alpha uppercase: use "A".
1635 ((and alphap (string-match "[A-Z]" bullet))
1636 (replace-match "A" nil nil bullet))
1637 ;; First bullet is alpha lowercase: use "a".
1638 ((and alphap (string-match "[a-z]" bullet))
1639 (replace-match "a" nil nil bullet))
1640 ;; First bullet is num: use "1".
1641 ((string-match "\\([0-9]+\\|[A-Za-z]\\)" bullet)
1642 (replace-match "1" nil nil bullet))
1643 ;; Not an ordered list: keep bullet.
1644 (t bullet)))))))))
1645 (mapc fix-bul (mapcar 'car struct))))
1646
1647(defun org-list-struct-fix-ind (struct parents &optional bullet-size)
1648 "Verify and correct indentation in STRUCT.
1649
1650PARENTS is the alist of parents, as returned by
1651`org-list-parents-alist'.
1652
1653If numeric optional argument BULLET-SIZE is set, assume all
1654bullets in list have this length to determine new indentation.
1655
1656This function modifies STRUCT."
1657 (let* ((ancestor (org-list-get-top-point struct))
1658 (top-ind (org-list-get-ind ancestor struct))
1659 (new-ind
afe98dfa 1660 (lambda (item)
3ab2c837
BG
1661 (let ((parent (org-list-get-parent item struct parents)))
1662 (if parent
1663 ;; Indent like parent + length of parent's bullet +
1664 ;; sub-list offset.
1665 (org-list-set-ind
1666 item struct (+ (or bullet-size
1667 (length
1668 (org-list-get-bullet parent struct)))
1669 (org-list-get-ind parent struct)
1670 org-list-indent-offset))
1671 ;; If no parent, indent like top-point.
1672 (org-list-set-ind item struct top-ind))))))
1673 (mapc new-ind (mapcar 'car (cdr struct)))))
1674
1675(defun org-list-struct-fix-box (struct parents prevs &optional ordered)
1676 "Verify and correct checkboxes in STRUCT.
1677
1678PARENTS is the alist of parents and PREVS is the alist of
1679previous items, as returned by, respectively,
1680`org-list-parents-alist' and `org-list-prevs-alist'.
1681
1682If ORDERED is non-nil, a checkbox can only be checked when every
1683checkbox before it is checked too. If there was an attempt to
1684break this rule, the function will return the blocking item. In
1685all others cases, the return value will be nil.
afe98dfa 1686
3ab2c837
BG
1687This function modifies STRUCT."
1688 (let ((all-items (mapcar 'car struct))
1689 (set-parent-box
1690 (function
1691 (lambda (item)
1692 (let* ((box-list
1693 (mapcar (lambda (child)
1694 (org-list-get-checkbox child struct))
1695 (org-list-get-children item struct parents))))
1696 (org-list-set-checkbox
1697 item struct
1698 (cond
1699 ((and (member "[ ]" box-list) (member "[X]" box-list)) "[-]")
1700 ((member "[-]" box-list) "[-]")
1701 ((member "[X]" box-list) "[X]")
1702 ((member "[ ]" box-list) "[ ]")
1703 ;; Parent has no boxed child: leave box as-is.
1704 (t (org-list-get-checkbox item struct))))))))
1705 parent-list)
1706 ;; 1. List all parents with a checkbox.
1707 (mapc
1708 (lambda (e)
1709 (let* ((parent (org-list-get-parent e struct parents))
1710 (parent-box-p (org-list-get-checkbox parent struct)))
1711 (when (and parent-box-p (not (memq parent parent-list)))
1712 (push parent parent-list))))
1713 all-items)
1714 ;; 2. Sort those parents by decreasing indentation.
1715 (setq parent-list (sort parent-list
1716 (lambda (e1 e2)
1717 (> (org-list-get-ind e1 struct)
1718 (org-list-get-ind e2 struct)))))
1719 ;; 3. For each parent, get all children's checkboxes to determine
1720 ;; and set its checkbox accordingly.
1721 (mapc set-parent-box parent-list)
1722 ;; 4. If ORDERED is set, see if we need to uncheck some boxes.
1723 (when ordered
1724 (let* ((box-list
1725 (mapcar (lambda (e) (org-list-get-checkbox e struct)) all-items))
1726 (after-unchecked (member "[ ]" box-list)))
1727 ;; There are boxes checked after an unchecked one: fix that.
1728 (when (member "[X]" after-unchecked)
1729 (let ((index (- (length struct) (length after-unchecked))))
1730 (mapc (lambda (e) (org-list-set-checkbox e struct "[ ]"))
1731 (nthcdr index all-items))
1732 ;; Verify once again the structure, without ORDERED.
1733 (org-list-struct-fix-box struct parents prevs nil)
1734 ;; Return blocking item.
1735 (nth index all-items)))))))
1736
e66ba1df
BG
1737(defun org-list-struct-fix-item-end (struct)
1738 "Verify and correct each item end position in STRUCT.
1739
1740This function modifies STRUCT."
1741 (let (end-list acc-end)
1742 (mapc (lambda (e)
1743 (let* ((pos (car e))
1744 (ind-pos (org-list-get-ind pos struct))
1745 (end-pos (org-list-get-item-end pos struct)))
1746 (unless (assq end-pos struct)
1747 ;; To determine real ind of an ending position that is
1748 ;; not at an item, we have to find the item it belongs
1749 ;; to: it is the last item (ITEM-UP), whose ending is
1750 ;; further than the position we're interested in.
1751 (let ((item-up (assoc-default end-pos acc-end '>)))
1752 (push (cons
1753 ;; Else part is for the bottom point.
1754 (if item-up (+ (org-list-get-ind item-up struct) 2) 0)
1755 end-pos)
1756 end-list)))
1757 (push (cons ind-pos pos) end-list)
1758 (push (cons end-pos pos) acc-end)))
1759 struct)
1760 (setq end-list (sort end-list (lambda (e1 e2) (< (cdr e1) (cdr e2)))))
1761 (org-list-struct-assoc-end struct end-list)))
1762
3ab2c837 1763(defun org-list-struct-apply-struct (struct old-struct)
e66ba1df 1764 "Apply set difference between STRUCT and OLD-STRUCT to the buffer.
3ab2c837
BG
1765
1766OLD-STRUCT is the structure before any modifications, and STRUCT
1767the structure to be applied. The function will only modify parts
1768of the list which have changed.
1769
1770Initial position of cursor is restored after the changes."
e66ba1df 1771 (let* ((origin (point-marker))
3ab2c837
BG
1772 (inlinetask-re (and (featurep 'org-inlinetask)
1773 (org-inlinetask-outline-regexp)))
1774 (item-re (org-item-re))
1775 (box-rule-p (cdr (assq 'checkbox org-list-automatic-rules)))
1776 (shift-body-ind
1777 (function
1778 ;; Shift the indentation between END and BEG by DELTA.
1779 ;; Start from the line before END.
1780 (lambda (end beg delta)
1781 (goto-char end)
1782 (skip-chars-backward " \r\t\n")
1783 (beginning-of-line)
1784 (while (or (> (point) beg)
1785 (and (= (point) beg)
1786 (not (looking-at item-re))))
1787 (cond
1788 ;; Skip inline tasks.
1789 ((and inlinetask-re (looking-at inlinetask-re))
1790 (org-inlinetask-goto-beginning))
1791 ;; Shift only non-empty lines.
1792 ((org-looking-at-p "^[ \t]*\\S-")
1793 (let ((i (org-get-indentation)))
1794 (org-indent-line-to (+ i delta)))))
1795 (forward-line -1)))))
1796 (modify-item
1797 (function
1798 ;; Replace ITEM first line elements with new elements from
1799 ;; STRUCT, if appropriate.
1800 (lambda (item)
1801 (goto-char item)
1802 (let* ((new-ind (org-list-get-ind item struct))
1803 (old-ind (org-get-indentation))
1804 (new-bul (org-list-bullet-string
1805 (org-list-get-bullet item struct)))
1806 (old-bul (org-list-get-bullet item old-struct))
1807 (new-box (org-list-get-checkbox item struct)))
1808 (looking-at org-list-full-item-re)
1809 ;; a. Replace bullet
1810 (unless (equal old-bul new-bul)
1811 (replace-match new-bul nil nil nil 1))
1812 ;; b. Replace checkbox.
1813 (cond
1814 ((and new-box box-rule-p
1815 (save-match-data (org-at-item-description-p)))
1816 (message "Cannot add a checkbox to a description list item"))
1817 ((equal (match-string 3) new-box))
1818 ((and (match-string 3) new-box)
1819 (replace-match new-box nil nil nil 3))
1820 ((match-string 3)
3ab2c837
BG
1821 (looking-at ".*?\\([ \t]*\\[[ X-]\\]\\)")
1822 (replace-match "" nil nil nil 1))
1823 (t (let ((counterp (match-end 2)))
1824 (goto-char (if counterp (1+ counterp) (match-end 1)))
e66ba1df 1825 (insert (concat new-box (unless counterp " "))))))
3ab2c837
BG
1826 ;; c. Indent item to appropriate column.
1827 (unless (= new-ind old-ind)
1828 (delete-region (goto-char (point-at-bol))
1829 (progn (skip-chars-forward " \t") (point)))
1830 (indent-to new-ind)))))))
1831 ;; 1. First get list of items and position endings. We maintain
1832 ;; two alists: ITM-SHIFT, determining indentation shift needed
1833 ;; at item, and END-POS, a pseudo-alist where key is ending
1834 ;; position and value point.
1835 (let (end-list acc-end itm-shift all-ends sliced-struct)
1836 (mapc (lambda (e)
1837 (let* ((pos (car e))
1838 (ind-pos (org-list-get-ind pos struct))
1839 (ind-old (org-list-get-ind pos old-struct))
1840 (bul-pos (org-list-get-bullet pos struct))
1841 (bul-old (org-list-get-bullet pos old-struct))
1842 (ind-shift (- (+ ind-pos (length bul-pos))
1843 (+ ind-old (length bul-old))))
1844 (end-pos (org-list-get-item-end pos old-struct)))
1845 (push (cons pos ind-shift) itm-shift)
1846 (unless (assq end-pos old-struct)
1847 ;; To determine real ind of an ending position that
1848 ;; is not at an item, we have to find the item it
1849 ;; belongs to: it is the last item (ITEM-UP), whose
1850 ;; ending is further than the position we're
1851 ;; interested in.
1852 (let ((item-up (assoc-default end-pos acc-end '>)))
1853 (push (cons end-pos item-up) end-list)))
1854 (push (cons end-pos pos) acc-end)))
1855 old-struct)
1856 ;; 2. Slice the items into parts that should be shifted by the
1857 ;; same amount of indentation. The slices are returned in
1858 ;; reverse order so changes modifying buffer do not change
1859 ;; positions they refer to.
1860 (setq all-ends (sort (append (mapcar 'car itm-shift)
1861 (org-uniquify (mapcar 'car end-list)))
1862 '<))
1863 (while (cdr all-ends)
1864 (let* ((up (pop all-ends))
1865 (down (car all-ends))
1866 (ind (if (assq up struct)
1867 (cdr (assq up itm-shift))
1868 (cdr (assq (cdr (assq up end-list)) itm-shift)))))
1869 (push (list down up ind) sliced-struct)))
1870 ;; 3. Shift each slice in buffer, provided delta isn't 0, from
1871 ;; end to beginning. Take a special action when beginning is
1872 ;; at item bullet.
1873 (mapc (lambda (e)
1874 (unless (zerop (nth 2 e)) (apply shift-body-ind e))
1875 (let* ((beg (nth 1 e))
1876 (cell (assq beg struct)))
1877 (unless (or (not cell) (equal cell (assq beg old-struct)))
1878 (funcall modify-item beg))))
1879 sliced-struct))
1880 ;; 4. Go back to initial position and clean marker.
1881 (goto-char origin)
1882 (move-marker origin nil)))
1883
e66ba1df 1884(defun org-list-write-struct (struct parents &optional old-struct)
3ab2c837 1885 "Correct bullets, checkboxes and indentation in list at point.
e66ba1df 1886
3ab2c837 1887STRUCT is the list structure. PARENTS is the alist of parents,
e66ba1df
BG
1888as returned by `org-list-parents-alist'.
1889
1890When non-nil, optional argument OLD-STRUCT is the reference
1891structure of the list. It should be provided whenever STRUCT
1892doesn't correspond anymore to the real list in buffer."
3ab2c837
BG
1893 ;; Order of functions matters here: checkboxes and endings need
1894 ;; correct indentation to be set, and indentation needs correct
1895 ;; bullets.
1896 ;;
1897 ;; 0. Save a copy of structure before modifications
e66ba1df 1898 (let ((old-struct (or old-struct (copy-tree struct))))
3ab2c837
BG
1899 ;; 1. Set a temporary, but coherent with PARENTS, indentation in
1900 ;; order to get items endings and bullets properly
1901 (org-list-struct-fix-ind struct parents 2)
e66ba1df
BG
1902 ;; 2. Fix each item end to get correct prevs alist.
1903 (org-list-struct-fix-item-end struct)
1904 ;; 3. Get bullets right.
1905 (let ((prevs (org-list-prevs-alist struct)))
1906 (org-list-struct-fix-bul struct prevs)
1907 ;; 4. Now get real indentation.
1908 (org-list-struct-fix-ind struct parents)
1909 ;; 5. Eventually fix checkboxes.
1910 (org-list-struct-fix-box struct parents prevs))
1911 ;; 6. Apply structure modifications to buffer.
1912 (org-list-struct-apply-struct struct old-struct)))
1913
1914
1915\f
3ab2c837 1916;;; Misc Tools
ce4fdcb9 1917
3ab2c837
BG
1918(defun org-apply-on-list (function init-value &rest args)
1919 "Call FUNCTION on each item of the list at point.
1920FUNCTION must be called with at least one argument: INIT-VALUE,
1921that will contain the value returned by the function at the
1922previous item, plus ARGS extra arguments.
47ffc456 1923
3ab2c837 1924FUNCTION is applied on items in reverse order.
afe98dfa 1925
3ab2c837
BG
1926As an example, \(org-apply-on-list \(lambda \(result\) \(1+ result\)\) 0\)
1927will return the number of items in the current list.
1928
1929Sublists of the list are skipped. Cursor is always at the
1930beginning of the item."
1931 (let* ((struct (org-list-struct))
1932 (prevs (org-list-prevs-alist struct))
1933 (item (copy-marker (point-at-bol)))
1934 (all (org-list-get-all-items (marker-position item) struct prevs))
1935 (value init-value))
1936 (mapc (lambda (e)
1937 (goto-char e)
1938 (setq value (apply function value args)))
1939 (nreverse all))
1940 (goto-char item)
1941 (move-marker item nil)
1942 value))
1943
1944(defun org-list-set-item-visibility (item struct view)
1945 "Set visibility of ITEM in STRUCT to VIEW.
1946
e66ba1df 1947Possible values are: `folded', `children' or `subtree'. See
3ab2c837
BG
1948`org-cycle' for more information."
1949 (cond
1950 ((eq view 'folded)
1951 (let ((item-end (org-list-get-item-end-before-blank item struct)))
1952 ;; Hide from eol
1953 (outline-flag-region (save-excursion (goto-char item) (point-at-eol))
1954 item-end t)))
1955 ((eq view 'children)
1956 ;; First show everything.
1957 (org-list-set-item-visibility item struct 'subtree)
1958 ;; Then fold every child.
1959 (let* ((parents (org-list-parents-alist struct))
1960 (children (org-list-get-children item struct parents)))
1961 (mapc (lambda (e)
1962 (org-list-set-item-visibility e struct 'folded))
1963 children)))
1964 ((eq view 'subtree)
1965 ;; Show everything
1966 (let ((item-end (org-list-get-item-end item struct)))
1967 (outline-flag-region item item-end nil)))))
1968
1969(defun org-list-item-body-column (item)
1970 "Return column at which body of ITEM should start."
1971 (let (bpos bcol tpos tcol)
1972 (save-excursion
1973 (goto-char item)
1974 (looking-at "[ \t]*\\(\\S-+\\)\\(.*[ \t]+::\\)?[ \t]+")
1975 (setq bpos (match-beginning 1) tpos (match-end 0)
1976 bcol (progn (goto-char bpos) (current-column))
1977 tcol (progn (goto-char tpos) (current-column)))
1978 (when (> tcol (+ bcol org-description-max-indent))
1979 (setq tcol (+ bcol 5))))
1980 tcol))
1981
1982
e66ba1df 1983\f
3ab2c837
BG
1984;;; Interactive functions
1985
1986(defalias 'org-list-get-item-begin 'org-in-item-p)
1987
1988(defun org-beginning-of-item ()
1989 "Go to the beginning of the current item.
1990Throw an error when not in a list."
afe98dfa 1991 (interactive)
3ab2c837
BG
1992 (let ((begin (org-in-item-p)))
1993 (if begin (goto-char begin) (error "Not in an item"))))
afe98dfa 1994
3ab2c837
BG
1995(defun org-beginning-of-item-list ()
1996 "Go to the beginning item of the current list or sublist.
1997Throw an error when not in a list."
1998 (interactive)
1999 (let ((begin (org-in-item-p)))
2000 (if (not begin)
2001 (error "Not in an item")
2002 (goto-char begin)
2003 (let* ((struct (org-list-struct))
2004 (prevs (org-list-prevs-alist struct)))
2005 (goto-char (org-list-get-list-begin begin struct prevs))))))
afe98dfa 2006
3ab2c837
BG
2007(defun org-end-of-item-list ()
2008 "Go to the end of the current list or sublist.
2009Throw an error when not in a list."
2010 (interactive)
2011 (let ((begin (org-in-item-p)))
2012 (if (not begin)
2013 (error "Not in an item")
2014 (goto-char begin)
2015 (let* ((struct (org-list-struct))
2016 (prevs (org-list-prevs-alist struct)))
2017 (goto-char (org-list-get-list-end begin struct prevs))))))
47ffc456 2018
3ab2c837
BG
2019(defun org-end-of-item ()
2020 "Go to the end of the current item.
2021Throw an error when not in a list."
2022 (interactive)
2023 (let ((begin (org-in-item-p)))
2024 (if (not begin)
2025 (error "Not in an item")
2026 (goto-char begin)
2027 (let ((struct (org-list-struct)))
2028 (goto-char (org-list-get-item-end begin struct))))))
47ffc456 2029
3ab2c837
BG
2030(defun org-previous-item ()
2031 "Move to the beginning of the previous item.
2032Throw an error when not in a list. Also throw an error when at
2033first item, unless `org-list-use-circular-motion' is non-nil."
2034 (interactive)
2035 (let ((item (org-in-item-p)))
2036 (if (not item)
2037 (error "Not in an item")
2038 (goto-char item)
2039 (let* ((struct (org-list-struct))
2040 (prevs (org-list-prevs-alist struct))
2041 (prevp (org-list-get-prev-item item struct prevs)))
2042 (cond
2043 (prevp (goto-char prevp))
2044 (org-list-use-circular-motion
2045 (goto-char (org-list-get-last-item item struct prevs)))
2046 (t (error "On first item")))))))
afe98dfa 2047
3ab2c837
BG
2048(defun org-next-item ()
2049 "Move to the beginning of the next item.
2050Throw an error when not in a list. Also throw an error when at
2051last item, unless `org-list-use-circular-motion' is non-nil."
2052 (interactive)
2053 (let ((item (org-in-item-p)))
2054 (if (not item)
2055 (error "Not in an item")
2056 (goto-char item)
2057 (let* ((struct (org-list-struct))
2058 (prevs (org-list-prevs-alist struct))
2059 (prevp (org-list-get-next-item item struct prevs)))
2060 (cond
2061 (prevp (goto-char prevp))
2062 (org-list-use-circular-motion
2063 (goto-char (org-list-get-first-item item struct prevs)))
2064 (t (error "On last item")))))))
afe98dfa 2065
3ab2c837
BG
2066(defun org-move-item-down ()
2067 "Move the item at point down, i.e. swap with following item.
2068Sub-items (items with larger indentation) are considered part of
2069the item, so this really moves item trees."
2070 (interactive)
2071 (unless (org-at-item-p) (error "Not at an item"))
2072 (let* ((col (current-column))
2073 (item (point-at-bol))
2074 (struct (org-list-struct))
2075 (prevs (org-list-prevs-alist struct))
2076 (next-item (org-list-get-next-item (point-at-bol) struct prevs)))
2077 (unless (or next-item org-list-use-circular-motion)
2078 (error "Cannot move this item further down"))
2079 (if (not next-item)
2080 (setq struct (org-list-send-item item 'begin struct))
2081 (setq struct (org-list-swap-items item next-item struct))
2082 (goto-char
2083 (org-list-get-next-item item struct (org-list-prevs-alist struct))))
2084 (org-list-write-struct struct (org-list-parents-alist struct))
2085 (org-move-to-column col)))
afe98dfa 2086
3ab2c837
BG
2087(defun org-move-item-up ()
2088 "Move the item at point up, i.e. swap with previous item.
2089Sub-items (items with larger indentation) are considered part of
2090the item, so this really moves item trees."
2091 (interactive)
2092 (unless (org-at-item-p) (error "Not at an item"))
2093 (let* ((col (current-column))
2094 (item (point-at-bol))
2095 (struct (org-list-struct))
2096 (prevs (org-list-prevs-alist struct))
2097 (prev-item (org-list-get-prev-item (point-at-bol) struct prevs)))
2098 (unless (or prev-item org-list-use-circular-motion)
2099 (error "Cannot move this item further up"))
2100 (if (not prev-item)
2101 (setq struct (org-list-send-item item 'end struct))
2102 (setq struct (org-list-swap-items prev-item item struct)))
2103 (org-list-write-struct struct (org-list-parents-alist struct))
2104 (org-move-to-column col)))
afe98dfa 2105
3ab2c837
BG
2106(defun org-insert-item (&optional checkbox)
2107 "Insert a new item at the current level.
2108If cursor is before first character after bullet of the item, the
2109new item will be created before the current one.
afe98dfa 2110
3ab2c837 2111If CHECKBOX is non-nil, add a checkbox next to the bullet.
afe98dfa 2112
3ab2c837
BG
2113Return t when things worked, nil when we are not in an item, or
2114item is invisible."
2115 (let ((itemp (org-in-item-p))
2116 (pos (point)))
2117 ;; If cursor isn't is a list or if list is invisible, return nil.
2118 (unless (or (not itemp)
2119 (save-excursion
2120 (goto-char itemp)
2121 (outline-invisible-p)))
2122 (if (save-excursion
2123 (goto-char itemp)
2124 (org-at-item-timer-p))
2125 ;; Timer list: delegate to `org-timer-item'.
2126 (progn (org-timer-item) t)
2127 (let* ((struct (save-excursion (goto-char itemp)
2128 (org-list-struct)))
2129 (prevs (org-list-prevs-alist struct))
2130 ;; If we're in a description list, ask for the new term.
2131 (desc (when (org-list-get-tag itemp struct)
2132 (concat (read-string "Term: ") " :: ")))
2133 ;; Don't insert a checkbox if checkbox rule is applied
2134 ;; and it is a description item.
2135 (checkp (and checkbox
2136 (or (not desc)
2137 (not (cdr (assq 'checkbox
2138 org-list-automatic-rules)))))))
2139 (setq struct
2140 (org-list-insert-item pos struct prevs checkp desc))
2141 (org-list-write-struct struct (org-list-parents-alist struct))
2142 (when checkp (org-update-checkbox-count-maybe))
2143 (looking-at org-list-full-item-re)
2144 (goto-char (match-end 0))
2145 t)))))
2146
2147(defun org-list-repair ()
2148 "Fix indentation, bullets and checkboxes is the list at point."
afe98dfa
CD
2149 (interactive)
2150 (unless (org-at-item-p) (error "This is not a list"))
3ab2c837
BG
2151 (let* ((struct (org-list-struct))
2152 (parents (org-list-parents-alist struct)))
2153 (org-list-write-struct struct parents)))
47ffc456 2154
afe98dfa
CD
2155(defun org-cycle-list-bullet (&optional which)
2156 "Cycle through the different itemize/enumerate bullets.
2157This cycle the entire list level through the sequence:
47ffc456 2158
afe98dfa 2159 `-' -> `+' -> `*' -> `1.' -> `1)'
86fbb8ca 2160
3ab2c837
BG
2161If WHICH is a valid string, use that as the new bullet. If WHICH
2162is an integer, 0 means `-', 1 means `+' etc. If WHICH is
2163`previous', cycle backwards."
afe98dfa 2164 (interactive "P")
3ab2c837 2165 (unless (org-at-item-p) (error "Not at an item"))
acedf35c 2166 (save-excursion
3ab2c837
BG
2167 (beginning-of-line)
2168 (let* ((struct (org-list-struct))
2169 (parents (org-list-parents-alist struct))
2170 (prevs (org-list-prevs-alist struct))
2171 (list-beg (org-list-get-first-item (point) struct prevs))
2172 (bullet (org-list-get-bullet list-beg struct))
2173 (bullet-rule-p (cdr (assq 'bullet org-list-automatic-rules)))
2174 (alpha-p (org-list-use-alpha-bul-p list-beg struct prevs))
2175 (case-fold-search nil)
acedf35c 2176 (current (cond
3ab2c837
BG
2177 ((string-match "[a-z]\\." bullet) "a.")
2178 ((string-match "[a-z])" bullet) "a)")
2179 ((string-match "[A-Z]\\." bullet) "A.")
2180 ((string-match "[A-Z])" bullet) "A)")
acedf35c
CD
2181 ((string-match "\\." bullet) "1.")
2182 ((string-match ")" bullet) "1)")
3ab2c837
BG
2183 (t (org-trim bullet))))
2184 ;; Compute list of possible bullets, depending on context.
2185 (bullet-list
2186 (append '("-" "+" )
2187 ;; *-bullets are not allowed at column 0.
2188 (unless (and bullet-rule-p
2189 (looking-at "\\S-")) '("*"))
2190 ;; Description items cannot be numbered.
2191 (unless (or (eq org-plain-list-ordered-item-terminator ?\))
2192 (and bullet-rule-p (org-at-item-description-p)))
2193 '("1."))
2194 (unless (or (eq org-plain-list-ordered-item-terminator ?.)
2195 (and bullet-rule-p (org-at-item-description-p)))
2196 '("1)"))
2197 (unless (or (not alpha-p)
2198 (eq org-plain-list-ordered-item-terminator ?\))
2199 (and bullet-rule-p (org-at-item-description-p)))
2200 '("a." "A."))
2201 (unless (or (not alpha-p)
2202 (eq org-plain-list-ordered-item-terminator ?.)
2203 (and bullet-rule-p (org-at-item-description-p)))
2204 '("a)" "A)"))))
acedf35c
CD
2205 (len (length bullet-list))
2206 (item-index (- len (length (member current bullet-list))))
2207 (get-value (lambda (index) (nth (mod index len) bullet-list)))
2208 (new (cond
2209 ((member which bullet-list) which)
2210 ((numberp which) (funcall get-value which))
2211 ((eq 'previous which) (funcall get-value (1- item-index)))
2212 (t (funcall get-value (1+ item-index))))))
3ab2c837
BG
2213 ;; Use a short variation of `org-list-write-struct' as there's
2214 ;; no need to go through all the steps.
2215 (let ((old-struct (copy-tree struct)))
2216 (org-list-set-bullet list-beg struct (org-list-bullet-string new))
2217 (org-list-struct-fix-bul struct prevs)
2218 (org-list-struct-fix-ind struct parents)
2219 (org-list-struct-apply-struct struct old-struct)))))
afe98dfa
CD
2220
2221(defun org-toggle-checkbox (&optional toggle-presence)
2222 "Toggle the checkbox in the current line.
2223With prefix arg TOGGLE-PRESENCE, add or remove checkboxes. With
2224double prefix, set checkbox to [-].
2225
2226When there is an active region, toggle status or presence of the
3ab2c837
BG
2227first checkbox there, and make every item inside have the same
2228status or presence, respectively.
afe98dfa
CD
2229
2230If the cursor is in a headline, apply this to all checkbox items
2231in the text below the heading, taking as reference the first item
2232in subtree, ignoring drawers."
2233 (interactive "P")
3ab2c837
BG
2234 (save-excursion
2235 (let* (singlep
2236 block-item
2237 lim-up
2238 lim-down
2239 (drawer-re (concat "^[ \t]*:\\("
2240 (mapconcat 'regexp-quote org-drawers "\\|")
2241 "\\):[ \t]*$"))
2242 (keyword-re (concat "^[ \t]*\\<\\(" org-scheduled-string
2243 "\\|" org-deadline-string
2244 "\\|" org-closed-string
2245 "\\|" org-clock-string "\\)"
2246 " *[[<]\\([^]>]+\\)[]>]"))
2247 (orderedp (org-entry-get nil "ORDERED"))
2248 (bounds
2249 ;; In a region, start at first item in region.
2250 (cond
2251 ((org-region-active-p)
2252 (let ((limit (region-end)))
2253 (goto-char (region-beginning))
2254 (if (org-list-search-forward (org-item-beginning-re) limit t)
2255 (setq lim-up (point-at-bol))
2256 (error "No item in region"))
2257 (setq lim-down (copy-marker limit))))
e66ba1df 2258 ((org-at-heading-p)
3ab2c837
BG
2259 ;; On an heading, start at first item after drawers and
2260 ;; time-stamps (scheduled, etc.).
2261 (let ((limit (save-excursion (outline-next-heading) (point))))
2262 (forward-line 1)
2263 (while (or (looking-at drawer-re) (looking-at keyword-re))
2264 (if (looking-at keyword-re)
2265 (forward-line 1)
2266 (re-search-forward "^[ \t]*:END:" limit nil)))
2267 (if (org-list-search-forward (org-item-beginning-re) limit t)
2268 (setq lim-up (point-at-bol))
2269 (error "No item in subtree"))
2270 (setq lim-down (copy-marker limit))))
2271 ;; Just one item: set SINGLEP flag.
2272 ((org-at-item-p)
2273 (setq singlep t)
2274 (setq lim-up (point-at-bol)
e66ba1df 2275 lim-down (copy-marker (point-at-eol))))
3ab2c837
BG
2276 (t (error "Not at an item or heading, and no active region"))))
2277 ;; Determine the checkbox going to be applied to all items
2278 ;; within bounds.
2279 (ref-checkbox
2280 (progn
2281 (goto-char lim-up)
2282 (let ((cbox (and (org-at-item-checkbox-p) (match-string 1))))
2283 (cond
2284 ((equal toggle-presence '(16)) "[-]")
2285 ((equal toggle-presence '(4))
2286 (unless cbox "[ ]"))
2287 ((equal "[X]" cbox) "[ ]")
2288 (t "[X]"))))))
2289 ;; When an item is found within bounds, grab the full list at
2290 ;; point structure, then: (1) set check-box of all its items
2291 ;; within bounds to REF-CHECKBOX, (2) fix check-boxes of the
2292 ;; whole list, (3) move point after the list.
2293 (goto-char lim-up)
2294 (while (and (< (point) lim-down)
2295 (org-list-search-forward (org-item-beginning-re)
2296 lim-down 'move))
2297 (let* ((struct (org-list-struct))
2298 (struct-copy (copy-tree struct))
2299 (parents (org-list-parents-alist struct))
2300 (prevs (org-list-prevs-alist struct))
2301 (bottom (copy-marker (org-list-get-bottom-point struct)))
2302 (items-to-toggle (org-remove-if
2303 (lambda (e) (or (< e lim-up) (> e lim-down)))
2304 (mapcar 'car struct))))
2305 (mapc (lambda (e) (org-list-set-checkbox
2306 e struct
2307 ;; If there is no box at item, leave as-is
2308 ;; unless function was called with C-u prefix.
2309 (let ((cur-box (org-list-get-checkbox e struct)))
2310 (if (or cur-box (equal toggle-presence '(4)))
2311 ref-checkbox
2312 cur-box))))
2313 items-to-toggle)
2314 (setq block-item (org-list-struct-fix-box
2315 struct parents prevs orderedp))
2316 ;; Report some problems due to ORDERED status of subtree.
2317 ;; If only one box was being checked, throw an error, else,
2318 ;; only signal problems.
2319 (cond
2320 ((and singlep block-item (> lim-up block-item))
2321 (error
2322 "Checkbox blocked because of unchecked box at line %d"
2323 (org-current-line block-item)))
2324 (block-item
2325 (message
2326 "Checkboxes were removed due to unchecked box at line %d"
2327 (org-current-line block-item))))
2328 (goto-char bottom)
3ab2c837 2329 (move-marker bottom nil)
e66ba1df
BG
2330 (org-list-struct-apply-struct struct struct-copy)))
2331 (move-marker lim-down nil)))
3ab2c837 2332 (org-update-checkbox-count-maybe))
afe98dfa
CD
2333
2334(defun org-reset-checkbox-state-subtree ()
2335 "Reset all checkboxes in an entry subtree."
2336 (interactive "*")
3ab2c837
BG
2337 (if (org-before-first-heading-p)
2338 (error "Not inside a tree")
2339 (save-restriction
2340 (save-excursion
2341 (org-narrow-to-subtree)
2342 (org-show-subtree)
2343 (goto-char (point-min))
2344 (let ((end (point-max)))
2345 (while (< (point) end)
2346 (when (org-at-item-checkbox-p)
2347 (replace-match "[ ]" t t nil 1))
2348 (beginning-of-line 2)))
2349 (org-update-checkbox-count-maybe 'all)))))
afe98dfa
CD
2350
2351(defun org-update-checkbox-count (&optional all)
2352 "Update the checkbox statistics in the current section.
3ab2c837
BG
2353This will find all statistic cookies like [57%] and [6/12] and
2354update them with the current numbers.
2355
2356With optional prefix argument ALL, do this for the whole buffer."
afe98dfa 2357 (interactive "P")
c8d0cf5c 2358 (save-excursion
3ab2c837
BG
2359 (let ((cookie-re "\\(\\(\\[[0-9]*%\\]\\)\\|\\(\\[[0-9]*/[0-9]*\\]\\)\\)")
2360 (box-re "^[ \t]*\\([-+*]\\|\\([0-9]+\\|[A-Za-z]\\)[.)]\\)[ \t]+\\(?:\\[@\\(?:start:\\)?\\([0-9]+\\|[A-Za-z]\\)\\][ \t]*\\)?\\(\\[[- X]\\]\\)")
2361 (recursivep
2362 (or (not org-hierarchical-checkbox-statistics)
2363 (string-match "\\<recursive\\>"
2364 (or (org-entry-get nil "COOKIE_DATA") ""))))
2365 (bounds (if all
2366 (cons (point-min) (point-max))
2367 (cons (or (ignore-errors (org-back-to-heading t) (point))
2368 (point-min))
2369 (save-excursion (outline-next-heading) (point)))))
2370 (count-boxes
2371 (function
2372 ;; Return number of checked boxes and boxes of all types
2373 ;; in all structures in STRUCTS. If RECURSIVEP is
2374 ;; non-nil, also count boxes in sub-lists. If ITEM is
2375 ;; nil, count across the whole structure, else count only
2376 ;; across subtree whose ancestor is ITEM.
2377 (lambda (item structs recursivep)
2378 (let ((c-on 0) (c-all 0))
2379 (mapc
2380 (lambda (s)
2381 (let* ((pre (org-list-prevs-alist s))
2382 (par (org-list-parents-alist s))
2383 (items
2384 (cond
2385 ((and recursivep item) (org-list-get-subtree item s))
2386 (recursivep (mapcar 'car s))
2387 (item (org-list-get-children item s par))
2388 (t (org-list-get-all-items
2389 (org-list-get-top-point s) s pre))))
2390 (cookies (delq nil (mapcar
2391 (lambda (e)
2392 (org-list-get-checkbox e s))
2393 items))))
2394 (setq c-all (+ (length cookies) c-all)
2395 c-on (+ (org-count "[X]" cookies) c-on))))
2396 structs)
2397 (cons c-on c-all)))))
2398 (backup-end 1)
2399 cookies-list structs-bak box-num)
2400 (goto-char (car bounds))
2401 ;; 1. Build an alist for each cookie found within BOUNDS. The
2402 ;; key will be position at beginning of cookie and values
2403 ;; ending position, format of cookie, and a cell whose car is
2404 ;; number of checked boxes to report, and cdr total number of
2405 ;; boxes.
2406 (while (re-search-forward cookie-re (cdr bounds) t)
2407 (catch 'skip
2408 (save-excursion
2409 (push
2410 (list
2411 (match-beginning 1) ; cookie start
2412 (match-end 1) ; cookie end
2413 (match-string 2) ; percent?
2414 (cond ; boxes count
2415 ;; Cookie is at an heading, but specifically for todo,
2416 ;; not for checkboxes: skip it.
e66ba1df 2417 ((and (org-at-heading-p)
3ab2c837
BG
2418 (string-match "\\<todo\\>"
2419 (downcase
2420 (or (org-entry-get nil "COOKIE_DATA") ""))))
2421 (throw 'skip nil))
2422 ;; Cookie is at an heading, but all lists before next
2423 ;; heading already have been read. Use data collected
2424 ;; in STRUCTS-BAK. This should only happen when
2425 ;; heading has more than one cookie on it.
e66ba1df 2426 ((and (org-at-heading-p)
3ab2c837
BG
2427 (<= (save-excursion (outline-next-heading) (point))
2428 backup-end))
2429 (funcall count-boxes nil structs-bak recursivep))
2430 ;; Cookie is at a fresh heading. Grab structure of
2431 ;; every list containing a checkbox between point and
2432 ;; next headline, and save them in STRUCTS-BAK.
e66ba1df 2433 ((org-at-heading-p)
3ab2c837
BG
2434 (setq backup-end (save-excursion
2435 (outline-next-heading) (point))
2436 structs-bak nil)
2437 (while (org-list-search-forward box-re backup-end 'move)
2438 (let* ((struct (org-list-struct))
2439 (bottom (org-list-get-bottom-point struct)))
2440 (push struct structs-bak)
2441 (goto-char bottom)))
2442 (funcall count-boxes nil structs-bak recursivep))
2443 ;; Cookie is at an item, and we already have list
2444 ;; structure stored in STRUCTS-BAK.
2445 ((and (org-at-item-p)
2446 (< (point-at-bol) backup-end)
2447 ;; Only lists in no special context are stored.
2448 (not (nth 2 (org-list-context))))
2449 (funcall count-boxes (point-at-bol) structs-bak recursivep))
2450 ;; Cookie is at an item, but we need to compute list
2451 ;; structure.
2452 ((org-at-item-p)
2453 (let ((struct (org-list-struct)))
2454 (setq backup-end (org-list-get-bottom-point struct)
2455 structs-bak (list struct)))
2456 (funcall count-boxes (point-at-bol) structs-bak recursivep))
2457 ;; Else, cookie found is at a wrong place. Skip it.
2458 (t (throw 'skip nil))))
2459 cookies-list))))
2460 ;; 2. Apply alist to buffer, in reverse order so positions stay
2461 ;; unchanged after cookie modifications.
2462 (mapc (lambda (cookie)
2463 (let* ((beg (car cookie))
2464 (end (nth 1 cookie))
2465 (percentp (nth 2 cookie))
2466 (checked (car (nth 3 cookie)))
2467 (total (cdr (nth 3 cookie)))
2468 (new (if percentp
2469 (format "[%d%%]" (/ (* 100 checked)
2470 (max 1 total)))
2471 (format "[%d/%d]" checked total))))
2472 (goto-char beg)
2473 (insert new)
2474 (delete-region (point) (+ (point) (- end beg)))
2475 (when org-auto-align-tags (org-fix-tags-on-the-fly))))
2476 cookies-list))))
afe98dfa
CD
2477
2478(defun org-get-checkbox-statistics-face ()
2479 "Select the face for checkbox statistics.
2480The face will be `org-done' when all relevant boxes are checked.
2481Otherwise it will be `org-todo'."
2482 (if (match-end 1)
2483 (if (equal (match-string 1) "100%")
2484 'org-checkbox-statistics-done
2485 'org-checkbox-statistics-todo)
2486 (if (and (> (match-end 2) (match-beginning 2))
2487 (equal (match-string 2) (match-string 3)))
2488 'org-checkbox-statistics-done
2489 'org-checkbox-statistics-todo)))
2490
3ab2c837 2491(defun org-update-checkbox-count-maybe (&optional all)
e66ba1df
BG
2492 "Update checkbox statistics unless turned off by user.
2493With an optional argument ALL, update them in the whole buffer."
3ab2c837
BG
2494 (when (cdr (assq 'checkbox org-list-automatic-rules))
2495 (org-update-checkbox-count all))
2496 (run-hooks 'org-checkbox-statistics-hook))
afe98dfa 2497
3ab2c837
BG
2498(defvar org-last-indent-begin-marker (make-marker))
2499(defvar org-last-indent-end-marker (make-marker))
2500(defun org-list-indent-item-generic (arg no-subtree struct)
2501 "Indent a local list item including its children.
2502When number ARG is a negative, item will be outdented, otherwise
2503it will be indented.
afe98dfa 2504
3ab2c837 2505If a region is active, all items inside will be moved.
afe98dfa 2506
3ab2c837
BG
2507If NO-SUBTREE is non-nil, only indent the item itself, not its
2508children.
2509
2510STRUCT is the list structure.
2511
2512Return t if successful."
2513 (save-excursion
3ab2c837
BG
2514 (let* ((regionp (org-region-active-p))
2515 (rbeg (and regionp (region-beginning)))
2516 (rend (and regionp (region-end)))
2517 (top (org-list-get-top-point struct))
2518 (parents (org-list-parents-alist struct))
2519 (prevs (org-list-prevs-alist struct))
2520 ;; Are we going to move the whole list?
2521 (specialp
2f885dca
BG
2522 (and (not regionp)
2523 (= top (point-at-bol))
3ab2c837
BG
2524 (cdr (assq 'indent org-list-automatic-rules))
2525 (if no-subtree
2526 (error
2527 "First item of list cannot move without its subtree")
2528 t))))
2529 ;; Determine begin and end points of zone to indent. If moving
2530 ;; more than one item, save them for subsequent moves.
2531 (unless (and (memq last-command '(org-shiftmetaright org-shiftmetaleft))
2532 (memq this-command '(org-shiftmetaright org-shiftmetaleft)))
2533 (if regionp
2534 (progn
2535 (set-marker org-last-indent-begin-marker rbeg)
2536 (set-marker org-last-indent-end-marker rend))
2f885dca 2537 (set-marker org-last-indent-begin-marker (point-at-bol))
3ab2c837
BG
2538 (set-marker org-last-indent-end-marker
2539 (cond
2540 (specialp (org-list-get-bottom-point struct))
2f885dca
BG
2541 (no-subtree (1+ (point-at-bol)))
2542 (t (org-list-get-item-end (point-at-bol) struct))))))
3ab2c837
BG
2543 (let* ((beg (marker-position org-last-indent-begin-marker))
2544 (end (marker-position org-last-indent-end-marker)))
2545 (cond
2546 ;; Special case: moving top-item with indent rule.
2547 (specialp
2548 (let* ((level-skip (org-level-increment))
2549 (offset (if (< arg 0) (- level-skip) level-skip))
2550 (top-ind (org-list-get-ind beg struct))
2551 (old-struct (copy-tree struct)))
2552 (if (< (+ top-ind offset) 0)
2553 (error "Cannot outdent beyond margin")
2554 ;; Change bullet if necessary.
2555 (when (and (= (+ top-ind offset) 0)
2556 (string-match "*"
2557 (org-list-get-bullet beg struct)))
2558 (org-list-set-bullet beg struct
2559 (org-list-bullet-string "-")))
2560 ;; Shift every item by OFFSET and fix bullets. Then
2561 ;; apply changes to buffer.
2562 (mapc (lambda (e)
2563 (let ((ind (org-list-get-ind (car e) struct)))
2564 (org-list-set-ind (car e) struct (+ ind offset))))
2565 struct)
2566 (org-list-struct-fix-bul struct prevs)
2567 (org-list-struct-apply-struct struct old-struct))))
2568 ;; Forbidden move:
2569 ((and (< arg 0)
2570 ;; If only one item is moved, it mustn't have a child.
2571 (or (and no-subtree
2572 (not regionp)
2573 (org-list-has-child-p beg struct))
2574 ;; If a subtree or region is moved, the last item
2575 ;; of the subtree mustn't have a child.
2576 (let ((last-item (caar
2577 (reverse
2578 (org-remove-if
2579 (lambda (e) (>= (car e) end))
2580 struct)))))
2581 (org-list-has-child-p last-item struct))))
2582 (error "Cannot outdent an item without its children"))
2583 ;; Normal shifting
2584 (t
2585 (let* ((new-parents
2586 (if (< arg 0)
2587 (org-list-struct-outdent beg end struct parents)
2588 (org-list-struct-indent beg end struct parents prevs))))
2589 (org-list-write-struct struct new-parents))
2590 (org-update-checkbox-count-maybe))))))
2591 t)
2592
2593(defun org-outdent-item ()
2594 "Outdent a local list item, but not its children.
2595If a region is active, all items inside will be moved."
2596 (interactive)
2f885dca
BG
2597 (let ((regionp (org-region-active-p)))
2598 (cond
2599 ((or (org-at-item-p)
2600 (and regionp
2601 (save-excursion (goto-char (region-beginning))
2602 (org-at-item-p))))
2603 (let ((struct (if (not regionp) (org-list-struct)
2604 (save-excursion (goto-char (region-beginning))
2605 (org-list-struct)))))
2606 (org-list-indent-item-generic -1 t struct)))
2607 (regionp (error "Region not starting at an item"))
2608 (t (error "Not at an item")))))
3ab2c837
BG
2609
2610(defun org-indent-item ()
2611 "Indent a local list item, but not its children.
2612If a region is active, all items inside will be moved."
2613 (interactive)
2f885dca
BG
2614 (let ((regionp (org-region-active-p)))
2615 (cond
2616 ((or (org-at-item-p)
2617 (and regionp
2618 (save-excursion (goto-char (region-beginning))
2619 (org-at-item-p))))
2620 (let ((struct (if (not regionp) (org-list-struct)
2621 (save-excursion (goto-char (region-beginning))
2622 (org-list-struct)))))
2623 (org-list-indent-item-generic 1 t struct)))
2624 (regionp (error "Region not starting at an item"))
2625 (t (error "Not at an item")))))
3ab2c837
BG
2626
2627(defun org-outdent-item-tree ()
2628 "Outdent a local list item including its children.
2629If a region is active, all items inside will be moved."
2630 (interactive)
2631 (let ((regionp (org-region-active-p)))
2632 (cond
2633 ((or (org-at-item-p)
2f885dca
BG
2634 (and regionp
2635 (save-excursion (goto-char (region-beginning))
2636 (org-at-item-p))))
2637 (let ((struct (if (not regionp) (org-list-struct)
2638 (save-excursion (goto-char (region-beginning))
2639 (org-list-struct)))))
3ab2c837
BG
2640 (org-list-indent-item-generic -1 nil struct)))
2641 (regionp (error "Region not starting at an item"))
2642 (t (error "Not at an item")))))
2643
2644(defun org-indent-item-tree ()
2645 "Indent a local list item including its children.
2646If a region is active, all items inside will be moved."
2647 (interactive)
2648 (let ((regionp (org-region-active-p)))
2649 (cond
2650 ((or (org-at-item-p)
2f885dca
BG
2651 (and regionp
2652 (save-excursion (goto-char (region-beginning))
2653 (org-at-item-p))))
2654 (let ((struct (if (not regionp) (org-list-struct)
2655 (save-excursion (goto-char (region-beginning))
2656 (org-list-struct)))))
3ab2c837
BG
2657 (org-list-indent-item-generic 1 nil struct)))
2658 (regionp (error "Region not starting at an item"))
2659 (t (error "Not at an item")))))
2660
2661(defvar org-tab-ind-state)
2662(defun org-cycle-item-indentation ()
2663 "Cycle levels of indentation of an empty item.
27e428e7 2664The first run indents the item, if applicable. Subsequent runs
3ab2c837
BG
2665outdent it at meaningful levels in the list. When done, item is
2666put back at its original position with its original bullet.
2667
2668Return t at each successful move."
2669 (when (org-at-item-p)
2670 (let* ((org-adapt-indentation nil)
2671 (struct (org-list-struct))
2672 (ind (org-list-get-ind (point-at-bol) struct))
2673 (bullet (org-trim (buffer-substring (point-at-bol) (point-at-eol)))))
2674 ;; Accept empty items or if cycle has already started.
2675 (when (or (eq last-command 'org-cycle-item-indentation)
2676 (and (save-excursion
2677 (beginning-of-line)
2678 (looking-at org-list-full-item-re))
2679 (>= (match-end 0) (save-excursion
2680 (goto-char (org-list-get-item-end
2681 (point-at-bol) struct))
2682 (skip-chars-backward " \r\t\n")
2683 (point)))))
2684 (setq this-command 'org-cycle-item-indentation)
2685 ;; When in the middle of the cycle, try to outdent first. If
2686 ;; it fails, and point is still at initial position, indent.
2687 ;; Else, re-create it at its original position.
2688 (if (eq last-command 'org-cycle-item-indentation)
2689 (cond
2690 ((ignore-errors (org-list-indent-item-generic -1 t struct)))
2691 ((and (= ind (car org-tab-ind-state))
2692 (ignore-errors (org-list-indent-item-generic 1 t struct))))
2693 (t (delete-region (point-at-bol) (point-at-eol))
2694 (org-indent-to-column (car org-tab-ind-state))
2695 (insert (cdr org-tab-ind-state) " ")
2696 ;; Break cycle
2697 (setq this-command 'identity)))
2698 ;; If a cycle is starting, remember indentation and bullet,
2699 ;; then try to indent. If it fails, try to outdent.
2700 (setq org-tab-ind-state (cons ind bullet))
2701 (cond
2702 ((ignore-errors (org-list-indent-item-generic 1 t struct)))
2703 ((ignore-errors (org-list-indent-item-generic -1 t struct)))
2704 (t (error "Cannot move item"))))
2705 t))))
afe98dfa
CD
2706
2707(defun org-sort-list (&optional with-case sorting-type getkey-func compare-func)
3ab2c837 2708 "Sort list items.
afe98dfa
CD
2709The cursor may be at any item of the list that should be sorted.
2710Sublists are not sorted. Checkboxes, if any, are ignored.
2711
3ab2c837
BG
2712Sorting can be alphabetically, numerically, by date/time as given
2713by a time stamp, by a property or by priority.
afe98dfa 2714
3ab2c837 2715Comparing entries ignores case by default. However, with an
afe98dfa
CD
2716optional argument WITH-CASE, the sorting considers case as well.
2717
2718The command prompts for the sorting type unless it has been given
2719to the function through the SORTING-TYPE argument, which needs to
2720be a character, \(?n ?N ?a ?A ?t ?T ?f ?F). Here is the precise
2721meaning of each character:
2722
2723n Numerically, by converting the beginning of the item to a number.
2724a Alphabetically. Only the first line of item is checked.
2725t By date/time, either the first active time stamp in the entry, if
2726 any, or by the first inactive one. In a timer list, sort the timers.
2727
2728Capital letters will reverse the sort order.
2729
3ab2c837
BG
2730If the SORTING-TYPE is ?f or ?F, then GETKEY-FUNC specifies
2731a function to be called with point at the beginning of the
2732record. It must return either a string or a number that should
e66ba1df 2733serve as the sorting key for that record. It will then use
3ab2c837 2734COMPARE-FUNC to compare entries."
afe98dfa
CD
2735 (interactive "P")
2736 (let* ((case-func (if with-case 'identity 'downcase))
3ab2c837
BG
2737 (struct (org-list-struct))
2738 (prevs (org-list-prevs-alist struct))
2739 (start (org-list-get-list-begin (point-at-bol) struct prevs))
2740 (end (org-list-get-list-end (point-at-bol) struct prevs))
afe98dfa
CD
2741 (sorting-type
2742 (progn
2743 (message
2744 "Sort plain list: [a]lpha [n]umeric [t]ime [f]unc A/N/T/F means reversed:")
2745 (read-char-exclusive)))
2746 (getkey-func (and (= (downcase sorting-type) ?f)
3ab2c837
BG
2747 (intern (org-icompleting-read "Sort using function: "
2748 obarray 'fboundp t nil nil)))))
afe98dfa
CD
2749 (message "Sorting items...")
2750 (save-restriction
2751 (narrow-to-region start end)
2752 (goto-char (point-min))
2753 (let* ((dcst (downcase sorting-type))
2754 (case-fold-search nil)
2755 (now (current-time))
2756 (sort-func (cond
2757 ((= dcst ?a) 'string<)
2758 ((= dcst ?f) compare-func)
2759 ((= dcst ?t) '<)
2760 (t nil)))
3ab2c837 2761 (next-record (lambda ()
afe98dfa
CD
2762 (skip-chars-forward " \r\t\n")
2763 (beginning-of-line)))
2764 (end-record (lambda ()
3ab2c837
BG
2765 (goto-char (org-list-get-item-end-before-blank
2766 (point) struct))))
afe98dfa
CD
2767 (value-to-sort
2768 (lambda ()
2769 (when (looking-at "[ \t]*[-+*0-9.)]+\\([ \t]+\\[[- X]\\]\\)?[ \t]+")
2770 (cond
2771 ((= dcst ?n)
2772 (string-to-number (buffer-substring (match-end 0)
2773 (point-at-eol))))
2774 ((= dcst ?a)
3ab2c837
BG
2775 (funcall case-func
2776 (buffer-substring (match-end 0) (point-at-eol))))
afe98dfa
CD
2777 ((= dcst ?t)
2778 (cond
2779 ;; If it is a timer list, convert timer to seconds
2780 ((org-at-item-timer-p)
2781 (org-timer-hms-to-secs (match-string 1)))
3ab2c837
BG
2782 ((or (re-search-forward org-ts-regexp (point-at-eol) t)
2783 (re-search-forward org-ts-regexp-both
2784 (point-at-eol) t))
afe98dfa
CD
2785 (org-time-string-to-seconds (match-string 0)))
2786 (t (org-float-time now))))
2787 ((= dcst ?f)
2788 (if getkey-func
2789 (let ((value (funcall getkey-func)))
2790 (if (stringp value)
2791 (funcall case-func value)
2792 value))
2793 (error "Invalid key function `%s'" getkey-func)))
2794 (t (error "Invalid sorting type `%c'" sorting-type)))))))
2795 (sort-subr (/= dcst sorting-type)
3ab2c837 2796 next-record
afe98dfa
CD
2797 end-record
2798 value-to-sort
2799 nil
2800 sort-func)
3ab2c837
BG
2801 ;; Read and fix list again, as `sort-subr' probably destroyed
2802 ;; its structure.
2803 (org-list-repair)
afe98dfa
CD
2804 (run-hooks 'org-after-sorting-entries-or-items-hook)
2805 (message "Sorting items...done")))))
47ffc456 2806
3ab2c837 2807
e66ba1df 2808\f
47ffc456
CD
2809;;; Send and receive lists
2810
2811(defun org-list-parse-list (&optional delete)
2812 "Parse the list at point and maybe DELETE it.
3ab2c837
BG
2813
2814Return a list whose car is a symbol of list type, among
2815`ordered', `unordered' and `descriptive'. Then, each item is
2816a list whose car is counter, and cdr are strings and other
2817sub-lists. Inside strings, check-boxes are replaced by
2818\"[CBON]\", \"[CBOFF]\" and \"[CBTRANS]\".
2819
2820For example, the following list:
2821
28221. first item
2823 + sub-item one
2824 + [X] sub-item two
2825 more text in first item
28262. [@3] last item
2827
2828will be parsed as:
2829
2830\(ordered
2831 \(nil \"first item\"
2832 \(unordered
2833 \(nil \"sub-item one\"\)
2834 \(nil \"[CBON] sub-item two\"\)\)
2835 \"more text in first item\"\)
2836 \(3 \"last item\"\)\)
2837
2838Point is left at list end."
2839 (let* ((struct (org-list-struct))
2840 (prevs (org-list-prevs-alist struct))
2841 (parents (org-list-parents-alist struct))
2842 (top (org-list-get-top-point struct))
2843 (bottom (org-list-get-bottom-point struct))
2844 out
2845 parse-item ; for byte-compiler
2846 (get-text
2847 (function
2848 ;; Return text between BEG and END, trimmed, with
2849 ;; checkboxes replaced.
2850 (lambda (beg end)
2851 (let ((text (org-trim (buffer-substring beg end))))
2852 (if (string-match "\\`\\[\\([-X ]\\)\\]" text)
2853 (replace-match
2854 (let ((box (match-string 1 text)))
2855 (cond
2856 ((equal box " ") "CBOFF")
2857 ((equal box "-") "CBTRANS")
2858 (t "CBON")))
2859 t nil text 1)
2860 text)))))
2861 (parse-sublist
2862 (function
2863 ;; Return a list whose car is list type and cdr a list of
2864 ;; items' body.
2865 (lambda (e)
2866 (cons (org-list-get-list-type (car e) struct prevs)
2867 (mapcar parse-item e)))))
2868 (parse-item
2869 (function
2870 ;; Return a list containing counter of item, if any, text
2871 ;; and any sublist inside it.
2872 (lambda (e)
2873 (let ((start (save-excursion
2874 (goto-char e)
2875 (looking-at "[ \t]*\\S-+\\([ \t]+\\[@\\(start:\\)?\\([0-9]+\\|[a-zA-Z]\\)\\]\\)?[ \t]*")
2876 (match-end 0)))
2877 ;; Get counter number. For alphabetic counter, get
2878 ;; its position in the alphabet.
2879 (counter (let ((c (org-list-get-counter e struct)))
2880 (cond
2881 ((not c) nil)
2882 ((string-match "[A-Za-z]" c)
2883 (- (string-to-char (upcase (match-string 0 c)))
2884 64))
2885 ((string-match "[0-9]+" c)
2886 (string-to-number (match-string 0 c))))))
2887 (childp (org-list-has-child-p e struct))
2888 (end (org-list-get-item-end e struct)))
2889 ;; If item has a child, store text between bullet and
2890 ;; next child, then recursively parse all sublists. At
2891 ;; the end of each sublist, check for the presence of
2892 ;; text belonging to the original item.
2893 (if childp
2894 (let* ((children (org-list-get-children e struct parents))
2895 (body (list (funcall get-text start childp))))
2896 (while children
2897 (let* ((first (car children))
2898 (sub (org-list-get-all-items first struct prevs))
2899 (last-c (car (last sub)))
2900 (last-end (org-list-get-item-end last-c struct)))
2901 (push (funcall parse-sublist sub) body)
2902 ;; Remove children from the list just parsed.
2903 (setq children (cdr (member last-c children)))
2904 ;; There is a chunk of text belonging to the
2905 ;; item if last child doesn't end where next
2906 ;; child starts or where item ends.
2907 (unless (= (or (car children) end) last-end)
2908 (push (funcall get-text
2909 last-end (or (car children) end))
2910 body))))
2911 (cons counter (nreverse body)))
2912 (list counter (funcall get-text start end))))))))
2913 ;; Store output, take care of cursor position and deletion of
2914 ;; list, then return output.
2915 (setq out (funcall parse-sublist (org-list-get-all-items top struct prevs)))
2916 (goto-char top)
afe98dfa 2917 (when delete
3ab2c837 2918 (delete-region top bottom)
153ae947 2919 (when (and (not (looking-at "[ \t]*$")) (looking-at org-list-end-re))
3ab2c837
BG
2920 (replace-match "")))
2921 out))
47ffc456 2922
c8d0cf5c
CD
2923(defun org-list-make-subtree ()
2924 "Convert the plain list at point into a subtree."
2925 (interactive)
3ab2c837 2926 (if (not (ignore-errors (goto-char (org-in-item-p))))
afe98dfa 2927 (error "Not in a list")
3ab2c837
BG
2928 (let ((list (save-excursion (org-list-parse-list t))))
2929 (insert (org-list-to-subtree list)))))
c8d0cf5c 2930
47ffc456
CD
2931(defun org-list-insert-radio-list ()
2932 "Insert a radio list template appropriate for this major mode."
2933 (interactive)
2934 (let* ((e (assq major-mode org-list-radio-list-templates))
2935 (txt (nth 1 e))
2936 name pos)
2937 (unless e (error "No radio list setup defined for %s" major-mode))
2938 (setq name (read-string "List name: "))
2939 (while (string-match "%n" txt)
2940 (setq txt (replace-match name t t txt)))
2941 (or (bolp) (insert "\n"))
2942 (setq pos (point))
2943 (insert txt)
2944 (goto-char pos)))
2945
2946(defun org-list-send-list (&optional maybe)
8bfe682a 2947 "Send a transformed version of this list to the receiver position.
3ab2c837
BG
2948With argument MAYBE, fail quietly if no transformation is defined
2949for this list."
47ffc456
CD
2950 (interactive)
2951 (catch 'exit
afe98dfa 2952 (unless (org-at-item-p) (error "Not at a list item"))
47ffc456 2953 (save-excursion
afe98dfa 2954 (re-search-backward "#\\+ORGLST" nil t)
86fbb8ca 2955 (unless (looking-at "[ \t]*#\\+ORGLST[: \t][ \t]*SEND[ \t]+\\([^ \t\r\n]+\\)[ \t]+\\([^ \t\r\n]+\\)\\([ \t]+.*\\)?")
47ffc456
CD
2956 (if maybe
2957 (throw 'exit nil)
2958 (error "Don't know how to transform this list"))))
2959 (let* ((name (match-string 1))
47ffc456 2960 (transform (intern (match-string 2)))
afe98dfa
CD
2961 (bottom-point
2962 (save-excursion
2963 (re-search-forward
2964 "\\(\\\\end{comment}\\|@end ignore\\|-->\\)" nil t)
2965 (match-beginning 0)))
2966 (top-point
2967 (progn
2968 (re-search-backward "#\\+ORGLST" nil t)
3ab2c837 2969 (re-search-forward (org-item-beginning-re) bottom-point t)
afe98dfa
CD
2970 (match-beginning 0)))
2971 (list (save-restriction
2972 (narrow-to-region top-point bottom-point)
2973 (org-list-parse-list)))
2974 beg txt)
47ffc456
CD
2975 (unless (fboundp transform)
2976 (error "No such transformation function %s" transform))
86fbb8ca
CD
2977 (let ((txt (funcall transform list)))
2978 ;; Find the insertion place
2979 (save-excursion
2980 (goto-char (point-min))
2981 (unless (re-search-forward
afe98dfa
CD
2982 (concat "BEGIN RECEIVE ORGLST +"
2983 name
2984 "\\([ \t]\\|$\\)") nil t)
86fbb8ca
CD
2985 (error "Don't know where to insert translated list"))
2986 (goto-char (match-beginning 0))
2987 (beginning-of-line 2)
2988 (setq beg (point))
2989 (unless (re-search-forward (concat "END RECEIVE ORGLST +" name) nil t)
2990 (error "Cannot find end of insertion region"))
afe98dfa 2991 (delete-region beg (point-at-bol))
86fbb8ca
CD
2992 (goto-char beg)
2993 (insert txt "\n")))
47ffc456
CD
2994 (message "List converted and installed at receiver location"))))
2995
e66ba1df
BG
2996(defsubst org-list-item-trim-br (item)
2997 "Trim line breaks in a list ITEM."
2998 (setq item (replace-regexp-in-string "\n +" " " item)))
2999
47ffc456
CD
3000(defun org-list-to-generic (list params)
3001 "Convert a LIST parsed through `org-list-parse-list' to other formats.
3ab2c837 3002Valid parameters PARAMS are:
47ffc456 3003
33306645
CD
3004:ustart String to start an unordered list
3005:uend String to end an unordered list
47ffc456 3006
33306645
CD
3007:ostart String to start an ordered list
3008:oend String to end an ordered list
47ffc456 3009
33306645
CD
3010:dstart String to start a descriptive list
3011:dend String to end a descriptive list
47ffc456 3012:dtstart String to start a descriptive term
33306645 3013:dtend String to end a descriptive term
47ffc456 3014:ddstart String to start a description
33306645 3015:ddend String to end a description
47ffc456 3016
33306645
CD
3017:splice When set to t, return only list body lines, don't wrap
3018 them into :[u/o]start and :[u/o]end. Default is nil.
47ffc456 3019
3ab2c837
BG
3020:istart String to start a list item.
3021:icount String to start an item with a counter.
33306645
CD
3022:iend String to end a list item
3023:isep String to separate items
0bd48b37 3024:lsep String to separate sublists
3ab2c837
BG
3025:csep String to separate text from a sub-list
3026
3027:cboff String to insert for an unchecked check-box
3028:cbon String to insert for a checked check-box
3029:cbtrans String to insert for a check-box in transitional state
3030
e66ba1df
BG
3031:nobr Non-nil means remove line breaks in lists items.
3032
3ab2c837
BG
3033Alternatively, each parameter can also be a form returning
3034a string. These sexp can use keywords `counter' and `depth',
27e428e7 3035representing respectively counter associated to the current
3ab2c837
BG
3036item, and depth of the current sub-list, starting at 0.
3037Obviously, `counter' is only available for parameters applying to
3038items."
47ffc456 3039 (interactive)
3ab2c837 3040 (let* ((p params)
47ffc456 3041 (splicep (plist-get p :splice))
afe98dfa
CD
3042 (ostart (plist-get p :ostart))
3043 (oend (plist-get p :oend))
3044 (ustart (plist-get p :ustart))
3045 (uend (plist-get p :uend))
3046 (dstart (plist-get p :dstart))
3047 (dend (plist-get p :dend))
3048 (dtstart (plist-get p :dtstart))
3049 (dtend (plist-get p :dtend))
3050 (ddstart (plist-get p :ddstart))
3051 (ddend (plist-get p :ddend))
3052 (istart (plist-get p :istart))
3ab2c837 3053 (icount (plist-get p :icount))
afe98dfa
CD
3054 (iend (plist-get p :iend))
3055 (isep (plist-get p :isep))
3056 (lsep (plist-get p :lsep))
3ab2c837 3057 (csep (plist-get p :csep))
afe98dfa 3058 (cbon (plist-get p :cbon))
3ab2c837
BG
3059 (cboff (plist-get p :cboff))
3060 (cbtrans (plist-get p :cbtrans))
e66ba1df 3061 (nobr (plist-get p :nobr))
3ab2c837
BG
3062 export-sublist ; for byte-compiler
3063 (export-item
3064 (function
3065 ;; Export an item ITEM of type TYPE, at DEPTH. First
3066 ;; string in item is treated in a special way as it can
3067 ;; bring extra information that needs to be processed.
3068 (lambda (item type depth)
3069 (let* ((counter (pop item))
3070 (fmt (concat
3071 (cond
3072 ((eq type 'descriptive)
3073 ;; Stick DTSTART to ISTART by
3074 ;; left-trimming the latter.
3075 (concat (let ((s (eval istart)))
3076 (or (and (string-match "[ \t\n\r]+\\'" s)
3077 (replace-match "" t t s))
3078 istart))
3079 "%s" (eval ddend)))
3080 ((and counter (eq type 'ordered))
3081 (concat (eval icount) "%s"))
3082 (t (concat (eval istart) "%s")))
3083 (eval iend)))
3084 (first (car item)))
3085 ;; Replace checkbox if any is found.
3086 (cond
3087 ((string-match "\\[CBON\\]" first)
3088 (setq first (replace-match cbon t t first)))
3089 ((string-match "\\[CBOFF\\]" first)
3090 (setq first (replace-match cboff t t first)))
3091 ((string-match "\\[CBTRANS\\]" first)
3092 (setq first (replace-match cbtrans t t first))))
e66ba1df
BG
3093 ;; Replace line breaks if required
3094 (when nobr (setq first (org-list-item-trim-br first)))
3ab2c837
BG
3095 ;; Insert descriptive term if TYPE is `descriptive'.
3096 (when (eq type 'descriptive)
3097 (let* ((complete (string-match "^\\(.*\\)[ \t]+::" first))
3098 (term (if complete
3099 (save-match-data
3100 (org-trim (match-string 1 first)))
3101 "???"))
3102 (desc (if complete
3103 (org-trim (substring first (match-end 0)))
3104 first)))
3105 (setq first (concat (eval dtstart) term (eval dtend)
3106 (eval ddstart) desc))))
3107 (setcar item first)
3108 (format fmt
3109 (mapconcat (lambda (e)
3110 (if (stringp e) e
3111 (funcall export-sublist e (1+ depth))))
3112 item (or (eval csep) "")))))))
3113 (export-sublist
3114 (function
3115 ;; Export sublist SUB at DEPTH.
3116 (lambda (sub depth)
3117 (let* ((type (car sub))
3118 (items (cdr sub))
3119 (fmt (concat (cond
3120 (splicep "%s")
3121 ((eq type 'ordered)
3122 (concat (eval ostart) "%s" (eval oend)))
3123 ((eq type 'descriptive)
3124 (concat (eval dstart) "%s" (eval dend)))
3125 (t (concat (eval ustart) "%s" (eval uend))))
3126 (eval lsep))))
3127 (format fmt (mapconcat (lambda (e)
3128 (funcall export-item e type depth))
3129 items (or (eval isep) ""))))))))
3130 (concat (funcall export-sublist list 0) "\n")))
47ffc456 3131
0bd48b37
CD
3132(defun org-list-to-latex (list &optional params)
3133 "Convert LIST into a LaTeX list.
86fbb8ca 3134LIST is as returned by `org-list-parse-list'. PARAMS is a property list
0bd48b37 3135with overruling parameters for `org-list-to-generic'."
47ffc456 3136 (org-list-to-generic
0bd48b37
CD
3137 list
3138 (org-combine-plists
3ab2c837
BG
3139 '(:splice nil :ostart "\\begin{enumerate}\n" :oend "\\end{enumerate}"
3140 :ustart "\\begin{itemize}\n" :uend "\\end{itemize}"
3141 :dstart "\\begin{description}\n" :dend "\\end{description}"
3142 :dtstart "[" :dtend "] "
3143 :istart "\\item " :iend "\n"
3144 :icount (let ((enum (nth depth '("i" "ii" "iii" "iv"))))
3145 (if enum
3146 ;; LaTeX increments counter just before
3147 ;; using it, so set it to the desired
3148 ;; value, minus one.
3149 (format "\\setcounter{enum%s}{%s}\n\\item "
3150 enum (1- counter))
3151 "\\item "))
3152 :csep "\n"
3153 :cbon "\\texttt{[X]}" :cboff "\\texttt{[ ]}"
3154 :cbtrans "\\texttt{[-]}")
0bd48b37
CD
3155 params)))
3156
3157(defun org-list-to-html (list &optional params)
3158 "Convert LIST into a HTML list.
86fbb8ca 3159LIST is as returned by `org-list-parse-list'. PARAMS is a property list
0bd48b37 3160with overruling parameters for `org-list-to-generic'."
47ffc456 3161 (org-list-to-generic
0bd48b37
CD
3162 list
3163 (org-combine-plists
3ab2c837
BG
3164 '(:splice nil :ostart "<ol>\n" :oend "\n</ol>"
3165 :ustart "<ul>\n" :uend "\n</ul>"
3166 :dstart "<dl>\n" :dend "\n</dl>"
3167 :dtstart "<dt>" :dtend "</dt>\n"
0bd48b37
CD
3168 :ddstart "<dd>" :ddend "</dd>"
3169 :istart "<li>" :iend "</li>"
3ab2c837
BG
3170 :icount (format "<li value=\"%s\">" counter)
3171 :isep "\n" :lsep "\n" :csep "\n"
3172 :cbon "<code>[X]</code>" :cboff "<code>[ ]</code>"
3173 :cbtrans "<code>[-]</code>")
0bd48b37
CD
3174 params)))
3175
3176(defun org-list-to-texinfo (list &optional params)
3177 "Convert LIST into a Texinfo list.
86fbb8ca 3178LIST is as returned by `org-list-parse-list'. PARAMS is a property list
0bd48b37 3179with overruling parameters for `org-list-to-generic'."
47ffc456 3180 (org-list-to-generic
c8d0cf5c 3181 list
0bd48b37 3182 (org-combine-plists
3ab2c837
BG
3183 '(:splice nil :ostart "@itemize @minus\n" :oend "@end itemize"
3184 :ustart "@enumerate\n" :uend "@end enumerate"
3185 :dstart "@table @asis\n" :dend "@end table"
3186 :dtstart " " :dtend "\n"
3187 :istart "@item\n" :iend "\n"
3188 :icount "@item\n"
3189 :csep "\n"
3190 :cbon "@code{[X]}" :cboff "@code{[ ]}"
3191 :cbtrans "@code{[-]}")
0bd48b37 3192 params)))
47ffc456 3193
3ab2c837
BG
3194(defun org-list-to-subtree (list &optional params)
3195 "Convert LIST into an Org subtree.
3196LIST is as returned by `org-list-parse-list'. PARAMS is a property list
3197with overruling parameters for `org-list-to-generic'."
3198 (let* ((rule (cdr (assq 'heading org-blank-before-new-entry)))
3199 (level (org-reduced-level (or (org-current-level) 0)))
3200 (blankp (or (eq rule t)
3201 (and (eq rule 'auto)
3202 (save-excursion
3203 (outline-previous-heading)
3204 (org-previous-line-empty-p)))))
3205 (get-stars
3206 (function
3207 ;; Return the string for the heading, depending on depth D
3208 ;; of current sub-list.
3209 (lambda (d)
3210 (let ((oddeven-level (+ level d 1)))
3211 (concat (make-string (if org-odd-levels-only
3212 (1- (* 2 oddeven-level))
3213 oddeven-level)
3214 ?*)
3215 " "))))))
3216 (org-list-to-generic
3217 list
3218 (org-combine-plists
3219 '(:splice t
3220 :dtstart " " :dtend " "
3221 :istart (funcall get-stars depth)
3222 :icount (funcall get-stars depth)
3223 :isep (if blankp "\n\n" "\n")
3224 :csep (if blankp "\n\n" "\n")
3225 :cbon "DONE" :cboff "TODO" :cbtrans "TODO")
3226 params))))
3227
47ffc456
CD
3228(provide 'org-list)
3229
3230;;; org-list.el ends here