Browse Source

org-bibtex-import-from-file: Improve performance

* lisp/ol-bibtex.el (org-bibtex-put): Add new optional argument to
insert node property at point directly, without leveraging
`org-set-property'.  Add docstring.
(org-bibtex-write): Insert headline properties directly.  Add new
optional argument to suppress indentation.  Do not use `length' to
check if `org-bibtex-entries' list empty---`length' is too slow on
large lists.
(org-bibtex-import-from-file): Postpone indentation after all the
entries are imported.
* lisp/org.el (org-indent-region): Use cache.
Ihor Radchenko 2 years ago
parent
commit
5ba90e161b
2 changed files with 39 additions and 22 deletions
  1. 38 21
      lisp/ol-bibtex.el
  2. 1 1
      lisp/org.el

+ 38 - 21
lisp/ol-bibtex.el

@@ -344,14 +344,20 @@ and `org-tags-exclude-from-inheritance'."
                                               (upcase property)))))))
     (when it (org-trim it))))
 
-(defun org-bibtex-put (property value)
-  (let ((prop (upcase (if (keywordp property)
-                          (substring (symbol-name property) 1)
-                        property))))
-    (org-set-property
-     (concat (unless (string= org-bibtex-key-property prop) org-bibtex-prefix)
-	     prop)
-     value)))
+(defun org-bibtex-put (property value &optional insert-raw)
+  "Set PROPERTY of headline at point to VALUE.
+The PROPERTY will be prefixed with `org-bibtex-prefix' when necessary.
+With non-nil optional argument INSERT-RAW, insert node property string
+at point."
+  (let* ((prop (upcase (if (keywordp property)
+                           (substring (symbol-name property) 1)
+                         property)))
+         (prop (concat (unless (string= org-bibtex-key-property prop)
+                         org-bibtex-prefix)
+	               prop)))
+    (if insert-raw
+        (insert (format ":%s: %s\n" prop value))
+      (org-set-property prop value))))
 
 (defun org-bibtex-headline ()
   "Return a bibtex entry of the given headline as a string."
@@ -703,10 +709,12 @@ Return the number of saved entries."
   (interactive "fFile: ")
   (org-bibtex-read-buffer (find-file-noselect file 'nowarn 'rawfile)))
 
-(defun org-bibtex-write ()
-  "Insert a heading built from the first element of `org-bibtex-entries'."
+(defun org-bibtex-write (&optional noindent)
+  "Insert a heading built from the first element of `org-bibtex-entries'.
+When optional argument NOINDENT is non-nil, do not indent the properties
+drawer."
   (interactive)
-  (when (= (length org-bibtex-entries) 0)
+  (unless org-bibtex-entries
     (error "No entries in `org-bibtex-entries'"))
   (let* ((entry (pop org-bibtex-entries))
 	 (org-special-properties nil) ; avoids errors with `org-entry-put'
@@ -714,14 +722,16 @@ Return the number of saved entries."
 	 (togtag (lambda (tag) (org-toggle-tag tag 'on))))
     (org-insert-heading)
     (insert (funcall org-bibtex-headline-format-function entry))
-    (org-bibtex-put "TITLE" (funcall val :title))
+    (insert "\n:PROPERTIES:\n")
+    (org-bibtex-put "TITLE" (funcall val :title) 'insert)
     (org-bibtex-put org-bibtex-type-property-name
-		    (downcase (funcall val :type)))
+		    (downcase (funcall val :type))
+                    'insert)
     (dolist (pair entry)
       (pcase (car pair)
 	(:title    nil)
 	(:type     nil)
-	(:key      (org-bibtex-put org-bibtex-key-property (cdr pair)))
+	(:key      (org-bibtex-put org-bibtex-key-property (cdr pair) 'insert))
 	(:keywords (if org-bibtex-tags-are-keywords
 		       (dolist (kw (split-string (cdr pair) ", *"))
 			 (funcall
@@ -729,9 +739,14 @@ Return the number of saved entries."
 			  (replace-regexp-in-string
 			   "[^[:alnum:]_@#%]" ""
 			   (replace-regexp-in-string "[ \t]+" "_" kw))))
-		     (org-bibtex-put (car pair) (cdr pair))))
-	(_ (org-bibtex-put (car pair) (cdr pair)))))
-    (mapc togtag org-bibtex-tags)))
+		     (org-bibtex-put (car pair) (cdr pair) 'insert)))
+	(_ (org-bibtex-put (car pair) (cdr pair) 'insert))))
+    (insert ":END:\n")
+    (mapc togtag org-bibtex-tags)
+    (unless noindent
+      (org-indent-region
+       (save-excursion (org-back-to-heading t) (point))
+       (point)))))
 
 (defun org-bibtex-yank ()
   "If kill ring holds a bibtex entry yank it as an Org headline."
@@ -745,10 +760,12 @@ Return the number of saved entries."
 (defun org-bibtex-import-from-file (file)
   "Read bibtex entries from FILE and insert as Org headlines after point."
   (interactive "fFile: ")
-  (dotimes (_ (org-bibtex-read-file file))
-    (save-excursion (org-bibtex-write))
-    (re-search-forward org-property-end-re)
-    (open-line 1) (forward-char 1)))
+  (let ((pos (point)))
+    (dotimes (i (org-bibtex-read-file file))
+      (save-excursion (org-bibtex-write 'noindent))
+      (re-search-forward org-property-end-re)
+      (insert "\n"))
+    (org-indent-region pos (point))))
 
 (defun org-bibtex-export-to-kill-ring ()
   "Export current headline to kill ring as bibtex entry."

+ 1 - 1
lisp/org.el

@@ -18734,7 +18734,7 @@ assumed to be significant there."
 	  (end (copy-marker end)))
       (while (< (point) end)
 	(if (or (looking-at-p " \r\t\n") (org-at-heading-p)) (forward-line)
-	  (let* ((element (org-element-at-point-no-context))
+	  (let* ((element (org-element-at-point))
 		 (type (org-element-type element))
 		 (element-end (copy-marker (org-element-property :end element)))
 		 (ind (org--get-expected-indentation element nil)))