-Depending on how you enter citations, you may have citations with no corresponding bibtex entry. This function finds them and gives you a clickable table to navigate to them.
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(require 'cl)
-
-(defun index (substring list)
- "return the index of string in a list of strings"
- (let ((i 0)
- (found nil))
- (dolist (arg list i)
- (if (string-match (concat "^" substring "$") arg)
- (progn
- (setq found t)
- (return i)))
- (setq i (+ i 1)))
- ;; return counter if found, otherwise return nil
- (if found i nil)))
-
-
-(defun org-ref-find-bad-citations ()
- "Create a list of citation keys in an org-file that do not have a bibtex entry in the known bibtex files.
-
-Makes a new buffer with clickable links."
- (interactive)
- ;; generate the list of bibtex-keys and cited keys
- (let* ((bibtex-files (org-ref-find-bibliography))
- (bibtex-file-path (mapconcat (lambda (x) (file-name-directory (file-truename x))) bibtex-files ":"))
- (bibtex-keys (mapcar (lambda (x) (car x)) (bibtex-global-key-alist)))
- (bad-citations '()))
-
- (org-element-map (org-element-parse-buffer) 'link
- (lambda (link)
- (let ((plist (nth 1 link)))
- (when (equal (plist-get plist ':type) "cite")
- (dolist (key (org-ref-split-and-strip-string (plist-get plist ':path)) )
- (when (not (index key bibtex-keys))
- (setq bad-citations (append bad-citations
- `(,(format "%s [[elisp:(progn (switch-to-buffer-other-frame \"%s\")(goto-char %s))][not found here]]\n"
- key (buffer-name)(plist-get plist ':begin)))))
- ))))))
-
- (if bad-citations
- (progn
- (switch-to-buffer-other-window "*Missing citations*")
- (org-mode)
- (erase-buffer)
- (insert "* List of bad cite links\n")
- (insert (mapconcat 'identity bad-citations ""))
- ;(setq buffer-read-only t)
- (use-local-map (copy-keymap org-mode-map))
- (local-set-key "q" #'(lambda () (interactive) (kill-buffer))))
-
- (when (get-buffer "*Missing citations*")
- (kill-buffer "*Missing citations*"))
- (message "No bad cite links found"))))
-#+END_SRC
-
-** helm interface to org-ref
-In [[id:8515E800-EDA0-4B2A-85FD-55B6FF849203][Find bad cite links]] we wrote a function that finds bad links and creates a buffer of links to them.
-
-Here we develop a similar idea, but instead of an org-buffer with links, we create helm sources for bad cite links, bad ref links, and multiple labels.
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-ref-bad-cite-candidates ()
- "Returns 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
- (bibtex-files (org-ref-find-bibliography))
- (bibtex-file-path (mapconcat
- (lambda (x)
- (file-name-directory (file-truename x)))
- bibtex-files ":"))
- (bibtex-keys (mapcar (lambda (x) (car x))
- (bibtex-global-key-alist)))
- (bad-citations '()))
-
- (org-element-map (org-element-parse-buffer) 'link
- (lambda (link)
- (let ((plist (nth 1 link)))
- (when (-contains? org-ref-cite-types (plist-get plist ':type))
- (dolist (key (org-ref-split-and-strip-string (plist-get plist ':path)) )
- (when (not (index key bibtex-keys))
- (goto-char (plist-get plist ':begin))
- (re-search-forward key)
- (push (cons key (point-marker)) bad-citations)))
- ))))
- (goto-char cp)
- bad-citations))
-
-;; It seems I forgot I already defined this earlier!
-;; (defun org-ref-get-labels ()
-;; "Returns a list of known labels in the org document. These include label links, latex labels, label tags, and table names. The list contains all labels, not just unique ones.
-;; "
-;; (let ((cp (point))
-;; (labels '()))
-;; (goto-char (point-min))
-;; (while (re-search-forward "[^#+]label:\\(.*\\)\\s-" nil t)
-;; (push (match-string 1) labels))
-
-;; (goto-char (point-min))
-;; (while (re-search-forward "\\label{\\(.*\\)}\\s-?" nil t)
-;; (push (match-string 1) labels))
-
-;; (goto-char (point-min))
-;; (while (re-search-forward "^#\\+label:\\s-*\\(.*\\)" nil t)
-;; (push (match-string 1) labels))
-
-;; (goto-char (point-min))
-;; (while (re-search-forward "^#\\+tblname:\\s-*\\(.*\\)" nil t)
-;; (push (match-string 1) labels))
-;; ;; check for CUSTOM_ID
-;; (org-map-entries
-;; (lambda ()
-;; (when (org-entry-get (point) "CUSTOM_ID")
-;; (push (org-entry-get (point) "CUSTOM_ID") labels))))
-;; ;; return to original place
-;; (goto-char cp)
-;; labels))
-
-
-(defun org-ref-bad-ref-candidates ()
- "Returns a list of conses (ref . marker) where ref is a ref link that does not point to anything (i.e. a label)."
- ;; first get a list of legitimate labels
- (let ((cp (point))
- (labels (org-ref-get-labels))
- (bad-refs '()))
- ;; now loop over ref links
- (goto-char (point-min))
- (org-element-map (org-element-parse-buffer) 'link
- (lambda (link)
- (let ((plist (nth 1 link)))
- (when (or (equal (plist-get plist ':type) "ref")
- (equal (plist-get plist ':type) "eqref")
- (equal (plist-get plist ':type) "pageref")
- (equal (plist-get plist ':type) "nameref"))
- (unless (-contains? labels (plist-get plist :path))
- (goto-char (plist-get plist :begin))
- (add-to-list
- 'bad-refs
- (cons (plist-get plist :path)
- (point-marker))))))))
- (goto-char cp)
- bad-refs))
-
-
-(defun org-ref-bad-label-candidates ()
- "Return a list of labels where label is multiply defined."
- (let ((labels (org-ref-get-labels))
- (multiple-labels '()))
- (when (not (= (length labels)
- (length (-uniq labels))))
- (dolist (label labels)
- (when (> (-count (lambda (a)
- (equal a label))
- labels) 1)
- ;; this is a multiply defined label.
- (let ((cp (point)))
- (goto-char (point-min))
- (while (re-search-forward
- (format "[^#+]label:%s\\s-" label) nil t)
- (push (cons label (point-marker)) multiple-labels))
-
- (goto-char (point-min))
- (while (re-search-forward
- (format "\\label{%s}\\s-?" label) nil t)
- (push (cons label (point-marker)) multiple-labels))
-
- (goto-char (point-min))
- (while (re-search-forward
- (format "^#\\+label:\\s-*%s" label) nil t)
- (push (cons label (point-marker)) multiple-labels))
-
- (goto-char (point-min))
- (while (re-search-forward
- (format "^#\\+tblname:\\s-*%s" label) nil t)
- (push (cons label (point-marker)) multiple-labels))
- (goto-char cp)))))
- multiple-labels))
-#+END_SRC
-
-#+RESULTS:
-: org-ref-bad-label-candidates
-
-Now, we have a functions for candidates, we can make helm sources for each one, and then run a helm command to view them.
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-ref ()
- "Opens a helm interface to actions for org-ref.
-Shows bad citations, ref links and labels"
- (interactive)
- (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)))
-
- (helm :sources `(((name . "Bad citations")
- (candidates . ,bad-citations)
- (action . (lambda (marker)
- (switch-to-buffer (marker-buffer marker))
- (goto-char marker))))
- ;;
- ((name . "Bad Labels")
- (candidates . ,bad-labels)
- (action . (lambda (marker)
- (switch-to-buffer (marker-buffer marker))
- (goto-char marker))))
- ;;
- ((name . "Bad ref links")
- (candidates . ,bad-refs)
- (action . (lambda (marker)
- (switch-to-buffer (marker-buffer marker))
- (goto-char marker))))
- ;;
- ((name . "Utilities")
- (candidates . (("Check buffer again" . org-ref)
- ("Insert citation" . helm-bibtex)
- ("Insert label link" . org-ref-helm-insert-label-link)
- ("Insert ref link" . org-ref-helm-insert-ref-link)
- ("List of figures" . org-ref-list-of-figures)
- ("List of tables" . org-ref-list-of-tables)
- ("Table of contents" . nil)
- ))
- (action . (lambda (x)
- (switch-to-buffer ,cb)
- (funcall x))))
- ;;
- ((name . "Export functions")
- (candidates . (("Extract cited entries" . org-ref-extract-bibtex-entries)
- ("Export to html and open" . (lambda () (org-open-file (org-html-export-to-html))))
- ("Export to pdf and open" . (lambda ()
- (org-open-file (org-latex-export-to-pdf))))
- ("Export to manuscript pdf and open" . ox-manuscript-export-and-build-and-open)
- ("Export submission manuscript pdf and open" . ox-manuscript-build-submission-manuscript-and-open)
-
- ))
- (action . (lambda (x)
- (switch-to-buffer ,cb)
- (funcall x))))
- ))))
-#+END_SRC