mirror of
https://git.savannah.gnu.org/git/emacs/org-mode.git
synced 2024-09-29 20:37:51 +00:00
Fix `C-e' with visible lines and arguments
* lisp/org.el (org-end-of-line): Correctly go to the end of visible line, when appropriate. * testing/lisp/test-org.el (test-org/end-of-line): Add tests.
This commit is contained in:
parent
2971c48cf1
commit
45048eb783
87
lisp/org.el
87
lisp/org.el
|
@ -23766,42 +23766,63 @@ the cursor is already beyond the end of the headline."
|
|||
(when (and (= (point) pos) (eq last-command this-command))
|
||||
(goto-char after-bullet))))))))
|
||||
|
||||
(defun org-end-of-line (&optional arg)
|
||||
"Go to the end of the line.
|
||||
(defun org-end-of-line (&optional n)
|
||||
"Go to the end of the line, but before ellipsis, if any.
|
||||
|
||||
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
|
||||
the cursor is already beyond the end of the headline."
|
||||
(interactive "P")
|
||||
(let ((special (if (consp org-special-ctrl-a/e) (cdr org-special-ctrl-a/e)
|
||||
org-special-ctrl-a/e))
|
||||
(move-fun (cond ((bound-and-true-p visual-line-mode)
|
||||
'end-of-visual-line)
|
||||
((fboundp 'move-end-of-line) 'move-end-of-line)
|
||||
(t 'end-of-line)))
|
||||
the cursor is already beyond the end of the headline.
|
||||
|
||||
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
|
||||
(`(_ . ,C-e) C-e) (_ org-special-ctrl-a/e)))
|
||||
deactivate-mark)
|
||||
(if (or (not special) arg) (call-interactively move-fun)
|
||||
(let* ((element (save-excursion (beginning-of-line)
|
||||
(org-element-at-point)))
|
||||
(type (org-element-type element)))
|
||||
(cond
|
||||
((memq type '(headline inlinetask))
|
||||
(let ((pos (point)))
|
||||
(beginning-of-line 1)
|
||||
(if (looking-at ".*?\\(?:\\([ \t]*\\)\\(:[[:alnum:]_@#%:]+:\\)?[ \t]*\\)?$")
|
||||
(if (eq special t)
|
||||
(if (or (< pos (match-beginning 1)) (= pos (match-end 0)))
|
||||
(goto-char (match-beginning 1))
|
||||
(goto-char (match-end 0)))
|
||||
(if (or (< pos (match-end 0))
|
||||
(not (eq this-command last-command)))
|
||||
(goto-char (match-end 0))
|
||||
(goto-char (match-beginning 1))))
|
||||
(call-interactively move-fun))))
|
||||
((outline-invisible-p (line-end-position))
|
||||
;; If element is hidden, `move-end-of-line' would put point
|
||||
;; after it. Use `end-of-line' to stay on current line.
|
||||
(call-interactively 'end-of-line))
|
||||
(t (call-interactively move-fun))))))
|
||||
;; First move to a visible line.
|
||||
(if (bound-and-true-p visual-line-mode)
|
||||
(beginning-of-visual-line n)
|
||||
(move-beginning-of-line n))
|
||||
(cond
|
||||
;; At a headline, with tags.
|
||||
((and special
|
||||
(save-excursion
|
||||
(beginning-of-line)
|
||||
(looking-at org-complex-heading-regexp))
|
||||
(match-end 5))
|
||||
(let ((tags (save-excursion
|
||||
(goto-char (match-beginning 5))
|
||||
(skip-chars-backward " \t")
|
||||
(point)))
|
||||
(visual-end (and (bound-and-true-p visual-line-mode)
|
||||
(save-excursion
|
||||
(end-of-visual-line)
|
||||
(point)))))
|
||||
;; If `end-of-visual-line' brings us before end of line or
|
||||
;; even tags, i.e., the headline spans over multiple visual
|
||||
;; lines, move there.
|
||||
(cond ((and visual-end
|
||||
(< visual-end tags)
|
||||
(<= origin visual-end))
|
||||
(goto-char visual-end))
|
||||
((eq special 'reversed)
|
||||
(if (and (= origin (line-end-position))
|
||||
(eq this-command last-command))
|
||||
(goto-char tags)
|
||||
(end-of-line)))
|
||||
(t
|
||||
(if (or (< origin tags) (= origin (line-end-position)))
|
||||
(goto-char tags)
|
||||
(end-of-line))))))
|
||||
((bound-and-true-p visual-line-mode)
|
||||
(let ((bol (line-beginning-position)))
|
||||
(end-of-visual-line)
|
||||
;; If `end-of-visual-line' gets us past the ellipsis at the
|
||||
;; end of a line, backtrack and use `end-of-line' instead.
|
||||
(when (/= bol (line-beginning-position))
|
||||
(goto-char bol)
|
||||
(end-of-line))))
|
||||
(t (end-of-line))))
|
||||
(setq disable-point-adjustment
|
||||
(or (not (invisible-p (point)))
|
||||
(not (invisible-p (max (point-min) (1- (point))))))))
|
||||
|
|
|
@ -2511,35 +2511,80 @@ http://article.gmane.org/gmane.emacs.orgmode/21459/"
|
|||
(should
|
||||
(org-test-with-temp-text "Some text\nSome other text"
|
||||
(progn (org-end-of-line) (eolp))))
|
||||
;; Standard test with `visual-line-mode'.
|
||||
;; With `visual-line-mode' active, move to end of visible line.
|
||||
;; However, never go past ellipsis.
|
||||
(should-not
|
||||
(org-test-with-temp-text "A long line of text\nSome other text"
|
||||
(progn (visual-line-mode)
|
||||
(forward-char 2)
|
||||
(dotimes (i 1000) (insert "very "))
|
||||
(goto-char (point-min))
|
||||
(org-end-of-line)
|
||||
(eolp))))
|
||||
;; At an headline with special movement.
|
||||
(org-test-with-temp-text "A <point>long line of text\nSome other text"
|
||||
(visual-line-mode)
|
||||
(dotimes (i 1000) (insert "very "))
|
||||
(goto-char (point-min))
|
||||
(org-end-of-line)
|
||||
(eolp)))
|
||||
(should-not
|
||||
(org-test-with-temp-text "* A short headline\nSome contents"
|
||||
(visual-line-mode)
|
||||
(org-overview)
|
||||
(org-end-of-line)
|
||||
(eobp)))
|
||||
;; In a wide headline, with `visual-line-mode', prefer going to end
|
||||
;; of visible line if tags, or end of line, are farther.
|
||||
(should-not
|
||||
(org-test-with-temp-text "* A <point>long headline"
|
||||
(visual-line-mode)
|
||||
(dotimes (i 1000) (insert "very "))
|
||||
(goto-char (point-min))
|
||||
(org-end-of-line)
|
||||
(eolp)))
|
||||
(should-not
|
||||
(org-test-with-temp-text "* A <point>long headline :tag:"
|
||||
(visual-line-mode)
|
||||
(dotimes (i 1000) (insert "very "))
|
||||
(goto-char (point-min))
|
||||
(org-end-of-line)
|
||||
(eolp)))
|
||||
;; At an headline without special movement, go to end of line.
|
||||
;; However, never go past ellipsis.
|
||||
(should
|
||||
(org-test-with-temp-text "* Headline2b :tag:\n"
|
||||
(let ((org-special-ctrl-a/e nil))
|
||||
(and (progn (org-end-of-line) (eolp))
|
||||
(progn (org-end-of-line) (eolp))))))
|
||||
(should
|
||||
(org-test-with-temp-text "* Headline2a :tag:\n** Sub"
|
||||
(org-overview)
|
||||
(let ((org-special-ctrl-a/e nil))
|
||||
(org-end-of-line)
|
||||
(= 1 (line-beginning-position)))))
|
||||
;; At an headline with special movement, first move before tags,
|
||||
;; then at the end of line, rinse, repeat. However, never go past
|
||||
;; ellipsis.
|
||||
(should
|
||||
(org-test-with-temp-text "* Headline1 :tag:\n"
|
||||
(let ((org-special-ctrl-a/e t))
|
||||
(and (progn (org-end-of-line) (looking-at " :tag:"))
|
||||
(progn (org-end-of-line) (eolp))
|
||||
(progn (org-end-of-line) (looking-at " :tag:"))))))
|
||||
;; At an headline without special movement.
|
||||
(should
|
||||
(org-test-with-temp-text "* Headline2 :tag:\n"
|
||||
(let ((org-special-ctrl-a/e nil))
|
||||
(and (progn (org-end-of-line) (eolp))
|
||||
(progn (org-end-of-line) (eolp))))))
|
||||
;; At an headline, with reversed movement.
|
||||
(org-test-with-temp-text "* Headline2a :tag:\n** Sub"
|
||||
(org-overview)
|
||||
(let ((org-special-ctrl-a/e t))
|
||||
(org-end-of-line)
|
||||
(org-end-of-line)
|
||||
(= 1 (line-beginning-position)))))
|
||||
;; At an headline, with reversed movement, first go to end of line,
|
||||
;; then before tags. However, never go past ellipsis.
|
||||
(should
|
||||
(org-test-with-temp-text "* Headline3 :tag:\n"
|
||||
(let ((org-special-ctrl-a/e 'reversed)
|
||||
(this-command last-command))
|
||||
(and (progn (org-end-of-line) (eolp))
|
||||
(progn (org-end-of-line) (looking-at " :tag:"))))))
|
||||
(should
|
||||
(org-test-with-temp-text "* Headline2a :tag:\n** Sub"
|
||||
(org-overview)
|
||||
(let ((org-special-ctrl-a/e 'reversed))
|
||||
(org-end-of-line)
|
||||
(= 1 (line-beginning-position)))))
|
||||
;; At a block without hidden contents.
|
||||
(should
|
||||
(org-test-with-temp-text "#+BEGIN_CENTER\nContents\n#+END_CENTER"
|
||||
|
@ -2550,7 +2595,12 @@ http://article.gmane.org/gmane.emacs.orgmode/21459/"
|
|||
(let ((org-special-ctrl-a/e t))
|
||||
(org-hide-block-toggle)
|
||||
(org-end-of-line)
|
||||
(eobp)))))
|
||||
(eobp))))
|
||||
;; Get past invisible characters at the end of line.
|
||||
(should
|
||||
(org-test-with-temp-text "[[http://orgmode.org]]"
|
||||
(org-end-of-line)
|
||||
(eolp))))
|
||||
|
||||
(ert-deftest test-org/open-line ()
|
||||
"Test `org-open-line' specifications."
|
||||
|
|
Loading…
Reference in a new issue