Fix tags alignment when headline contains invisible text

* lisp/org.el (org-align-tags-here): Do not use `org-move-to-column',
  which may move point on the other side of some invisible text.
  Refactor code.

* testing/lisp/test-org.el (test-org/tag-align): Add test.

Reported-by: Michael Fiano <michael.fiano@gmail.com>
<http://permalink.gmane.org/gmane.emacs.orgmode/109435>
This commit is contained in:
Nicolas Goaziou 2016-09-30 00:56:58 +02:00
parent 12196b8472
commit b3c556d83a
2 changed files with 30 additions and 26 deletions

View File

@ -14951,28 +14951,23 @@ If ONOFF is `on' or `off', don't toggle but set to this state."
res))
(defun org-align-tags-here (to-col)
;; Assumes that this is a headline
"Align tags on the current headline to TO-COL."
(let ((pos (point)) (col (current-column)) ncol tags-l p)
(beginning-of-line 1)
(if (and (looking-at ".*?\\([ \t]+\\)\\(:[[:alnum:]_@#%:]+:\\)[ \t]*$")
(< pos (match-beginning 2)))
(progn
(setq tags-l (string-width (match-string 2)))
(goto-char (match-beginning 1))
(insert " ")
(delete-region (point) (1+ (match-beginning 2)))
(setq ncol (max (current-column)
(1+ col)
(if (> to-col 0)
to-col
(- (abs to-col) tags-l))))
(setq p (point))
(insert (make-string (- ncol (current-column)) ?\ ))
(setq ncol (current-column))
(when indent-tabs-mode (tabify p (point-at-eol)))
(org-move-to-column (min ncol col)))
(goto-char pos))))
"Align tags on the current headline to TO-COL.
Assume point is on a headline."
(let ((pos (point)))
(beginning-of-line)
(if (or (not (looking-at ".*?\\([ \t]+\\)\\(:[[:alnum:]_@#%:]+:\\)[ \t]*$"))
(>= pos (match-beginning 2)))
;; No tags or point within tags: do not align.
(goto-char pos)
(goto-char (match-beginning 1))
(let ((shift (max (- (if (>= to-col 0) to-col
(- (abs to-col) (string-width (match-string 2))))
(current-column))
1)))
(replace-match (make-string shift ?\s) nil nil nil 1)
;; Preserve initial position, if possible. In any case, stop
;; before tags.
(when (< pos (point)) (goto-char pos))))))
(defun org-set-tags-command (&optional arg just-align)
"Call the set-tags command for the current entry."

View File

@ -4524,14 +4524,15 @@ Paragraph<point>"
'((:startgroup) ("group") ("t1") ("t2") (:endgroup)))))
(ert-deftest test-org/tag-align ()
"Test `org-align-tags-here' with different display width."
"Test `org-align-tags-here' specifications"
;; Test aligning tags with different display width.
(should
;; 12345678901234567890
(equal "* Test :abc:"
(org-test-with-temp-text "* Test :abc:"
(let ((org-tags-column -20)
(indent-tabs-mode nil))
(org-fix-tags-on-the-fly))
(org-fix-tags-on-the-fly))
(buffer-string))))
(should
;; 12345678901234567890
@ -4539,8 +4540,16 @@ Paragraph<point>"
(org-test-with-temp-text "* Test :日本語:"
(let ((org-tags-column -20)
(indent-tabs-mode nil))
(org-fix-tags-on-the-fly))
(buffer-string)))))
(org-fix-tags-on-the-fly))
(buffer-string))))
;; Make sure aligning tags do not skip invisible text.
(should
(equal "* [[linkx]] :tag:"
(org-test-with-temp-text "* [[link<point>]] :tag:"
(let ((org-tags-column 0))
(org-fix-tags-on-the-fly)
(insert "x")
(buffer-string))))))
(ert-deftest test-org/tags-at ()
(should