org-cycle-list-bullet: Preserve relative point position

* lisp/org-list.el (org-cycle-list-bullet): Keep point position
relative to bullet beginning/end when changing the list bullet.

* testing/lisp/test-org-list.el (test-org-list/cycle-bullet): Add
tests.

Fixes https://orgmode.org/list/m2wndjfi32.fsf@gmail.com
This commit is contained in:
Ihor Radchenko 2022-06-16 19:33:58 +08:00
parent 3bbbf77f36
commit 707d3a093b
No known key found for this signature in database
GPG Key ID: 6470762A7DA11D8B
2 changed files with 75 additions and 3 deletions

View File

@ -2327,12 +2327,19 @@ is an integer, 0 means `-', 1 means `+' etc. If WHICH is
`previous', cycle backwards."
(interactive "P")
(unless (org-at-item-p) (error "Not at an item"))
(save-excursion
(let ((origin (point-marker)))
(beginning-of-line)
(let* ((struct (org-list-struct))
(parents (org-list-parents-alist struct))
(prevs (org-list-prevs-alist struct))
(list-beg (org-list-get-first-item (point) struct prevs))
;; Record relative point position to bullet beginning.
(origin-offset (- origin
(+ (point) (org-list-get-ind (point) struct))))
;; Record relative point position to bullet end.
(origin-offset2 (- origin
(+ (point) (org-list-get-ind (point) struct)
(length (org-list-get-bullet (point) struct)))))
(bullet (org-list-get-bullet list-beg struct))
(alpha-p (org-list-use-alpha-bul-p list-beg struct prevs))
(case-fold-search nil)
@ -2378,7 +2385,24 @@ is an integer, 0 means `-', 1 means `+' etc. If WHICH is
(org-list-set-bullet list-beg struct (org-list-bullet-string new))
(org-list-struct-fix-bul struct prevs)
(org-list-struct-fix-ind struct parents)
(org-list-struct-apply-struct struct old-struct)))))
(org-list-struct-apply-struct struct old-struct))
(goto-char origin)
(setq struct (org-list-struct))
(cond
((>= origin-offset2 0)
(beginning-of-line)
(move-marker origin (+ (point)
(org-list-get-ind (point) struct)
(length (org-list-get-bullet (point) struct))
origin-offset2))
(goto-char origin))
((>= origin-offset 0)
(beginning-of-line)
(move-marker origin (+ (point)
(org-list-get-ind (point) struct)
origin-offset))
(goto-char origin)))
(move-marker origin nil))))
;;;###autoload
(define-minor-mode org-list-checkbox-radio-mode

View File

@ -216,7 +216,55 @@
(let ((org-plain-list-ordered-item-terminator t)
(org-list-allow-alphabetical t))
(org-cycle-list-bullet)
(buffer-substring (point) (line-end-position)))))))
(buffer-substring (point) (line-end-position))))))
;; Preserve point position while cycling.
(org-test-with-temp-text "- this is test
- asd
- asd
<point> - this is
* headline
"
(should (= (point) 36))
(dotimes (_ 10)
(org-cycle-list-bullet)
(should (= 1 (- (point) (line-beginning-position))))))
(org-test-with-temp-text "
- this is test
+ asd
- asd
<point>+ this is
* headline
"
(should (= (point) 37))
(dotimes (_ 10)
(org-cycle-list-bullet)
(should (= 2 (- (point) (line-beginning-position))))))
(org-test-with-temp-text "
- this is test
+ asd
- asd
+<point> this is
* headline
"
(should (= (point) 38))
(dotimes (_ 10)
(org-cycle-list-bullet)
(should (= 3 (- (point) (line-beginning-position))))))
(org-test-with-temp-text "
- this is test
- asd
- asd
- <point>this is
* headline
"
(should (= (point) 39))
(dotimes (i 5)
(org-cycle-list-bullet)
(should
(if (or (< i 2) (= i 4))
(should (= 4 (- (point) (line-beginning-position))))
(should (= 5 (- (point) (line-beginning-position)))))))))
(ert-deftest test-org-list/indent-item ()
"Test `org-indent-item' specifications."