forked from mirrors/org-mode
Fix `C-a' with visual lines and arguments
* lisp/org.el (org-beginning-of-line): Move to beginning of visual line when appropriate. Fix docstring. * testing/lisp/test-org.el (test-org/beginning-of-line): Add tests.
This commit is contained in:
parent
5c85409464
commit
8d2f0a4411
69
lisp/org.el
69
lisp/org.el
|
@ -23710,45 +23710,50 @@ package ox-bibtex by Taru Karttunen."
|
||||||
|
|
||||||
;;;; Functions extending outline functionality
|
;;;; Functions extending outline functionality
|
||||||
|
|
||||||
(defun org-beginning-of-line (&optional arg)
|
(defun org-beginning-of-line (&optional n)
|
||||||
"Go to the beginning of the current line.
|
"Go to the beginning of the current visible line.
|
||||||
|
|
||||||
If that is invisible, continue to a visible line beginning.
|
|
||||||
|
|
||||||
If this is a headline, and `org-special-ctrl-a/e' is set, ignore
|
If this is a headline, and `org-special-ctrl-a/e' is set, ignore
|
||||||
tags on the first attempt, and only move to after the tags when
|
tags on the first attempt, and only move to after the tags when
|
||||||
the cursor is already beyond the end of the headline."
|
the cursor is already beyond the end of the headline.
|
||||||
(interactive "P")
|
|
||||||
(let ((pos (point))
|
With argument N not nil or 1, move forward N - 1 lines first."
|
||||||
|
(interactive "^p")
|
||||||
|
(let ((origin (point))
|
||||||
(special (pcase org-special-ctrl-a/e
|
(special (pcase org-special-ctrl-a/e
|
||||||
(`(,C-a . _) C-a)
|
(`(,C-a . _) C-a) (_ org-special-ctrl-a/e)))
|
||||||
(C-a C-a)))
|
|
||||||
deactivate-mark)
|
deactivate-mark)
|
||||||
|
;; First move to a visible line.
|
||||||
(if (bound-and-true-p visual-line-mode)
|
(if (bound-and-true-p visual-line-mode)
|
||||||
(call-interactively #'beginning-of-visual-line)
|
(beginning-of-visual-line n)
|
||||||
(call-interactively #'move-beginning-of-line)
|
(move-beginning-of-line n)
|
||||||
;; `move-beginning-of-line' may leave point after invisible
|
;; `move-beginning-of-line' may leave point after invisible
|
||||||
;; characters if line starts with such of these (e.g., with
|
;; characters if line starts with such of these (e.g., with
|
||||||
;; a link at column 0). Really move to the beginning of the
|
;; a link at column 0). Really move to the beginning of the
|
||||||
;; current visible line.
|
;; current visible line.
|
||||||
(beginning-of-line))
|
(beginning-of-line))
|
||||||
(cond
|
(cond
|
||||||
((or arg (not special)))
|
;; No special behavior. Point is already at the beginning of
|
||||||
((and (looking-at org-complex-heading-regexp)
|
;; a line, logical or visual.
|
||||||
(eq (char-after (match-end 1)) ?\s))
|
((not special))
|
||||||
|
;; `beginning-of-visual-line' left point before logical beginning
|
||||||
|
;; of line: point is at the beginning of a visual line. Bail
|
||||||
|
;; out.
|
||||||
|
((and (bound-and-true-p visual-line-mode) (not (bolp))))
|
||||||
|
((looking-at org-complex-heading-regexp)
|
||||||
|
;; At a headline, special position is before the title, but
|
||||||
|
;; after any TODO keyword or priority cookie.
|
||||||
(let ((refpos (min (1+ (or (match-end 3) (match-end 2) (match-end 1)))
|
(let ((refpos (min (1+ (or (match-end 3) (match-end 2) (match-end 1)))
|
||||||
(line-end-position))))
|
(line-end-position)))
|
||||||
(goto-char
|
(bol (point)))
|
||||||
(if (eq special t)
|
(if (eq special 'reversed)
|
||||||
(cond ((> pos refpos) refpos)
|
(when (and (= origin bol) (eq last-command this-command))
|
||||||
((= pos (point)) refpos)
|
(goto-char refpos))
|
||||||
(t (point)))
|
(when (or (> origin refpos) (= origin bol))
|
||||||
(cond ((> pos (point)) (point))
|
(goto-char refpos)))))
|
||||||
((not (eq last-command this-command)) (point))
|
|
||||||
(t refpos))))))
|
|
||||||
((and (looking-at org-list-full-item-re)
|
((and (looking-at org-list-full-item-re)
|
||||||
(save-match-data (memq (org-element-type (org-element-at-point))
|
(memq (org-element-type (save-match-data (org-element-at-point)))
|
||||||
'(item plain-list))))
|
'(item plain-list)))
|
||||||
;; Set special position at first white space character after
|
;; Set special position at first white space character after
|
||||||
;; bullet, and check-box, if any.
|
;; bullet, and check-box, if any.
|
||||||
(let ((after-bullet
|
(let ((after-bullet
|
||||||
|
@ -23756,15 +23761,13 @@ the cursor is already beyond the end of the headline."
|
||||||
(cond ((not box) (match-end 1))
|
(cond ((not box) (match-end 1))
|
||||||
((eq (char-after box) ?\s) (1+ box))
|
((eq (char-after box) ?\s) (1+ box))
|
||||||
(t box)))))
|
(t box)))))
|
||||||
;; Special case: Move point to special position when currently
|
(if (eq special 'reversed)
|
||||||
;; after it or at beginning of line.
|
(when (and (= (point) origin) (eq last-command this-command))
|
||||||
(if (eq special t)
|
|
||||||
(when (or (> pos after-bullet) (= (point) pos))
|
|
||||||
(goto-char after-bullet))
|
(goto-char after-bullet))
|
||||||
;; Reversed case: Move point to special position when point
|
(when (or (> origin after-bullet) (= (point) origin))
|
||||||
;; was already at beginning of line and command is repeated.
|
(goto-char after-bullet)))))
|
||||||
(when (and (= (point) pos) (eq last-command this-command))
|
;; No special context. Point is already at beginning of line.
|
||||||
(goto-char after-bullet))))))))
|
(t nil))))
|
||||||
|
|
||||||
(defun org-end-of-line (&optional n)
|
(defun org-end-of-line (&optional n)
|
||||||
"Go to the end of the line, but before ellipsis, if any.
|
"Go to the end of the line, but before ellipsis, if any.
|
||||||
|
|
|
@ -2467,24 +2467,78 @@ http://article.gmane.org/gmane.emacs.orgmode/21459/"
|
||||||
|
|
||||||
(ert-deftest test-org/beginning-of-line ()
|
(ert-deftest test-org/beginning-of-line ()
|
||||||
"Test `org-beginning-of-line' specifications."
|
"Test `org-beginning-of-line' specifications."
|
||||||
;; Standard test.
|
;; Move to beginning of line. If current line in invisible, move to
|
||||||
|
;; beginning of visible line instead.
|
||||||
(should
|
(should
|
||||||
(org-test-with-temp-text "Some text\nSome other text<point>"
|
(org-test-with-temp-text "Some text\nSome other text<point>"
|
||||||
(progn (org-beginning-of-line) (bolp))))
|
(org-beginning-of-line)
|
||||||
;; Standard test with `visual-line-mode'.
|
(bolp)))
|
||||||
|
(should
|
||||||
|
(org-test-with-temp-text "* H1\n** H2<point>"
|
||||||
|
(org-overview)
|
||||||
|
(org-beginning-of-line)
|
||||||
|
(= (line-beginning-position) 1)))
|
||||||
|
;; With `visual-line-mode' active, move to beginning of visual line.
|
||||||
(should-not
|
(should-not
|
||||||
(org-test-with-temp-text "A <point>long line of text\nSome other text"
|
(org-test-with-temp-text "A <point>long line of text\nSome other text"
|
||||||
(progn (visual-line-mode)
|
(visual-line-mode)
|
||||||
(dotimes (i 1000) (insert "very "))
|
(dotimes (i 1000) (insert "very "))
|
||||||
(org-beginning-of-line)
|
(org-beginning-of-line)
|
||||||
(bolp))))
|
(bolp)))
|
||||||
;; At an headline with special movement.
|
;; In a wide headline, with `visual-line-mode', prefer going to the
|
||||||
|
;; beginning of a visual line than to the logical beginning of line,
|
||||||
|
;; even if special movement is active.
|
||||||
|
(should-not
|
||||||
|
(org-test-with-temp-text "* A <point>long headline"
|
||||||
|
(visual-line-mode)
|
||||||
|
(dotimes (i 1000) (insert "very "))
|
||||||
|
(goto-char (point-max))
|
||||||
|
(org-beginning-of-line)
|
||||||
|
(bobp)))
|
||||||
|
(should-not
|
||||||
|
(org-test-with-temp-text "* A <point>long headline"
|
||||||
|
(visual-line-mode)
|
||||||
|
(dotimes (i 1000) (insert "very "))
|
||||||
|
(goto-char (point-max))
|
||||||
|
(let ((org-special-ctrl-a/e t)) (org-beginning-of-line))
|
||||||
|
(bobp)))
|
||||||
|
;; At an headline with special movement, first move at beginning of
|
||||||
|
;; title, then at the beginning of line, rinse, repeat.
|
||||||
(should
|
(should
|
||||||
(org-test-with-temp-text "* TODO Headline<point>"
|
(org-test-with-temp-text "* TODO Headline<point>"
|
||||||
(let ((org-special-ctrl-a/e t))
|
(let ((org-special-ctrl-a/e t))
|
||||||
(and (progn (org-beginning-of-line) (looking-at "Headline"))
|
(and (progn (org-beginning-of-line) (looking-at "Headline"))
|
||||||
(progn (org-beginning-of-line) (bolp))
|
(progn (org-beginning-of-line) (bolp))
|
||||||
(progn (org-beginning-of-line) (looking-at "Headline"))))))
|
(progn (org-beginning-of-line) (looking-at "Headline"))))))
|
||||||
|
(should
|
||||||
|
(org-test-with-temp-text "* TODO [#A] Headline<point>"
|
||||||
|
(let ((org-special-ctrl-a/e t))
|
||||||
|
(org-beginning-of-line)
|
||||||
|
(looking-at "Headline"))))
|
||||||
|
;; At an headline with reversed movement, first move to beginning of
|
||||||
|
;; line, then to the beginning of title.
|
||||||
|
(should
|
||||||
|
(org-test-with-temp-text "* TODO Headline<point>"
|
||||||
|
(let ((org-special-ctrl-a/e 'reversed)
|
||||||
|
(this-command last-command))
|
||||||
|
(and (progn (org-beginning-of-line) (bolp))
|
||||||
|
(progn (org-beginning-of-line) (looking-at "Headline"))))))
|
||||||
|
;; At an item with special movement, first move after to beginning
|
||||||
|
;; of title, then to the beginning of line, rinse, repeat.
|
||||||
|
(should
|
||||||
|
(org-test-with-temp-text "- [ ] Item<point>"
|
||||||
|
(let ((org-special-ctrl-a/e t))
|
||||||
|
(and (progn (org-beginning-of-line) (looking-at "Item"))
|
||||||
|
(progn (org-beginning-of-line) (bolp))
|
||||||
|
(progn (org-beginning-of-line) (looking-at "Item"))))))
|
||||||
|
;; At an item with reversed movement, first move to beginning of
|
||||||
|
;; line, then to the beginning of title.
|
||||||
|
(should
|
||||||
|
(org-test-with-temp-text "- [X] Item<point>"
|
||||||
|
(let ((org-special-ctrl-a/e 'reversed)
|
||||||
|
(this-command last-command))
|
||||||
|
(and (progn (org-beginning-of-line) (bolp))
|
||||||
|
(progn (org-beginning-of-line) (looking-at "Item"))))))
|
||||||
;; Leave point before invisible characters at column 0.
|
;; Leave point before invisible characters at column 0.
|
||||||
(should
|
(should
|
||||||
(org-test-with-temp-text "[[http://orgmode.org]]<point>"
|
(org-test-with-temp-text "[[http://orgmode.org]]<point>"
|
||||||
|
@ -2496,6 +2550,11 @@ http://article.gmane.org/gmane.emacs.orgmode/21459/"
|
||||||
(let ((org-special-ctrl-a/e t))
|
(let ((org-special-ctrl-a/e t))
|
||||||
(org-beginning-of-line)
|
(org-beginning-of-line)
|
||||||
(bolp))))
|
(bolp))))
|
||||||
|
(should
|
||||||
|
(org-test-with-temp-text "[[http<point>://orgmode.org]]"
|
||||||
|
(visual-line-mode)
|
||||||
|
(org-beginning-of-line)
|
||||||
|
(bolp)))
|
||||||
;; Special case: Do not error when the buffer contains only a single
|
;; Special case: Do not error when the buffer contains only a single
|
||||||
;; asterisk.
|
;; asterisk.
|
||||||
(should
|
(should
|
||||||
|
|
Loading…
Reference in a new issue