Browse Source

Fix cache update when radio targets are being refreshed

* lisp/org-element.el (org-element-cache-refresh): New function.
* lisp/org.el (org-update-radio-target-regexp): Make it standalone.
  Also refresh fontification only when necessary.
(org-all-targets, org-make-target-link-regexp): Remove functions.

* testing/lisp/test-org.el (test-org/update-radio-target-regexp): New
  test
(test-org/all-targets): Remove test.

We need to manually reset cache on radio links as re-fontification
doesn't trigger a buffer change, and, as a consequence, a cache reset.
Nicolas Goaziou 11 years ago
parent
commit
6eb940a8dc
3 changed files with 55 additions and 50 deletions
  1. 9 2
      lisp/org-element.el
  2. 33 32
      lisp/org.el
  3. 13 16
      testing/lisp/test-org.el

+ 9 - 2
lisp/org-element.el

@@ -5510,8 +5510,7 @@ change, as an integer."
 (defun org-element-cache-reset (&optional all)
   "Reset cache in current buffer.
 When optional argument ALL is non-nil, reset cache in all Org
-buffers.  This function will do nothing if
-`org-element-use-cache' is nil."
+buffers."
   (interactive "P")
   (dolist (buffer (if all (buffer-list) (list (current-buffer))))
     (with-current-buffer buffer
@@ -5530,6 +5529,14 @@ buffers.  This function will do nothing if
 	(add-hook 'after-change-functions
 		  #'org-element--cache-after-change nil t)))))
 
+;;;###autoload
+(defun org-element-cache-refresh (pos)
+  "Refresh cache at position POS."
+  (when (org-element--cache-active-p)
+    (org-element--cache-sync (current-buffer) pos)
+    (org-element--cache-submit-request pos pos 0)
+    (org-element--cache-set-timer (current-buffer))))
+
 
 
 ;;; The Toolbox

+ 33 - 32
lisp/org.el

@@ -6089,12 +6089,41 @@ by a #."
 	    t)))))
 
 (defun org-update-radio-target-regexp ()
-  "Find all radio targets in this file and update the regular expression."
+  "Find all radio targets in this file and update the regular expression.
+Also refresh fontification if needed."
   (interactive)
-  (when (memq 'radio org-activate-links)
+  (let ((old-regexp org-target-link-regexp)
+	(targets
+	 (org-with-wide-buffer
+	  (goto-char (point-min))
+	  (let (rtn)
+	    (while (re-search-forward org-radio-target-regexp nil t)
+	      ;; Make sure point is really within the object.
+	      (backward-char)
+	      (let ((obj (org-element-context)))
+		(when (eq (org-element-type obj) 'radio-target)
+		  (add-to-list 'rtn (org-element-property :value obj)))))
+	    rtn))))
     (setq org-target-link-regexp
-	  (org-make-target-link-regexp (org-all-targets 'radio)))
-    (org-restart-font-lock)))
+	  (and targets
+	       (concat "\\(?:^\\|[^[:alnum:]]\\)\\("
+		       (mapconcat
+			(lambda (x)
+			  (replace-regexp-in-string
+			   " +" "\\s-+" (regexp-quote x) t t))
+			targets
+			"\\|")
+		       "\\)\\(?:$\\|[^[:alnum:]]\\)")))
+    (unless (equal old-regexp org-target-link-regexp)
+      ;; Clean-up cache.
+      (when old-regexp
+	(org-with-wide-buffer
+	 (goto-char (point-min))
+	 (while (re-search-forward old-regexp nil t)
+	   (org-element-cache-refresh (match-beginning 1)))))
+      ;; Re fontify buffer.
+      (when (memq 'radio org-activate-links)
+	(org-restart-font-lock)))))
 
 (defun org-hide-wide-columns (limit)
   (let (s e)
@@ -6160,34 +6189,6 @@ done, nil otherwise."
     (font-lock-mode -1)
     (font-lock-mode 1)))
 
-(defun org-all-targets (&optional radio)
-  "Return a list of all targets in this file.
-When optional argument RADIO is non-nil, only find radio
-targets."
-  (let ((re (if radio org-radio-target-regexp org-target-regexp)) rtn)
-    (save-excursion
-      (goto-char (point-min))
-      (while (re-search-forward re nil t)
-	;; Make sure point is really within the object.
-	(backward-char)
-	(let ((obj (org-element-context)))
-	  (when (memq (org-element-type obj) '(radio-target target))
-	    (add-to-list 'rtn (downcase (org-element-property :value obj))))))
-      rtn)))
-
-(defun org-make-target-link-regexp (targets)
-  "Make regular expression matching all strings in TARGETS.
-The regular expression finds the targets also if there is a line break
-between words."
-  (and targets
-       (concat "\\(?:^\\|[^[:alnum:]]\\)\\("
-	       (mapconcat
-		(lambda (x)
-		  (replace-regexp-in-string " +" "\\s-+" (regexp-quote x) t t))
-		targets
-		"\\|")
-	       "\\)\\(?:$\\|[^[:alnum:]]\\)")))
-
 (defun org-activate-tags (limit)
   (if (re-search-forward (org-re "^\\*+.*[ \t]\\(:[[:alnum:]_@#%:]+:\\)[ \r\n]") limit t)
       (progn

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

@@ -1514,23 +1514,20 @@ Text.
 
 
 
-;;; Targets and Radio Targets
+;;; Radio Targets
+
+(ert-deftest test-org/update-radio-target-regexp ()
+  "Test `org-update-radio-target-regexp' specifications."
+  (org-test-with-temp-text "radio\n\nParagraph\n\nradio"
+    (save-excursion (goto-char (point-max)) (org-element-context))
+    (insert "<<<")
+    (search-forward "o")
+    (insert ">>>")
+    (replace-match "<<<radio>>>")
+    (org-update-radio-target-regexp)
+    (goto-char (point-max))
+    (org-element-type (org-element-context))))
 
-(ert-deftest test-org/all-targets ()
-  "Test `org-all-targets' specifications."
-  ;; Without an argument.
-  (should
-   (equal '("radio-target" "target")
-	  (org-test-with-temp-text "<<target>> <<<radio-target>>>\n: <<verb>>"
-	    (org-all-targets))))
-  (should
-   (equal '("radio-target")
-	  (org-test-with-temp-text "<<<radio-target>>>!" (org-all-targets))))
-  ;; With argument.
-  (should
-   (equal '("radio-target")
-	  (org-test-with-temp-text "<<target>> <<<radio-target>>>"
-	    (org-all-targets t)))))
 
 
 ;;; Visibility