X-Git-Url: https://git.donarmstrong.com/?p=org-ref.git;a=blobdiff_plain;f=org-ref.el;h=71252ebccd34183bb0a2f0db2b6d32177622dbd5;hp=a7b4929ab879c5e833097d640d23e4fa89e3a8cb;hb=5f80ebd42388dea16aeb397e0685500c4101f9cf;hpb=c5676b2e6b5bdf96f30f557e61c4a6cdc23c2668 diff --git a/org-ref.el b/org-ref.el index a7b4929..71252eb 100644 --- a/org-ref.el +++ b/org-ref.el @@ -41,6 +41,7 @@ (require 'helm-config) (require 'helm-bibtex) (require 'org) +(require 'org-element) ;; * Custom variables (defgroup org-ref nil @@ -81,11 +82,9 @@ You should use full-paths for each file." '(("article" . "%a, %t, %j, %v(%n), %p (%y). link. doi.") ("book" . "%a, %t, %u (%y).") - + ("techreport" . "%a, %t, %i, %u (%y).") ("proceedings" . "%e, %t in %S, %u (%y).") - ("inproceedings" . "%a, %t, %p, in %b, edited by %e, %u (%y)")) - "String to format an entry. Just the reference, no numbering at the beginning, etc... see the `org-ref-reftex-format-citation' docstring for the escape codes." :type 'string :group 'org-ref) @@ -326,7 +325,7 @@ You will see a message in the minibuffer when on a cite, ref or label link." (replace-regexp-in-string "\*" "\\\\*" x) ) org-ref-cite-types "\\|") "\\)" - ":\\([a-zA-Z0-9-_:]*,?\\)*")) + ":\\([a-zA-Z0-9-_:\\./]*,?\\)*")) (setq org-ref-label-re @@ -423,7 +422,6 @@ Beware that all this only works with BibTeX database files. When citations are made from the \bibitems in an explicit thebibliography environment, only %l is available." ;; Format a citation from the info in the BibTeX ENTRY - (unless (stringp format) (setq format "\\cite{%l}")) (if (and reftex-comment-citations @@ -504,16 +502,21 @@ Format according to the type in `org-ref-bibliography-entry-format'." (loop for file in org-ref-bibliography-files do (if (org-ref-key-in-file-p key (file-truename file)) (throw 'result file) - (message "%s not found in %s" key (file-truename file)))))) + (message "%s not found in %s" + key (file-truename file)))))) (with-temp-buffer (insert-file-contents file) (bibtex-search-entry key nil 0) (setq bibtex-entry (bibtex-parse-entry)) + ;; downcase field names so they work in the format-citation code + (dolist (cons-cell bibtex-entry) + (setf (car cons-cell) (downcase (car cons-cell)))) (setq entry-type (downcase (cdr (assoc "=type=" bibtex-entry)))) (setq format (cdr (assoc entry-type org-ref-bibliography-entry-format))) (if format (setq entry (org-ref-reftex-format-citation bibtex-entry format)) + ;; if no format, we use the bibtex entry itself as a fallback (save-restriction (bibtex-narrow-to-entry) (setq entry (buffer-string))))) @@ -539,8 +542,22 @@ Format according to the type in `org-ref-bibliography-entry-format'." (defun org-ref-get-bibtex-entry-html (key) "Return an html string for the bibliography entry corresponding to KEY." - - (format "
  • [%s] %s
  • " key key (org-ref-get-bibtex-entry-citation key))) + (let ((output)) + (setq output (org-ref-get-bibtex-entry-citation key)) + ;; unescape the & + (setq output (replace-regexp-in-string "\\\\&" "&" output)) + ;; hack to replace {} around text + (setq output (replace-regexp-in-string "{" "" output)) + (setq output (replace-regexp-in-string "}" "" output)) + ;; get rid of empty parens + (setq output (replace-regexp-in-string "()" "" output)) + ;; get rid of empty link and doi + (setq output (replace-regexp-in-string " link\\." "" output)) + ;; change double dash to single dash + (setq output (replace-regexp-in-string "--" "-" output)) + (setq output (replace-regexp-in-string " doi\\." "" output)) + (format "
  • [%s] %s
  • " + key key output))) (defun org-ref-get-html-bibliography () "Create an html bibliography when there are keys." @@ -611,45 +628,53 @@ Format according to the type in `org-ref-bibliography-entry-format'." ;; may contain multiple files. this code finds the ;; one you clicked on and opens it. (lambda (link-string) - ;; get link-string boundaries - ;; we have to go to the beginning of the line, and then search forward - + ;; get link-string boundaries we have to go to the + ;; beginning of the line, and then search forward (let* ((bibfile) ;; object is the link you clicked on (object (org-element-context)) (link-string-beginning) - (link-string-end)) - + (link-string-end) + (cp (point))) (save-excursion (goto-char (org-element-property :begin object)) (search-forward link-string nil nil 1) (setq link-string-beginning (match-beginning 0)) (setq link-string-end (match-end 0))) - ;; We set the reftex-default-bibliography - ;; here. it should be a local variable only in - ;; the current buffer. We need this for using - ;; reftex to do citations. - (set (make-local-variable 'reftex-default-bibliography) - (split-string (org-element-property :path object) ",")) - - ;; now if we have comma separated bibliographies - ;; we find the one clicked on. we want to - ;; search forward to next comma from point - (save-excursion - (if (search-forward "," link-string-end 1 1) - (setq key-end (- (match-end 0) 1)) ; we found a match - (setq key-end (point)))) ; no comma found so take the point - ;; and backward to previous comma from point - (save-excursion - (if (search-backward "," link-string-beginning 1 1) - (setq key-beginning (+ (match-beginning 0) 1)) ; we found a match - (setq key-beginning (point)))) ; no match found + ;; Make sure point is in the link-path. + (if (< cp link-string-beginning) + (goto-char link-string-beginning)) + ;; We set the reftex-default-bibliography + ;; here. it should be a local variable only in + ;; the current buffer. We need this for using + ;; reftex to do citations. + (set (make-local-variable 'reftex-default-bibliography) + (split-string + (org-element-property :path object) ",")) + + ;; now if we have comma separated bibliographies + ;; we find the one clicked on. we want to + ;; search forward to next comma from point + (save-excursion + (if (search-forward "," link-string-end 1 1) + ;; we found a match + (setq key-end (- (match-end 0) 1)) + ;; no comma found so take the point + (setq key-end (point)))) + ;; and backward to previous comma from point + (save-excursion + (if (search-backward "," link-string-beginning 1 1) + ;; we found a match + (setq key-beginning (+ (match-beginning 0) 1)) + (setq key-beginning (point)))) ; no match found ;; save the key we clicked on. - (setq bibfile (org-ref-strip-string (buffer-substring key-beginning key-end))) - (find-file bibfile))) ; open file on click + (setq bibfile (org-ref-strip-string + (buffer-substring key-beginning key-end))) + ;; open file on click + (find-file bibfile))) - ;; formatting code + ;; formatting code (lambda (keyword desc format) (cond ((eq format 'org) (org-ref-get-org-bibliography)) @@ -657,10 +682,14 @@ Format according to the type in `org-ref-bibliography-entry-format'." ((eq format 'html) (org-ref-get-html-bibliography)) ((eq format 'latex) ;; write out the latex bibliography command - (format "\\bibliography{%s}" (replace-regexp-in-string "\\.bib" "" (mapconcat 'identity - (mapcar 'expand-file-name - (split-string keyword ",")) - ","))))))) + (format "\\bibliography{%s}" + (replace-regexp-in-string + "\\.bib" "" + (mapconcat + 'identity + (mapcar 'expand-file-name + (split-string keyword ",")) + ","))))))) (org-add-link-type "nobibliography" ;; this code is run on clicking. The bibliography @@ -714,20 +743,11 @@ Format according to the type in `org-ref-bibliography-entry-format'." ((eq format 'html) (org-ref-get-html-bibliography)) ((eq format 'latex) ;; write out the latex bibliography command - -; (format "{\\setbox0\\vbox{\\bibliography{%s}}}" -; (replace-regexp-in-string "\\.bib" "" (mapconcat 'identity -; (mapcar 'expand-file-name -; (split-string keyword ",")) -; ","))) - (format "\\nobibliography{%s}" (replace-regexp-in-string "\\.bib" "" (mapconcat 'identity (mapcar 'expand-file-name (split-string keyword ",")) - ","))) - - )))) + ","))))))) (org-add-link-type "printbibliography" (lambda (arg) (message "Nothing implemented for clicking here.")) @@ -737,8 +757,7 @@ Format according to the type in `org-ref-bibliography-entry-format'." ((eq format 'html) (org-ref-get-html-bibliography)) ((eq format 'latex) ;; write out the biblatex bibliography command - "\\printbibliography")) -)) + "\\printbibliography")))) (org-add-link-type "bibliographystyle" (lambda (arg) (message "Nothing implemented for clicking here.")) @@ -746,7 +765,10 @@ Format according to the type in `org-ref-bibliography-entry-format'." (cond ((eq format 'latex) ;; write out the latex bibliography command - (format "\\bibliographystyle{%s}" keyword))))) + (format "\\bibliographystyle{%s}" keyword)) + ;; Other styles should not have an output for this + (t + "")))) (defun org-bibliographystyle-complete-link (&optional arg) @@ -992,10 +1014,8 @@ ARG does nothing." "on clicking goto the label. Navigate back with C-c &" (org-mark-ring-push) ;; next search from beginning of the buffer - ;; it is possible you would not find the label if narrowing is in effect (widen) - (unless (or ;; our label links @@ -1011,12 +1031,14 @@ ARG does nothing." ;; #+label: name org-definition (progn (goto-char (point-min)) - (re-search-forward (format "^#\\+label:\\s-*\\(%s\\)\\b" label) nil t)) + (re-search-forward + (format "^#\\+label:\\s-*\\(%s\\)\\b" label) nil t)) ;; org tblname (progn (goto-char (point-min)) - (re-search-forward (format "^#\\+tblname:\\s-*\\(%s\\)\\b" label) nil t)) + (re-search-forward + (format "^#\\+tblname:\\s-*\\(%s\\)\\b" label) nil t))) ;; we did not find anything, so go back to where we came (org-mark-ring-goto) @@ -1072,6 +1094,7 @@ ARG does nothing." (lambda (table) (org-element-property :name table)))) + (defun org-ref-get-labels () "Return a list of labels in the buffer that you can make a ref link to. This is used to complete ref links and in helm menus." @@ -1095,6 +1118,7 @@ This is used to complete ref links and in helm menus." ;; CUSTOM_IDs (org-ref-get-custom-ids)))))) + (defun org-ref-helm-insert-label-link () "Insert a label link. helm just shows you what labels already exist. If you are on a label link, replace it." @@ -1106,7 +1130,8 @@ If you are on a label link, replace it." ;; default action is to open to the label (action . (lambda (label) ;; unfortunately I do not have markers here - (org-open-link-from-string (format "ref:%s" label)))) + (org-open-link-from-string + (format "ref:%s" label)))) ;; if you select a label, replace current one (action . (lambda (label) (switch-to-buffer ,cb) @@ -1168,6 +1193,7 @@ If you are on a label link, replace it." (or label helm-pattern)))))))))))) + (defun org-ref-complete-link (&optional arg) "Completion function for ref links. Optional argument ARG Does nothing." @@ -1175,11 +1201,13 @@ Optional argument ARG Does nothing." (setq label (completing-read "label: " (org-ref-get-labels))) (format "ref:%s" label))) + (defun org-ref-insert-ref-link () "Completion function for a ref link." (interactive) (insert (org-ref-complete-link))) + (defun org-ref-helm-insert-ref-link () "Helm menu to insert ref links to labels in the document. If you are on link, replace with newly selected label. @@ -1278,20 +1306,14 @@ Use C-u C-u to insert a [[#custom-id]] link" ;; #+label: name org-definition (progn (goto-char (point-min)) - (re-search-forward (format "^#\\+label:\\s-*\\(%s\\)\\b" label) nil t)) + (re-search-forward + (format "^#\\+label:\\s-*\\(%s\\)\\b" label) nil t)) ;; org tblname (progn (goto-char (point-min)) - (re-search-forward (format "^#\\+tblname:\\s-*\\(%s\\)\\b" label) nil t)) - -;; Commented out because these ref links do not actually translate correctly in LaTeX. -;; you need [[#label]] links. - ;; CUSTOM_ID -; (progn -; (goto-char (point-min)) -; (re-search-forward (format ":CUSTOM_ID:\s-*\\(%s\\)" label) nil t)) - ) + (re-search-forward + (format "^#\\+tblname:\\s-*\\(%s\\)\\b" label) nil t))) ;; we did not find anything, so go back to where we came (org-mark-ring-goto) (error "%s not found" label)) @@ -1303,6 +1325,7 @@ Use C-u C-u to insert a [[#custom-id]] link" ((eq format 'latex) (format "\\pageref{%s}" keyword))))) + (defun org-pageref-complete-link (&optional arg) "Completion function for ref links. Optional argument ARG Does nothing." @@ -1310,11 +1333,13 @@ Optional argument ARG Does nothing." (setq label (completing-read "label: " (org-ref-get-labels))) (format "ref:%s" label))) + (defun org-pageref-insert-ref-link () "Insert a pageref link with completion." (interactive) (insert (org-pageref-complete-link))) + ;; *** nameref link (org-add-link-type "nameref" @@ -1411,7 +1436,9 @@ keyword we clicked on. We also strip the text properties." (setq key-beginning (+ (match-beginning 0) 1)) ; we found a match (setq key-beginning link-string-beginning))) ; no match found ;; save the key we clicked on. - (setq bibtex-key (org-ref-strip-string (buffer-substring key-beginning key-end))) + (setq bibtex-key + (org-ref-strip-string + (buffer-substring key-beginning key-end))) (set-text-properties 0 (length bibtex-key) nil bibtex-key) bibtex-key) ;; link with description. assume only one key @@ -2083,7 +2110,6 @@ This assumes you are in an article." (defun org-ref-bib-html-citation () "From a bibtex entry, create and return a simple citation with html links." - (bibtex-beginning-of-entry) (let* ((cb (current-buffer)) (bibtex-expand-strings t) @@ -2097,14 +2123,13 @@ This assumes you are in an article." (volume (reftex-get-bib-field "volume" entry)) (pages (reftex-get-bib-field "pages" entry)) (doi (reftex-get-bib-field "doi" entry)) - (url (reftex-get-bib-field "url" entry)) - ) + (url (reftex-get-bib-field "url" entry))) ;;authors, "title", Journal, vol(iss):pages (year). (concat (format "%s, \"%s\", %s, %s:%s (%s)." author title journal volume pages year) (when url (format " link" url)) - (when doi (format " doi" doi))) - )) + (when doi + (format " doi" doi))))) ;; ** Open pdf in bibtex entry (defun org-ref-open-bibtex-pdf () @@ -2389,7 +2414,7 @@ Makes a new buffer with clickable links." (kill-buffer "*Missing citations*")) (message "No bad cite links found")))) -;; ** helm interface to bad citations, labels, refs in orgfile +;; ** helm interface to bad citations, labels, refs and files in orgfile (defun org-ref-bad-cite-candidates () "Return a list of conses (key . marker) where key does not exist in the known bibliography files, and marker points to the key." (let* ((cp (point)) ; save to return to later @@ -2476,6 +2501,29 @@ Makes a new buffer with clickable links." (goto-char cp))))) multiple-labels)) +(defun org-ref-bad-file-link-candidates () + "Return list of conses (link . marker) wehre the file in the link does not exist." + (let* ((bad-files '())) + (org-element-map (org-element-parse-buffer) 'link + (lambda (link) + (let ((type (org-element-property :type link))) + (when (or (string= "file" type) + (string= "attachfile" type)) + (unless (file-exists-p (org-element-property :path link)) + (add-to-list 'bad-files + (cons (org-element-property :path link) + (save-excursion + (goto-char + (org-element-property :begin link)) + (point-marker))))))))) + ;; Let us also check \attachfile{fname} + (save-excursion + (goto-char (point-min)) + (while (re-search-forward "\\attachfile{\\(.*\\)}" nil t) + (unless (file-exists-p (match-string 1)) + (add-to-list 'bad-files (cons (match-string 1) (point-marker)))))) + bad-files)) + ;;;###autoload (defun org-ref () "Opens a helm interface to actions for org-ref. @@ -2484,7 +2532,8 @@ Shows bad citations, ref links and labels" (let ((cb (current-buffer)) (bad-citations (org-ref-bad-cite-candidates)) (bad-refs (org-ref-bad-ref-candidates)) - (bad-labels (org-ref-bad-label-candidates))) + (bad-labels (org-ref-bad-label-candidates)) + (bad-files (org-ref-bad-file-link-candidates))) (helm :sources `(((name . "Bad citations") (candidates . ,bad-citations) @@ -2504,6 +2553,12 @@ Shows bad citations, ref links and labels" (switch-to-buffer (marker-buffer marker)) (goto-char marker)))) ;; + ((name . "Bad file links") + (candidates . ,bad-files) + (lambda (marker) + (switch-to-buffer (marker-buffer marker)) + (goto-char marker))) + ;; ((name . "Utilities") (candidates . (("Check buffer again" . org-ref) ("Insert citation" . helm-bibtex) @@ -2528,8 +2583,7 @@ Shows bad citations, ref links and labels" )) (action . (lambda (x) (switch-to-buffer ,cb) - (funcall x)))) - )))) + (funcall x)))))))) ;; ** Find non-ascii charaters (defun org-ref-find-non-ascii-characters () @@ -2698,7 +2752,7 @@ Shows bad citations, ref links and labels" (setq keys (org-ref-split-and-strip-string link-string)) (setq years (mapcar 'org-ref-get-citation-year keys)) (setq data (mapcar* (lambda (a b) `(,a . ,b)) years keys)) - (setq data (cl-sort data (lambda (x y) (< (string-to-int (car x)) (string-to-int (car y)))))) + (setq data (cl-sort data (lambda (x y) (< (string-to-number (car x)) (string-to-number (car y)))))) ;; now get the keys separated by commas (setq keys (mapconcat (lambda (x) (cdr x)) data ",")) ;; and replace the link with the sorted keys @@ -2810,87 +2864,88 @@ Shows bad citations, ref links and labels" (defun org-ref-link-message () "Print a minibuffer message about the link that point is on." (interactive) - (when (eq major-mode 'org-mode) - (let* ((object (org-element-context)) - (type (org-element-property :type object))) - (save-excursion - (cond - ;; cite links - ((-contains? org-ref-cite-types type) - (message (org-ref-get-citation-string-at-point))) - - ;; message some context about the label we are referring to - ((string= type "ref") - (message "%scount: %s" - (org-ref-get-label-context - (org-element-property :path object)) - (org-ref-count-labels - (org-element-property :path object)))) - - ((string= type "eqref") - (message "%scount: %s" - (org-ref-get-label-context - (org-element-property :path object)) - (org-ref-count-labels - (org-element-property :path object)))) - - ;; message the count - ((string= type "label") - (let ((count (org-ref-count-labels - (org-element-property :path object)))) - ;; get plurality on occurrence correct - (message (concat - (number-to-string count) - " occurence" - (when (or (= count 0) - (> count 1)) - "s"))))) - - ((string= type "custom-id") - (save-excursion - (org-open-link-from-string - (format "[[#%s]]" (org-element-property :path object))) - (message "%s" (org-get-heading)))) - - ;; check if the bibliography files exist. - ((string= type "bibliography") - (let* ((bibfile) - ;; object is the link you clicked on - (object (org-element-context)) - (link-string (org-element-property :path object)) - (link-string-beginning) - (link-string-end)) - (save-excursion - (goto-char (org-element-property :begin object)) - (search-forward link-string nil nil 1) - (setq link-string-beginning (match-beginning 0)) - (setq link-string-end (match-end 0))) - - ;; make sure we are in link and not before the : - (when (> link-string-beginning (point)) - (goto-char link-string-beginning)) - - ;; now if we have comma separated bibliographies - ;; we find the one clicked on. we want to - ;; search forward to next comma from point + (save-restriction + (widen) + (when (eq major-mode 'org-mode) + (let* ((object (org-element-context)) + (type (org-element-property :type object))) + (save-excursion + (cond + ;; cite links + ((-contains? org-ref-cite-types type) + (message (org-ref-get-citation-string-at-point))) + + ;; message some context about the label we are referring to + ((string= type "ref") + (message "%scount: %s" + (org-ref-get-label-context + (org-element-property :path object)) + (org-ref-count-labels + (org-element-property :path object)))) + + ((string= type "eqref") + (message "%scount: %s" + (org-ref-get-label-context + (org-element-property :path object)) + (org-ref-count-labels + (org-element-property :path object)))) + + ;; message the count + ((string= type "label") + (let ((count (org-ref-count-labels + (org-element-property :path object)))) + ;; get plurality on occurrence correct + (message (concat + (number-to-string count) + " occurence" + (when (or (= count 0) + (> count 1)) + "s"))))) + + ((string= type "custom-id") (save-excursion - (if (search-forward "," link-string-end 1 1) - (setq key-end (- (match-end 0) 1)) ; we found a match - (setq key-end (point)))) ; no comma found so take the point + (org-open-link-from-string + (format "[[#%s]]" (org-element-property :path object))) + (message "%s" (org-get-heading)))) + + ;; check if the bibliography files exist. + ((string= type "bibliography") + (let* ((bibfile) + ;; object is the link you clicked on + (object (org-element-context)) + (link-string (org-element-property :path object)) + (link-string-beginning) + (link-string-end)) + (save-excursion + (goto-char (org-element-property :begin object)) + (search-forward link-string nil nil 1) + (setq link-string-beginning (match-beginning 0)) + (setq link-string-end (match-end 0))) + + ;; make sure we are in link and not before the : + (when (> link-string-beginning (point)) + (goto-char link-string-beginning)) + + ;; now if we have comma separated bibliographies + ;; we find the one clicked on. we want to + ;; search forward to next comma from point + (save-excursion + (if (search-forward "," link-string-end 1 1) + (setq key-end (- (match-end 0) 1)) ; we found a match + (setq key-end (point)))) ; no comma found so take the point - ;; and backward to previous comma from point - (save-excursion - (if (search-backward "," link-string-beginning 1 1) - (setq key-beginning (+ (match-beginning 0) 1)) ; we found a match - (setq key-beginning (point)))) ; no match found - ;; save the key we clicked on. - (setq bibfile - (org-ref-strip-string - (buffer-substring key-beginning key-end))) - (if (file-exists-p bibfile) - (message "%s exists." bibfile) - (message "!!! %s NOT FOUND !!!" bibfile)))) - ))))) + ;; and backward to previous comma from point + (save-excursion + (if (search-backward "," link-string-beginning 1 1) + (setq key-beginning (+ (match-beginning 0) 1)) ; we found a match + (setq key-beginning (point)))) ; no match found + ;; save the key we clicked on. + (setq bibfile + (org-ref-strip-string + (buffer-substring key-beginning key-end))) + (if (file-exists-p bibfile) + (message "%s exists." bibfile) + (message "!!! %s NOT FOUND !!!" bibfile)))))))))) ;; ** aliases (defalias 'oro 'org-ref-open-citation-at-point) @@ -3025,7 +3080,7 @@ first key that partially matches. This version avoids that." User is prompted for tags. This function is called from `helm-bibtex'. Argument CANDIDATES helm candidates." (message "") - (let ((keywords (read-input "Keywords (comma separated): "))) + (let ((keywords (read-string "Keywords (comma separated): "))) (loop for key in (helm-marked-candidates) do (save-window-excursion @@ -3063,11 +3118,13 @@ In the helm-bibtex buffer, C-u will give you a helm menu to select a new link ty C-u C-u will change the key at point to the selected keys." (let* ((object (org-element-context)) (last-char (save-excursion - (goto-char (org-element-property :end object)) - (backward-char) - (if (looking-at " ") - " " - "")))) + (when (org-element-property :end object) + (goto-char (org-element-property :end object)) + (unless (bobp) + (backward-char)) + (if (looking-at " ") + " " + ""))))) (cond ;; case where we are in a link ((and (equal (org-element-type object) 'link) @@ -3101,7 +3158,7 @@ C-u C-u will change the key at point to the selected keys." ;; We are next to a link, and we want to append ;; next to a link means one character back is on a link. ((save-excursion - (backward-char) + (unless (bobp) (backward-char)) (and (equal (org-element-type (org-element-context)) 'link) (-contains? org-ref-cite-types