Skip to content

Commit

Permalink
Added support for PDFs specified in a BibTeX field.
Browse files Browse the repository at this point in the history
  • Loading branch information
tmalsburg committed Nov 15, 2015
1 parent 6553324 commit 545a5b5
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 21 deletions.
9 changes: 9 additions & 0 deletions README.org
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
[[http://melpa.org/#/helm-bibtex][http://melpa.org/packages/helm-bibtex-badge.svg]]

* News
- [2015-11-10 Tue] :: Added support for PDFs specified in a BibTeX field. See customization variable ~helm-bibtex-pdf-field~.
- [2015-11-09 Mon] :: Improved insertion of LaTeX cite commands.
- [2015-05-14 Thu] :: Added support for multiple PDF directories.
- [2015-02-23 Mon] :: Added a workaround for a bug in Emacs 24.3.1. If you
Expand Down Expand Up @@ -73,6 +74,14 @@ Specify where PDFs can be found:

Helm-bibtex assumes that the name of a PDF consists of the BibTeX key followed by the suffix ~.pdf~. Example, if a BibTeX entry has the key ~Darwin1859~, helm-bibtex searches for ~Darvin1859.pdf~ when trying to open the corresponding PDF.

If the BibTeX entries have a field that specifies the full path to the PDFs, that field can also be used. For example, JabRef stores the location of the PDFs in a field called ~File~:

#+BEGIN_SRC emacs-lisp
(setq helm-bibtex-pdf-field "File")
#+END_SRC

If ~helm-bibtex-pdf-field~ is non-nil, helm-bibtex will first try to retrieve the file specified in this field. If the field is not set for an entry or if the specified file does not exists, helm-bibtex falls back to the method described above (searching for key + ~.pdf~ in the directories listed in ~helm-bibtex-library-path~).

** Notes

Notes for a publication are currently stored in separate files, one file per publication. The names of these files consist of the BibTeX key plus a user-defined suffix (~.org~ by default).
Expand Down
72 changes: 51 additions & 21 deletions helm-bibtex.el
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
;; A BibTeX bibliography manager based on Helm.
;;
;; News:
;; - 11/10/2015: Added support for PDFs specified in a BibTeX
;; field. See customization variable
;; `helm-bibtex-pdf-field'.
;; - 11/09/2015: Improved insertion of LaTeX cite commands.
;; - 05/14/2015: Added support for multiple PDF directories.
;; - 02/23/2015: Added a workaround for a bug in Emacs 24.3.1. If you
Expand Down Expand Up @@ -267,6 +270,15 @@ it is used as the default if the user doesn't enter anything."
:group 'helm-bibtex
:type 'boolean)

(defcustom helm-bibtex-pdf-field nil
"The name of the BibTeX field in which the path to PDF files is
stored or nil if no such field should be used. If an entry has
no value for this field, or if the specified file does not exist,
or if this variable is nil, helm-bibtex will look up the PDF in
the directories listed in `helm-bibtex-library-path'."
:group 'helm-bibtex
:type 'string)

(easy-menu-add-item nil '("Tools" "Helm" "Tools") ["BibTeX" helm-bibtex t])

(defvar helm-bibtex-bibliography-hash nil
Expand Down Expand Up @@ -360,7 +372,7 @@ appended to the requested entry."
:test (lambda (x y) (string= (s-downcase x) (s-downcase y)))
:key 'car :from-end t)))

(defun helm-bibtex-get-entry1 (entry-key)
(defun helm-bibtex-get-entry1 (entry-key &optional do-not-find-pdf)
(with-temp-buffer
(mapc #'insert-file-contents
(-flatten (list helm-bibtex-bibliography)))
Expand All @@ -369,7 +381,7 @@ appended to the requested entry."
"\\)[[:space:]]*[\(\{][[:space:]]*"
(regexp-quote entry-key) "[[:space:]]*,"))
(let ((entry-type (match-string 1)))
(reverse (helm-bibtex-prepare-entry (parsebib-read-entry entry-type))))))
(reverse (helm-bibtex-prepare-entry (parsebib-read-entry entry-type) nil do-not-find-pdf)))))

(defun helm-bibtex-prepare-entries (entries)
"Do some preprocessing of the entries."
Expand All @@ -381,36 +393,54 @@ appended to the requested entry."
collect (helm-bibtex-prepare-entry entry
(cons (if (assoc-string "author" entry 'case-fold) "author" "editor") fields))))

(defun helm-bibtex-find-pdf (key)
"Searches in all directories in `helm-bibtex-library-path' for
a PDF whose name is KEY + \".pdf\". Returns the first matching PDF."
(-first 'f-exists?
(--map (f-join it (s-concat key ".pdf"))
(-flatten (list helm-bibtex-library-path)))))

(defun helm-bibtex-prepare-entry (entry &optional fields)
(defun helm-bibtex-find-pdf (key-or-entry)
"Returns the path of the PDF associated with the specified
entry. This is either the path specified in the field
`helm-bibtex-pdf-field' or if that path doesn't exists the first
PDF in any of the directories in `helm-bibtex-library-path' whose
name is key + \".pdf\"."
(let ((pdf-path (and helm-bibtex-pdf-field
(let* ((entry (if (stringp key-or-entry)
(helm-bibtex-get-entry1 key-or-entry t)
key-or-entry))
(pdf-path (helm-bibtex-get-value helm-bibtex-pdf-field entry)))
(and pdf-path (f-exists? pdf-path) pdf-path)))))
(or pdf-path
(let ((key (if (stringp key-or-entry)
key-or-entry
(helm-bibtex-get-value "=key=" key-or-entry))))
(-first 'f-exists?
(--map (f-join it (s-concat key ".pdf"))
(-flatten (list helm-bibtex-library-path))))))))

(defun helm-bibtex-prepare-entry (entry &optional fields do-not-find-pdf)
"Prepare ENTRY for display.
ENTRY is an alist representing an entry as returned by
parsebib-read-entry. All the fields not in FIELDS are removed
from ENTRY, with the exception of the \"=type=\" and \"=key=\"
fields. If FIELDS is empty, all fields are kept. Also add a
=has-pdf= and/or =has-notes= field, if they exist for ENTRY."
=has-pdf= and/or =has-notes= field, if they exist for ENTRY. If
DO-NOT-FIND-PDF is non-nil, this function does not attempt to
find a PDF file."
(when entry ; entry may be nil, in which case just return nil
(when fields
(setq fields (append fields (list "=type=" "=key="))))
(let* ((entry (if fields
(let* ((fields (when fields (append fields (list "=type=" "=key=" "=has-pdf=" "=has-note="))))
; Check for PDF:
(entry (if (and (not do-not-find-pdf) (helm-bibtex-find-pdf entry))
(setq entry (cons (cons "=has-pdf=" helm-bibtex-pdf-symbol) entry))
entry))
; Check for notes:
(entry (if (and helm-bibtex-notes-path
(f-exists? (f-join helm-bibtex-notes-path
(s-concat entry-key helm-bibtex-notes-extension))))
(cons (cons "=has-note=" helm-bibtex-notes-symbol) entry)
entry))
; Remove unwanted fields:
(entry (if fields
(--filter (member-ignore-case (car it) fields) entry)
entry))
(entry-key (cdr (assoc "=key=" entry))))
;; Normalize case of entry type:
(setcdr (assoc "=type=" entry) (downcase (cdr (assoc "=type=" entry))))
;; Check for PDF and notes:
(if (helm-bibtex-find-pdf entry-key)
(setq entry (cons (cons "=has-pdf=" helm-bibtex-pdf-symbol) entry)))
(if (and helm-bibtex-notes-path
(f-exists? (f-join helm-bibtex-notes-path
(s-concat entry-key helm-bibtex-notes-extension))))
(setq entry (cons (cons "=has-note=" helm-bibtex-notes-symbol) entry)))
;; Remove duplicated fields:
(cl-remove-duplicates entry
:test (lambda (x y) (string= (s-downcase x) (s-downcase y)))
Expand Down

0 comments on commit 545a5b5

Please sign in to comment.