Prechádzať zdrojové kódy

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>
Nicolas Goaziou 8 rokov pred
rodič
commit
b3c556d83a
2 zmenil súbory, kde vykonal 30 pridanie a 26 odobranie
  1. 17 22
      lisp/org.el
  2. 13 4
      testing/lisp/test-org.el

+ 17 - 22
lisp/org.el

@@ -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."

+ 13 - 4
testing/lisp/test-org.el

@@ -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