Function: org-list-struct
org-list-struct is a byte-compiled function defined in org-list.el.gz.
Signature
(org-list-struct)
Documentation
Return structure of list at point.
A list structure is an alist where key is point at item, and
values are:
1. indentation,
2. bullet with trailing whitespace,
3. bullet counter, if any,
4. checkbox, if any,
5. description tag, if any,
6. position at item end.
Thus the following list, where numbers in parens are point-at-bol:
- [X] first item (1)
1. sub-item 1 (18)
5. [@5] sub-item 2 (34)
some other text belonging to first item (55)
- last item (97)
+ tag :: description (109)
(131)
will get the following structure:
((1 0 "- " nil "[X]" nil 97)
(18 2 "1. " nil nil nil 34)
(34 2 "5. " "5" nil nil 55)
(97 0 "- " nil nil nil 131)
(109 2 "+ " nil nil "tag" 131))
Assume point is at an item.
Source Code
;; Defined in /usr/src/emacs/lisp/org/org-list.el.gz
(defun org-list-struct ()
"Return structure of list at point.
A list structure is an alist where key is point at item, and
values are:
1. indentation,
2. bullet with trailing whitespace,
3. bullet counter, if any,
4. checkbox, if any,
5. description tag, if any,
6. position at item end.
Thus the following list, where numbers in parens are
point-at-bol:
- [X] first item (1)
1. sub-item 1 (18)
5. [@5] sub-item 2 (34)
some other text belonging to first item (55)
- last item (97)
+ tag :: description (109)
(131)
will get the following structure:
((1 0 \"- \" nil \"[X]\" nil 97)
(18 2 \"1. \" nil nil nil 34)
(34 2 \"5. \" \"5\" nil nil 55)
(97 0 \"- \" nil nil nil 131)
(109 2 \"+ \" nil nil \"tag\" 131))
Assume point is at an item."
(save-excursion
(beginning-of-line)
(let* ((case-fold-search t)
(context (org-list-context))
(lim-up (car context))
(lim-down (nth 1 context))
(text-min-ind 10000)
(item-re (org-item-re))
(inlinetask-re (and (featurep 'org-inlinetask)
(org-inlinetask-outline-regexp)))
(beg-cell (cons (point) (current-indentation)))
itm-lst itm-lst-2 end-lst end-lst-2 struct
(assoc-at-point
;; Return association at point.
(lambda (ind)
(looking-at org-list-full-item-re)
(let ((bullet (match-string-no-properties 1)))
(list (point)
ind
bullet
(match-string-no-properties 2) ; counter
(match-string-no-properties 3) ; checkbox
;; Description tag.
(and (string-match-p "[-+*]" bullet)
(match-string-no-properties 4))))))
(end-before-blank
;; Ensure list ends at the first blank line.
(lambda ()
(skip-chars-backward " \r\t\n")
(min (1+ (point-at-eol)) lim-down))))
;; 1. Read list from starting item to its beginning, and save
;; top item position and indentation in BEG-CELL. Also store
;; ending position of items in END-LST.
(save-excursion
(catch 'exit
(while t
(let ((ind (current-indentation)))
(cond
((<= (point) lim-up)
;; At upward limit: if we ended at an item, store it,
;; else dismiss useless data recorded above BEG-CELL.
;; Jump to part 2.
(throw 'exit
(setq itm-lst
(if (not (looking-at item-re))
(memq (assq (car beg-cell) itm-lst) itm-lst)
(setq beg-cell (cons (point) ind))
(cons (funcall assoc-at-point ind) itm-lst)))))
;; Looking at a list ending regexp. Dismiss useless
;; data recorded above BEG-CELL. Jump to part 2.
((looking-at org-list-end-re)
(throw 'exit
(setq itm-lst
(memq (assq (car beg-cell) itm-lst) itm-lst))))
;; Point is at an item. Add data to ITM-LST. It may
;; also end a previous item: save it in END-LST. If
;; ind is less or equal than BEG-CELL and there is no
;; end at this ind or lesser, this item becomes the new
;; BEG-CELL.
((looking-at item-re)
(push (funcall assoc-at-point ind) itm-lst)
(push (cons ind (point)) end-lst)
(when (< ind text-min-ind) (setq beg-cell (cons (point) ind)))
(forward-line -1))
;; Skip blocks, drawers, inline tasks, blank lines.
((and (looking-at "^[ \t]*#\\+end_")
(re-search-backward "^[ \t]*#\\+begin_" lim-up t)))
((and (looking-at "^[ \t]*:END:")
(re-search-backward org-drawer-regexp lim-up t))
(beginning-of-line))
((and inlinetask-re (looking-at inlinetask-re))
(org-inlinetask-goto-beginning)
(forward-line -1))
((looking-at "^[ \t]*$")
(forward-line -1))
;; From there, point is not at an item. Interpret
;; line's indentation:
;; - text at column 0 is necessarily out of any list.
;; Dismiss data recorded above BEG-CELL. Jump to
;; part 2.
;; - any other case may be an ending position for an
;; hypothetical item above. Store it and proceed.
((zerop ind)
(throw 'exit
(setq itm-lst
(memq (assq (car beg-cell) itm-lst) itm-lst))))
(t
(when (< ind text-min-ind) (setq text-min-ind ind))
(push (cons ind (point)) end-lst)
(forward-line -1)))))))
;; 2. Read list from starting point to its end, that is until we
;; get out of context, or that a non-item line is less or
;; equally indented than BEG-CELL's cdr. Also, store ending
;; position of items in END-LST-2.
(catch 'exit
(while t
(let ((ind (current-indentation)))
(cond
((>= (point) lim-down)
;; At downward limit: this is de facto the end of the
;; list. Save point as an ending position, and jump to
;; part 3.
(throw 'exit
(push (cons 0 (funcall end-before-blank)) end-lst-2)))
;; Looking at a list ending regexp. Save point as an
;; ending position and jump to part 3.
((looking-at org-list-end-re)
(throw 'exit (push (cons 0 (point)) end-lst-2)))
((looking-at item-re)
;; Point is at an item. Add data to ITM-LST-2. It may
;; also end a previous item, so save it in END-LST-2.
(push (funcall assoc-at-point ind) itm-lst-2)
(push (cons ind (point)) end-lst-2)
(forward-line 1))
;; Skip inline tasks and blank lines along the way
((and inlinetask-re (looking-at inlinetask-re))
(org-inlinetask-goto-end))
((looking-at "^[ \t]*$")
(forward-line 1))
;; Ind is lesser or equal than BEG-CELL's. The list is
;; over: store point as an ending position and jump to
;; part 3.
((<= ind (cdr beg-cell))
(throw 'exit
(push (cons 0 (funcall end-before-blank)) end-lst-2)))
;; Else, if ind is lesser or equal than previous item's,
;; this is an ending position: store it. In any case,
;; skip block or drawer at point, and move to next line.
(t
(when (<= ind (nth 1 (car itm-lst-2)))
(push (cons ind (point)) end-lst-2))
(cond
((and (looking-at "^[ \t]*#\\+begin_")
(re-search-forward "^[ \t]*#\\+end_" lim-down t)))
((and (looking-at org-drawer-regexp)
(re-search-forward "^[ \t]*:END:" lim-down t))))
(forward-line 1))))))
(setq struct (append itm-lst (cdr (nreverse itm-lst-2)))
end-lst (append end-lst (cdr (nreverse end-lst-2))))
;; 3. Associate each item to its end position.
(org-list-struct-assoc-end struct end-lst)
;; 4. Return STRUCT
struct)))