From 707d3a093b3ff30bd048a95c83aa8df84a253e30 Mon Sep 17 00:00:00 2001 From: Ihor Radchenko Date: Thu, 16 Jun 2022 19:33:58 +0800 Subject: [PATCH] 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 --- lisp/org-list.el | 28 ++++++++++++++++++-- testing/lisp/test-org-list.el | 50 ++++++++++++++++++++++++++++++++++- 2 files changed, 75 insertions(+), 3 deletions(-) diff --git a/lisp/org-list.el b/lisp/org-list.el index 872436fd6..55fb7d18e 100644 --- a/lisp/org-list.el +++ b/lisp/org-list.el @@ -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 diff --git a/testing/lisp/test-org-list.el b/testing/lisp/test-org-list.el index d3e6fc176..da1841e73 100644 --- a/testing/lisp/test-org-list.el +++ b/testing/lisp/test-org-list.el @@ -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 + - 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 + + 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 + + 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 + - 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."