diff options
author | Nicolas Goaziou <n.goaziou@gmail.com> | 2010-12-24 00:54:48 +0100 |
---|---|---|
committer | Nicolas Goaziou <n.goaziou@gmail.com> | 2011-02-18 12:45:08 +0100 |
commit | e865ce445a2061d02da75c38d222fe04cb1b54c0 (patch) | |
tree | c8617eb361853c1cdfd956a6a0f8a3599e1dced9 | |
parent | b2c369725adbf14cf490bd6811f37d3ee706ef13 (diff) | |
download | org-mode-e865ce445a2061d02da75c38d222fe04cb1b54c0.tar.gz |
org-list: interactive navigation functions use accessors
* lisp/org-list.el (org-list-in-item-p): unify methods for this predicate.
(org-list-in-item-p-with-indent): removed function
(org-list-ending-between): removed function
(org-list-maybe-skip-block): removed function
(org-list-in-item-p-with-regexp): removed function
(org-list-top-point-with-regexp): removed function
(org-list-top-point-with-indent): removed function
(org-list-bottom-point-with-indent): removed function
(org-list-bottom-point-with-regexp): removed function
(org-list-get-item-same-level): removed function
(org-list-top-point): removed function
(org-list-bottom-point): removed function
(org-get-item-beginning): renamed to org-list-get-item-begin to be
consistent with naming policy of non-interactive functions.
(org-get-beginning-of-list): removed function
(org-beginning-of-item-list): use new accessors
(org-get-end-of-list): removed function
(org-end-of-list): use new accessors
(org-get-end-of-item): removed function
(org-end-of-item): use new accessors
(org-get-previous-item): removed function
(org-previous-item): use new accessors
(org-get-next-item): removed function
(org-next-item): use new accessors
(org-end-of-item-before-blank): renamed to
(org-list-get-item-end-before-blank): Use new accessors.
-rw-r--r-- | lisp/org-list.el | 522 |
1 files changed, 133 insertions, 389 deletions
diff --git a/lisp/org-list.el b/lisp/org-list.el index c7d897e..cc98cad 100644 --- a/lisp/org-list.el +++ b/lisp/org-list.el @@ -419,40 +419,6 @@ Symbols `block' and `invalid' refer to `org-list-blocks'." ;; Return the closest context around (assq (apply 'max (mapcar 'car context-list)) context-list))))))) -(defun org-list-ending-between (min max &optional firstp) - "Find the position of a list ending between MIN and MAX, or nil. -This function looks for `org-list-end-re' outside a block. - -If FIRSTP in non-nil, return the point at the beginning of the -nearest valid terminator from MIN. Otherwise, return the point at -the end of the nearest terminator from MAX." - (save-excursion - (let* ((start (if firstp min max)) - (end (if firstp max min)) - (search-fun (if firstp - #'org-search-forward-unenclosed - #'org-search-backward-unenclosed)) - (list-end-p (progn - (goto-char start) - (funcall search-fun (org-list-end-re) end t)))) - ;; Is there a valid list ending somewhere ? - (and list-end-p - ;; we want to be on the first line of the list ender - (match-beginning 0))))) - -(defun org-list-maybe-skip-block (search limit) - "Return non-nil value if point is in a block, skipping it on the way. -It looks for the boundary of the block in SEARCH direction, -stopping at LIMIT." - (save-match-data - (let ((case-fold-search t) - (boundary (if (eq search 're-search-forward) 3 5))) - (when (save-excursion - (and (funcall search "^[ \t]*#\\+\\(begin\\|end\\)_" limit t) - (= (length (match-string 1)) boundary))) - ;; We're in a block: get out of it - (goto-char (match-beginning 0)))))) - (defun org-list-search-unenclosed-generic (search re bound noerr) "Search a string outside blocks and protected places. Arguments SEARCH, RE, BOUND and NOERR are similar to those in @@ -485,171 +451,6 @@ Arguments REGEXP, BOUND and NOERROR are similar to those used in (org-list-search-unenclosed-generic #'re-search-forward regexp (or bound (point-max)) noerror)) -(defun org-list-in-item-p-with-indent (limit) - "Is the cursor inside a plain list? -Plain lists are considered ending when a non-blank line is less -indented than the previous item within LIMIT." - (save-excursion - (beginning-of-line) - (cond - ;; do not start searching inside a block... - ((org-list-maybe-skip-block #'re-search-backward limit)) - ;; ... or at a blank line - ((looking-at "^[ \t]*$") - (skip-chars-backward " \r\t\n") - (beginning-of-line))) - (beginning-of-line) - (or (org-at-item-p) - (let* ((case-fold-search t) - (ind-ref (org-get-indentation)) - ;; Ensure there is at least an item above - (up-item-p (save-excursion - (org-search-backward-unenclosed - org-item-beginning-re limit t)))) - (and up-item-p - (catch 'exit - (while t - (cond - ((org-at-item-p) - (throw 'exit (< (org-get-indentation) ind-ref))) - ((looking-at "^[ \t]*$") - (skip-chars-backward " \r\t\n") - (beginning-of-line)) - ((looking-at "^[ \t]*#\\+end_") - (re-search-backward "^[ \t]*#\\+begin_")) - (t - (setq ind-ref (min (org-get-indentation) ind-ref)) - (forward-line -1)))))))))) - -(defun org-list-in-item-p-with-regexp (limit) - "Is the cursor inside a plain list? -Plain lists end when `org-list-end-regexp' is matched, or at a -blank line if `org-empty-line-terminates-plain-lists' is true. - -Argument LIMIT specifies the upper-bound of the search." - (save-excursion - (let* ((actual-pos (goto-char (point-at-eol))) - ;; Moved to eol so current line can be matched by - ;; `org-item-re'. - (last-item-start (save-excursion - (org-search-backward-unenclosed - org-item-beginning-re limit t))) - (list-ender (org-list-ending-between - last-item-start actual-pos))) - ;; We are in a list when we are on an item line or when we can - ;; find an item before point and there is no valid list ender - ;; between it and the point. - (and last-item-start (not list-ender))))) - -(defun org-list-top-point-with-regexp (limit) - "Return point at the top level item in a list. -Argument LIMIT specifies the upper-bound of the search. - -List ending is determined by regexp. See -`org-list-ending-method'. for more information." - (save-excursion - (let ((pos (point-at-eol))) - ;; Is there some list above this one ? If so, go to its ending. - ;; Otherwise, go back to the heading above or bob. - (goto-char (or (org-list-ending-between limit pos) limit)) - ;; From there, search down our list. - (org-search-forward-unenclosed org-item-beginning-re pos t) - (point-at-bol)))) - -(defun org-list-bottom-point-with-regexp (limit) - "Return point just before list ending. -Argument LIMIT specifies the lower-bound of the search. - -List ending is determined by regexp. See -`org-list-ending-method'. for more information." - (save-excursion - (let ((pos (org-get-item-beginning))) - ;; The list ending is either first point matching - ;; `org-list-end-re', point at first white-line before next - ;; heading, or eob. - (or (org-list-ending-between (min pos limit) limit t) limit)))) - -(defun org-list-top-point-with-indent (limit) - "Return point at the top level in a list. -Argument LIMIT specifies the upper-bound of the search. - -List ending is determined by indentation of text. See -`org-list-ending-method'. for more information." - (save-excursion - (let ((case-fold-search t)) - (let ((item-ref (goto-char (org-get-item-beginning))) - (ind-ref 10000)) - (forward-line -1) - (catch 'exit - (while t - (let ((ind (+ (or (get-text-property (point) 'original-indentation) 0) - (org-get-indentation)))) - (cond - ((looking-at "^[ \t]*:END:") - (throw 'exit item-ref)) - ((<= (point) limit) - (throw 'exit - (if (and (org-at-item-p) (< ind ind-ref)) - (point-at-bol) - item-ref))) - ((looking-at "^[ \t]*$") - (skip-chars-backward " \r\t\n") - (beginning-of-line)) - ((looking-at "^[ \t]*#\\+end_") - (re-search-backward "^[ \t]*#\\+begin_")) - ((not (org-at-item-p)) - (setq ind-ref (min ind ind-ref)) - (forward-line -1)) - ((>= ind ind-ref) - (throw 'exit item-ref)) - (t - (setq item-ref (point-at-bol) ind-ref 10000) - (forward-line -1)))))))))) - -(defun org-list-bottom-point-with-indent (limit) - "Return point just before list ending or nil if not in a list. -Argument LIMIT specifies the lower-bound of the search. - -List ending is determined by the indentation of text. See -`org-list-ending-method' for more information." - (save-excursion - (let ((ind-ref (progn - (goto-char (org-get-item-beginning)) - (org-get-indentation))) - (case-fold-search t)) - ;; do not start inside a block - (org-list-maybe-skip-block #'re-search-forward limit) - (beginning-of-line) - (catch 'exit - (while t - (skip-chars-forward " \t") - (let ((ind (+ (or (get-text-property (point) 'original-indentation) 0) - (org-get-indentation)))) - (cond - ((or (>= (point) limit) - (looking-at ":END:")) - (throw 'exit (progn - ;; Ensure bottom is just after a - ;; non-blank line. - (skip-chars-backward " \r\t\n") - (min (point-max) (1+ (point-at-eol)))))) - ((= (point) (point-at-eol)) - (skip-chars-forward " \r\t\n") - (beginning-of-line)) - ((org-at-item-p) - (setq ind-ref ind) - (forward-line 1)) - ((<= ind ind-ref) - (throw 'exit (progn - ;; Again, ensure bottom is just after a - ;; non-blank line. - (skip-chars-backward " \r\t\n") - (min (point-max) (1+ (point-at-eol)))))) - ((looking-at "#\\+begin_") - (re-search-forward "[ \t]*#\\+end_") - (forward-line 1)) - (t (forward-line 1))))))))) - (defun org-list-at-regexp-after-bullet-p (regexp) "Is point at a list item with REGEXP after bullet?" (and (org-at-item-p) @@ -660,23 +461,6 @@ List ending is determined by the indentation of text. See (goto-char (match-end 0))) (looking-at regexp)))) -(defun org-list-get-item-same-level (search-fun pos limit pre-move) - "Return point at the beginning of next item at the same level. -Search items using function SEARCH-FUN, from POS to LIMIT. It -uses PRE-MOVE before search. Return nil if no item was found." - (save-excursion - (goto-char pos) - (let* ((start (org-get-item-beginning)) - (ind (progn (goto-char start) (org-get-indentation)))) - ;; We don't want to match the current line. - (funcall pre-move) - ;; Skip any sublist on the way - (while (and (funcall search-fun org-item-beginning-re limit t) - (> (org-get-indentation) ind))) - (when (and (/= (point-at-bol) start) ; Have we moved ? - (= (org-get-indentation) ind)) - (point-at-bol))))) - (defun org-list-separating-blank-lines-number (pos top bottom) "Return number of blank lines that should separate items in list. POS is the position of point to be considered. @@ -744,7 +528,7 @@ function ends." (let* ((true-pos (point)) (top (org-list-top-point)) (bottom (copy-marker (org-list-bottom-point))) - (bullet (and (goto-char (org-get-item-beginning)) + (bullet (and (goto-char (org-list-get-item-begin)) (org-list-bullet-string (org-get-bullet)))) (ind (org-get-indentation)) (before-p (progn @@ -761,7 +545,7 @@ function ends." (lambda (text) ;; insert bullet above item in order to avoid bothering ;; with possible blank lines ending last item. - (goto-char (org-get-item-beginning)) + (goto-char (org-list-get-item-begin)) (org-indent-to-column ind) (insert (concat bullet (when checkbox "[ ] ") after-bullet)) ;; Stay between after-bullet and before text. @@ -773,7 +557,7 @@ function ends." (setq bottom (marker-position bottom)) (let ((col (current-column))) (org-list-exchange-items - (org-get-item-beginning) (org-get-next-item (point) bottom) + (org-list-get-item-begin) (org-get-next-item (point) bottom) bottom) ;; recompute next-item: last sexp modified list (goto-char (org-get-next-item (point) bottom)) @@ -910,32 +694,50 @@ Return t if successful." (defun org-in-item-p () "Is the cursor inside a plain list? This checks `org-list-ending-method'." - (unless (let ((outline-regexp org-outline-regexp)) (org-at-heading-p)) - (let* ((prev-head (save-excursion (outline-previous-heading))) - (bound (if prev-head - (or (save-excursion - (let ((case-fold-search t)) - (re-search-backward "^[ \t]*:END:" prev-head t))) - prev-head) - (point-min)))) - (cond - ((eq org-list-ending-method 'regexp) - (org-list-in-item-p-with-regexp bound)) - ((eq org-list-ending-method 'indent) - (org-list-in-item-p-with-indent bound)) - (t (and (org-list-in-item-p-with-regexp bound) - (org-list-in-item-p-with-indent bound))))))) - -(defun org-list-first-item-p (top) - "Is this item the first item in a plain list? -Assume point is at an item. - -TOP is the position of list's top-item." (save-excursion (beginning-of-line) - (let ((ind (org-get-indentation))) - (or (not (org-search-backward-unenclosed org-item-beginning-re top t)) - (< (org-get-indentation) ind))))) + (unless (or (let ((outline-regexp org-outline-regexp)) (org-at-heading-p)) + (and (not (eq org-list-ending-method 'indent)) + (looking-at (org-list-end-re)) + (progn (forward-line -1) (looking-at (org-list-end-re))))) + (or (and (org-at-item-p) (point-at-bol)) + (let* ((case-fold-search t) + (context (org-list-context)) + (lim-up (car context)) + (inlinetask-re (and (featurep 'org-inlinetask) + (org-inlinetask-outline-regexp))) + (ind-ref (if (looking-at "^[ \t]*$") + 10000 + (org-get-indentation)))) + (catch 'exit + (while t + (let ((ind (org-get-indentation))) + (cond + ((<= (point) lim-up) + (throw 'exit (and (org-at-item-p) (< ind ind-ref)))) + ((and (not (eq org-list-ending-method 'indent)) + (looking-at (org-list-end-re))) + (throw 'exit nil)) + ;; Skip blocks, drawers, inline-tasks, blank lines + ((looking-at "^[ \t]*#\\+end_") + (re-search-backward "^[ \t]*#\\+begin_" nil t)) + ((looking-at "^[ \t]*:END:") + (re-search-backward org-drawer-regexp nil t) + (beginning-of-line)) + ((and inlinetask-re (looking-at inlinetask-re)) + (org-inlinetask-goto-beginning) + (forward-line -1)) + ((looking-at "^[ \t]*$") + (forward-line -1)) + ((< ind ind-ref) + (if (org-at-item-p) + (throw 'exit (point)) + (setq ind-ref ind) + (forward-line -1))) + (t (if (and (eq org-list-ending-method 'regexp) + (org-at-item-p)) + (throw 'exit (point)) + (forward-line -1)))))))))))) (defun org-at-item-p () "Is point in a line starting a hand-formatted item?" @@ -963,178 +765,86 @@ TOP is the position of list's top-item." ;;; Navigate -;; Every interactive navigation function is derived from a -;; non-interactive one, which doesn't move point, assumes point is -;; already in a list and doesn't compute list boundaries. - -;; If you plan to use more than one org-list function is some code, -;; you should therefore first check if point is in a list with -;; `org-in-item-p' or `org-at-item-p', then compute list boundaries -;; with `org-list-top-point' and `org-list-bottom-point', and make use -;; of non-interactive forms. - -(defun org-list-top-point () - "Return point at the top level in a list. -Assume point is in a list." - (let* ((prev-head (save-excursion (outline-previous-heading))) - (bound (if prev-head - (or (save-excursion - (let ((case-fold-search t)) - (re-search-backward "^[ \t]*:END:" prev-head t))) - prev-head) - (point-min)))) - (cond - ((eq org-list-ending-method 'regexp) - (org-list-top-point-with-regexp bound)) - ((eq org-list-ending-method 'indent) - (org-list-top-point-with-indent bound)) - (t (let ((top-re (org-list-top-point-with-regexp bound))) - (org-list-top-point-with-indent (or top-re bound))))))) - -(defun org-list-bottom-point () - "Return point just before list ending. -Assume point is in a list." - (let* ((next-head (save-excursion - (and (let ((outline-regexp org-outline-regexp)) - ;; Use default regexp because folding - ;; changes OUTLINE-REGEXP. - (outline-next-heading))))) - (limit (or (save-excursion - (and (re-search-forward "^[ \t]*:END:" next-head t) - (point-at-bol))) - next-head - (point-max)))) - (cond - ((eq org-list-ending-method 'regexp) - (org-list-bottom-point-with-regexp limit)) - ((eq org-list-ending-method 'indent) - (org-list-bottom-point-with-indent limit)) - (t (let ((bottom-re (org-list-bottom-point-with-regexp limit))) - (org-list-bottom-point-with-indent (or bottom-re limit))))))) - -(defun org-get-item-beginning () - "Return position of current item beginning." - (save-excursion - ;; possibly match current line - (end-of-line) - (org-search-backward-unenclosed org-item-beginning-re nil t) - (point-at-bol))) +(defalias 'org-list-get-item-begin 'org-in-item-p) (defun org-beginning-of-item () "Go to the beginning of the current hand-formatted item. If the cursor is not in an item, throw an error." (interactive) - (if (org-in-item-p) - (goto-char (org-get-item-beginning)) - (error "Not in an item"))) - -(defun org-get-beginning-of-list (top) - "Return position of the first item of the current list or sublist. -TOP is the position at list beginning." - (save-excursion - (let (prev-p) - (while (setq prev-p (org-get-previous-item (point) top)) - (goto-char prev-p)) - (point-at-bol)))) + (let ((begin (org-in-item-p))) + (if begin (goto-char begin) (error "Not in an item")))) (defun org-beginning-of-item-list () "Go to the beginning item of the current list or sublist. Return an error if not in a list." (interactive) - (if (org-in-item-p) - (goto-char (org-get-beginning-of-list (org-list-top-point))) - (error "Not in an item"))) - -(defun org-get-end-of-list (bottom) - "Return position at the end of the current list or sublist. -BOTTOM is the position at list ending." - (save-excursion - (goto-char (org-get-item-beginning)) - (let ((ind (org-get-indentation))) - (while (and (/= (point) bottom) - (>= (org-get-indentation) ind)) - (org-search-forward-unenclosed org-item-beginning-re bottom 'move)) - (if (= (point) bottom) bottom (point-at-bol))))) + (let ((begin (org-in-item-p))) + (if (not begin) + (error "Not in an item") + (goto-char begin) + (let ((struct (org-list-struct))) + (goto-char (org-list-get-list-begin begin (org-list-struct))))))) (defun org-end-of-item-list () "Go to the end of the current list or sublist. If the cursor in not in an item, throw an error." (interactive) - (if (org-in-item-p) - (goto-char (org-get-end-of-list (org-list-bottom-point))) - (error "Not in an item"))) - -(defun org-get-end-of-item (bottom) - "Return position at the end of the current item. -BOTTOM is the position at list ending." - (or (org-get-next-item (point) bottom) - (org-get-end-of-list bottom))) + (let ((begin (org-in-item-p))) + (if (not begin) + (error "Not in an item") + (goto-char begin) + (let ((struct (org-list-struct))) + (goto-char (org-list-get-list-end begin (org-list-struct))))))) (defun org-end-of-item () "Go to the end of the current hand-formatted item. If the cursor is not in an item, throw an error." (interactive) - (if (org-in-item-p) - (goto-char (org-get-end-of-item (org-list-bottom-point))) - (error "Not in an item"))) - -(defun org-end-of-item-or-at-child (bottom) - "Move to the end of the item, stops before the first child if any. -BOTTOM is the position at list ending." - (end-of-line) - (goto-char - (if (org-search-forward-unenclosed org-item-beginning-re bottom t) - (point-at-bol) - (org-get-end-of-item bottom)))) - -(defun org-end-of-item-before-blank (bottom) - "Return point at end of item, before any blank line. -Point returned is at eol. - -BOTTOM is the position at list ending." - (save-excursion - (goto-char (org-get-end-of-item bottom)) - (skip-chars-backward " \r\t\n") - (point-at-eol))) - -(defun org-get-previous-item (pos limit) - "Return point of the previous item at the same level as POS. -Stop searching at LIMIT. Return nil if no item is found." - (org-list-get-item-same-level - #'org-search-backward-unenclosed pos limit #'beginning-of-line)) + (let ((begin (org-in-item-p))) + (if (not begin) + (error "Not in an item") + (goto-char begin) + (let ((struct (org-list-struct))) + (goto-char (org-list-get-item-end begin struct)))))) (defun org-previous-item () "Move to the beginning of the previous item. Item is at the same level in the current plain list. Error if not in a plain list, or if this is the first item in the list." (interactive) - (if (not (org-in-item-p)) - (error "Not in an item") - (let ((prev-p (org-get-previous-item (point) (org-list-top-point)))) - (if prev-p (goto-char prev-p) (error "On first item"))))) - -(defun org-get-next-item (pos limit) - "Return point of the next item at the same level as POS. -Stop searching at LIMIT. Return nil if no item is found." - (org-list-get-item-same-level - #'org-search-forward-unenclosed pos limit #'end-of-line)) + (let ((begin (org-in-item-p))) + (if (not begin) + (error "Not in an item") + (goto-char begin) + (let* ((struct (org-list-struct)) + (prevs (org-list-struct-prev-alist struct)) + (prevp (org-list-get-prev-item begin struct prevs))) + (if prevp (goto-char prevp) (error "On first item")))))) (defun org-next-item () "Move to the beginning of the next item. Item is at the same level in the current plain list. Error if not in a plain list, or if this is the last item in the list." (interactive) - (if (not (org-in-item-p)) - (error "Not in an item") - (let ((next-p (org-get-next-item (point) (org-list-bottom-point)))) - (if next-p (goto-char next-p) (error "On last item"))))) + (let ((begin (org-in-item-p))) + (if (not begin) + (error "Not in an item") + (goto-char begin) + (let* ((struct (org-list-struct)) + (prevs (org-list-struct-prev-alist struct)) + (prevp (org-list-get-next-item begin struct prevs))) + (if prevp (goto-char prevp) (error "On last item")))))) ;;; Manipulate (defun org-list-exchange-items (beg-A beg-B struct) - "Swap item starting at BEG-A with item starting at BEG-B. -Blank lines at the end of items are left in place. Assume BEG-A -is lesser than BEG-B." + "Swap item starting at BEG-A with item starting at BEG-B in STRUCT. +Blank lines at the end of items are left in place. + +Assume BEG-A is lesser than BEG-B and that BEG-A and BEG-B +belong to the same sub-list. + +This function modifies STRUCT." (save-excursion (let* ((end-of-item-no-blank (lambda (pos) @@ -1146,7 +856,21 @@ is lesser than BEG-B." (between-A-no-blank-and-B (buffer-substring end-A-no-blank beg-B))) (goto-char beg-A) (delete-region beg-A end-B-no-blank) - (insert (concat body-B between-A-no-blank-and-B body-A))))) + (insert (concat body-B between-A-no-blank-and-B body-A)) + ;; Now modify struct. No need to re-read the list, the + ;; transformation is just a shift of positions + (let* ((sub-A (cons beg-A (org-list-get-subtree beg-A struct))) + (sub-B (cons beg-B (org-list-get-subtree beg-B struct))) + (end-A (org-list-get-item-end beg-A struct)) + (end-B (org-list-get-item-end beg-B struct)) + (inter-A-B (- beg-B end-A)) + (size-A (- end-A beg-A)) + (size-B (- end-B beg-B))) + (mapc (lambda (e) (org-list-set-pos e struct (+ e size-B inter-A-B))) + sub-A) + (mapc (lambda (e) (org-list-set-pos e struct (- e size-A inter-A-B))) + sub-B) + (sort struct (lambda (e1 e2) (< (car e1) (car e2)))))))) (defun org-move-item-down () "Move the plain list item at point down, i.e. swap with following item. @@ -1164,12 +888,17 @@ so this really moves item trees." (progn (goto-char pos) (error "Cannot move this item further down")) - (let ((next-item-size (- (org-list-get-item-end next-item struct) - next-item))) - (org-list-exchange-items actual-item next-item struct) - (org-list-repair) - (goto-char (+ (point) next-item-size)) - (org-move-to-column col))))) + (org-list-exchange-items actual-item next-item struct) + ;; Use a short variation of `org-list-struct-fix-struct' as + ;; there's no need to go through all the steps. + (let ((old-struct (mapcar (lambda (e) (copy-alist e)) struct)) + (prevs (org-list-struct-prev-alist struct)) + (parents (org-list-struct-parent-alist struct))) + (org-list-struct-fix-bul struct prevs) + (org-list-struct-fix-ind struct parents) + (org-list-struct-apply-struct struct old-struct) + (goto-char (org-list-get-next-item (point-at-bol) struct prevs))) + (org-move-to-column col)))) (defun org-move-item-up () "Move the plain list item at point up, i.e. swap with previous item. @@ -1188,7 +917,14 @@ so this really moves item trees." (goto-char pos) (error "Cannot move this item further up")) (org-list-exchange-items prev-item actual-item struct) - (org-list-repair) + ;; Use a short variation of `org-list-struct-fix-struct' as + ;; there's no need to go through all the steps. + (let ((old-struct (mapcar (lambda (e) (copy-alist e)) struct)) + (prevs (org-list-struct-prev-alist struct)) + (parents (org-list-struct-parent-alist struct))) + (org-list-struct-fix-bul struct prevs) + (org-list-struct-fix-ind struct parents) + (org-list-struct-apply-struct struct old-struct)) (org-move-to-column col)))) (defun org-insert-item (&optional checkbox) @@ -1205,13 +941,13 @@ item is invisible." (goto-char (org-get-item-beginning)) (outline-invisible-p))) (if (save-excursion - (goto-char (org-get-item-beginning)) + (goto-char (org-list-get-item-begin)) (org-at-item-timer-p)) ;; Timer list: delegate to `org-timer-item'. (progn (org-timer-item) t) ;; if we're in a description list, ask for the new term. (let ((desc-text (when (save-excursion - (and (goto-char (org-get-item-beginning)) + (and (goto-char (org-list-get-item-begin)) (org-at-item-description-p))) (concat (read-string "Term: ") " :: ")))) ;; Don't insert a checkbox if checkbox rule is applied and it @@ -1612,6 +1348,14 @@ previous items. See `org-list-struct-prev-alist'." "Return end position of ITEM in STRUCT." (org-list-get-nth 5 item struct)) +(defun org-list-get-item-end-before-blank (item struct) + "Return point at end of item, before any blank line. +Point returned is at end of line." + (save-excursion + (goto-char (org-list-get-item-end item struct)) + (skip-chars-backward " \r\t\n") + (point-at-eol))) + (defun org-list-struct-fix-bul (struct prevs) "Verify and correct bullets for every association in STRUCT. \nThis function modifies STRUCT." |