From 6eb940a8dcc38797d1c8abfff7a1feac7e7d0407 Mon Sep 17 00:00:00 2001 From: Nicolas Goaziou Date: Sat, 19 Apr 2014 14:38:25 +0200 Subject: [PATCH] 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. --- lisp/org-element.el | 11 +++++-- lisp/org.el | 65 ++++++++++++++++++++-------------------- testing/lisp/test-org.el | 29 ++++++++---------- 3 files changed, 55 insertions(+), 50 deletions(-) diff --git a/lisp/org-element.el b/lisp/org-element.el index e9f0b2c58..195fecdde 100644 --- a/lisp/org-element.el +++ b/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 diff --git a/lisp/org.el b/lisp/org.el index 66fa622c9..14a287e5a 100644 --- a/lisp/org.el +++ b/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 diff --git a/testing/lisp/test-org.el b/testing/lisp/test-org.el index 9350f9348..f89fd32a5 100644 --- a/testing/lisp/test-org.el +++ b/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 "<<>>") + (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 "<> <<>>\n: <>" - (org-all-targets)))) - (should - (equal '("radio-target") - (org-test-with-temp-text "<<>>!" (org-all-targets)))) - ;; With argument. - (should - (equal '("radio-target") - (org-test-with-temp-text "<> <<>>" - (org-all-targets t))))) ;;; Visibility