Browse Source

Speed up refile target collection.

This patch introduces three improvements to refile target construction,
which should speed these functions up significantly.

1. A faster way to move up a level in the outline hierarchy
2. A better way to construct the outline path, in the case
   that the command is scanning the entire hierarchy anyway
3. Avoid comparing the true-names of files.
Carsten Dominik 17 years ago
parent
commit
552ededaae
2 changed files with 46 additions and 25 deletions
  1. 10 0
      lisp/ChangeLog
  2. 36 25
      lisp/org.el

+ 10 - 0
lisp/ChangeLog

@@ -1,3 +1,13 @@
+2008-12-15  Carsten Dominik  <carsten.dominik@gmail.com>
+
+	* org.el (org-up-heading-safe): Speed up function by using a
+	direct regexp search.
+	(org-olpa): New variable.
+	(org-get-outline-path): Speed-up path constructions in cases where
+	this is possible because the entire hierarchy is scanned anyway.
+	(org-refile-get-location): Don't compare the truenames of files,
+	this is too slow.
+
 2008-12-12  Tassilo Horn  <tassilo@member.fsf.org>
 2008-12-12  Tassilo Horn  <tassilo@member.fsf.org>
 
 
 	* org-gnus.el (org-gnus-article-link, org-gnus-article-link):
 	* org-gnus.el (org-gnus-article-link, org-gnus-article-link):

+ 36 - 25
lisp/org.el

@@ -7456,10 +7456,12 @@ on the system \"/user@host:\"."
 (defun org-get-refile-targets (&optional default-buffer)
 (defun org-get-refile-targets (&optional default-buffer)
   "Produce a table with refile targets."
   "Produce a table with refile targets."
   (let ((entries (or org-refile-targets '((nil . (:level . 1)))))
   (let ((entries (or org-refile-targets '((nil . (:level . 1)))))
-	targets txt re files f desc descre)
+	targets txt re files f desc descre fast-path-p)
+    (message "Getting targets...")
     (with-current-buffer (or default-buffer (current-buffer))
     (with-current-buffer (or default-buffer (current-buffer))
       (while (setq entry (pop entries))
       (while (setq entry (pop entries))
 	(setq files (car entry) desc (cdr entry))
 	(setq files (car entry) desc (cdr entry))
+	(setq fast-path-p nil)
 	(cond
 	(cond
 	 ((null files) (setq files (list (current-buffer))))
 	 ((null files) (setq files (list (current-buffer))))
 	 ((eq files 'org-agenda-files)
 	 ((eq files 'org-agenda-files)
@@ -7483,6 +7485,7 @@ on the system \"/user@host:\"."
 					    (cdr desc)))
 					    (cdr desc)))
 			       "\\}[ \t]")))
 			       "\\}[ \t]")))
 	 ((eq (car desc) :maxlevel)
 	 ((eq (car desc) :maxlevel)
+	  (setq fast-path-p t)
 	  (setq descre (concat "^\\*\\{1," (number-to-string
 	  (setq descre (concat "^\\*\\{1," (number-to-string
 					    (if org-odd-levels-only
 					    (if org-odd-levels-only
 						(1- (* 2 (cdr desc)))
 						(1- (* 2 (cdr desc)))
@@ -7500,7 +7503,8 @@ on the system \"/user@host:\"."
 		(while (re-search-forward descre nil t)
 		(while (re-search-forward descre nil t)
 		  (goto-char (point-at-bol))
 		  (goto-char (point-at-bol))
 		  (when (looking-at org-complex-heading-regexp)
 		  (when (looking-at org-complex-heading-regexp)
-		    (setq txt (org-link-display-format (match-string 4))
+		    (setq level (org-reduced-level (- (match-end 1) (match-beginning 1)))
+			  txt (org-link-display-format (match-string 4))
 			  re (concat "^" (regexp-quote
 			  re (concat "^" (regexp-quote
 					  (buffer-substring (match-beginning 1)
 					  (buffer-substring (match-beginning 1)
 							    (match-end 4)))))
 							    (match-end 4)))))
@@ -7516,26 +7520,37 @@ on the system \"/user@host:\"."
 						       (buffer-file-name (buffer-base-buffer))))
 						       (buffer-file-name (buffer-base-buffer))))
 					      (if (eq org-refile-use-outline-path 'full-file-path)
 					      (if (eq org-refile-use-outline-path 'full-file-path)
 						  (list (buffer-file-name (buffer-base-buffer)))))
 						  (list (buffer-file-name (buffer-base-buffer)))))
-					    (org-get-outline-path)
+					    (org-get-outline-path fast-path-p level txt)
 					    (list txt))
 					    (list txt))
 					   "/")))
 					   "/")))
 		    (push (list txt f re (point)) targets))
 		    (push (list txt f re (point)) targets))
 		  (goto-char (point-at-eol))))))))
 		  (goto-char (point-at-eol))))))))
-      (nreverse targets))))
+    (message "Getting targets...done")
+    (nreverse targets))))
 
 
 (defun org-protect-slash (s)
 (defun org-protect-slash (s)
   (while (string-match "/" s)
   (while (string-match "/" s)
     (setq s (replace-match "\\" t t s)))
     (setq s (replace-match "\\" t t s)))
   s)
   s)
 
 
-(defun org-get-outline-path ()
+(defvar org-olpa (make-vector 20 nil))
+
+(defun org-get-outline-path (&optional fastp level heading)
   "Return the outline path to the current entry, as a list."
   "Return the outline path to the current entry, as a list."
-  (let (rtn)
-    (save-excursion
-      (while (org-up-heading-safe)
-	(when (looking-at org-complex-heading-regexp)
-	  (push (org-match-string-no-properties 4) rtn)))
-      rtn)))
+  (if (> level 19) (error "Outline path failure, more than 19 levels."))
+  (if fastp
+      (progn
+	(loop for i from level upto 19 do
+	      (aset org-olpa i nil))
+	(prog1
+	    (delq nil (append org-olpa nil))
+	  (aset org-olpa level heading)))
+    (let (rtn)
+      (save-excursion
+	(while (org-up-heading-safe)
+	  (when (looking-at org-complex-heading-regexp)
+	    (push (org-match-string-no-properties 4) rtn)))
+	rtn))))
 
 
 (defvar org-refile-history nil
 (defvar org-refile-history nil
   "History for refiling operations.")
   "History for refiling operations.")
@@ -7635,10 +7650,9 @@ operation has put the subtree."
 		  'org-ido-completing-read))
 		  'org-ido-completing-read))
 	 (extra (if org-refile-use-outline-path "/" ""))
 	 (extra (if org-refile-use-outline-path "/" ""))
 	 (filename (buffer-file-name (buffer-base-buffer cbuf)))
 	 (filename (buffer-file-name (buffer-base-buffer cbuf)))
-	 (fname (and filename (file-truename filename)))
 	 (tbl (mapcar
 	 (tbl (mapcar
 	       (lambda (x)
 	       (lambda (x)
-		 (if (not (equal fname (file-truename (nth 1 x))))
+		 (if (not (equal filename (nth 1 x)))
 		     (cons (concat (car x) extra " ("
 		     (cons (concat (car x) extra " ("
 				   (file-name-nondirectory (nth 1 x)) ")")
 				   (file-name-nondirectory (nth 1 x)) ")")
 			   (cdr x))
 			   (cdr x))
@@ -9502,10 +9516,9 @@ ignore inherited ones."
 (defun org-toggle-tag (tag &optional onoff)
 (defun org-toggle-tag (tag &optional onoff)
   "Toggle the tag TAG for the current line.
   "Toggle the tag TAG for the current line.
 If ONOFF is `on' or `off', don't toggle but set to this state."
 If ONOFF is `on' or `off', don't toggle but set to this state."
-  (unless (org-on-heading-p t) (error "Not on headling"))
   (let (res current)
   (let (res current)
     (save-excursion
     (save-excursion
-      (beginning-of-line)
+      (org-back-to-heading t)
       (if (re-search-forward (org-re "[ \t]:\\([[:alnum:]_@:]+\\):[ \t]*$")
       (if (re-search-forward (org-re "[ \t]:\\([[:alnum:]_@:]+\\):[ \t]*$")
 			     (point-at-eol) t)
 			     (point-at-eol) t)
 	  (progn
 	  (progn
@@ -14406,16 +14419,14 @@ With argument, move up ARG levels."
   "Move to the heading line of which the present line is a subheading.
   "Move to the heading line of which the present line is a subheading.
 This version will not throw an error.  It will return the level of the
 This version will not throw an error.  It will return the level of the
 headline found, or nil if no higher level is found."
 headline found, or nil if no higher level is found."
-  (let ((pos (point)) start-level level
-	(re (concat "^" outline-regexp)))
-    (catch 'exit
-      (org-back-to-heading t)
-      (setq start-level (funcall outline-level))
-      (if (equal start-level 1) (throw 'exit nil))
-      (while (re-search-backward re nil t)
-	(setq level (funcall outline-level))
-	(if (< level start-level) (throw 'exit level)))
-      nil)))
+  (let (start-level re)
+    (org-back-to-heading t)
+    (setq start-level (funcall outline-level))
+    (if (equal start-level 1)
+	nil
+      (setq re (concat "^\\*\\{1," (number-to-string (1- start-level)) "\\} "))
+      (if (re-search-backward re nil t)
+	  (funcall outline-level)))))
 
 
 (defun org-first-sibling-p ()
 (defun org-first-sibling-p ()
   "Is this heading the first child of its parents?"
   "Is this heading the first child of its parents?"