Okay... I was pretty keen to get his set up so spent a while fiddling.
Zotero
As Tyler says I think Zotero with helm-bibtex is the way to go, and this still seems pretty lightweight. There's a little bit of magic need to get Zotero to create a bibtex file and keep it up-to-date, for this you can use zotero better bibtex.
- Install Zotero
- Download better bibtex for zotero. Firefox will try to open the xpi extension itself - so right click and the download link and click "save as".
- Go to
Tools > Addons and add add the better bibtex extension that you downloaded - Restart zotero
- Go to your library. Right click on a collection, click export, setting the exporter to better bibtex and click "keep uptodate". Export to ~/references.bib
- Install
helm-bibtex - Set the bibliography path
(setq bibtex-completion-bibliography '("~/library.bib") helm-bibtex can then open references from your bibliography. If you press tab in helm you can also insert citations - To insert a citation you can use
(defun my-helm-bibtex-cite () (interactive) (let ((helm-source-bibtex (copy-alist helm-source-bibtex))) (helm-add-action-to-source "Reference 4" 'helm-bibtex-insert-reference helm-source-bibtex 0) (helm-bibtex)))
Including URLs
This works well enough... unless you want urls. The code to creating cites is all rather hard coded and "monkey patch'y". A similar approach could be used for custom interfaces
Zotero does not include urls by default - because apparently bibtex clients don't support urls. So you need to enable an option in better bibtex in zotero
(defun my-helm-bibtex-cite-with-url () (interactive) (let ((helm-source-bibtex (copy-alist helm-source-bibtex))) (helm-add-action-to-source "Reference" 'my-helm-bibtex-insert-reference-and-url helm-source-bibtex 0) (helm-bibtex))) ;; hack won't work for multiple entries (helm-bibtex-helmify-action my-bibtex-completion-insert-reference-and-url my-helm-bibtex-insert-reference-and-url) (defun my-bibtex-completion-insert-reference-and-url (keys) "Insert references for entries in KEYS." (let* ((refs (--map (s-word-wrap fill-column (concat "\n- " (bibtex-completion-apa-format-reference it))) keys))) (insert (s-format "${url} ${doi}" 'bibtex-completion-apa-get-value (bibtex-completion-get-entry (car keys))) "\n" (s-join "\n" refs) "\n")))
User experience
Copying and pasting a URL is wonderfully simple. Things aren't so simple with zotero... though it's not too bad.
- You can add zotero connect to your toolbar in firefox (no shortcut unfortunately) by right-clicking.
- You still need to look up added entry once you've added it. But the bibtex file seems to be updated pretty instantly and you often will only need to type a few characters.
Not using zotero
So before this I also did it in a command line way... given the time now I think it was quicker to do than use zotero. But the zotero solution has a few benefits (zotero is kept up-to-date, files are downloaded, zotero has quite a nice interfaces for some things, zotero allows annotation, etc etc).
This script (called cite-fetch) will fetch citations from arxiv (and only arxiv). There is also a way of getting citations in bibtex format from crossref - but arxiv citations appeared to be missing.
#!/usr/bin/python3 import argparse import io import subprocess from subprocess import PIPE import tempfile from pathlib import Path from urllib.parse import urlparse, urlunparse import requests HERE = Path(__file__).parent EXPORT = HERE / "simple.bibtexconv" parser = argparse.ArgumentParser() parser.add_argument("url") parser.add_argument( "-f", "--format", type=str, help="What format to output in. (Defaults to bibtex)", choices=("simple", "bibtex"), default="bibtex", ) args = parser.parse_args() parts = urlparse(args.url) if parts.path.startswith("/pdf/"): new_path = Path("/bibtex") / Path(parts.path).relative_to(Path("/pdf")) elif parts.path.startswith("/abs/"): new_path = Path("/bibtex") / Path(parts.path).relative_to(Path("/abs")) else: raise ValueError(args.url) new_parts = parts._replace(path=str(new_path)) new_path = urlunparse(new_parts) response = requests.get(new_path) content = response.text if args.format == "bibtex": print(content) elif args.format == "simple": with tempfile.TemporaryDirectory() as temp_dir: temp_dir = Path(temp_dir) bib_file = temp_dir / "bib.bib" with open(bib_file, "w") as stream: stream.write(response.text) with open(EXPORT) as stream: template = stream.read() p = subprocess.Popen( ["bibtexconv", bib_file], stdin=PIPE, stdout=PIPE, stderr=PIPE ) output, _ = p.communicate(template.encode("utf-8")) print(args.url) print(output.decode("utf8"))
You can then use this after copying a url from the clipboard to insert a citation.
(defun my-insert-cite (url) (interactive (list (shell-command-to-string "pbpaste || xclip -o"))) (insert (shell-command-to-string (format "cite-fetch -f simple %s" url))))
Alternatives to helm-bibtex
It looks like there are a few alternatives to helm-bibtex that could similarly read a citation generate by better bibtex in zotero.
org-citar in one choice - which can also read CSL citation libraries - which seems like it might be a more common standard.
org-refbut I see that @Tyler has already recommended it. I'm not sure what you mean by "getting a citation": just unformatted text, containing the metadata you mentioned? IME, "citations" are entries in a database, so they need to conform to the database schema.ivy-bibtex, which is part ofhelm-bibtex, is likely the simplest option.