rm {} individually and add techreport.
[org-ref.git] / org-ref.el
index cc3ac5f..0b86ed0 100644 (file)
@@ -81,11 +81,9 @@ You should use full-paths for each file."
   '(("article" . "%a, %t, <i>%j</i>, <b>%v(%n)</b>, %p (%y). <a href=\"%U\">link</a>. <a href=\"http://dx.doi.org/%D\">doi</a>.")
 
     ("book" . "%a, %t, %u (%y).")
-
+    ("techreport" . "%a, %t, %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 +324,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 +421,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 +501,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 +541,20 @@ 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 "<li><a id=\"%s\">[%s] %s</a></li>" 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 " <a href=\"\">link</a>\\." "" output))
+    (setq output (replace-regexp-in-string " <a href=\"http://dx\\.doi\\.org/\">doi</a>\\." "" output))
+    (format "<li><a id=\"%s\">[%s] %s</a></li>"
+           key key output)))
 
 (defun org-ref-get-html-bibliography ()
   "Create an html bibliography when there are keys."
@@ -611,45 +625,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 +679,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 +740,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 +754,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 +762,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)
@@ -2088,7 +2107,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)
@@ -2102,14 +2120,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 " <a href=\"%s\">link</a>" url))
-           (when doi (format " <a href=\"http://dx.doi.org/%s\">doi</a>" doi)))
-    ))
+           (when doi
+             (format " <a href=\"http://dx.doi.org/%s\">doi</a>" doi)))))
 
 ;; ** Open pdf in bibtex entry
 (defun org-ref-open-bibtex-pdf ()
@@ -2394,7 +2411,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
@@ -2481,6 +2498,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.
@@ -2489,7 +2529,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)
@@ -2509,6 +2550,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)
@@ -2533,8 +2580,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 ()
@@ -2815,87 +2861,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)
@@ -3030,7 +3077,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
@@ -3068,11 +3115,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)
@@ -3106,7 +3155,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