Update all packages

This commit is contained in:
Mateus Pinto Rodrigues
2018-07-17 19:34:58 -03:00
parent 3c61003537
commit 25baa00351
259 changed files with 1404 additions and 4340 deletions

View File

@@ -0,0 +1,214 @@
<?xml version="1.0" encoding="utf-8"?>
<style xmlns="http://purl.org/net/xbiblio/csl" class="in-text" version="1.0" demote-non-dropping-particle="sort-only" page-range-format="expanded" default-locale="en-US">
<info>
<title>ACS Nano</title>
<title-short>ACS Nano</title-short>
<id>http://www.zotero.org/styles/acs-nano</id>
<link href="http://www.zotero.org/styles/acs-nano" rel="self"/>
<link href="http://www.zotero.org/styles/american-chemical-society-with-titles" rel="template"/>
<link href="http://pubs.acs.org/paragonplus/submission/ancac3/ancac3_authguide.pdf" rel="documentation"/>
<category citation-format="numeric"/>
<category field="chemistry"/>
<issn>1936-0851</issn>
<eissn>1936-086X</eissn>
<summary>ACS style with et al in italics</summary>
<updated>2014-09-21T00:39:49+00:00</updated>
<rights license="http://creativecommons.org/licenses/by-sa/3.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights>
</info>
<macro name="editor">
<names variable="editor">
<name sort-separator=", " initialize-with=". " name-as-sort-order="all" delimiter="; " delimiter-precedes-last="always"/>
<et-al font-style="italic"/>
<label form="short" prefix=", " text-case="capitalize-first"/>
</names>
</macro>
<macro name="author">
<names variable="author" suffix=".">
<name sort-separator=", " initialize-with=". " name-as-sort-order="all" delimiter="; " delimiter-precedes-last="always"/>
<et-al font-style="italic"/>
<label form="short" prefix=", " text-case="capitalize-first"/>
</names>
</macro>
<macro name="publisher">
<group delimiter=": ">
<text variable="publisher"/>
<text variable="publisher-place"/>
</group>
</macro>
<macro name="title">
<choose>
<if type="bill book graphic legal_case legislation motion_picture report song" match="any">
<text variable="title" text-case="title" font-style="italic"/>
</if>
<else>
<text variable="title" text-case="title"/>
</else>
</choose>
</macro>
<macro name="volume">
<group delimiter=" ">
<text term="volume" form="short" text-case="capitalize-first"/>
<text variable="volume"/>
</group>
</macro>
<macro name="series">
<text variable="collection-title"/>
</macro>
<macro name="pages">
<label variable="page" form="short" suffix=" "/>
<text variable="page"/>
</macro>
<macro name="book-container">
<group delimiter=" ">
<text macro="title" suffix="."/>
<text term="in" text-case="capitalize-first"/>
<text variable="container-title" font-style="italic"/>
</group>
</macro>
<macro name="issued">
<date variable="issued" delimiter=" ">
<date-part name="year"/>
</date>
</macro>
<macro name="full-issued">
<date variable="issued" delimiter=" ">
<date-part name="month" form="long" suffix=" "/>
<date-part name="day" suffix=", "/>
<date-part name="year"/>
</date>
</macro>
<macro name="edition">
<choose>
<if is-numeric="edition">
<group delimiter=" ">
<number variable="edition" form="ordinal"/>
<text term="edition" form="short"/>
</group>
</if>
<else>
<text variable="edition" suffix="."/>
</else>
</choose>
</macro>
<citation collapse="citation-number">
<sort>
<key variable="citation-number"/>
</sort>
<layout delimiter="," vertical-align="sup">
<text variable="citation-number"/>
</layout>
</citation>
<bibliography second-field-align="flush" entry-spacing="0" et-al-min="11" et-al-use-first="10">
<layout suffix=".">
<text variable="citation-number" prefix="(" suffix=") "/>
<text macro="author" suffix=" "/>
<choose>
<if type="article-magazine">
<group delimiter=" ">
<text macro="title" suffix="."/>
<text variable="container-title" font-style="italic" suffix="."/>
<text macro="edition"/>
<text macro="publisher"/>
<text macro="full-issued" suffix=","/>
<text macro="pages"/>
</group>
</if>
<else-if type="thesis">
<group delimiter=", ">
<group delimiter=". ">
<text macro="title"/>
<text variable="genre"/>
</group>
<text macro="publisher"/>
<text macro="issued"/>
<text macro="volume"/>
<text macro="pages"/>
</group>
</else-if>
<else-if type="bill book graphic legal_case legislation motion_picture report song" match="any">
<group delimiter="; ">
<text macro="title"/>
<text macro="editor" prefix=" "/>
<text macro="series"/>
<text macro="edition"/>
<choose>
<if type="report">
<group delimiter=" ">
<text variable="genre"/>
<text variable="number"/>
</group>
</if>
</choose>
<group delimiter=", ">
<text macro="publisher"/>
<text macro="issued"/>
</group>
<group delimiter=", ">
<text macro="volume"/>
<text macro="pages"/>
</group>
</group>
</else-if>
<else-if type="patent">
<group delimiter=", ">
<group delimiter=". ">
<text macro="title"/>
<text variable="number"/>
</group>
<date variable="issued" form="text"/>
</group>
</else-if>
<else-if type="chapter paper-conference" match="any">
<group delimiter="; ">
<text macro="book-container"/>
<text macro="editor"/>
<text macro="series"/>
<group delimiter=", ">
<text macro="publisher"/>
<text macro="issued"/>
</group>
<group delimiter=", ">
<text macro="volume"/>
<text macro="pages"/>
</group>
</group>
</else-if>
<else-if type="webpage">
<group delimiter=" ">
<text variable="title"/>
<text variable="URL"/>
<date variable="accessed" prefix="(accessed " suffix=")" delimiter=" ">
<date-part name="month" form="short" strip-periods="true"/>
<date-part name="day" suffix=", "/>
<date-part name="year"/>
</date>
</group>
</else-if>
<else-if type="article-journal">
<group delimiter=" ">
<text macro="title" suffix="."/>
<text variable="container-title" font-style="italic" form="short"/>
<group delimiter=", ">
<text macro="issued" font-weight="bold"/>
<text variable="volume" font-style="italic"/>
<text variable="page"/>
</group>
</group>
</else-if>
<else>
<group delimiter=", ">
<group delimiter=". ">
<text macro="title"/>
<text variable="container-title" font-style="italic"/>
</group>
<group delimiter=", ">
<text macro="issued"/>
<text variable="volume" font-style="italic"/>
<text variable="page"/>
</group>
</group>
</else>
</choose>
</layout>
</bibliography>
</style>

View File

@@ -0,0 +1,92 @@
;;; author-year.el --- Citation Style Lisp - the other CSL
;;; Commentary:
;;
;;; Code:
(setq citation-style
'((label . orcp-citation-author-year-label)
(prefix . "(")
(suffix . ")")
(delimiter . "; ")
(citeauthor . ((vertical-align . baseline)
(label . orcp-citation-author-label)
(prefix . "")
(suffix . " ")))
(citeyear . ((vertical-align . baseline)
(label . orcp-citation-year-label)
(prefix . "")
(suffix . " ")
(chomp-leading-space . nil)
))))
(setq bibliography-style
'((sort . nil)
(hanging-indent . 3)
(justification . full)
(spacing . 1)
(label . orcp-citation-author-year-label)
(label-prefix . "(")
(label-suffix . ") ")
(header . ((text . "Bibliography")
(font-style . bold)))
;; Formatting of fields
;; Single author name
(author . ((initialize . t) ; use initials, not full names
;; use firstname and lastname symbols
(name-order . (firstname lastname))
(name-separator . " ")
(et-al . 4) ; after 4 authors use et-al
(delimiter . "; ")
(last-author-delimiter . " and ")
(suffix . "")
(field-separator . ", ")
;; ; function to convert (first von last jr) to a string.)
(name-format . ''format-author-name)
(field-separator ", ")))
(title . ((font-style . italics)
(suffix . "")
(field-separator . ", ")))
(booktitle . ((font-style . italics)
(suffix . "")
(field-separator . "in ")))
(journal . ((suffix . "")
(field-separator . ", ")))
;; here we use some logic to group volume(issue) or volume
(volume . ((suffix . (when (orcp-get-entry-field "number" entry)
(orcp-issue entry)))
(field-separator . ", ")))
(issue . ((font-style . bold)
(prefix . "(")
(suffix . ")")
(field-separator . ", ")))
(pages . ((prefix . "pp. ")
(suffix . "")
(field-separator . " ")
(collapse-range . nil)))
(year . ((prefix . "(")
(suffix . ")")
(field-separator . ".")))
(doi . ((prefix . " ")
(suffix . ".")
(field-separator . "")
(formatter . orcp-doi-formatter)))
;; Formatting of entries
(entries . ((article . (author title journal volume pages year doi))
(inproceedings . (author title booktitle year))
(book . (author title year))
(manual . (author title url doi))
(misc . (author title url doi))
(techreport . (author title institution year))
(mastersthesis . (author title school year))
(phdthesis . (author title school year))
(t . (author title year))))))
(provide 'author-year)
;;; author-year.el ends here

View File

@@ -0,0 +1,86 @@
;;; unsrt-footnote.el --- Citation Style Lisp - the other CSL
;;; Commentary:
;; Convert citations to org-mode footnotes
;;; Code:
(setq citation-style
'((label . orcp-footnote-label)
(prefix . "")
(suffix . "")
;; sort on increasing citation numbers.
(sort . (lambda (key1 key2)
(let ((i1 (-find-index
(lambda (entry)
(string= key1 (car entry)))
*orcp-unique-entries*))
(i2 (-find-index
(lambda (entry)
(string= key2 (car entry)))
*orcp-unique-entries*)))
(> i2 i1))))
(delimiter . ", ")
(vertical-align . baseline)))
(setq bibliography-style
'((sort . nil)
(hanging-indent . 3)
(justification . full)
(spacing . 1)
(label . orcp-footnote-label)
(label-prefix . "")
(label-suffix . " ")
(header . ((text . "Bibliography")
(font-style . bold)))
;; Formatting of fields
;; Single author name
(author . ((initialize . t) ; use initials, not full names
(name-order . (lastname firstname))
(name-separator . ", ")
(et-al . 4) ; after 4 authors use et-al
(delimiter . "; ")
(last-author-delimiter . " and ")
(suffix . "")
(field-separator . ", ")
;; ; function to convert (first von last jr) to a string.)
(name-format . ''format-author-name)
(field-separator ", ")))
(title . ((font-style . italics)
(suffix . "")
(field-separator . ", ")))
(journal . ((suffix . "")
(field-separator . ", ")))
;; here we use some logic to group volume(issue) or volume
(volume . ((suffix . (when (orcp-get-entry-field "number" entry)
(orcp-issue entry)))
(field-separator . ", ")))
(issue . ((font-style . bold)
(prefix . "(")
(suffix . ")")
(field-separator . ", ")))
(pages . ((prefix . "pp. ")
(suffix . "")
(field-separator . " ")
(collapse-range . nil)))
(year . ((prefix . "(")
(suffix . ")")
(field-separator . ".")))
(doi . ((prefix . " ")
(suffix . ".")
(field-separator . "")
(formatter . orcp-doi-formatter)))
;; Formatting of entries
(entries . ((article . (author title journal volume pages year doi))
(book . (author title year))
(misc . (author title url doi))
(techreport . (author title institution year))
(mastersthesis . (author title school year))
(phdthesis . (author title school year))
(t . (author title year))))))
(provide 'unsrt)
;;; unsrt.el ends here

View File

@@ -0,0 +1,107 @@
;;; unsrt-paren.el --- numbered citations in ()
;;; Commentary:
;; This does not work well for brackets because org-mode interprets them as
;; footnotes.
;;; Code:
(setq citation-style
'((label . orcp-citation-number-label)
(prefix . "(")
(suffix . ")")
(chomp-leading-space . nil)
(chomp-trailing-space . nil)
;; sort on increasing citation numbers.
(sort . (lambda (key1 key2)
(let ((i1 (-find-index
(lambda (entry)
(string= key1 (car entry)))
*orcp-unique-entries*))
(i2 (-find-index
(lambda (entry)
(string= key2 (car entry)))
*orcp-unique-entries*)))
(> i2 i1))))
(collapse . 'orcp-collapse-numeric-range)
(delimiter . ",")
(vertical-align . baseline)
(transpose-punctuation . nil) ;put citations on right of punctuation
(citenum . ((vertical-align . baseline)
(prefix . "")
(suffix . "")
(chomp-leading-space . nil)
(chomp-trailing-space . nil)))
(citeauthor . ((vertical-align . baseline)
(label . orcp-citation-author-label)
(prefix . "")
(suffix . "")
(chomp-leading-space . nil)
(chomp-trailing-space . nil)))
(citeyear . ((vertical-align . baseline)
(label . orcp-citation-year-label)
(prefix . "")
(suffix . "")
(chomp-leading-space . nil)
(chomp-trailing-space . nil)))))
(setq bibliography-style
'((sort . nil)
(hanging-indent . 3)
(justification . full)
(spacing . 1)
(label . orcp-citation-number-label)
(label-prefix . "")
(label-suffix . ") ")
(header . ((text . "Bibliography")
(font-style . bold)))
;; Formatting of fields
;; Single author name
(author . ((initialize . t) ; use initials, not full names
(name-order . (lastname firstname))
(name-separator . ", ")
(et-al . 4) ; after 4 authors use et-al
(delimiter . "; ")
(last-author-delimiter . " and ")
(suffix . "")
(field-separator . ", ")
;; ; function to convert (first von last jr) to a string.)
(name-format . ''format-author-name)
(field-separator ", ")))
(title . ((font-style . italics)
(suffix . "")
(field-separator . ", ")))
(journal . ((suffix . "")
(field-separator . ", ")))
;; here we use some logic to group volume(issue) or volume
(volume . ((suffix . (when (orcp-get-entry-field "number" entry)
(orcp-issue entry)))
(field-separator . ", ")))
(issue . ((font-style . bold)
(prefix . "(")
(suffix . ")")
(field-separator . ", ")))
(pages . ((prefix . "pp. ")
(suffix . "")
(field-separator . " ")
(collapse-range . nil)))
(year . ((prefix . "(")
(suffix . ")")
(field-separator . ".")))
(doi . ((prefix . " ")
(suffix . ".")
(field-separator . "")
(formatter . orcp-doi-formatter)))
;; Formatting of entries
(entries . ((article . (author title journal volume pages year doi))
(book . (author title year))
(misc . (author title url doi))
(techreport . (author title institution year))
(mastersthesis . (author title school year))
(phdthesis . (author title school year))
(t . (author title year))))))
(provide 'unsrt-paren)
;;; unsrt-paren.el ends here

View File

@@ -0,0 +1,111 @@
;;; unsrt.el --- Citation Style Lisp - the other CSL
;;; Commentary:
;;
;;; Code:
(setq citation-style
'((label . orcp-citation-number-label)
(prefix . "")
(suffix . "")
(chomp-leading-space . t)
(chomp-trailing-space . nil)
;; sort on increasing citation numbers.
(sort . (lambda (key1 key2)
(let ((i1 (-find-index
(lambda (entry)
(string= key1 (car entry)))
*orcp-unique-entries*))
(i2 (-find-index
(lambda (entry)
(string= key2 (car entry)))
*orcp-unique-entries*)))
(> i2 i1))))
(collapse . 'orcp-collapse-numeric-range)
(delimiter . ",")
(vertical-align . superscript)
(transpose-punctuation . t) ;put citations on right of punctuation
(citenum . ((vertical-align . baseline)
(prefix . " ")
(suffix . " ")
(chomp-leading-space . nil)
(chomp-trailing-space . nil)))
(citeauthor . ((vertical-align . baseline)
(label . orcp-citation-author-label)
(prefix . "")
(suffix . " ")
(chomp-leading-space . nil)
(chomp-trailing-space . nil)))
(citeyear . ((vertical-align . baseline)
(label . orcp-citation-year-label)
(prefix . "")
(suffix . " ")
(chomp-leading-space . nil)
(chomp-trailing-space . nil)))))
(setq bibliography-style
'((sort . nil)
(hanging-indent . 3)
(justification . full)
(spacing . 1)
(label . orcp-citation-number-label)
(label-prefix . "")
(label-suffix . ". ")
(header . ((text . "Bibliography")
(font-style . bold)))
;; Formatting of fields
;; Single author name
(author . ((initialize . t) ; use initials, not full names
(name-order . (lastname firstname))
(name-separator . ", ")
(et-al . 4) ; after 4 authors use et-al
(delimiter . "; ")
(last-author-delimiter . " and ")
(suffix . "")
(field-separator . ", ")
;; ; function to convert (first von last jr) to a string.)
(name-format . ''format-author-name)
(field-separator ", ")))
(title . ((font-style . italics)
(suffix . "")
(field-separator . ", ")))
(booktitle . ((font-style . italics)
(suffix . "")
(field-separator . "in ")))
(journal . ((suffix . "")
(field-separator . ", ")))
;; here we use some logic to group volume(issue) or volume
(volume . ((suffix . (when (orcp-get-entry-field "number" entry)
(orcp-issue entry)))
(field-separator . ", ")))
(issue . ((font-style . bold)
(prefix . "(")
(suffix . ")")
(field-separator . ", ")))
(pages . ((prefix . "pp. ")
(suffix . "")
(field-separator . " ")
(collapse-range . nil)))
(year . ((prefix . "(")
(suffix . ")")
(field-separator . ".")))
(doi . ((prefix . " ")
(suffix . ".")
(field-separator . "")
(formatter . orcp-doi-formatter)))
;; Formatting of entries
(entries . ((article . (author title journal volume pages year doi))
(inproceedings . (author title booktitle year))
(book . (author title year))
(misc . (author title url doi))
(techreport . (author title institution year))
(mastersthesis . (author title school year))
(phdthesis . (author title school year))
(t . (author title year))))))
(provide 'unsrt)
;;; unsrt.el ends here

View File

@@ -0,0 +1,92 @@
* DONE Introduction to a citation processor in org-ref
CLOSED: [2015-12-11 Fri 18:05]
:PROPERTIES:
:categories: emacs,orgref,orgmode,citations
:date: 2015/12/11 18:05:43
:updated: 2015/12/11 18:22:40
:END:
As a potential solution for citions in org-mode for non-LaTeX export, here we introduce csl (citation syntax lisp). The idea is heavily influenced by the xml-based Citation Syntax Language, but uses lisp sexps instead.
Briefly, there is a csl file that contains two variables: citation-style and bibliography-style. The citation-style defines how the in-text citations are represented for different types of citations. The bibliography-style defines how the bibliography is constructed.
What do we gain by this?
1. No need for external citeproc program, and hackability by org-mode experts.
2. Punctuation transposition and space chomping, i.e. put superscripts on the right side of punctuation if you want it, and remove whitespace before superscripts if you want it.
3. Total tunability of the citation format to different backends.
4. Easy to change bibliography format with the bibliographystyle link.
5. The use of Bibtex databases. These are plain text, and flexible.
The real code for this is too long to blog about. Instead, you should check it out here: https://github.com/jkitchin/org-ref/tree/master/citeproc
** Reference types
- A book cite:kittel-2005-introd-solid.
- An article cite:kitchin-2015-examp
- A miscellaneous bibtex type cite:xu-suppor.
There is work to do in supporting other types of entry types that are common in bibtex files.
** Citation types
- Regular citation: cite:kitchin-2015-examp
- citenum: See Ref. citenum:kitchin-2015-examp
- citeauthor: citeauthor:kitchin-2015-examp
- citeyear: citeyear:kitchin-2015-examp
There is work to do in supporting other types of citations.
** Multiple citations and sorting within citation
You can specify that the cites within a citation are consistently sorted in the export.
- a,b: cite:kitchin-2015-examp,kitchin-2015-data-surfac-scien
- b,a: cite:kitchin-2015-data-surfac-scien,kitchin-2015-examp
There is work to do for range collapsing, e.g. to turn 1,2,3 into 1-3.
** Space chomping and punctuation testing
I think citations should always be put in the sentence they logically belong to. LaTeX has a feature through natbib I think where for some styles, e.g. superscripts, the citations are moved to the right side of punctuation, and whitespace is chomped so the superscript is next to words, not separated by spaces. We can do that here too.
- Citation at end of sentence cite:kitchin-2015-examp.
- Citation in clause cite:kitchin-2015-examp,kitchin-2015-data-surfac-scien, with a comma.
- Citation in middle of cite:kitchin-2015-examp,kitchin-2015-data-surfac-scien a sentence.
** Building
:PROPERTIES:
:date: 2015/12/11 14:47:59
:updated: 2015/12/11 14:48:26
:END:
At the moment, you have to add a hook function to put the replacements in the document before parsing.
#+BEGIN_SRC emacs-lisp
(add-to-list 'load-path ".")
(require 'org-ref-citeproc)
(let ((org-export-before-parsing-hook '(orcp-citeproc)))
(browse-url (org-html-export-to-html)))
#+End_src
#+RESULTS:
: #<process open ./readme-author-year.html>
** Summary thoughts
This looks promising. There is probably a lot of work to do to make this as robust as say citeproc-js or the Zotero handler. I am not sure if we could write this in a way to directly use the CSL. My feeling is it would not be as flexible as this, and we would have to add to it anyway.
Here are some remaining things that could be worked on if we continue this direction.
1. Other bibtex entries need to be tested out.
2. Remaining bibtex fields need to be defined.
3. Standardization of styling that can be done. Not all features described in my csl are supported, e.g. et. al. and probably others.
4. The author-year style needs name disambiguation somehow.
5. Hyperlinking in html.
6. Make sure export to other backends works.
7. Can this work for notes-based styles?
** Bibliography
You use a bibliographystyle link to specify a csl. These are similar to bibtex styles, and in some cases no change is needed for LaTeX export (although you may have to remove the citeproc hook function).
bibliographystyle:author-year
bibliography:~/Dropbox/bibliography/references.bib

View File

@@ -0,0 +1,93 @@
* DONE Introduction to a citation processor in org-ref
CLOSED: [2015-12-11 Fri 18:05]
:PROPERTIES:
:categories: emacs,orgref,orgmode,citations
:date: 2015/12/11 18:05:43
:updated: 2015/12/11 18:22:40
:END:
As a potential solution for citions in org-mode for non-LaTeX export, here we introduce csl (citation syntax lisp). The idea is heavily influenced by the xml-based Citation Syntax Language, but uses lisp sexps instead.
Briefly, there is a csl file that contains two variables: citation-style and bibliography-style. The citation-style defines how the in-text citations are represented for different types of citations. The bibliography-style defines how the bibliography is constructed.
What do we gain by this?
1. No need for external citeproc program, and hackability by org-mode experts.
2. Punctuation transposition and space chomping, i.e. put superscripts on the right side of punctuation if you want it, and remove whitespace before superscripts if you want it.
3. Total tunability of the citation format to different backends.
4. Easy to change bibliography format with the bibliographystyle link.
5. The use of Bibtex databases. These are plain text, and flexible.
The real code for this is too long to blog about. Instead, you should check it out here: https://github.com/jkitchin/org-ref/tree/master/citeproc
** Reference types
- A book cite:kittel-2005-introd-solid.
- An article cite:kitchin-2015-examp
- A miscellaneous bibtex type cite:xu-suppor.
There is work to do in supporting other types of entry types that are common in bibtex files.
** Citation types
- Regular citation: cite:kitchin-2015-examp
- citenum: See Ref. citenum:kitchin-2015-examp
- citeauthor: citeauthor:kitchin-2015-examp
- citeyear: citeyear:kitchin-2015-examp
There is work to do in supporting other types of citations.
** Multiple citations and sorting within citation
You can specify that the cites within a citation are consistently sorted in the export.
- a,b: cite:kitchin-2015-examp,kitchin-2015-data-surfac-scien
- b,a: cite:kitchin-2015-data-surfac-scien,kitchin-2015-examp
There is work to do for range collapsing, e.g. to turn 1,2,3 into 1-3.
** Space chomping and punctuation testing
I think citations should always be put in the sentence they logically belong to. LaTeX has a feature through natbib I think where for some styles, e.g. superscripts, the citations are moved to the right side of punctuation, and whitespace is chomped so the superscript is next to words, not separated by spaces. We can do that here too.
- Citation at end of sentence cite:kitchin-2015-examp.
- Citation in clause cite:kitchin-2015-examp,kitchin-2015-data-surfac-scien, with a comma.
- Citation in middle of cite:kitchin-2015-examp,kitchin-2015-data-surfac-scien a sentence.
** Building
:PROPERTIES:
:date: 2015/12/11 14:47:59
:updated: 2015/12/11 14:48:26
:END:
At the moment, you have to add a hook function to put the replacements in the document before parsing.
#+BEGIN_SRC emacs-lisp
(add-to-list 'load-path ".")
(require 'org-ref-citeproc)
(when (file-exists-p "readme.html") (delete-file "readme.html"))
(let ((org-export-before-parsing-hook '(orcp-citeproc)))
(browse-url (org-html-export-to-html)))
#+End_src
#+RESULTS:
: #<process open ./readme-unsrt.html>
** Summary thoughts
This looks promising. There is probably a lot of work to do to make this as robust as say citeproc-js or the Zotero handler. I am not sure if we could write this in a way to directly use the CSL. My feeling is it would not be as flexible as this, and we would have to add to it anyway.
Here are some remaining things that could be worked on if we continue this direction.
1. Other bibtex entries need to be tested out.
2. Remaining bibtex fields need to be defined.
3. Standardization of styling that can be done. Not all features described in my csl are supported, e.g. et. al. and probably others.
4. The author-year style needs name disambiguation somehow.
5. Hyperlinking in html.
6. Make sure export to other backends works.
7. Can this work for notes-based styles?
** Bibliography
You use a bibliographystyle link to specify a csl. These are similar to bibtex styles, and in some cases no change is needed for LaTeX export (although you may have to remove the citeproc hook function).
bibliographystyle:unsrt
bibliography:~/Dropbox/bibliography/references.bib

View File

@@ -0,0 +1,203 @@
@techreport{2011-mater-genom,
title = {Materials Genome Initiative for Global Competitiveness},
institution = {National Science and Technology Council},
year = {2011},
type = {Report}
}
@phdthesis{Hossein-thesis,
author = {Hossein Pourmatin},
title = {Computational Multiscale Methods for Defects: 1. Line Defects
in Liquid Crystals; 2. Electron Scattering in Defected
Crystals},
school = {Carnegie Mellon University},
year = 2014,
note = {Available at
\url{sites.google.com/site/kaushikdayal/publications#Theses}}
}
@inproceedings{abolhasani-2011-model,
Author = {Abolhasani, M. and Kumacheva, E. and G{\"u}nther,
A.},
Title = {Model-predictive Strategy for Exploration of Carbon
Dioxide Dissolution and Mass Transfer},
Booktitle = {15th International Conference on Miniaturized
Systems for Chemistry and Life Sciences},
Year = 2011,
Month = {October},
Url =
{"http://www.rsc.org/images/LOC/2011/PDFs/Papers/224_1180.pdf}
}
@article{anderson-1977-raman,
author = {George R. Anderson},
title = {The {R}aman Spectra of Carbon Dioxide in Liquid Water and
Water-D2},
journal = {J. Phys. Chem.},
volume = 81,
number = 3,
pages = {273-276},
year = 1977,
doi = {10.1021/j100518a017},
url = {http://dx.doi.org/10.1021/j100518a017},
month = 2,
eprint = {http://pubs.acs.org/doi/pdf/10.1021/j100518a017},
}
@MastersThesis{ding-2012-metal-oxide,
author = {Zhizhong Ding},
title = {Metal Oxide Oxygen Carriers for Chemical-Looping Combustion},
school = {Carnegie Mellon University},
year = 2012}
@article{kitchin-2015-data-surfac-scien,
author = "John R. Kitchin",
title = {Data Sharing in Surface Science},
journal = "Surface Science ",
volume = "N/A",
pages = "in press",
year = 2015,
doi = {10.1016/j.susc.2015.05.007},
url =
"http://www.sciencedirect.com/science/article/pii/S0039602815001326",
issn = "0039-6028",
keywords = {DESC0004031, early-career, orgmode, Data sharing },
}
@article{kitchin-2015-examp,
author = {Kitchin, John R.},
title = {Examples of Effective Data Sharing in Scientific Publishing},
journal = {ACS Catalysis},
volume = {5},
number = {6},
pages = {3894-3899},
year = 2015,
doi = {10.1021/acscatal.5b00538},
url = { http://dx.doi.org/10.1021/acscatal.5b00538 },
keywords = {DESC0004031, early-career, orgmode, Data sharing },
eprint = { http://dx.doi.org/10.1021/acscatal.5b00538 },
}
@book{kittel-2005-introd-solid,
author = {Charles Kittel},
title = {Introduction to Solid State Physics},
publisher = {Wiley},
year = 2005,
edition = {8th}
}
@misc{xu-suppor,
author = {Zhongnan Xu and Jan Rossmeisl and John R. Kitchin},
title = {Supporting data for: A linear response, {DFT+U} study of trends
in the oxygen evolution activity of transition metal rutile
dioxides. doi:10.5281/zenodo.12635},
keywords = {DESC0004031, early-career, },
year = {2015},
url = {https://zenodo.org/record/12635},
doi = {10.5281/zenodo.12635}
}
@article{ye-2012-proces-charac,
author = {Y. E. Chunbo and Guangwen CHEN and Quan YUAN},
title = {Process Characteristics of \ce{CO2} Absorption By Aqueous
Monoethanolamine in a Microchannel Reactor},
journal = {Chinese Journal of Chemical Engineering},
volume = 20,
number = 1,
pages = {111-119},
year = 2012,
doi = {10.1016/s1004-9541(12)60370-x},
url = {http://dx.doi.org/10.1016/S1004-9541(12)60370-X},
}
@article{yeo-2012-in-situ,
author = {Yeo, Boon Siang and Bell, Alexis T.},
title = {In Situ {R}aman Study of Nickel Oxide and Gold-Supported
Nickel Oxide Catalysts for the Electrochemical Evolution of
Oxygen},
journal = {The Journal of Physical Chemistry C},
volume = 116,
number = 15,
pages = {8394-8400},
year = 2012,
doi = {10.1021/jp3007415},
url = {http://pubs.acs.org/doi/abs/10.1021/jp3007415},
eprint = {http://pubs.acs.org/doi/pdf/10.1021/jp3007415},
}
@article{zhu-2013-sulfur,
author = {Zhu, Qingjun and Wegener, Staci L. and Xie, Chao and Uche,
Obioma and Neurock, Matthew and Marks, Tobin J.},
title = {Sulfur As a Selective "soft" Oxidant for Catalytic Methane
Conversion Probed By Experiment and Theory},
journal = {Nature chemistry},
volume = 5,
pages = {104-109},
year = 2013,
doi = "10.1002/ange.201311111",
url =
"http://www.nature.com/nchem/journal/v5/n2/full/nchem.1527.html",
}
@article{lizzit-2001-surfac-ru,
author = {S. Lizzit and A. Baraldi and A. Groso and K. Reuter and M. V.
Ganduglia-Pirovano and C. Stampfl and M. Scheffler and M.
Stichler and C. Keller and W. Wurth and D. Menzel},
title = {Surface Core-Level Shifts of Clean and Oxygen-Covered
{Ru}(0001)},
journal = {Phys. Rev. B},
volume = 63,
number = 20,
pages = {205419},
year = 2001,
doi = {10.1103/physrevb.63.205419},
url = {http://dx.doi.org/10.1103/physrevb.63.205419},
date_added = {Mon Nov 16 16:28:01 2015},
}
@article{weaver-2011-high-selec,
author = {Jason F. Weaver and Can Hakanoglu and Abbin Antony and Aravind
Asthagiri},
title = {High Selectivity for Primary {C-H} Bond Cleavage of Propane
$\sigma$-complexes on the {PdO}(101) Surface},
keywords = {alkane},
journal = {J. Am. Chem. Soc.},
volume = 133,
number = 40,
pages = {16196-16200},
year = 2011,
doi = {10.1021/ja206599k},
url = {http://dx.doi.org/10.1021/ja206599k},
date_added = {Sat Nov 28 09:10:59 2015},
}
@article{antony-2012-pathw-c,
author = {Abbin Antony and Aravind Asthagiri and Jason F. Weaver},
title = {Pathways for {C-H} Bond Cleavage of Propane $\sigma$-complexes on
{PdO}(101)},
keywords = {alkane},
journal = {Phys. Chem. Chem. Phys.},
volume = 14,
number = 35,
pages = 12202,
year = 2012,
doi = {10.1039/c2cp41900a},
url = {http://dx.doi.org/10.1039/c2cp41900a},
date_added = {Sat Nov 28 09:13:32 2015},
}
@article{wang-2013-immob-co2,
author = {Xianfeng Wang and Novruz G. Akhmedov and Yuhua Duan and David
Luebke and Bingyun Li},
title = {Immobilization of Amino Acid Ionic Liquids Into Nanoporous
Microspheres As Robust Sorbents for CO2 Capture},
journal = {J. Mater. Chem. A},
volume = 1,
number = 9,
pages = 2978,
year = 2013,
doi = {10.1039/c3ta00768e},
url = {http://dx.doi.org/10.1039/C3TA00768E},
date_added = {Thu Dec 3 06:13:09 2015},
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,42 @@
;;; nist-webbook.el --- Integration of Emacs with NIST Webbook
;; Integration of Emacs with NIST webbook
;;; Commentary:
;; nist-webbook-name :: search for a chemical name
;; nist-webbook-formula :: search by chemical formula
;;; Code:
(require 'org)
(require 'org-ref-utils)
;;;###autoload
(defun nist-webbook-formula (formula)
"Search NIST webbook for FORMULA."
(interactive "sFormula: ")
(browse-url
(concat
"http://webbook.nist.gov/cgi/cbook.cgi?Formula="
formula
"&NoIon=on&Units=SI")))
;;;###autoload
(defun nist-webbook-name (name)
"Search NIST webbook for NAME."
(interactive "sChemical Name: ")
(browse-url
(concat "http://webbook.nist.gov/cgi/cbook.cgi?Name="
(url-hexify-string name)
"&Units=SI")))
(org-ref-link-set-parameters "nist-wb-name"
:follow (lambda (name)
(nist-webbook-name name)))
(org-ref-link-set-parameters "nist-wb-formula"
:follow (lambda (formula)
(nist-webbook-formula formula)))
(provide 'nist-webbook)
;;; nist-webbook.el ends here

View File

@@ -0,0 +1,235 @@
;;; org-ref-arxiv.el --- arxiv utilities for org-mode -*- lexical-binding: t; -*-
;; Copyright (C) 2015 John Kitchin
;; Author: John Kitchin <jkitchin@andrew.cmu.edu>
;; Keywords:
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;; this library creates a new org-link for Arxiv (http://arxiv.org/) entries,
;; and provides functions to retrieve bibtex entries from an Arxiv number.
;;
;; An Arxiv number might look like: cond-mat/0410285 or 1503.01742
;;; Code:
(require 'bibtex)
(require 'dash)
(require 'f)
(require 'org)
(require 's)
(require 'org-ref-utils)
;; This is a local variable defined in `url-http'. We need it to avoid
;; byte-compiler errors.
(defvar url-http-end-of-headers)
(defvar org-ref-default-bibliography)
(defvar org-ref-pdf-directory)
(declare-function parsebib-find-bibtex-dialect "parsebib")
(declare-function org-ref-clean-bibtex-entry "org-ref-core")
;; this is a C function
(declare-function libxml-parse-xml-region "xml")
;;* The org-mode link
;; this just makes a clickable link that opens the entry.
;; example: arxiv:cond-mat/0410285
(org-ref-link-set-parameters "arxiv"
:follow (lambda (link-string)
(browse-url (format "http://arxiv.org/abs/%s" link-string)))
:export (lambda (keyword desc format)
(cond
((eq format 'html)
(format "<a href=\"http://arxiv.org/abs/%s\">arxiv:%s</a>"
keyword (or desc keyword)))
((eq format 'latex)
;; write out the latex command
(format "\\url{http://arxiv.org/abs/%s}{%s}" keyword (or desc keyword))))))
;;* Getting a bibtex entry for an arXiv article using remote service:
;; For an arxiv article, there is a link to a NASA ADS page like this:
;; http://adsabs.harvard.edu/cgi-bin/bib_query?arXiv:1503.01742
;; On that page, there is a link to a bibtex entry:
;; http://adsabs.harvard.edu/cgi-bin/nph-bib_query?bibcode=2015arXiv150301742H&data_type=BIBTEX&db_key=PRE&nocookieset=1
;;
;; It looks like you need to get a Bibliographic code from the arxiv number to
;; then get the bibtex entry.
(defun arxiv-get-bibliographic-code (arxiv-number)
"Get Bibliographic code for ARXIV-NUMBER."
(with-current-buffer
(url-retrieve-synchronously
(concat
"http://adsabs.harvard.edu/cgi-bin/bib_query?arXiv:"
arxiv-number))
(search-forward-regexp "name=\\\"bibcode\\\" value=\\\"\\(.*\\)\\\"")
(match-string 1)))
(defun arxiv-get-bibtex-entry (arxiv-bibliographic-code)
"Get bibtex entry for ARXIV-BIBLIOGRAPHIC-CODE."
(with-current-buffer
(url-retrieve-synchronously
(format
"http://adsabs.harvard.edu/cgi-bin/nph-bib_query?bibcode=%s&data_type=BIBTEX&db_key=PRE&nocookieset=1"
arxiv-bibliographic-code))
(goto-char url-http-end-of-headers)
(if (search-forward "Retrieved 1 abstracts" (point-max) t)
(progn
(forward-line)
(buffer-substring (point) (point-max)))
(error "Did not get one entry: %s" (buffer-substring (point) (point-max))))))
;;* Getting a bibtex entry for an arXiv article using arXiv API:
;; Retrieves the meta data of an article view arXiv's http API,
;; extracts the necessary information, and formats a new BibTeX entry.
(defvar arxiv-entry-format-string "@article{%s,
journal = {CoRR},
title = {%s},
author = {%s},
archivePrefix = {arXiv},
year = {%s},
eprint = {%s},
primaryClass = {%s},
abstract = {%s},
url = {%s},
}"
"Template for BibTeX entries of arXiv articles.")
(defun arxiv-get-bibtex-entry-via-arxiv-api (arxiv-number)
"Retrieve meta data for ARXIV-NUMBER.
Returns a formatted BibTeX entry."
(with-current-buffer
(url-retrieve-synchronously (format "http://export.arxiv.org/api/query?id_list=%s" arxiv-number) t)
(let* ((parse-tree (libxml-parse-xml-region
(progn (goto-char 0)
(search-forward "<?xml ")
(match-beginning 0))
(point-max)))
(entry (assq 'entry parse-tree))
(authors (--map (nth 2 (nth 2 it))
(--filter (and (listp it) (eq (car it) 'author)) entry)))
(year (format-time-string "%Y" (date-to-time (nth 2 (assq 'published entry)))))
(title (nth 2 (assq 'title entry)))
(names (arxiv-bibtexify-authors authors))
(category (cdar (nth 1 (assq 'primary_category entry))))
(abstract (s-trim (nth 2 (assq 'summary entry))))
(url (nth 2 (assq 'id entry)))
(temp-bibtex (format arxiv-entry-format-string "" title names year arxiv-number category abstract url))
(key (with-temp-buffer
(insert temp-bibtex)
(bibtex-mode)
(bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
(bibtex-generate-autokey))))
(format arxiv-entry-format-string key title names year arxiv-number category abstract url))))
(defun arxiv-bibtexify-authors (authors)
"Return names in 'SURNAME, FIRST NAME' format from AUTHORS list."
(s-join " and "
(--map (concat (-last-item it) ", " (s-join " " (-remove-last 'stringp it)))
(--map (s-split " +" it) authors))))
;;;###autoload
(defun arxiv-add-bibtex-entry (arxiv-number bibfile)
"Add bibtex entry for ARXIV-NUMBER to BIBFILE."
(interactive
(list (read-string "arxiv: ")
;; now get the bibfile to add it to
(completing-read
"Bibfile: "
(append (f-entries "." (lambda (f) (f-ext? f "bib")))
org-ref-default-bibliography))))
(save-window-excursion
(find-file bibfile)
(goto-char (point-max))
(when (not (looking-at "^")) (insert "\n"))
(insert (arxiv-get-bibtex-entry-via-arxiv-api arxiv-number))
(org-ref-clean-bibtex-entry)
(save-buffer)))
;;;###autoload
(defun arxiv-get-pdf (arxiv-number pdf)
"Retrieve a pdf for ARXIV-NUMBER and save it to PDF."
(interactive "sarxiv: \nsPDF: ")
(let ((pdf-url (with-current-buffer
(url-retrieve-synchronously
(concat
"http://arxiv.org/abs/" arxiv-number))
;; <meta name="citation_pdf_url" content="http://arxiv.org/pdf/0801.1144" />
(goto-char (point-min))
(search-forward-regexp
"name=\\\"citation_pdf_url\\\" content=\\\"\\(.*\\)\\\"")
(match-string 1))))
(url-copy-file pdf-url pdf)
;; now check if we got a pdf
(if (org-ref-pdf-p pdf)
(org-open-file pdf)
(delete-file pdf)
(message "Error downloading arxiv pdf %s" pdf-url))))
;;;###autoload
(defun arxiv-get-pdf-add-bibtex-entry (arxiv-number bibfile pdfdir)
"Add bibtex entry for ARXIV-NUMBER to BIBFILE.
Remove troublesome chars from the bibtex key, retrieve a pdf
for ARXIV-NUMBER and save it to PDFDIR with the same name of the
key."
(interactive
(list (read-string "arxiv: ")
;; now get the bibfile to add it to
(completing-read
"Bibfile: "
(append (f-entries "." (lambda (f) (f-ext? f "bib")))
org-ref-default-bibliography))
(read-directory-name
"PDF directory: "
org-ref-pdf-directory)))
(arxiv-add-bibtex-entry arxiv-number bibfile)
(save-window-excursion
(let ((key ""))
(find-file bibfile)
(goto-char (point-max))
(bibtex-beginning-of-entry)
(re-search-forward bibtex-entry-maybe-empty-head)
(if (match-beginning bibtex-key-in-head)
(progn
(setq key (delete-and-extract-region
(match-beginning bibtex-key-in-head)
(match-end bibtex-key-in-head)))
;; remove potentially troublesome characters from key
;; as it will be used as a filename
(setq key (replace-regexp-in-string "\"\\|\\*\\|/\\|:\\|<\\|>\\|\\?\\|\\\\\\||\\|\\+\\|,\\|\\.\\|;\\|=\\|\\[\\|]\\|:\\|!\\|@"
"" key))
;; check if the key is in the buffer
(when (save-excursion
(bibtex-search-entry key))
(save-excursion
(bibtex-search-entry key)
(bibtex-copy-entry-as-kill)
(switch-to-buffer-other-window "*duplicate entry*")
(bibtex-yank))
(setq key (bibtex-read-key "Duplicate Key found, edit: " key))))
(setq key (bibtex-read-key "Key not found, insert: ")))
(insert key)
(arxiv-get-pdf arxiv-number (concat pdfdir key ".pdf")))))
(provide 'org-ref-arxiv)
;;; org-ref-arxiv.el ends here

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,919 @@
;;; readme.org --- org-ref-citeproc - Citation processor for org-mode
;;; Commentary: This code is style agnostic. It will get information from the
;;; information in `citation-style' and `bibliography-style'. These are defined
;;; in a csl.el file.
;;
;; Conventions:
;; an "entry" is the result of `bibtex-parse-entry'.
;;
;;; Commentary:
;;
(declare-function org-ref-get-bibtex-key-and-file "org-ref-core")
(declare-function org-ref-get-bibtex-keys "org-ref-core")
(declare-function parsebib-find-bibtex-dialect "parsebib")
(defvar org-export-current-backend)
(defvar org-ref-cite-types)
(require 'org-element)
;;; Code:
(defvar *orcp-citation-links* '()
"List of citation links in the text.
A link may have more than one citation in it. These links get
replaced by the new citation text.")
(defvar *orcp-unique-entries* '()
"List of unique (key . entry) parsed bibtex entries in the document.
The list is sorted according to the style. This list eventually
makes up the bibliography.")
(defvar citation-style '()
"Style data for an in-text citation.
For unsrt, a regular cite is superscripted, sorted,
range-collapsed numbers.
LABEL is a function that is run to get the label.
PREFIX goes before a citation.
SUFFIX goes after a citation.
citations are separated by DELIMITER.
SORT specifies that 3, 1, 2 be converted to 1,2,3
COLLAPSE is a function to collapse multiple citations, e.g. 1,2,3 becomes 1-3.
VERTICAL-ALIGN is a function that places the citation, e.g.
superscript, nil for baseline, etc...
Additional entries provide overrides for special citation types.")
(defvar bibliography-style '()
"Bibliography style data.
SORT is a function that sorts the entries, e.g. by author, or
year, or nil. It should take one argument, the list of unique
entries (key . entry).
LABEL is a function that returns how the entry is numbered, or
referenced in the text.
HANGING-INDENT is for the indentation of the entry on the left.
JUSTIFICATION is the overall justification on the right.
SPACING is the number of lines between entries.
HEADER is a string that is inserted above the bibliography.
ENTRIES is a alist of entry type and fields to make the entry from.")
;;* Collect citations
(defun orcp-collect-citations ()
"Return a list of citation links in the document."
(setq *orcp-citation-links*
(cl-loop for link in (org-element-map
(org-element-parse-buffer) 'link 'identity)
if (-contains?
org-ref-cite-types
(org-element-property :type link))
collect link)))
(defun orcp-key-to-entry (key)
"Return a parsed bibtex entry for KEY.
The KEY is found for the bibliography in the file."
(let* ((results (org-ref-get-bibtex-key-and-file key))
(bibfile (cdr results)))
(save-excursion
(with-temp-buffer
(insert-file-contents bibfile)
(bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
(bibtex-search-entry key)
(let ((entry (bibtex-parse-entry t)))
(dolist (cons-cell entry)
(setf (car cons-cell) (downcase (car cons-cell))))
(setf (cdr (assoc "=type=" entry))
(downcase (cdr (assoc "=type=" entry))))
entry)))))
(defun orcp-collect-unique-entries ()
"Return a list of unique entries, sorted as required by the style.
Each entry is (key . entry)."
(let ((keys (org-ref-get-bibtex-keys))
sort-func
entries)
(setq entries
(cl-loop for key in keys
collect (cons key (orcp-key-to-entry key))))
;; Now we should sort them if the style requires it
(setq sort-func (cdr (assoc 'sort bibliography-style)))
(when sort-func
(setq entries (funcall sort-func entries)))
(setq *orcp-unique-entries* entries)))
;;** Unique entry sorting functions
(defun orcp-sort-entries-increasing-year (unique-entries)
"Sort UNIQUE-ENTRIES in increasing year of publication.
i.e. oldest stuff first."
(sort unique-entries
(lambda (a b)
(let* ((e1 (cdr a))
(e2 (cdr b))
(year1 (string-to-number (cdr (assoc "year" e1))))
(year2 (string-to-number (cdr (assoc "year" e2)))))
(> year2 year1)))))
(defun orcp-sort-entries-decreasing-year (unique-entries)
"Sort UNIQUE-ENTRIES in decreasing year.
i.e. most current first."
(reverse (orcp-sort-entries-increasing-year unique-entries)))
(defun orcp-get-entry-field (field entry)
"RETURN FIELD from ENTRY.
Strip extra spaces and carriage returns."
(let ((result (cdr (assoc field entry))))
(when result
(while (string-match "[\n\t\r]\\|[ \t][ \t]+" result)
(setq result (replace-match " " nil t result))))
result))
(defun orcp-sort-entries-alphabetical (unique-entries)
"Sort UNIQUE-ENTRIES alphabetically by first author last name."
(sort unique-entries
(lambda (a b)
(let* ((e1 (cdr a))
(e2 (cdr b))
(authors1 (s-split
" and "
(orcp-get-entry-field "author" e1)))
(author1 (orcp-parse-authorname (car authors1)))
;; lastname is "von last"
(last1 (concat (nth 1 author1) " " (nth 2 author1)))
(authors2 (s-split
" and "
(orcp-get-entry-field "author" e2)))
(author2 (orcp-parse-authorname (car authors2)))
(last2 (concat (nth 1 author2) " " (nth 2 author2))))
(string-lessp last1 last2)))))
;;* Citation labels for one citation key
;; No styling is done here.
(defun orcp-citation-number-label (key unique-entries)
"Find the numeric index of KEY in UNIQUE-ENTRIES and return as a string.
Indexing starts at 0 so we add one."
(number-to-string
(+ 1
(-find-index
(lambda (entry)
(string= key (car entry)))
unique-entries))))
(defun orcp-footnote-label (key unique-entries)
"Return an org footnote label for KEY in UNIQUE-ENTRIES."
(format "[fn:%s]" (orcp-citation-number-label key unique-entries)))
(defun orcp-citation-author-label (key unique-entries)
"Return an author last name label for KEY.
KEY is found in UNIQUE-ENTRIES."
(let* ((i (-find-index
(lambda (entry)
(string= key (car entry)))
unique-entries))
(entry (cdr (nth i unique-entries)))
(authors (s-split
" and "
(orcp-get-entry-field "author" entry)))
(first-author (orcp-parse-authorname (car authors))))
(format "%s" (concat (nth 1 first-author)
(nth 2 first-author)))))
(defun orcp-citation-year-label (key unique-entries)
"Return a year label for KEY.
KEY is found in UNIQUE-ENTRIES."
(let* ((i (-find-index
(lambda (entry)
(string= key (car entry)))
unique-entries))
(entry (cdr (nth i unique-entries)))
(year (orcp-get-entry-field "year" entry)))
(format "%s" year)))
(defun orcp-citation-author-year-label (key unique-entries)
"Return an author last name year label for KEY.
KEY is found in UNIQUE-ENTRIES.
We do not have a disambiguation strategy yet."
(let* ((i (-find-index
(lambda (entry)
(string= key (car entry)))
unique-entries))
(entry (cdr (nth i unique-entries)))
(authors (s-split
" and "
(orcp-get-entry-field "author" entry)))
(first-author (orcp-parse-authorname (car authors)))
(year (orcp-get-entry-field "year" entry)))
(format "%s %s" (concat (nth 1 first-author)
(nth 2 first-author))
year)))
;;* Replacements for citation links
;; Here we have to map over the keys in a citation, sort them according to the
;; style, get replacement labels, concat them together with the style delimiter,
;; add the prefix and suffix, and finally format for the type and output
;; backend.
(defun orcp-get-citation-style (symbol type)
"Get the style info for SYMBOL for a citation TYPE from `citation-style'.
Styles have a default, but allow TYPE overrides. This function
returns the style with the override."
(let (style)
;; first get default style
(setq style (cdr (assoc symbol citation-style)))
;; now check for an override
;; we need to find the type, and the symbol in the type
(when (and (assoc type citation-style)
(assoc symbol (assoc type citation-style)))
(setq style (cdr (assoc symbol (assoc type citation-style)))))
style))
(defun orcp-get-text-replacement (citation-link)
"Return replacement string for CITATION-LINK."
(let* ((type (intern (org-element-property :type citation-link)))
(path (org-element-property :path citation-link))
(keys (s-split "," path))
(entries (mapcar 'orcp-key-to-entry keys))
(label-func (orcp-get-citation-style 'label type))
(delimiter (orcp-get-citation-style 'delimiter type))
(sort-func (orcp-get-citation-style 'sort type))
labels
replacement-text)
;; sort is not coded yet. I am not sure the best data to sort here. the keys?
(when sort-func
(setq keys (sort keys sort-func)))
;; get labels. This function is where you would, for example, create
;; hyperlinks to the bibliography. This function should return a list of
;; strings
(setq labels
(mapcar
(lambda (key)
(funcall label-func key *orcp-unique-entries*))
keys))
;; collapse range - not used yet.
;; now get a string collecting everything
(setq labels (mapconcat 'identity labels delimiter))
(setq replacement-text (concat
(orcp-get-citation-style 'prefix type)
labels
(orcp-get-citation-style 'suffix type)))
;; finally, call formatter
(funcall (or (orcp-get-citation-style 'vertical-align type)
'baseline)
replacement-text)))
(defun orcp-get-citation-replacements ()
"Get a list of replacements for all links in `*orcp-citation-links*'."
(mapcar 'orcp-get-text-replacement *orcp-citation-links*))
;;* Formatted bibliography
(defun orcp-formatted-bibliography ()
"Return the formatted bibliography."
(let* ((spacing (or (cdr (assoc 'spacing bibliography-style)) 1))
(label-func (cdr (assoc 'label bibliography-style)))
(label-prefix (cdr (assoc 'label-prefix bibliography-style)))
(label-suffix (cdr (assoc 'label-suffix bibliography-style)))
(justification (cdr (assoc 'justification bibliography-style)))
(hanging-indent (cdr (assoc 'hanging-indent bibliography-style)))
(header (cdr (assoc 'header bibliography-style)))
(unique-entries (orcp-collect-unique-entries))
(adaptive-fill-function '(lambda () " "))
(indent-tabs-mode nil)
bibliography-string)
(setq bibliography-string
(mapconcat
'identity
;; loop over the entries in the bibliography
(cl-loop for entry in unique-entries
collect
(progn
(let* ((entry-type (downcase
(cdr (assoc "=type=" (cdr entry)))))
(key (cdr (assoc "=key=" (cdr entry))))
(entry-styles (cdr (assoc 'entries bibliography-style)))
(entry-fields
(progn
(if (cdr (assoc (intern entry-type) entry-styles))
(cdr (assoc (intern entry-type) entry-styles))
(warn "%s not found. Using default." entry-type)
(cdr (assoc 't entry-styles))
)))
(funcs (mapcar
(lambda (field)
(if (fboundp (intern
(format "orcp-%s" field)))
(intern
(format "orcp-%s" field))
;; No formatter found. just get the data
`(lambda (entry)
(orcp-get-entry-field
,(symbol-name field) entry))))
entry-fields))
(label (concat label-prefix
(funcall label-func key unique-entries)
label-suffix)))
;; this is the entry. We do this in a buffer to make it
;; easy to indent, fill, etc...
(with-temp-buffer
(insert label)
(insert (mapconcat (lambda (field-func)
(funcall field-func entry))
funcs
""))
(goto-char (point-min))
(forward-word)
;; It doesn't make sense to do this for all formats, e.g.HTML.
;; commenting out for now.
;; (increase-left-margin
;; (point-min) (point-max) hanging-indent)
;; (fill-region (point-min) (point-max) justification)
(buffer-string)))))
;; Here we put in the separator between entries
(cond
;; placeholder for other formats
((eq org-export-current-backend 'html)
" @@html:<br>@@\n")
(t
;; put in a \n for each spacing
(mapconcat 'identity
(cl-loop for i to spacing
collect "\n")
"")))))
;; TODO: figure out header. how do we insert it properly formatted?
bibliography-string))
;;* Text formatting functions.
;; These take text, and format them according to a backend. We derive the
;; backend from `org-export-current-backend' because I anticipate using this
;; during export.
(defun baseline (text)
"Return TEXT."
text)
(defun superscript (text)
"Format TEXT as superscripted."
(cond
((eq org-export-current-backend 'html)
(format "@@html:<sup>%s</sup>@@" text))
;; the catch-all case is org-syntax
(t
(format "^{%s}" text))))
(defun italics (text)
"Format TEXT as italics."
(cond
((eq org-export-current-backend 'html)
(format "@@html:<i>%s</i>@@" text))
;; the catch-all case is org-syntax
(t
(format "/%s/" text))))
(defun bold (text)
"Format TEXT in bold."
(cond
((eq org-export-current-backend 'html)
(format "@@html:<b>%s</b>@@" text))
;; the catch-all case is org-syntax
(t
(format "*%s*" text))))
;;* Field formatting functions
;;These should be style agnostic functions. They take an entry and return a
;; formatted field for the entry, using information from the csl file.
(defun firstname (author-cell)
"Return firstname from AUTHOR-CELL."
(car author-cell))
(defun lastname (author-cell)
"Return lastname from AUTHOR-CELL."
(cdr author-cell))
(defun orcp-author (entry)
"Return formatted author string from the ENTRY.
ENTRY is from `bibtex-parse-entry'.
Style information comes from `bibliography'"
(let* ((style (cdr (assoc 'author bibliography-style)))
(delimiter (cdr (assoc 'delimiter style)))
(name1 (nth 0 (cdr (assoc 'name-order style))))
(name2 (nth 1 (cdr (assoc 'name-order style))))
(name-separator (cdr (assoc 'name-separator style)))
(suffix (cdr (assoc 'suffix style)))
(field-separator (cdr (assoc 'field-separator style)))
(et-al (cdr (assoc 'et-al style)))
(authors (s-split
" and "
(or
(orcp-get-entry-field "author" entry)
"")))
;; parse to list of (first von last jr)
(author-data (mapcar
(lambda (x)
(let ((aud (orcp-parse-authorname x)))
(cons (nth 0 aud)
(concat
(or (nth 1 aud) "")
(or (nth 2 aud) "")
(or (nth 3 aud) "")))))
authors))
;; map first and last names, in order specified in style with separator
(author-names
(mapcar
(lambda (x)
(concat
(funcall name1 x)
name-separator
(funcall name2 x)))
author-data)))
;; check on et-al - not implemented yet
;; work on initialize - not implemented yet
;; mapconcat on delimiter then last author.
(if (= 1 (length author-names))
(concat (car author-names) suffix field-separator)
(concat
(mapconcat
'identity
(butlast author-names)
delimiter)
(cdr (assoc 'last-author-delimiter style))
(car (last author-names))
suffix
field-separator))))
(defun orcp-title (entry)
"Return formatted title for the bibtex ENTRY."
(let* ((style (cdr (assoc 'title bibliography-style)))
(font-style (cdr (assoc 'font-style style)))
(suffix (cdr (assoc 'suffix style)))
(field-separator (cdr (assoc 'field-separator style)))
(title (orcp-get-entry-field "title" entry)))
(concat
(if font-style
(funcall font-style title)
title)
suffix
field-separator)))
(defun orcp-journal (entry)
"Return formatted journal for the bibtex ENTRY."
(let* ((style (cdr (assoc 'journal bibliography-style)))
(font-style (cdr (assoc 'font-style style)))
(suffix (cdr (assoc 'suffix style)))
(field-separator (cdr (assoc 'field-separator style)))
(journal (orcp-get-entry-field "journal" entry)))
(concat
(if font-style
(funcall font-style journal)
journal)
suffix
field-separator)))
(defun orcp-volume (entry)
"Return formatted volume for the bibtex ENTRY."
(let* ((style (cdr (assoc 'volume bibliography-style)))
(font-style (cdr (assoc 'font-style style)))
(prefix (cdr (assoc 'prefix style)))
(suffix (eval (cdr (assoc 'suffix style))))
(field-separator (cdr (assoc 'field-separator style)))
(volume (orcp-get-entry-field "volume" entry)))
(setq volume (concat prefix volume suffix))
(concat
(if font-style
(funcall font-style volume)
volume)
field-separator)))
(defun orcp-issue (entry)
"Return formatted issue for the bibtex ENTRY."
(let* ((style (cdr (assoc 'issue bibliography-style)))
(font-style (cdr (assoc 'font-style style)))
(prefix (cdr (assoc 'prefix style)))
(suffix (cdr (assoc 'suffix style)))
(field-separator (cdr (assoc 'field-separator style)))
(issue (orcp-get-entry-field "number" entry)))
;; issue is optional and isn't always present.
(if (not issue)
field-separator
(setq issue (concat prefix issue suffix))
(if font-style
(funcall font-style
issue)
issue))))
(defun orcp-pages (entry)
"Return formatted pages for the bibtex ENTRY."
(let* ((style (cdr (assoc 'pages bibliography-style)))
(font-style (cdr (assoc 'font-style style)))
(prefix (cdr (assoc 'prefix style)))
(suffix (cdr (assoc 'suffix style)))
(field-separator (cdr (assoc 'field-separator style)))
(pages (orcp-get-entry-field "pages" entry)))
(setq pages (concat prefix pages suffix))
;; collapse-range not supported yet
(concat (if font-style
(funcall font-style
pages)
pages)
field-separator)))
(defun orcp-year (entry)
"Return formatted year for the bibtex ENTRY."
(let* ((style (cdr (assoc 'year bibliography-style)))
(font-style (cdr (assoc 'font-style style)))
(prefix (cdr (assoc 'prefix style)))
(suffix (cdr (assoc 'suffix style)))
(field-separator (cdr (assoc 'field-separator style)))
(year (orcp-get-entry-field "year" entry)))
(setq year (concat prefix year suffix))
;; collapse-range not supported yet
(concat
(if font-style
(funcall font-style
year)
year)
field-separator)))
(defun orcp-doi-formatter (doi)
"Return formatted DOI for different backends."
(cond
((eq org-export-current-backend 'html)
(format "http://dx.doi.org/%s" doi))
(t
(format "doi:%s" doi))))
(defun orcp-doi (entry)
"Return formatted doi for the bibtex ENTRY."
(let* ((style (cdr (assoc 'doi bibliography-style)))
(font-style (cdr (assoc 'font-style style)))
(prefix (cdr (assoc 'prefix style)))
(suffix (cdr (assoc 'suffix style)))
(formatter (cdr (assoc 'formatter style)))
(doi (orcp-get-entry-field "doi" entry)))
(when formatter
(setq doi (funcall formatter doi)))
(setq doi (concat prefix doi suffix))
(if font-style
(funcall font-style
(concat prefix doi suffix))
doi)))
(defun orcp-url (entry)
"Return formatted url for the bibtex ENTRY."
(let* ((style (cdr (assoc 'doi bibliography-style)))
(font-style (cdr (assoc 'font-style style)))
(prefix (cdr (assoc 'prefix style)))
(suffix (cdr (assoc 'suffix style)))
(formatter (cdr (assoc 'formatter style)))
(url (orcp-get-entry-field "url" entry)))
(when formatter
(setq url (funcall formatter url)))
(setq url (concat prefix url suffix))
(if font-style
(funcall font-style
(concat prefix url suffix))
url)))
;;* Data structures for Author names
(defun orcp-unprotect-brackets (piece protected-strings)
"Unprotect PIECE with the information in PROTECTED-STRINGS.
PROTECTED-STRINGS is a list of cons-cells (\"protection\" .
original text)."
(when piece
(mapc
(lambda (cons-cell)
(when (string-match (car cons-cell) piece)
(setq piece (replace-match (cdr cons-cell) t t piece))))
protected-strings))
piece)
;; See http://maverick.inria.fr/~Xavier.Decoret/resources/xdkbibtex/bibtex_summary.html#names for the parsing rules.
(defun orcp-parse-authorname (name)
"Convert an author NAME to (first von last jr) data structure.
Valid name forms are:
First1 First2 Last
First1 First 2 {Last1 Last2}
First1 First2 von1 von2 Last1 Last2
von1 von2 Last1 Last2, Jr., First1 First2
Last1, First1 First2
{Von Last1}, First1 First2
We try to protect strings in curly brackets."
(let* (protected-strings
uuid
ncommas
fields
first von last jr)
;; protect bracketed strings
(while (string-match "{\\(.*\\)}" name)
;; We want our substitute to look like a name, not a von part so we add a
;; capital letter to the front.
(setq uuid (concat "A" (md5 (format "%s%s%s%s%s%s%s"
(random)
(current-time)
(user-uid)
(emacs-pid)
(user-full-name)
user-mail-address
(recent-keys)))))
(add-to-list 'protected-strings (cons uuid (match-string 0 name)))
(setq name (replace-match uuid nil nil name)))
(setq ncommas (s-count-matches "," name))
(cond
;; "First von Last"
((= 0 ncommas)
(setq fields (s-split " " name))
(while (and (s-capitalized? (car fields)) (> (length fields) 1))
(setq first (append first (list (pop fields)))))
(when first
(setq first (mapconcat 'identity first " ")))
;; Next, we get the von part. this is the longest white space delimited
;; string that ends with a lowercase word, and is not the rest of the
;; string.
(let ((last-lower-index nil))
(cl-loop for i to (length fields)
for word in (butlast fields)
if (s-lowercase? word)
do (setq last-lower-index i))
(when last-lower-index
(setq von (mapconcat
'identity
(-slice fields 0 (+ 1 last-lower-index)) " "))
(setq fields (-slice fields (+ 1 last-lower-index)))))
;; all that should be left is the last name but it might be more than one
;; word, e.g. with a Jr. or a two work last name.
(setq last (mapconcat 'identity fields " "))
(mapcar
(lambda (x)
(orcp-unprotect-brackets x protected-strings))
(list first von last jr)))
;; "von Last, First"
((= 1 ncommas)
(setq fields (s-split "," name))
(setq first (nth 1 fields))
;; split first field which could be von Lastname.
(setq fields (s-split " " (car fields)))
(let ((last-lower-index nil))
(cl-loop for i to (length fields)
for word in fields
if (s-lowercase? word)
do (setq last-lower-index i))
(when last-lower-index
(setq von (mapconcat
'identity
(-slice fields 0 (+ 1 last-lower-index)) " "))
(setq fields (-slice fields (+ 1 last-lower-index)))))
;; all that should be left is the last name
(setq last (mapconcat 'identity fields " "))
(mapcar
(lambda (x)
(orcp-unprotect-brackets x protected-strings))
(list first von last jr)))
;; "von Last, Jr, First"
((= 2 ncommas)
(setq fields (s-split "," name))
(setq first (nth 2 fields))
(setq jr (nth 1 fields))
;; split first field which could be von Lastname.
(setq fields (s-split " " (car fields)))
(let ((last-lower-index nil))
(cl-loop for i to (length fields)
for word in fields
if (s-lowercase? word)
do (setq last-lower-index i))
(when last-lower-index
(setq von (mapconcat 'identity (-slice fields 0 (+ 1 last-lower-index)) " "))
(setq fields (-slice fields (+ 1 last-lower-index)))))
;; all that should be left is the last name
(setq last (mapconcat 'identity fields " "))
(mapcar
(lambda (x)
(orcp-unprotect-brackets x protected-strings))
(list first von last jr))))))
;;* Collapse numeric range
(defun orcp-collapse-numeric-range (cites delimiter)
"TODO use style info.
Collapse a numeric list of CITES into a range.
Collapsed ranges are separated by DELIMITER."
(let (n
(groups '()))
(while cites
(setq n (pop cites))
(if (and (caar groups) (= (- n 1) (elt (car groups) 0)))
(setf (car groups) (append `(,n) (car groups)))
(setf groups (append `((,n)) groups))))
;; Now for each group
(mapconcat 'identity
(mapcar
(lambda (lst)
(cond
((>= (length lst) 3)
(format "%s-%s" (car lst) (car (last lst))))
((= (length lst) 2)
(format "%s,%s" (nth 0 lst) (nth 1 lst)))
(t
(number-to-string (car lst)))))
(mapcar 'reverse (reverse groups)))
delimiter)))
;;* Putting it all together
(defun sentence-beginning-p ()
"Determine if point is at the beginning of a sentence.
The idea is to move forward a sentence, then back. If the point
doesn't move, it means you were at the beginning of a sentence."
(let ((cp (point)))
(save-excursion
(forward-sentence)
(backward-sentence)
(= cp (point)))))
(defun orcp-citeproc (&optional backend)
"Format citations and bibliography for BACKEND.
Warning. Destructive to your document! Will replace links.
Meant to be used in export on a temporary version of the
documents."
;; Get the style from bibliographystyle link
;; and eliminate bibliography style links
;; This will load all style modules
(cl-loop for link in (org-element-map
(org-element-parse-buffer) 'link 'identity)
if (string= "bibliographystyle"
(org-element-property :type link))
do
;; get path for style and load it
(load-library (org-element-property :path link))
;; get rid of the link in the buffer
(setf (buffer-substring (org-element-property :begin link)
(org-element-property :end link))
""))
(orcp-collect-citations)
(orcp-collect-unique-entries)
(let ((link-replacements (cl-loop for link in *orcp-citation-links*
for repl in (orcp-get-citation-replacements)
collect
(list repl
(org-element-property :begin link)
(org-element-property :end link))))
(bibliography-string (orcp-formatted-bibliography))
punctuation
trailing-space
bibliography-link)
;; replace citation links
(cl-loop for (repl start end) in (reverse link-replacements)
for link in (reverse *orcp-citation-links*)
do
;; chomp leading spaces if needed
(when (orcp-get-citation-style
'chomp-leading-space
(intern (org-element-property :type link)))
(goto-char start)
(while (and (not (sentence-beginning-p))
(looking-back " " (- (point) 2)))
(delete-char -1)
(setq start (- start 1))
(setq end (- end 1))))
;; chomp trailing spaces if needed
(when (orcp-get-citation-style
'chomp-trailing-space
(intern (org-element-property :type link)))
(goto-char end)
(while (looking-back " " (- (point) 2))
(delete-char 1)))
;; Check for transposing punctuation
(setq punctuation nil)
(when (orcp-get-citation-style
'transpose-punctuation
(intern (org-element-property :type link)))
;; goto end of link
(goto-char end)
(when (looking-at "\\.\\|,\\|;")
(setq punctuation (buffer-substring end (+ 1 end)))
(delete-char 1)))
;; preserve trailing space
(goto-char end)
(setq trailing-space (if (looking-back " " (line-beginning-position)) " " ""))
(setf (buffer-substring start end) (concat repl trailing-space))
(when punctuation
(goto-char start)
;; I can't figure out why this is necessary. I would have thought
;; the chomp leading spaces would get it.
(when (thing-at-point 'whitespace)
(delete-char -1))
(insert punctuation)))
;; Insert bibliography section at the bibliography link
(setq bibliography-link (cl-loop for link
in (org-element-map
(org-element-parse-buffer)
'link 'identity)
if (string= "bibliography"
(org-element-property :type link))
collect link))
(pcase (length bibliography-link)
((pred (< 1)) (error "Only one bibliography link allowed"))
((pred (= 1))
;; replace bibliography link
(setq bibliography-link (car bibliography-link))
(setf (buffer-substring (org-element-property :begin bibliography-link)
(org-element-property :end bibliography-link))
bibliography-string))
((pred (= 0))
;; no bibliography link in document
(when link-replacements
(message "Warning: No bibliography link found although there are citations to process"))))))
;; * the end
(provide 'org-ref-citeproc)
;;; org-ref-citeproc.el ends here

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,496 @@
;;; org-ref-glossary.el --- glossary support in org-ref -*- lexical-binding: t; -*-
;; Copyright (C) 2016 John Kitchin
;; Author: John Kitchin <jkitchin@andrew.cmu.edu>
;; Keywords:
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;; Provides Some glossary support for org-mode. Only export to LaTeX is
;; supported. The functionality is based on the LaTeX glossaries package. See
;; https://en.wikibooks.org/wiki/LaTeX/Glossary and
;; http://ctan.math.washington.edu/tex-archive/macros/latex/contrib/glossaries/glossaries-user.pdf
;; Put something like this in your org-file.
;; #+latex_header: \usepackage{glossaries}
;; #+latex_header: \makeglossaries
;; Put this where you want the glossaries to appear in your org-file.
;; \printglossaries
;; Add new glossary entries to your org-file like this. Enclose strings
;; containing a comma in {}. Multiline entries are supported.
;; #+latex_header_extra: \newglossaryentry{computer}{name=computer,description={A machine, that computes}}
;; #+latex_header_extra: \newglossaryentry{tree}{name=tree,description=a big plant}
;; #+latex_header_extra: \newglossaryentry{naiive}
;; #+latex_header_extra: {
;; #+latex_header_extra: name=na\"{\i}ve,
;; #+latex_header_extra: description={is a French loanword (adjective, form of naïf)
;; #+latex_header_extra: indicating having or showing a lack of experience,
;; #+latex_header_extra: understanding or sophistication}
;; #+latex_header_extra: }
;; Here is an example acronym definition
;; #+latex_header_extra: \newacronym{lvm}{LVM}{Logical Volume Manager}
;; New links defined:
;; gls:name A reference to the glossary entry NAME.
;; glspl:name The plural version of the entry
;; Gls:name Capitalized glossary entry
;; Glspl: Capitalized, plural glossary entry
;; [[gslink:name][alternate text]]
;; glssymbol:name Outputs the symbol value of the glossary entry settings.
;; glsdesc:name The description of name
;; The links export to LaTeX. You can click on the link and jump to the
;; definition. The links have tooltips for the definitions.
;; Acronym links
;; acrshort:label
;; acrfull:label
;; acrlong:label
;; ac:label (exports to \gls{label})
;; Ac:label (exports to \Gls{label})
;; acp:label (exports to \glspl{label})
;; Acp:label (exports to \Glspl{label})
(require 'org-element)
(require 'org-ref-utils)
(declare-function helm "helm")
(declare-function helm-build-sync-source "helm-source")
;;; Code:
(defgroup org-ref-glossary nil
"Customization group for org-ref-glossary."
:tag "Org Ref glossary"
:group 'org)
(defcustom org-ref-glossary-color "Mediumpurple3"
"Color for glossary links."
:type 'string
:group 'org-ref)
(defcustom org-ref-acronym-color "Darkorange2"
"Color for acronym links."
:type 'string
:group 'org-ref)
(defun or-find-closing-curly-bracket (&optional limit)
"Find closing bracket for the bracket at point and move point to it.
Go up to LIMIT or `point-max'. This is a parsing function. I
wrote this because using `forward-list' does not always work if
there is an escaped \" for example. This seems pretty robust."
(unless (looking-at "{") (error "Not at a curley bracket"))
(let ((level 1))
(while (and (not (= 0 level))
(not (eobp))
(< (point) (or limit (point-max))))
(forward-char)
(when (and (looking-at "{")
(not (looking-back "\\\\" (- (point) 2))))
(cl-incf level))
(when (and (looking-at "}")
(not (looking-back "\\\\" (- (point) 2))))
(cl-decf level)))
(point)))
;;* Glossary
(defun or-parse-glossary-entry (entry)
"Parse glossary ENTRY definition to a p-list of key=value.
Typically:
(:name name :description description)
but there could be other :key value pairs."
(save-excursion
(let (end-of-entry
data
key value p1 p2)
(goto-char (point-min))
;; We may not find an entry if it is defined as an acronym
(when (re-search-forward
(format "\\newglossaryentry{%s}" entry) nil t)
(re-search-forward "{")
(save-excursion
(backward-char)
(or-find-closing-curly-bracket)
(setq end-of-entry (point)))
(while (re-search-forward "\\(\\w+?\\)=" end-of-entry t)
(setq key (match-string 1))
;; get value
(goto-char (+ 1 (match-end 1)))
(setq p1 (point))
(if (looking-at "{")
;; value is wrapped in {}
(progn
(or-find-closing-curly-bracket)
(setq p2 (point)
value (buffer-substring (+ 1 p1) p2)))
;; value is up to the next comma
(re-search-forward "," end-of-entry 'mv)
(setq value (buffer-substring p1 (- (point) 1))))
;; remove #+latex_header_extra:
(setq value (replace-regexp-in-string
"#\\+latex_header_extra: " "" value))
(setq value (replace-regexp-in-string
"\n +" " " value))
(setq data (append data
(list (intern (format ":%s" key)))
(list value))))
data))))
;;;###autoload
(defun org-ref-add-glossary-entry (label name description)
"Insert a new glossary entry.
LABEL is how you refer to it with links.
NAME is the name of the entry to be defined.
DESCRIPTION is the definition of the entry.
Entry gets added after the last #+latex_header line."
(interactive "sLabel: \nsName: \nsDescription: ")
(save-excursion
(re-search-backward "#\\+latex_header" nil t)
(forward-line)
(when (not (looking-at "^$"))
(beginning-of-line)
(insert "\n")
(forward-line -1))
(insert (format "#+latex_header_extra: \\newglossaryentry{%s}{name={%s},description={%s}}\n"
label name description))))
;;** Glossary links
(defun or-follow-glossary (entry)
"Goto beginning of the glossary ENTRY."
(org-mark-ring-push)
(goto-char (point-min))
(re-search-forward (format "\\newglossaryentry{%s}" entry))
(goto-char (match-beginning 0)))
(defvar org-ref-glossary-gls-commands
'("gls" "glspl" "Gls" "Glspl" "glssymbol" "glsdesc"))
(dolist (command org-ref-glossary-gls-commands)
(org-ref-link-set-parameters command
:follow #'or-follow-glossary
:face 'org-ref-glossary-face
:help-echo 'or-glossary-tooltip
:export (lambda (path _ format)
(cond
((eq format 'latex)
(format "\\%s{%s}" command path))
(t
(format "%s" path))))))
(org-ref-link-set-parameters "glslink"
:follow #'or-follow-glossary
:face 'org-ref-glossary-face
:help-echo 'or-glossary-tooltip
:export (lambda (path desc format)
(cond
((eq format 'latex)
(format "\\glslink{%s}{%s}" path desc))
(t
(format "%s" path)))))
;;** Tooltips on glossary entries
(defface org-ref-glossary-face
`((t (:inherit org-link :foreground ,org-ref-glossary-color)))
"Face for glossary links.")
(defun or-glossary-tooltip (_window _object position)
"Return tooltip for the glossary entry.
The entry is in WINDOW and OBJECT at POSITION.
Used in fontification."
(save-excursion
(goto-char position)
(let* ((label (org-element-property :path (org-element-context)))
(data (or (or-parse-glossary-entry label)
(or-parse-acronym-entry label)))
(name (or (plist-get data :name)
(plist-get data :abbrv)))
(description (or (plist-get data :description)
(plist-get data :full))))
(format
"%s: %s"
name
(with-temp-buffer
(insert (concat description "."))
(fill-paragraph)
(buffer-string))))))
(unless (fboundp 'org-link-set-parameters)
(defun or-next-glossary-link (limit)
"Search to next glossary link up to LIMIT.
Adds a tooltip to the link that is found."
(when (and (re-search-forward
(concat
(regexp-opt '("gls" "glspl"
"Gls" "Glspl"
"glslink"
"glssymbol"
"glsdesc"))
":[a-zA-Z]\\{2,\\}")
limit t)
(not (org-in-src-block-p))
(not (org-at-comment-p)))
(forward-char -2)
(let ((next-link (org-element-context)))
(if next-link
(progn
(set-match-data (list (org-element-property :begin next-link)
(- (org-element-property :end next-link)
(org-element-property :post-blank next-link))))
(add-text-properties
(org-element-property :begin next-link)
(- (org-element-property :end next-link)
(org-element-property :post-blank next-link))
(list
'help-echo 'or-glossary-tooltip))
(goto-char (org-element-property :end next-link)))
(goto-char limit)
nil)))))
;;* Acronyms
;;;###autoload
(defun org-ref-add-acronym-entry (label abbrv full)
"Add an acronym entry with LABEL.
ABBRV is the abbreviated form.
FULL is the expanded acronym."
(interactive "sLabel: \nsAcronym: \nsFull name: ")
(save-excursion
(re-search-backward "#\\+latex_header" nil t)
(forward-line)
(when (not (looking-at "^$"))
(beginning-of-line)
(insert "\n")
(forward-line -1))
(insert (format "#+latex_header_extra: \\newacronym{%s}{%s}{%s}\n"
label abbrv full))))
(defun or-parse-acronym-entry (label)
"Parse an acronym entry LABEL to a plist.
\(:abbrv abbrv :full full)
\newacronym{<label>}{<abbrv>}{<full>}"
(save-excursion
(let (abbrv full p1)
(goto-char (point-min))
(when
(re-search-forward (format "\\newacronym{%s}" label) nil t)
(setq p1 (+ 1 (point)))
(forward-list)
(setq abbrv (buffer-substring p1 (- (point) 1)))
(setq p1 (+ 1 (point)))
(forward-list)
(setq full (buffer-substring p1 (- (point) 1)))
(list :abbrv abbrv :full full)))))
;;** Acronym links
(defun or-follow-acronym (label)
"Go to the definition of the acronym LABEL."
(org-mark-ring-push)
(goto-char (point-min))
(re-search-forward (format "\\\\newacronym{%s}" label))
(goto-char (match-beginning 0)))
(defvar org-ref-glossary-acr-commands-mapping
'(("acrshort" . "acrshort")
("acrlong" . "acrlong")
("acrfull" . "acrfull")
("ac" . "gls")
("Ac" . "Gls")
("acp" . "glspl")
("Acp" . "Glspl")))
(dolist (mapping org-ref-glossary-acr-commands-mapping)
(org-ref-link-set-parameters (car mapping)
:follow #'or-follow-acronym
:face 'org-ref-acronym-face
:help-echo 'or-acronym-tooltip
:export (lambda (path _ format)
(cond
((eq format 'latex)
(format "\\%s{%s}" (cdr mapping) path))
(t
(format "%s" (upcase path)))))))
;;** Tooltips on acronyms
(defface org-ref-acronym-face
`((t (:inherit org-link :foreground ,org-ref-acronym-color)))
"Face for acronym links.")
(defun or-acronym-tooltip (_window _object position)
"Return tooltip for the acronym entry.
The entry is in WINDOW and OBJECT at POSITION.
Used in fontification.
WINDOW and OBJECT are ignored."
(save-excursion
(goto-char position)
(let* ((label (org-element-property :path (org-element-context)))
(acronym-data (or-parse-acronym-entry label))
(abbrv (plist-get acronym-data :abbrv))
(full (plist-get acronym-data :full)))
(if acronym-data
(format
"%s: %s"
abbrv full)
(format "%s is not defined in this file." label)))))
;; We use search instead of a regexp to match links with descriptions. These are
;; hard to do with regexps.
(unless (fboundp 'org-link-set-parameters)
(defun or-next-acronym-link (limit)
"Search to next acronym link up to LIMIT and add a tooltip."
(when (and (re-search-forward
(concat
(regexp-opt '("acrshort" "acrfull" "acrlong" "ac" "Ac" "acp" "Acp"))
":[a-zA-Z]\\{2,\\}")
limit t)
(not (org-in-src-block-p))
(not (org-at-comment-p)))
(save-excursion
(forward-char -2)
(let ((next-link (org-element-context)))
(if next-link
(progn
(set-match-data
(list (org-element-property :begin next-link)
(- (org-element-property :end next-link)
(org-element-property :post-blank next-link))))
(add-text-properties
(org-element-property :begin next-link)
(- (org-element-property :end next-link)
(org-element-property :post-blank next-link))
(list
'help-echo 'or-acronym-tooltip))
(goto-char (org-element-property :end next-link)))
(goto-char limit)
nil))))))
;; * Helm command to insert entries
;;;###autoload
(defun org-ref-insert-glossary-link ()
"Helm command to insert glossary and acronym entries as links."
(interactive)
;; gather entries
(let ((glossary-candidates '())
(acronym-candidates '())
key
entry)
(save-excursion
(goto-char (point-min))
(while (re-search-forward
"\\\\newglossaryentry{\\([[:ascii:]]+?\\)}" nil t)
(setq key (match-string 1)
entry (or-parse-glossary-entry key))
(setq glossary-candidates
(append
glossary-candidates
(list
(cons
;; for helm
(format "%s: %s."
(plist-get entry :name)
(plist-get entry :description))
;; the returned candidate
(list key
(plist-get entry :name))))))))
;; acronym candidates
(save-excursion
(goto-char (point-min))
(while (re-search-forward
"\\\\newacronym{\\([[:ascii:]]+?\\)}" nil t)
(setq key (match-string 1)
entry (or-parse-acronym-entry key))
(setq acronym-candidates
(append
acronym-candidates
(list
(cons
;; for helm
(format "%s (%s)."
(plist-get entry :full)
(plist-get entry :abbrv))
;; the returned candidate
(list key
(plist-get entry :abbrv))))))))
(helm :sources
`(,(helm-build-sync-source "Insert glossary term"
:candidates glossary-candidates
:action (lambda (candidate)
(insert (format
"[[%s:%s][%s]]"
(completing-read "Type: "
'("gls"
"glspl"
"Gls"
"Glspl"
"glssymbol"
"glsdesc")
nil t
"gls")
(nth 0 candidate)
(nth 1 candidate)))))
,(helm-build-sync-source "Insert acronym term"
:candidates acronym-candidates
:action (lambda (candidate)
(insert (format
"[[%s:%s][%s]]"
(completing-read "Type: "
'("acrshort"
"acrlong"
"acrfull"
"ac"
"Ac"
"acp"
"Acp")
nil t
"ac")
(nth 0 candidate)
(nth 1 candidate)))))
,(helm-build-sync-source "Add new term"
:candidates '(("Add glossary term" . org-ref-add-glossary-entry)
("Add acronym term" . org-ref-add-acronym-entry))
:action (lambda (x)
(call-interactively x)))))))
(provide 'org-ref-glossary)
;;; org-ref-glossary.el ends here

View File

@@ -0,0 +1,736 @@
;;; org-ref-helm-bibtex.el --- Customization of helm-bibtex for org-ref -*- lexical-binding: t; -*-
;; Copyright (C) 2016 John Kitchin
;; Author: John Kitchin <jkitchin@andrew.cmu.edu>
;; Keywords:
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;; This file defines the completion engine for org-ref using `helm-bibtex'.
(declare-function 'org-ref-find-bibliography "org-ref-core.el")
(declare-function 'org-ref-get-bibtex-key-and-file "org-ref-core.el")
(defvar org-ref-get-pdf-filename-function)
(defvar org-ref-default-citation-link)
(defvar org-ref-cite-types)
(defvar org-ref-insert-link-function)
(defvar org-ref-insert-cite-function)
(defvar org-ref-insert-label-function)
(defvar org-ref-insert-ref-function)
(defvar org-ref-cite-onclick-function)
(defvar org-ref-insert-cite-key)
;;; Code:
(require 'helm-config)
(require 'helm)
(require 'helm-bibtex)
(require 'helm-utils)
(require 'org-ref-helm)
(require 'async)
(require 'package)
;;;###autoload
(defun org-ref-bibtex-completion-completion ()
"Use helm and helm-bibtex for completion."
(interactive)
;; Define core functions for org-ref
(setq org-ref-insert-link-function 'org-ref-helm-insert-cite-link
org-ref-insert-cite-function 'org-ref-helm-insert-cite-link
org-ref-insert-label-function 'org-ref-helm-insert-label-link
org-ref-insert-ref-function 'org-ref-helm-insert-ref-link
org-ref-cite-onclick-function 'org-ref-cite-click-helm))
(org-ref-bibtex-completion-completion)
(define-key org-mode-map
(kbd org-ref-insert-cite-key)
org-ref-insert-link-function)
(defcustom org-ref-bibtex-completion-actions
'(("Insert citation" . helm-bibtex-insert-citation)
("Open PDF, URL or DOI" . helm-bibtex-open-any)
("Open URL or DOI in browser" . helm-bibtex-open-url-or-doi)
("Insert reference" . helm-bibtex-insert-reference)
("Insert BibTeX key" . helm-bibtex-insert-key)
("Insert BibTeX entry" . helm-bibtex-insert-bibtex)
("Insert formatted citation(s)" . (lambda (_)
(insert
(mapconcat 'identity
(cl-loop for key in (helm-marked-candidates)
collect (org-ref-format-entry key))
"\n\n"))))
("Attach PDF to email" . helm-bibtex-add-PDF-attachment)
("Edit notes" . helm-bibtex-edit-notes)
("Show entry" . helm-bibtex-show-entry)
("Add keywords to entries" . org-ref-helm-tag-entries)
("Copy entry to clipboard" . bibtex-completion-copy-candidate)
("Add PDF to library" . helm-bibtex-add-pdf-to-library))
"Cons cells of string and function to set the actions of `helm-bibtex' to.
The car of cons cell is the string describing the function.
The cdr of the the cons cell is the function to use."
:type '(alist :key-type (string) :value-type (function))
:group 'org-ref)
(cl-loop for i from 0 to (length org-ref-bibtex-completion-actions)
for ccell in org-ref-bibtex-completion-actions
do
(helm-delete-action-from-source (car ccell) helm-source-bibtex)
(helm-add-action-to-source
(car ccell)
(cdr ccell)
helm-source-bibtex))
(defcustom org-ref-bibtex-completion-format-org
'org-ref-bibtex-completion-format-org
"Function for how `helm-bibtex' inserts citations."
:type 'function
:group 'org-ref)
(setf (cdr (assoc 'org-mode bibtex-completion-format-citation-functions))
org-ref-bibtex-completion-format-org)
(setq org-ref-insert-cite-function 'org-ref-helm-insert-cite-link
org-ref-cite-onclick-function 'org-ref-cite-click-helm)
;;* Helm bibtex setup.
(setq bibtex-completion-additional-search-fields '(keywords))
(setq bibtex-completion-display-formats
'((t . "${author:36} ${title:*} ${year:4} ${=has-pdf=:1}${=has-note=:1} ${=type=:7} ${keywords:31}")))
(defun bibtex-completion-copy-candidate (_candidate)
"Copy the selected bibtex entries to the clipboard.
Used as a new action in `helm-bibtex'.
CANDIDATE is ignored."
(with-temp-buffer
(bibtex-mode)
(mapc #'insert-file-contents
(-flatten (list bibtex-completion-bibliography)))
(let ((entries '()))
(cl-loop for bibtex-key in (helm-marked-candidates)
do
(goto-char (point-min))
(re-search-forward (concat "^@\\(" parsebib--bibtex-identifier
"\\)[[:space:]]*[\(\{][[:space:]]*"
(regexp-quote bibtex-key)
"[[:space:]]*,"))
(cl-pushnew (buffer-substring
(bibtex-beginning-of-entry)
(bibtex-end-of-entry))
entries))
(with-temp-buffer
(dolist (entry entries)
(insert (format "%s\n\n" entry)))
(kill-new (buffer-string))))))
(defun org-ref-helm-tag-entries (_candidates)
"Set tags on selected bibtex entries from `helm-bibtex'.
User is prompted for tags. This function is called from `helm-bibtex'.
Argument CANDIDATES helm candidates."
(message "")
(let* ((keys (helm-marked-candidates))
(entry (bibtex-completion-get-entry (car keys)))
(field (cdr (assoc-string "keywords" entry)))
(value (when field (replace-regexp-in-string "^{\\|}$" "" field)))
(keywords (read-string "Keywords (comma separated): "
(when (and value (not (equal "" value)))
(concat value ", ")))))
(cl-loop for key in keys
do
(save-window-excursion
(bibtex-completion-show-entry (list key))
;; delete keyword field if empty
(if (equal "" keywords)
(save-restriction
(bibtex-narrow-to-entry)
(goto-char (car (cdr (bibtex-search-forward-field "keywords" t))))
(bibtex-kill-field))
(bibtex-set-field
"keywords"
(concat
(if (listp keywords)
(if (string-match value keywords)
(and (replace-match "")
(mapconcat 'identity keywords ", "))
(mapconcat 'identity keywords ", "))
;; remove trailing comma
(replace-regexp-in-string ", $" "" keywords)))))
(save-buffer)))))
(defun org-ref-bibtex-completion-format-org (keys)
"Insert selected KEYS as cite link.
Append KEYS if you are on a link.
Technically, this function should return a string that is
inserted by helm. This function does the insertion and gives helm
an empty string to insert. This lets us handle appending to a
link properly.
In the `helm-bibtex' buffer, \\[universal-argument] will give you a helm menu to
select a new link type for the selected entries.
A double \\[universal-argument] \\[universal-argument] will
change the key at point to the selected keys."
(let* ((object (org-element-context))
(last-char (save-excursion
(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)
(-contains?
org-ref-cite-types
(org-element-property :type object)))
(cond
;; no prefix. insert or append keys
((equal helm-current-prefix-arg nil)
(cond
;; point after :
((looking-back ":" (- (point) 2))
(insert (concat (mapconcat 'identity keys ",") ",")))
;; point on :
((looking-at ":")
(forward-char)
(insert (concat (mapconcat 'identity keys ",") ",")))
;; point on the cite type
((-contains? org-ref-cite-types (thing-at-point 'word))
(re-search-forward ":")
(insert (concat (mapconcat 'identity keys ",") ",")))
;; after ,
((looking-back "," (- (point) 2))
(insert (concat (mapconcat 'identity keys ",") ",")))
;; on comma
((looking-at ",")
(forward-char)
(insert (concat (mapconcat 'identity keys ",") ",")))
;; somewhere in the middle or end
(t
;; goto next comma or end
(re-search-forward
","
(org-element-property :end object) 'mv)
(skip-chars-backward " ")
(skip-chars-backward "]")
(unless (looking-at ",") (insert ","))
(insert (mapconcat 'identity keys ",")))))
;; double prefix, replace key at point
((equal helm-current-prefix-arg '(16))
(setf (buffer-substring
(org-element-property :begin object)
(org-element-property :end object))
(concat
(replace-regexp-in-string
(car (org-ref-get-bibtex-key-and-file)) ; key
(mapconcat 'identity keys ",") ; new keys
(org-element-property :raw-link object))
;; replace space at end to avoid collapsing into next word.
last-char))
;; and we want to go to the end of the new link
(goto-char
(org-element-property :end (org-element-context))))
(t
(message "Not found"))))
;; 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
(unless (bobp) (backward-char))
(and (equal (org-element-type (org-element-context)) 'link)
(-contains?
org-ref-cite-types
(org-element-property :type (org-element-context)))))
(skip-chars-backward " ")
(insert (concat "," (mapconcat 'identity keys ","))))
;; insert fresh link
(t
(insert
(concat
(when org-ref-prefer-bracket-links "[[")
(if (equal helm-current-prefix-arg '(4))
(helm :sources `((name . "link types")
(candidates . ,org-ref-cite-types)
(action . (lambda (x) x))))
org-ref-default-citation-link)
":"
(s-join "," keys)
(when org-ref-prefer-bracket-links "]]"))))))
;; return empty string for helm
"")
(defun org-ref-format-citation (keys)
"Formatter for org-ref citation commands.
Prompt for the command and additional arguments if the commands can
take any. If point is inside a citation link, append KEYS. Otherwise
prompt for pre/post text. Prompts can also be switched off by setting
the variable `bibtex-completion-cite-prompt-for-optional-arguments' to
nil. To enable this formatter, add it to
`bibtex-completion-format-citation-functions'. For example:
\(setf (cdr (assoc 'org-mode bibtex-completion-format-citation-functions)) 'org-ref-format-citation)
Note also that pre text is preceded by a double colon, for example:
\[[cite:key][See::Chapter 1]], which exports to:
\\cite[See][Chapter 1]{key}."
;; Check if point is inside a cite link
(let ((link (org-element-context))
end path)
(if (-contains? org-ref-cite-types (org-element-property :type link))
(progn
(setq end (org-element-property :end link)
path (org-element-property :path link))
(goto-char end)
(skip-chars-backward " ")
;; Check if link has pre/post text
(if (looking-back "\]" (line-beginning-position))
(progn
(re-search-backward path nil t)
(re-search-forward "\]" nil t)
(backward-char 1)
(format ",%s" (s-join "," keys))))
(format ",%s" (s-join "," keys)))
(let* ((initial (when bibtex-completion-cite-default-as-initial-input bibtex-completion-cite-default-command))
(default
(unless bibtex-completion-cite-default-as-initial-input bibtex-completion-cite-default-command))
(default-info
(if default (format " (default \"%s\")" default) ""))
(cite-command
(completing-read (format "Cite command%s: " default-info)
bibtex-completion-cite-commands nil nil initial
'bibtex-completion-cite-command-history default nil)))
(if (member cite-command '("nocite" "supercite")) ; These don't want arguments.
(format "%s:%s" cite-command (s-join "," keys))
(let ((text (if bibtex-completion-cite-prompt-for-optional-arguments
(read-from-minibuffer "Pre/post text: ")
"")))
(if (string= "" text)
(format "%s:%s" cite-command (s-join "," keys))
(format "[[%s:%s][%s]]" cite-command (s-join "," keys) text))))))))
(defvar bibtex-completion-cached-candidates)
(defvar bibtex-completion-bibliography-hash)
;;;###autoload
(defun org-ref-helm-load-completions-async ()
"Load the bibtex files into helm sources asynchronously.
For large bibtext files, the intial call to org-ref-helm-insert-cite-link
can take a long time to load the completion sources. This function loads
the completion sources in the background so the initial call to org-ref-helm-insert-cite-link is much faster."
(interactive)
(async-start
`(lambda (&optional formatter)
(require 'package)
(package-initialize)
(require 'helm-bibtex)
,(async-inject-variables "bibtex-compl.*")
(with-temp-buffer
(mapc #'insert-file-contents
(-flatten (list bibtex-completion-bibliography)))
;; Check hash of bibliography and reparse if necessary:
(let ((bibliography-hash (secure-hash 'sha256 (current-buffer))))
(unless (and bibtex-completion-cached-candidates
(string= bibtex-completion-bibliography-hash bibliography-hash))
(message "Loading bibliography ...")
(let* ((entries (bibtex-completion-parse-bibliography))
(entries (bibtex-completion-resolve-crossrefs entries))
(entries (bibtex-completion-prepare-entries entries))
(entries (nreverse entries))
(entries
(--map (cons (bibtex-completion-clean-string
(s-join " " (-map #'cdr it))) it)
entries)))
(setq bibtex-completion-cached-candidates
(if (functionp formatter)
(funcall formatter entries)
entries)))
(setq bibtex-completion-bibliography-hash bibliography-hash))
(cons bibliography-hash bibtex-completion-cached-candidates))))
(lambda (result)
(setq bibtex-completion-cached-candidates (cdr result))
(setq bibtex-completion-bibliography-hash (car result))
(message "Finished loading org-ref completions"))))
;;;###autoload
(defun org-ref-helm-insert-cite-link (&optional arg)
"Insert a citation link with `helm-bibtex'.
With one prefix ARG, insert a ref link.
With two prefix ARGs, insert a label link."
(interactive "P")
;; save all bibtex buffers so we get the most up-to-date selection. I find
;; that I often edit a bibliography and forget to save it, so the newest entry
;; does not show in helm-bibtex.
(org-ref-save-all-bibtex-buffers)
(cond
((equal arg nil)
(let ((bibtex-completion-bibliography (org-ref-find-bibliography)))
(helm-bibtex)))
((equal arg '(4))
(org-ref-helm-insert-ref-link))
((equal arg '(16))
(org-ref-helm-insert-label-link))))
;; add our own fallback entries where we want them. These appear in reverse
;; order of adding in the menu
(setq bibtex-completion-fallback-options
(-insert-at 1 '("Crossref" . "http://search.crossref.org/?q=%s") bibtex-completion-fallback-options))
(setq bibtex-completion-fallback-options
(-insert-at
1
'("Scopus" . "http://www.scopus.com/scopus/search/submit/xadvanced.url?searchfield=TITLE-ABS-KEY(%s)")
bibtex-completion-fallback-options))
(setq bibtex-completion-fallback-options
(-insert-at 1 '("WOS" . "http://gateway.webofknowledge.com/gateway/Gateway.cgi?topic=%s&GWVersion=2&SrcApp=WEB&SrcAuth=HSB&DestApp=UA&DestLinkType=GeneralSearchSummary") bibtex-completion-fallback-options))
(defun org-ref-cite-candidates ()
"Generate the list of possible candidates for click actions on a cite link.
Checks for pdf and doi, and add appropriate functions."
(let* ((results (org-ref-get-bibtex-key-and-file))
(key (car results))
(bibfile (cdr results))
(bibtex-completion-bibliography (list bibfile))
(entry (bibtex-completion-get-entry key))
(pdf-file (funcall org-ref-get-pdf-filename-function key))
(pdf-bibtex-completion (car (bibtex-completion-find-pdf key)))
(notes-p (cdr (assoc "=has-note=" entry)))
(url (save-excursion
(with-temp-buffer
(insert-file-contents bibfile)
(bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
(bibtex-search-entry key)
(bibtex-autokey-get-field "url"))))
(doi (save-excursion
(with-temp-buffer
(insert-file-contents bibfile)
(bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
(bibtex-search-entry key)
;; I like this better than bibtex-url which does not always find
;; the urls
(bibtex-autokey-get-field "doi"))))
(candidates `(("Quit" . org-ref-citation-at-point)
("Open bibtex entry" . org-ref-open-citation-at-point))))
;; for some reason, when there is no doi or url, they are returned as "". I
;; prefer nil so we correct this here.
(when (string= doi "") (setq doi nil))
(when (string= url "") (setq url nil))
;; Conditional pdf functions
;; try with org-ref first
(cond ((file-exists-p pdf-file)
(cl-pushnew
'("Open pdf" . (lambda ()
(funcall org-ref-open-pdf-function)))
candidates))
;; try with bibtex-completion
(pdf-bibtex-completion
(cl-pushnew
'("Open pdf" . (lambda ()
(funcall org-ref-open-pdf-function)))
candidates))
;; try with doi
(t
(cl-pushnew
'("Try to get pdf" . (lambda ()
(save-window-excursion
(org-ref-open-citation-at-point)
(bibtex-beginning-of-entry)
(doi-utils-get-bibtex-entry-pdf))))
candidates)))
(if notes-p
(cl-pushnew
'("Open notes" . org-ref-open-notes-at-point)
candidates)
(cl-pushnew
'("Add notes" . org-ref-open-notes-at-point)
candidates))
;; conditional url and doi functions
(when (or url doi)
(cl-pushnew
'("Open in browser" . org-ref-open-url-at-point)
candidates))
(when doi
(mapc (lambda (x)
(cl-pushnew x candidates))
`(("WOS" . org-ref-wos-at-point)
("Related articles in WOS" . org-ref-wos-related-at-point)
("Citing articles in WOS" . org-ref-wos-citing-at-point)
("Google Scholar" . org-ref-google-scholar-at-point)
("Pubmed" . org-ref-pubmed-at-point)
("Crossref" . org-ref-crossref-at-point))))
(cl-pushnew
'("Insert new citation" . (lambda ()
(org-ref-helm-insert-cite-link nil)))
candidates)
(cl-pushnew
'("Delete key at point" . org-ref-delete-key-at-point)
candidates)
;; This is kind of clunky. We store the key at point. Add the new ref. Get
;; it off the end, and put it in the original position.
(cl-pushnew
'("Replace key at point" . org-ref-replace-key-at-point)
candidates)
(cl-pushnew
'("Delete citation at point" . org-ref-delete-cite-at-point)
candidates)
(when bibtex-completion-cite-prompt-for-optional-arguments
(cl-pushnew
'("Update pre/post text" . org-ref-update-pre-post-text)
candidates))
(cl-pushnew
'("Sort keys by year" . org-ref-sort-citation-link)
candidates)
(cl-pushnew
'("Copy formatted citation to clipboard" . org-ref-copy-entry-as-summary)
candidates)
(cl-pushnew
'("Copy key to clipboard" . (lambda ()
(kill-new
(car (org-ref-get-bibtex-key-and-file)))))
candidates)
(cl-pushnew
'("Copy bibtex entry to file" . org-ref-copy-entry-at-point-to-file)
candidates)
(cl-pushnew
'("Email bibtex entry and pdf" . (lambda ()
(save-excursion
(org-ref-open-citation-at-point)
(org-ref-email-bibtex-entry))))
candidates)
;; add Scopus functions. These work by looking up a DOI to get a Scopus
;; EID. This may only work for Scopus articles. Not all DOIs are recognized
;; in the Scopus API. We only load these if you have defined a
;; `*scopus-api-key*', which is required to do the API queries. See
;; `scopus'. These functions are appended to the candidate list.
(when (and (boundp '*scopus-api-key*) *scopus-api-key*)
(cl-pushnew
'("Open in Scopus" . (lambda ()
(let ((eid (scopus-doi-to-eid (org-ref-get-doi-at-point))))
(if eid
(scopus-open-eid eid)
(message "No EID found.")))))
candidates)
(cl-pushnew
'("Scopus citing articles" . (lambda ()
(let ((url (scopus-citing-url
(org-ref-get-doi-at-point))))
(if url
(browse-url url)
(message "No url found.")))))
candidates)
(cl-pushnew
'("Scopus related by authors" . (lambda ()
(let ((url (scopus-related-by-author-url
(org-ref-get-doi-at-point))))
(if url
(browse-url url)
(message "No url found.")))))
candidates)
(cl-pushnew
'("Scopus related by references" . (lambda ()
(let ((url (scopus-related-by-references-url
(org-ref-get-doi-at-point))))
(if url
(browse-url url)
(message "No url found.")))))
candidates)
(cl-pushnew
'("Scopus related by keywords" . (lambda ()
(let ((url (scopus-related-by-keyword-url
(org-ref-get-doi-at-point))))
(if url
(browse-url url)
(message "No url found.")))))
candidates))
;; finally return a numbered list of the candidates
(cl-loop for i from 0
for cell in (reverse candidates)
collect (cons (format "%2s. %s" i (car cell))
(cdr cell)))))
(defvar org-ref-helm-user-candidates '()
"List of user-defined candidates to act when clicking on a cite link.
This is a list of cons cells '((\"description\" . action)). The
action function should not take an argument, and should assume
point is on the cite key of interest.")
;; example of adding your own function
(add-to-list
'org-ref-helm-user-candidates
'("Open pdf in emacs" . (lambda ()
(find-file
(concat
(file-name-as-directory org-ref-pdf-directory)
(car (org-ref-get-bibtex-key-and-file))
".pdf"))))
t)
;;;###autoload
(defun org-ref-cite-click-helm (_key)
"Open helm for actions on a cite link.
subtle points.
1. get name and candidates before entering helm because we need
the org-buffer.
2. switch back to the org buffer before evaluating the
action. most of them need the point and buffer.
KEY is returned for the selected item(s) in helm."
(interactive)
(let ((name (org-ref-format-entry (org-ref-get-bibtex-key-under-cursor)))
(candidates (org-ref-cite-candidates))
(cb (current-buffer)))
(helm :sources `(((name . ,name)
(candidates . ,candidates)
(action . (lambda (f)
(switch-to-buffer ,cb)
(funcall f))))
((name . "User functions")
(candidates . ,org-ref-helm-user-candidates)
(action . (lambda (f)
(switch-to-buffer ,cb)
(funcall f))))))))
;; browse labels
(defun org-ref-browser-label-source ()
(let ((labels (org-ref-get-labels)))
(helm-build-sync-source "Browse labels"
:follow 1
:candidates labels
:action '(("Browse labels" . (lambda (label)
(with-selected-window (selected-window)
(org-open-link-from-string
(format "ref:%s" label)))))))))
;; browse citation links
(defun org-ref-browser-transformer (candidates)
"Add counter to candidates."
(let ((counter 0))
(cl-loop for i in candidates
collect (format "%s %s" (cl-incf counter) i))))
(defun org-ref-browser-display (candidate)
"Strip counter from candidates."
(replace-regexp-in-string "^[0-9]+? " "" candidate))
;;;###autoload
(defun org-ref-browser (&optional arg)
"Quickly browse label links in helm.
With a prefix ARG, browse citation links."
(interactive "P")
(if arg
(let ((keys nil)
(alist nil))
(widen)
(outline-show-all)
(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))
(let ((start (org-element-property :begin link)))
(dolist (key
(org-ref-split-and-strip-string (plist-get plist ':path)))
(setq keys (append keys (list key)))
(setq alist (append alist (list (cons key start))))))))))
(let ((counter 0)
count-key-pos)
;; the idea here is to create an alist with ("counter key" .
;; position) to produce unique candidates
(setq count-key-pos (mapcar (lambda (x)
(cons
(format "%s %s" (cl-incf counter) (car x)) (cdr x)))
alist))
;; push mark to restore position with C-u C-SPC
(push-mark (point))
;; move point to the first citation link in the buffer
(goto-char (cdr (assoc (caar alist) alist)))
(helm :sources
(helm-build-sync-source "Browse citation links"
:follow 1
:candidates keys
:candidate-transformer 'org-ref-browser-transformer
:real-to-display 'org-ref-browser-display
:persistent-action (lambda (candidate)
(helm-goto-char
(cdr (assoc candidate count-key-pos))))
:action `(("Open menu" . ,(lambda (candidate)
(helm-goto-char
(cdr (assoc candidate count-key-pos)))
(org-open-at-point)))))
:candidate-number-limit 10000
:buffer "*helm browser*")))
(helm :sources (org-ref-browser-label-source)
:buffer "*helm labels*")))
(provide 'org-ref-helm-bibtex)
;;; org-ref-helm-bibtex.el ends here

View File

@@ -0,0 +1,770 @@
;;; org-ref-helm-cite.el --- Helm interface to insert citations from bibtex files for org-ref -*- lexical-binding: t; -*-
;; Copyright (C) 2016 John Kitchin
;; Author: John Kitchin <jkitchin@andrew.cmu.edu>
;; Keywords:
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary: This is a competitor of `helm-bibtex'.
;; The main difference is the format of the candidates, which are full citations
;; in this package, and multiline. This package also makes the candidates
;; sortable in different ways, and provides different, context specific actions
;; depending on what buffer you call `org-ref-helm-cite' from, and depending
;; on the properties of the selected candidate.
;;
;; Another significant feature is persistent caching of bibtex files to make
;; startup fast.
;;
(declare-function 'org-ref-find-bibliography "org-ref-core.el")
(declare-function 'org-ref-get-bibtex-key-and-file "org-ref-core.el")
(defvar org-ref-pdf-directory)
(defvar org-ref-notes-directory)
(defvar org-ref-cite-types)
(defvar org-ref-default-citation-link)
(defvar org-ref-insert-link-function)
(defvar org-ref-insert-cite-function)
(defvar org-ref-insert-label-function)
(defvar org-ref-insert-ref-function)
(defvar org-ref-cite-onclick-function)
(defvar org-ref-insert-cite-key)
;;; Code:
(require 'org-ref-helm)
(require 'org-ref-bibtex)
(defun org-ref-helm-cite-completion ()
"Use helm and org-ref for completion."
(interactive)
(setq org-ref-insert-link-function 'org-ref-insert-link
org-ref-insert-cite-function 'org-ref-helm-cite
org-ref-insert-label-function 'org-ref-helm-insert-label-link
org-ref-insert-ref-function 'org-ref-helm-insert-ref-link
org-ref-cite-onclick-function 'org-ref-helm-cite-click))
(org-ref-helm-cite-completion)
(define-key org-mode-map
(kbd org-ref-insert-cite-key)
org-ref-insert-link-function)
;;* Variables
(defvar org-ref-helm-cite-from nil
"Variable to store the mode `org-ref-helm-cite' was called
from. This is used to provide some context specific actions.")
(defvar org-ref-helm-cite-help-message
"* Org-ref helm bibtex.
M-<down> allows you to sort the entries by year or first author
last name.")
(defvar org-ref-helm-cite-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map helm-map)
(define-key map (kbd "M-<down>") 'org-ref-helm-cite-sort)
map))
(defvar orhc-sort-fn nil
"Function for sorting the helm entries.")
;;* Helm functions
(defun orhc-helm-cite-sort-alphabetical-a (c1 c2)
"Sort entries by first author last name from a to z."
(let* ((a1 (cdr c1))
(au1 (cdr (assoc "author" a1)))
(a2 (cdr c2))
(au2 (cdr (assoc "author" a2)))
fa1 fa2)
(if (or (not (stringp au1))
(not (stringp au2)))
nil
;; we need to parse names
(setq fa1 (car (s-split " and " au1))
fa2 (car (s-split " and " au2)))
(if (string-match "," fa1)
;; last, first
(setq fa1 (car (s-split "," fa1)))
;; first last, ignore von names and jr
(setq fa1 (car (last (s-split " " fa1)))))
(if (string-match "," fa2)
;; last, first
(setq fa2 (car (s-split "," fa2)))
;; first last, ignore von names, and jr
(setq fa2 (car (last (s-split " " fa2)))))
(string< fa1 fa2))))
(defun orhc-helm-cite-sort-alphabetical-z (c1 c2)
"Sort entries by first author last name from z to a."
(let* ((a1 (cdr c1))
(au1 (cdr (assoc "author" a1)))
(a2 (cdr c2))
(au2 (cdr (assoc "author" a2)))
fa1 fa2)
(if (or (not (stringp au1))
(not (stringp au2)))
nil
;; we need to parse names to get lastname
(setq fa1 (car (s-split " and " au1))
fa2 (car (s-split " and " au2)))
(if (string-match "," fa1)
;; last, first
(setq fa1 (car (s-split "," fa1)))
;; first last, ignore von names and jr
(setq fa1 (car (last (s-split " " fa1)))))
(if (string-match "," fa2)
;; last, first
(setq fa2 (car (s-split "," fa2)))
;; first last, ignore von names, and jr
(setq fa2 (car (last (s-split " " fa2)))))
(string< fa2 fa1))))
(defun org-ref-helm-cite-sort ()
"Sort interface for `org-ref-helm-cite'."
(interactive)
(let ((action (read-char "year↓ (y) year↑ (Y)
1st author↓ (a) 1st author↑ (z)
key↓ (k) key↑ (K): ")))
(cond
;; sort on year
((eq action ?y)
(setq orhc-sort-fn
(lambda (c1 c2)
(let* ((a1 (cdr c1))
(y1 (cdr (assoc "year" a1)))
(a2 (cdr c2))
(y2 (cdr (assoc "year" a2))))
(if (or (null y1) (null y2))
nil
(> (string-to-number y1) (string-to-number y2)))))))
((eq action ?Y)
(setq orhc-sort-fn
(lambda (c1 c2)
(let* ((a1 (cdr c1))
(y1 (cdr (assoc "year" a1)))
(a2 (cdr c2))
(y2 (cdr (assoc "year" a2))))
(if (or (null y1) (null y2))
nil
(< (string-to-number y1) (string-to-number y2)))))))
;; sort on key
((eq action ?k)
(setq orhc-sort-fn
(lambda (c1 c2)
(let* ((a1 (cdr c1))
(k1 (cdr (assoc "=key=" a1)))
(a2 (cdr c2))
(k2 (cdr (assoc "=key=" a2))))
(string< k2 k1)))))
((eq action ?K)
(setq orhc-sort-fn
(lambda (c1 c2)
(let* ((a1 (cdr c1))
(k1 (cdr (assoc "=key=" a1)))
(a2 (cdr c2))
(k2 (cdr (assoc "=key=" a2))))
(string< k1 k2)))))
;; sort on first author last name
((eq action ?a)
(setq orhc-sort-fn #'orhc-helm-cite-sort-alphabetical-a))
((eq action ?z)
(setq orhc-sort-fn #'orhc-helm-cite-sort-alphabetical-z))
(t (setq orhc-sort-fn nil)))
(helm-update)
(setq orhc-sort-fn nil)))
(defun org-ref-helm-candidate-transformer (candidates _source)
"Transform CANDIDATES, sorting if needed.
SOURCE is ignored, but required."
(if orhc-sort-fn
(-sort orhc-sort-fn candidates)
candidates))
(defun org-ref-helm-cite-action-transformer (actions candidate)
"Compute ACTIONS for CANDIDATE."
;; Check for pdf and add open or get action.
(setq actions (append
actions
'(("insert citation(s)" . org-ref-helm-cite-insert-citation)
("show entry" . org-ref-helm-cite-open-entry))))
(let ((pdf (expand-file-name
(concat (cdr (assoc "=key=" candidate)) ".pdf")
org-ref-pdf-directory)))
(if (file-exists-p pdf)
(setq actions (append actions
(list
(cons
(format "Open %s" pdf)
(lambda (_candidate)
(org-open-file pdf))))))
(when (assoc "doi" candidate)
(setq actions
(append actions
(list
(cons
(format "Get PDF")
(lambda (candidate)
(save-window-excursion
(find-file (cdr (assoc "file" candidate)))
(goto-char (cdr (assoc "position" candidate)))
(doi-utils-get-bibtex-entry-pdf))))))))))
;; check for url/doi
(when (assoc "url" candidate)
(setq actions (append actions
(list
(cons (format "Open %s"
(cdr (assoc "url" candidate)))
(lambda (x)
(browse-url (cdr (assoc "url" x)))))))))
(when (assoc "doi" candidate)
(setq actions (append actions
(list
(cons
(format "Open doi (%s)"
(cdr (assoc "doi" candidate)))
(lambda (x)
(browse-url
(format "http://dx.doi.org/%s"
(cdr (assoc "doi" x))))))))))
;; Notes, open or create.
(let ((note-file (expand-file-name
(concat (cdr (assoc "=key=" candidate)) ".org")
org-ref-notes-directory)))
(if (file-exists-p note-file)
(setq actions (append actions (list (cons "Open notes"
(lambda (_x)
(find-file note-file))))))
(setq actions (append actions (list (cons "Create notes"
(lambda (_x)
(find-file note-file))))))))
(setq actions (append
actions
'(("Add keywords" . org-ref-helm-cite-set-keywords)
("copy to clipboard" . org-ref-helm-cite-copy-entries)
("email" . org-ref-helm-cite-email-entries)
("Insert formatted entries" . (lambda (_)
(insert
(mapconcat 'identity
(cl-loop for key in (helm-marked-candidates)
collect (org-ref-format-entry key))
"\n\n"))))
("Copy formatted entry" . (lambda (_)
(kill-new
(mapconcat 'identity
(cl-loop for key in (helm-marked-candidates)
collect (org-ref-format-entry key))
"\n\n")))))))
;; this is where we could add WOK/scopus functions
actions)
(defun org-ref-helm-cite-insert-citation (_candidate)
"Insert selected CANDIDATE as cite link.
This is an action for helm, and it actually works on
`helm-marked-candidates'. Append KEYS if you are on a link.
In the `org-ref-helm-cite' buffer, \\[universal-argument] will give you
a helm menu to select a new link type for the selected entries.
A double \\[universal-argument] \\[universal-argument] will
change the key at point to the selected keys."
(let* ((keys (cl-loop for entry in (helm-marked-candidates)
collect (cdr (assoc "=key=" entry))))
(object (org-element-context))
(last-char (save-excursion
(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)
(-contains?
org-ref-cite-types
(org-element-property :type object)))
(cond
;; no prefix. insert or append keys
((equal helm-current-prefix-arg nil)
(cond
;; point after :
((looking-back ":" (- (point) 2))
(insert (concat (mapconcat 'identity keys ",") ",")))
;; point on :
((looking-at ":")
(forward-char)
(insert (concat (mapconcat 'identity keys ",") ",")))
;; point on the cite type
((-contains? org-ref-cite-types (thing-at-point 'word))
(re-search-forward ":")
(insert (concat (mapconcat 'identity keys ",") ",")))
;; after ,
((looking-back "," (- (point) 2))
(insert (concat (mapconcat 'identity keys ",") ",")))
;; on comma
((looking-at ",")
(forward-char)
(insert (concat (mapconcat 'identity keys ",") ",")))
;; somewhere in the middle or end
(t
;; goto next comma or end
(re-search-forward
","
(org-element-property :end object) t)
(skip-chars-backward " ")
(insert (mapconcat 'identity keys ","))
(unless (looking-at ",") (insert ",")))))
;; double prefix, replace key at point
((equal helm-current-prefix-arg '(16))
(setf (buffer-substring
(org-element-property :begin object)
(org-element-property :end object))
(concat
(replace-regexp-in-string
(car (org-ref-get-bibtex-key-and-file)) ; key
(mapconcat 'identity keys ",") ; new keys
(org-element-property :raw-link object))
;; replace space at end to avoid collapsing into next word.
last-char))
;; and we want to go to the end of the new link
(goto-char
(org-element-property :end (org-element-context))))
(t
(message "Not found"))))
;; 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
(unless (bobp) (backward-char))
(and (equal (org-element-type (org-element-context)) 'link)
(-contains?
org-ref-cite-types
(org-element-property :type (org-element-context)))))
(skip-chars-backward " ")
(insert (concat "," (mapconcat 'identity keys ","))))
;; insert fresh link
(t
;;(message-box "fresh link")
(insert
(concat (if (equal helm-current-prefix-arg '(4))
(helm :sources `((name . "link types")
(candidates . ,org-ref-cite-types)
(action . (lambda (x) x))))
org-ref-default-citation-link)
":"
(s-join "," keys)))))))
(defun org-ref-helm-cite-init ()
"Initializes the source, setting bibtex files from the
originating buffer, and mode of originating buffer."
(org-ref-save-all-bibtex-buffers)
(setq org-ref-bibtex-files (org-ref-find-bibliography))
;; save major-mode we came from so we can do context specific things.
(setq org-ref-helm-cite-from major-mode)
(message "initialized."))
(defun org-ref-helm-cite-open-entry (entry)
"Open the selected bibtex entry in its file."
(find-file (cdr (assoc "bibfile" entry)))
(goto-char (cdr (assoc "position" entry)))
(bibtex-beginning-of-entry))
(defun org-ref-helm-cite-copy-entries (_candidate)
"Copy selected bibtex entries to the clipboard."
(with-temp-buffer
(cl-loop for entry in (helm-marked-candidates)
do
(save-window-excursion
(org-ref-helm-cite-open-entry entry)
(bibtex-copy-entry-as-kill))
(bibtex-yank)
(insert "\n"))
(kill-region (point-min) (point-max))))
(defun org-ref-helm-cite-email-entries (_candidate)
"Insert selected entries and attach pdf files to an email.
Create email unless called from an email."
(unless (or (eq org-ref-helm-cite-from 'message-mode)
(eq org-ref-helm-cite-from 'mu4e-compose-mode))
(compose-mail))
(cl-loop for entry in (helm-marked-candidates)
do
(save-window-excursion
(org-ref-helm-cite-open-entry entry)
(bibtex-copy-entry-as-kill))
(message-goto-body)
(insert (pop bibtex-entry-kill-ring))
(insert "\n")
if (file-exists-p (expand-file-name
(concat (cdr (assoc "=key=" entry)) ".pdf")
org-ref-pdf-directory))
do
(mml-attach-file (expand-file-name
(concat (cdr (assoc "=key=" entry)) ".pdf")
org-ref-pdf-directory)))
(message-goto-to))
(defun org-ref-helm-cite-set-keywords (_candidate)
"Prompt for keywords, and put them on the selected entries."
(let ((keywords (read-string "Keyword(s) comma-separated: " ))
entry-keywords)
(cl-loop for entry in (helm-marked-candidates)
do
(save-window-excursion
(org-ref-helm-cite-open-entry entry)
(setq entry-keywords (bibtex-autokey-get-field "keywords"))
(bibtex-set-field
"keywords"
(if (> (length entry-keywords) 0)
(concat entry-keywords ", " keywords)
keywords))))))
;;** Helm sources
(defvar orhc-multiline t
"Make helm-source multiline if non-nil.
This adds a small separator between the candidates which is a
little more readable.")
(defvar org-ref-helm-user-candidates '()
"List of user-defined candidates to act when clicking on a cite link.
This is a list of cons cells '((\"description\" . action)). The
action function should not take an argument, and should assume
point is on the cite key of interest.")
(defvar org-ref-helm-cite-source
(helm-build-sync-source "org-ref Bibtex"
:init #'org-ref-helm-cite-init
:candidates #'orhc-bibtex-candidates
:keymap 'org-ref-helm-cite-map
:multiline orhc-multiline
:help-message 'org-ref-helm-cite-help-message
:filtered-candidate-transformer 'org-ref-helm-candidate-transformer
:action-transformer 'org-ref-helm-cite-action-transformer
:action '()))
;; Fallback sources
;; The candidates here are functions that work on `helm-pattern'.
(defvar org-ref-helm-cite-fallback-source
nil
"Helm fallback source.")
(setq org-ref-helm-cite-fallback-source
(helm-build-sync-source "org-ref bibtex Fallbacks"
:candidates '(("Google" . (lambda ()
(browse-url
(format "http://www.google.com/search?q=%s"
(url-hexify-string helm-pattern)))))
("Google Scholar" . (lambda ()
(browse-url
(format "http://scholar.google.com/scholar?q=%s"
(url-hexify-string helm-pattern)))))
("Crossref" . (lambda ()
(browse-url
(format
"http://search.crossref.org/?q=%s"
(url-hexify-string helm-pattern)))))
("Pubmed" . (lambda ()
(browse-url
(format
"http://www.ncbi.nlm.nih.gov/pubmed/?term=%s"
(url-hexify-string helm-pattern)))))
("Arxiv" . (lambda ()
(browse-url
(format
"http://arxiv.org/find/all/1/all:+AND+%s/0/1/0/all/0/1"
(url-hexify-string helm-pattern)))))
("WebOfKnowledge" . (lambda ()
(browse-url
(format
"http://gateway.webofknowledge.com/gateway/Gateway.cgi?topic=%s&GWVersion=2&SrcApp=WEB&SrcAuth=HSB&DestApp=UA&DestLinkType=GeneralSearchSummary"
(url-hexify-string helm-pattern)))))
("Scopus" . (lambda ()
(browse-url
(format
"http://www.scopus.com//search/submit/basic.url?field1=TITLE-ABS-KEY&searchterm1=%s"
(url-hexify-string helm-pattern)))))
)
;; This keeps all the fallback candidates available, by tricking it into
;; thinking every candidate is a match.
:match (lambda (_candidate) t)
:action (lambda (candidate) (funcall candidate))))
(defun org-ref-helm-cite ()
"Helm interface to bibtex files for `org-ref'."
(interactive)
(helm :sources '(org-ref-helm-cite-source
org-ref-helm-cite-fallback-source)))
(defalias 'orhc 'org-ref-helm-cite)
;; ** Onclick function
;; These are adapted from org-ref-helm-bibtex, and the dependencies on helm-bibtex removed.
(defun org-ref-helm-cite-candidates ()
"Generate the list of possible candidates for click actions on a cite link.
Checks for pdf and doi, and add appropriate functions."
(let* ((results (org-ref-get-bibtex-key-and-file))
(key (car results))
(bibfile (cdr results))
(pdf-file (funcall org-ref-get-pdf-filename-function key))
(url (save-excursion
(with-temp-buffer
(insert-file-contents bibfile)
(bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
(bibtex-search-entry key)
(bibtex-autokey-get-field "url"))))
(doi (save-excursion
(with-temp-buffer
(insert-file-contents bibfile)
(bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
(bibtex-search-entry key)
;; I like this better than bibtex-url which does not always find
;; the urls
(bibtex-autokey-get-field "doi"))))
(candidates `(("Quit" . org-ref-citation-at-point)
("Open bibtex entry" . org-ref-open-citation-at-point))))
;; for some reason, when there is no doi or url, they are returned as "". I
;; prefer nil so we correct this here.
(when (string= doi "") (setq doi nil))
(when (string= url "") (setq url nil))
;; Conditional pdf functions
;; try with org-ref first
(cond ((file-exists-p pdf-file)
(cl-pushnew
'("Open pdf" . (lambda ()
(funcall org-ref-open-pdf-function)))
candidates))
;; try with doi
(t
(cl-pushnew
'("Try to get pdf" . (lambda ()
(save-window-excursion
(org-ref-open-citation-at-point)
(bibtex-beginning-of-entry)
(doi-utils-get-bibtex-entry-pdf))))
candidates)))
(cl-pushnew
'("Add/Open notes" . org-ref-open-notes-at-point)
candidates)
;; conditional url and doi functions
(when (or url doi)
(cl-pushnew
'("Open in browser" . org-ref-open-url-at-point)
candidates))
(when doi
(mapc (lambda (x)
(cl-pushnew x candidates))
`(("WOS" . org-ref-wos-at-point)
("Related articles in WOS" . org-ref-wos-related-at-point)
("Citing articles in WOS" . org-ref-wos-citing-at-point)
("Google Scholar" . org-ref-google-scholar-at-point)
("Pubmed" . org-ref-pubmed-at-point)
("Crossref" . org-ref-crossref-at-point))))
(cl-pushnew
'("Insert new citation" . (lambda ()
(org-ref-helm-insert-cite-link nil)))
candidates)
(cl-pushnew
'("Delete key at point" . org-ref-delete-key-at-point)
candidates)
;; This is kind of clunky. We store the key at point. Add the new ref. Get
;; it off the end, and put it in the original position.
(cl-pushnew
'("Replace key at point" . org-ref-replace-key-at-point)
candidates)
(cl-pushnew
'("Delete citation at point" . org-ref-delete-cite-at-point)
candidates)
(cl-pushnew
'("Sort keys by year" . org-ref-sort-citation-link)
candidates)
(cl-pushnew
'("Copy formatted citation to clipboard" . org-ref-copy-entry-as-summary)
candidates)
(cl-pushnew
'("Copy key to clipboard" . (lambda ()
(kill-new
(car (org-ref-get-bibtex-key-and-file)))))
candidates)
(cl-pushnew
'("Copy bibtex entry to file" . org-ref-copy-entry-at-point-to-file)
candidates)
(cl-pushnew
'("Email bibtex entry and pdf" . (lambda ()
(save-excursion
(org-ref-open-citation-at-point)
(org-ref-email-bibtex-entry))))
candidates)
;; add Scopus functions. These work by looking up a DOI to get a Scopus
;; EID. This may only work for Scopus articles. Not all DOIs are recognized
;; in the Scopus API. We only load these if you have defined a
;; `*scopus-api-key*', which is required to do the API queries. See
;; `scopus'. These functions are appended to the candidate list.
(when (and (boundp '*scopus-api-key*) *scopus-api-key*)
(cl-pushnew
'("Open in Scopus" . (lambda ()
(let ((eid (scopus-doi-to-eid (org-ref-get-doi-at-point))))
(if eid
(scopus-open-eid eid)
(message "No EID found.")))))
candidates)
(cl-pushnew
'("Scopus citing articles" . (lambda ()
(let ((url (scopus-citing-url
(org-ref-get-doi-at-point))))
(if url
(browse-url url)
(message "No url found.")))))
candidates)
(cl-pushnew
'("Scopus related by authors" . (lambda ()
(let ((url (scopus-related-by-author-url
(org-ref-get-doi-at-point))))
(if url
(browse-url url)
(message "No url found.")))))
candidates)
(cl-pushnew
'("Scopus related by references" . (lambda ()
(let ((url (scopus-related-by-references-url
(org-ref-get-doi-at-point))))
(if url
(browse-url url)
(message "No url found.")))))
candidates)
(cl-pushnew
'("Scopus related by keywords" . (lambda ()
(let ((url (scopus-related-by-keyword-url
(org-ref-get-doi-at-point))))
(if url
(browse-url url)
(message "No url found.")))))
candidates))
;; finally return a numbered list of the candidates
(cl-loop for i from 0
for cell in (reverse candidates)
collect (cons (format "%2s. %s" i (car cell))
(cdr cell)))))
(defun org-ref-helm-cite-click (_key)
"Open helm for actions on a cite link.
subtle points.
1. get name and candidates before entering helm because we need
the org-buffer.
2. switch back to the org buffer before evaluating the
action. most of them need the point and buffer.
KEY is returned for the selected item(s) in helm."
(interactive)
(let ((name (org-ref-format-entry (org-ref-get-bibtex-key-under-cursor)))
(candidates (org-ref-helm-cite-candidates))
(cb (current-buffer)))
(helm :sources `(((name . ,name)
(candidates . ,candidates)
(action . (lambda (f)
(switch-to-buffer ,cb)
(funcall f))))
((name . "User functions")
(candidates . ,org-ref-helm-user-candidates)
(action . (lambda (f)
(switch-to-buffer ,cb)
(funcall f))))))))
;;* Formatted citations
(defun orhc-formatted-citations (_candidate)
"Return string containing formatted citations for entries in
`helm-marked-candidates'."
(load-library
(completing-read "Style: " '("unsrt" "author-year") nil nil "unsrt"))
(with-temp-buffer
(cl-loop for i from 1 to (length (helm-marked-candidates))
for entry in (helm-marked-candidates)
do
(insert (format "%s. %s\n\n" i (orhc-formatted-citation entry))))
(buffer-string)))
(defun orhc-insert-formatted-citations (candidate)
"Insert formatted citations at point for selected entries."
(insert (orhc-formatted-citations candidate)))
(defun orhc-copy-formatted-citations (candidate)
"Copy formatted citations to clipboard for selected entries."
(with-temp-buffer
(orhc-insert-formatted-citations candidate)
(kill-ring-save (point-min) (point-max))))
(provide 'org-ref-helm-cite)
;;; org-ref-helm-cite.el ends here

View File

@@ -0,0 +1,474 @@
;;; org-ref-helm.el --- Generic helm functions for org-ref -*- lexical-binding: t; -*-
;; Copyright (C) 2016 John Kitchin
;; Author: John Kitchin <jkitchin@andrew.cmu.edu>
;; Keywords:
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;; These are not specific to helm-bibtex.
;;; Code:
(declare-function 'org-ref-get-bibtex-key-and-file "org-ref-core.el")
(declare-function 'org-ref-bad-file-link-candidates "org-ref-core.el")
(declare-function 'org-ref-get-labels "org-ref-core.el")
(declare-function 'org-ref-bad-cite-candidates "org-ref-core.el")
(declare-function 'org-ref-bad-ref-candidates "org-ref-core.el")
(declare-function 'org-ref-bad-label-candidates "org-ref-core.el")
(require 'helm)
(require 'org-element)
(require 'org-ref-core)
;;;###autoload
(defun org-ref-helm-insert-label-link ()
"Insert label link at point.
Helm will display existing labels in the current buffer to avoid
duplication. If you use a prefix arg insert a radio target
instead of a label."
(interactive)
(let ((labels (org-ref-get-labels)))
(helm :sources `(,(helm-build-sync-source "Existing labels"
:candidates labels
:action (lambda (label)
(with-helm-current-buffer
(org-open-link-from-string
(format "ref:%s" label)))))
,(helm-build-dummy-source "Create new label"
:action (lambda (label)
(with-helm-current-buffer
(if helm-current-prefix-arg
(insert (concat "<<" label ">>"))
(insert (concat "label:" label)))))))
:buffer "*helm labels*")))
;;;###autoload
(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. Use
\\[universal-argument] to insert a different kind of ref link.
Use a double \\[universal-argument] \\[universal-argument] to insert a
[[#custom-id]] link"
(interactive)
(let* ((labels (org-ref-get-labels))
(contexts (mapcar 'org-ref-get-label-context labels))
(cb (current-buffer)))
(helm :input (thing-at-point 'word)
:sources `(((name . "Available labels to ref")
(multiline)
(candidates . ,(cl-loop for label in labels
for context in contexts
;; we do some kludgy adding spaces
;; and bars to make it "easier" to
;; see in helm.
collect (cons (concat
label "\n"
(mapconcat
(lambda (x)
(concat " |" x))
(split-string context "\n")
"\n"
) "\n\n") label)))
;; default action to replace or insert ref link.
(action . (lambda (label)
(switch-to-buffer ,cb)
(cond
;; no prefix or on a link
((equal helm-current-prefix-arg nil)
(let* ((object (org-element-context))
(last-char
(save-excursion
(goto-char (org-element-property :end object))
(backward-char)
(if (looking-at " ")
" "
""))))
(if (-contains? org-ref-ref-types
(org-element-property :type object))
;; we are on a link, so replace it.
(setf
(buffer-substring
(org-element-property :begin object)
(org-element-property :end object))
(concat
(replace-regexp-in-string
(org-element-property :path object)
label
(org-element-property :raw-link object))
last-char))
;; insert a new link
(insert
(concat
org-ref-default-ref-type ":" label))
)))
;; one prefix, alternate ref link
((equal helm-current-prefix-arg '(4))
(insert
(concat
(helm :sources `((name . "Ref link types")
(candidates . ,org-ref-ref-types)
(action . (lambda (x) x))))
":" label)))
;; two prefixes, insert section custom-id link
((equal helm-current-prefix-arg '(16))
(insert
(format "[[#%s]]" label)))))))))))
;;;###autoload
(defun org-ref ()
"Opens a helm interface to actions for `org-ref'.
Shows bad citations, ref links and labels.
This widens the file so that all links go to the right place."
(interactive)
;; (widen)
;; (org-cycle '(64))
(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-files (org-ref-bad-file-link-candidates))
(bib-candidates '())
(unreferenced-labels '())
natbib-required
natbib-used
cleveref-required
cleveref-used
biblatex-required
biblatex-used
(org-latex-prefer-user-labels (and (boundp 'org-latex-prefer-user-labels)
org-latex-prefer-user-labels)))
;; See if natbib, biblatex or cleveref are required
(org-element-map (org-element-parse-buffer) 'link
(lambda (link)
(when (member (org-element-property :type link) org-ref-natbib-types)
(setq natbib-required t))
(when (member (org-element-property :type link) org-ref-biblatex-types)
(setq biblatex-required t))
(when (member (org-element-property :type link) '("cref" "Cref"))
(setq cleveref-required t)))
nil t)
;; See if natbib is probably used. This will miss a case where natbib is included somehow.
(setq natbib-used
(or
(member "natbib" (mapcar (lambda (x) (when (listp x) (nth 1 x))) org-latex-default-packages-alist))
(member "natbib" (mapcar (lambda (x) (when (listp x) (nth 1 x))) org-latex-packages-alist))
;; see of something like \usepackage{natbib} exists.
(save-excursion
(goto-char (point-min))
(re-search-forward "{natbib}" nil t))))
(setq biblatex-used
(or
(member "biblatex" (mapcar (lambda (x) (when (listp x) (nth 1 x))) org-latex-default-packages-alist))
(member "biblatex" (mapcar (lambda (x) (when (listp x) (nth 1 x))) org-latex-packages-alist))
;; see of something like \usepackage{biblatex} exists.
(save-excursion
(goto-char (point-min))
(re-search-forward "{biblatex}" nil t))))
(setq cleveref-used
(or
(member "cleveref" (mapcar (lambda (x) (when (listp x) (nth 1 x))) org-latex-default-packages-alist))
(member "cleveref" (mapcar (lambda (x) (when (listp x) (nth 1 x))) org-latex-packages-alist))
;; see of something like \usepackage{cleveref} exists.
(save-excursion
(goto-char (point-min))
(re-search-forward "{cleveref}" nil t))))
;; setup bib-candidates. This checks a variety of things in the
;; bibliography, bibtex files. check for which bibliographies are used
(cl-pushnew
(cons (format "Using these bibtex files: %s"
(org-ref-find-bibliography))
(lambda () nil))
bib-candidates)
;; Check bibliography style exists
(save-excursion
(goto-char 0)
(unless (re-search-forward "bibliographystyle:\\|\\\\bibliographystyle{" nil t)
(cl-pushnew
(cons "No bibliographystyle found."
(lambda ()
(switch-to-buffer "*org-ref*")
(erase-buffer)
(insert "No bibliography style found. This may be ok, if your latex class style sets that up, but if not this is an error. Try adding something like:
bibliographystyle:unsrt
at the end of you file.
")
(org-mode)))
bib-candidates)))
;; Check if latex knows of the bibliographystyle. We only check links here.
;; I also assume this style exists as a bst file that kpsewhich can find.
(save-excursion
(goto-char 0)
(when (re-search-forward "bibliographystyle:" nil t)
;; on a link. get style
(let ((path (org-element-property :path (org-element-context))))
(unless (= 0 (shell-command (format "kpsewhich %s.bst" path)))
(cl-pushnew
(cons (format "bibliographystyle \"%s\" may be unknown" path)
(lambda ()
(goto-char 0)
(re-search-forward "bibliographystyle:")))
bib-candidates)))))
;; check for multiple bibliography links
(let* ((bib-links (-filter
(lambda (el)
(string= (org-element-property :type el) "bibliography"))
(org-element-map (org-element-parse-buffer) 'link 'identity)))
(n-bib-links (length bib-links)))
(when (> n-bib-links 1)
(mapc (lambda (link)
(setq
bib-candidates
(append
bib-candidates
(list (cons (format "Multiple bibliography link: %s"
(org-element-property :raw-link link))
`(lambda ()
(goto-char ,(org-element-property :begin link))))))))
bib-links)))
;; Check for bibliography files existence.
(mapc (lambda (bibfile)
(unless (file-exists-p bibfile)
(cl-pushnew
(cons
(format "%s does not exist." bibfile)
(lambda ()
(message "Non-existent bibfile.")))
bib-candidates)))
(org-ref-find-bibliography))
;; check for spaces in bibliography
(let ((bibfiles (mapcar 'expand-file-name
(org-ref-find-bibliography))))
(mapc (lambda (bibfile)
(when (string-match " " bibfile)
(cl-pushnew
(cons (format "One or more spaces found in path to %s" bibfile)
(lambda ()
(message "No spaces are allowed in bibtex file paths. We recommend replacing them with -. Underscores usually cause other problems if you don't know what you are doing.")))
bib-candidates)))
bibfiles))
;; validate bibtex files
(let ((bibfiles (mapcar 'expand-file-name
(org-ref-find-bibliography))))
(mapc
(lambda (bibfile)
(unless (with-current-buffer
(find-file-noselect bibfile)
(bibtex-validate))
(cl-pushnew
(cons
(format "Invalid bibtex file found. %S" bibfile)
`(lambda ()
(find-file ,bibfile)))
bib-candidates)))
bibfiles))
;; unreferenced labels
(save-excursion
(save-restriction
(widen)
(goto-char (point-min))
(let ((matches '()))
;; these are the org-ref label:stuff kinds
(while (re-search-forward
"[^#+]label:\\([a-zA-z0-9:-]*\\)" nil t)
(cl-pushnew (cons
(match-string-no-properties 1)
(point))
matches))
;; now add all the other kinds of labels.
;; #+label:
(save-excursion
(goto-char (point-min))
(while (re-search-forward "^#\\+label:\\s-+\\(.*\\)\\b" nil t)
;; do not do this for tables. We get those in `org-ref-get-tblnames'.
;; who would have thought you have save match data here? Trust me. When
;; I wrote this, you did.
(unless (save-match-data (equal (car (org-element-at-point)) 'table))
(cl-pushnew (cons (match-string-no-properties 1) (point)) matches))))
;; \label{}
(save-excursion
(goto-char (point-min))
(while (re-search-forward "\\\\label{\\([a-zA-z0-9:-]*\\)}"
nil t)
(cl-pushnew (cons (match-string-no-properties 1) (point)) matches)))
;; #+tblname: and actually #+label
(cl-loop for cell in (org-element-map (org-element-parse-buffer 'element) 'table
(lambda (table)
(cons (org-element-property :name table)
(org-element-property :begin table))))
do
(cl-pushnew cell matches))
;; CUSTOM_IDs
(org-map-entries
(lambda ()
(let ((custom_id (org-entry-get (point) "CUSTOM_ID")))
(when (not (null custom_id))
(cl-pushnew (cons custom_id (point)) matches)))))
(goto-char (point-min))
(while (re-search-forward "^#\\+name:\\s-+\\(.*\\)" nil t)
(cl-pushnew (cons (match-string 1) (point)) matches))
;; unreference labels
(let ((refs (org-element-map (org-element-parse-buffer) 'link
(lambda (el)
(when (or (string= "ref" (org-element-property :type el))
(string= "eqref" (org-element-property :type el))
(string= "pageref" (org-element-property :type el))
(string= "nameref" (org-element-property :type el))
(string= "autoref" (org-element-property :type el))
(string= "cref" (org-element-property :type el))
(string= "Cref" (org-element-property :type el)))
(org-element-property :path el))))))
(cl-loop for (label . p) in matches
do
(when (not (-contains? refs label))
(cl-pushnew
(cons label (set-marker (make-marker) p))
unreferenced-labels)))))))
(helm :sources `(((name . "Bad citations")
(candidates . ,bad-citations)
(action . (lambda (marker)
(switch-to-buffer (marker-buffer marker))
(goto-char marker)
(org-show-entry))))
((name . "Multiply defined labels")
(candidates . ,bad-labels)
(action . (lambda (marker)
(switch-to-buffer (marker-buffer marker))
(goto-char marker)
(org-show-entry))))
((name . "Bad ref links")
(candidates . ,bad-refs)
(action . (lambda (marker)
(switch-to-buffer (marker-buffer marker))
(goto-char marker)
(org-show-entry))))
((name . "Bad file links")
(candidates . ,bad-files)
(lambda (marker)
(switch-to-buffer (marker-buffer marker))
(goto-char marker)
(org-show-entry)))
((name . "Labels with no ref links")
(candidates . ,unreferenced-labels)
(action . (lambda (marker)
(switch-to-buffer (marker-buffer marker))
(goto-char marker)
(org-show-entry))))
((name . "Bibliography")
(candidates . ,bib-candidates)
(action . (lambda (x)
(switch-to-buffer ,cb)
(funcall x))))
((name . "Miscellaneous")
(candidates . (,(format "org-latex-prefer-user-labels = %s"
org-latex-prefer-user-labels)
,(format "bibtex-dialect = %s" bibtex-dialect)
,(format "biblatex is%srequired." (if biblatex-required " " " not "))
,(format "biblatex is%sused." (if biblatex-used " " " not "))
,(format "org-version = %s" (org-version))
,(format "completion backend = %s" org-ref-completion-library)
,(format "org-latex-pdf-process is defined as %s" org-latex-pdf-process)
,(format "natbib is%srequired." (if natbib-required " " " not "))
,(format "natbib is%sused." (if natbib-used " " " not "))
,(format "cleveref is%srequired." (if cleveref-required " " " not "))
,(format "cleveref is%sused." (if cleveref-used " " " not "))))
(action . nil))
((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" . helm-org-in-buffer-headings)))
(action . (lambda (x)
(switch-to-buffer ,cb)
(funcall x))))
((name . "Document utilities")
(candidates . (("Spell check document" . ispell)))
(action . (lambda (x)
(switch-to-buffer ,cb)
(funcall x))))
;; Exports
((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))))))))
;;;###autoload
(defun helm-tag-bibtex-entry ()
"Helm interface to add keywords to a bibtex entry.
Run this with the point in a bibtex entry."
(interactive)
(let ((keyword-source `((name . "Existing keywords")
(candidates . ,(org-ref-bibtex-keywords))
(action . (lambda (candidate)
(org-ref-set-bibtex-keywords
(mapconcat
'identity
(helm-marked-candidates)
", "))))))
(fallback-source `((name . "Add new keywords")
(dummy)
(action . (lambda (candidate)
(org-ref-set-bibtex-keywords helm-pattern))))))
(helm :sources `(,keyword-source ,fallback-source))))
(provide 'org-ref-helm)
;;; org-ref-helm.el ends here

View File

@@ -0,0 +1,206 @@
;;; org-ref-isbn.el --- utilities for generating bibtex entries from an ISBN -*- lexical-binding: t; -*-
;; Copyright (C) 2015 John Kitchin
;; Author: John Kitchin <jkitchin@andrew.cmu.edu>
;; Keywords: convenience
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;; Provides functions to download bibtex entries from isbn numbers.
;;; Code:
(require 'f)
(require 'org)
(require 'org-ref-core)
(defvar url-http-end-of-headers)
;;* ISBN utility
(defcustom org-ref-isbn-clean-bibtex-entry-hook
'(oricb-remove-enclosing-brackets
oricb-clean-author-field
oricb-remove-period
oricb-kill-fields
oricb-replace-field-names)
"Hook that is run in `org-ref-isbn-clean-bibtex-entry'.
The functions should have no arguments, and operate on the bibtex
entry at point. You can assume point starts at the beginning of the
entry. These functions are wrapped in `save-restriction' and
`save-excursion' so you do not need to save the point position."
:group 'org-ref-isbn
:type 'hook)
(defcustom org-ref-isbn-exclude-fields nil
"List of bibtex fields to kill when new entry is inserted."
:group 'org-ref-isbn
:type '(repeat :tag "List of bibtex fields to kill" string))
(defcustom org-ref-isbn-field-name-replacements nil
"List of bitex field name/replacement pairs.
The entries in this list are cons cells where the car is the field name
and cdr is the replacement name."
:group 'org-ref-isbn
:type '(repeat (cons (string :tag "Field name")
(string :tag "Field name replacement"))))
(defun oricb-replace-field-names ()
"Replace bibtex field names defined in
`org-ref-isbn-field-name-replacements'."
(when org-ref-isbn-field-name-replacements
(mapcar (lambda (field)
(bibtex-beginning-of-entry)
(let ((f (bibtex-autokey-get-field (car field))))
(unless (string= "" f)
(goto-char (cadr (bibtex-search-forward-field (car field) t)))
(bibtex-kill-field)
(bibtex-make-field (cdr field))
(backward-char)
(insert f))))
org-ref-isbn-field-name-replacements)))
(defun oricb-kill-fields ()
"Kill all bibtex fields defined in `org-ref-isbn-exclude-fields'."
(when org-ref-isbn-exclude-fields
(mapcar (lambda (field)
(bibtex-beginning-of-entry)
(let ((f (bibtex-autokey-get-field field)))
(unless (string= "" f)
(goto-char (cadr (bibtex-search-forward-field field t)))
(bibtex-kill-field))))
org-ref-isbn-exclude-fields)))
(defun oricb-remove-enclosing-brackets ()
"Remove enclosing brackets from fields."
(save-restriction
(bibtex-narrow-to-entry)
(while (re-search-forward "\\({\\)\\(\\[\\)\\(.+\\)\\(]\\)\\(}\\)" nil t)
(replace-match "\\1\\3\\5"))))
(defun oricb-clean-author-field ()
"Remove extra information from author's field."
(goto-char (cadr (bibtex-search-forward-field "author" t)))
(let ((case-fold-search nil))
(when (re-search-forward "\\({\\)\\(by \\|ed. by \\|edited by \\)" nil t)
(replace-match "\\1"))))
(defun oricb-remove-period ()
"Remove period from author's field."
(goto-char (cadr (bibtex-search-forward-field "author" t)))
(when (re-search-forward "\\(\\.\\)\\(}\\)" nil t)
(replace-match "\\2")))
;;;###autoload
(defun org-ref-isbn-clean-bibtex-entry ()
"Clean a bibtex entry inserted via `isbn-to-bibtex'.
See functions in `org-ref-isbn-clean-bibtex-entry-hook'."
(interactive)
(bibtex-beginning-of-entry)
(mapc (lambda (x)
(save-restriction
(save-excursion
(funcall x))))
org-ref-isbn-clean-bibtex-entry-hook))
;; I found this on the web. It can be handy, but the bibtex entry has a lot of stuff in it.
;;;###autoload
(defun isbn-to-bibtex-lead (isbn)
"Search lead.to for ISBN bibtex entry.
You have to copy the entry if it is on the page to your bibtex
file."
(interactive "sISBN: ")
(browse-url
(format
"http://lead.to/amazon/en/?key=%s+&si=all&op=bt&bn=&so=sa&ht=us"
isbn)))
;; Here we get isbn metadata and build a bibtex entry.
;; http://xisbn.worldcat.org/xisbnadmin/doc/api.htm#getmetadata
;;;###autoload
(defun isbn-to-bibtex (isbn bibfile)
"Get bibtex entry for ISBN and insert it into BIBFILE.
Nothing happens if an entry with the generated key already exists
in the file. Data comes from worldcat."
(interactive
(list
(read-string
"ISBN: "
;; now set initial input
(cond
;; If region is active and it starts with a number, we use it
((and (region-active-p)
(s-match "^[0-9]" (buffer-substring (region-beginning) (region-end))))
(buffer-substring (region-beginning) (region-end)))
;; if first entry in kill ring starts with a number assume it is an isbn
;; and use it as the guess
((stringp (car kill-ring))
(when (s-match "^[0-9]" (car kill-ring))
(car kill-ring)))
;; type or paste it in
(t
nil)))
(completing-read
"Bibfile: "
(append (f-entries "." (lambda (f) (f-ext? f "bib")))
;; Convert relative path to absolute path
(list (file-truename (car org-ref-default-bibliography)))))))
(let* ((results (with-current-buffer
(url-retrieve-synchronously
(format
"http://xisbn.worldcat.org/webservices/xid/isbn/%s?method=getMetadata&format=json&fl=*"
isbn))
(json-read-from-string
(buffer-substring url-http-end-of-headers (point-max)))))
(status (cdr (assoc 'stat results)))
(metadata)
(new-entry))
;; check if we got something
(unless (string= "ok" status)
(error "Status is %s" status))
(setq metadata (aref (cdr (assoc 'list results)) 0))
;; construct an alphabetically sorted bibtex entry. I assume ISBN numbers go
;; with book entries.
(setq new-entry
(concat "\n@book{,\n"
(mapconcat
'identity
(cl-loop for field in (-sort 'string-lessp (mapcar 'car metadata))
collect
(format " %s={%s}," field (cdr (assoc field metadata))))
"\n")
"\n}\n"))
;; build entry in temp buffer to get the key so we can check for duplicates
(setq new-entry (with-temp-buffer
(insert (decode-coding-string new-entry 'utf-8))
(s-trim (buffer-string))))
(find-file bibfile)
(goto-char (point-max))
(insert new-entry)
(org-ref-isbn-clean-bibtex-entry)
(org-ref-clean-bibtex-entry)
(bibtex-fill-entry)
(save-buffer)))
(provide 'org-ref-isbn)
;;; org-ref-isbn.el ends here

View File

@@ -0,0 +1,533 @@
;;; org-ref-ivy-cite.el --- Use ivy for completion in org-ref -*- lexical-binding: t; -*-
;; Copyright (C) 2016 John Kitchin
;; Author: John Kitchin <jkitchin@andrew.cmu.edu>
;; Keywords:
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;;
(declare-function 'org-ref-insert-key-at-point "org-ref-core.el")
(declare-function 'org-ref-find-bibliography "org-ref-core.el")
(declare-function 'org-ref-get-labels "org-ref-core.el")
(declare-function 'org-ref-get-bibtex-key-and-file "org-ref-core.el")
;;; Code:
(require 'ivy)
(require 'org-ref-bibtex)
(require 'org-ref-citeproc)
(require 'bibtex-completion)
(defvar org-ref-cite-types)
(defvar org-ref-show-citation-on-enter)
(defvar org-ref-ivy-cite-marked-candidates '()
"Holds entries marked in `org-ref-ivy-insert-cite-link'.")
;;;###autoload
(defun org-ref-ivy-cite-completion ()
"Use ivy for completion."
(interactive)
;; Define core functions for org-ref
(setq org-ref-insert-link-function 'org-ref-insert-link
org-ref-insert-cite-function 'org-ref-ivy-insert-cite-link
org-ref-insert-label-function 'org-ref-ivy-insert-label-link
org-ref-insert-ref-function 'org-ref-ivy-insert-ref-link
org-ref-cite-onclick-function (lambda (_) (org-ref-cite-hydra/body))))
(org-ref-ivy-cite-completion)
(define-key org-mode-map
(kbd org-ref-insert-cite-key)
org-ref-insert-link-function)
(defun or-looking-forward-cite ()
"Return if point is in the position before a citation."
(save-excursion
(forward-char)
(-contains? org-ref-cite-types
(org-element-property
:type
(org-element-context)))))
(defun or-looking-back-cite ()
"Return if point is in the position after a citation."
(save-excursion
(forward-char -1)
(-contains? org-ref-cite-types
(org-element-property
:type
(org-element-context)))))
(defun or-ivy-bibtex-insert-cite (entry)
"Insert a citation for ENTRY.
If `org-ref-ivy-cite-marked-candidates' is non-nil then they are added instead of ENTRY.
ENTRY is selected from `orhc-bibtex-candidates'."
(with-ivy-window
(if org-ref-ivy-cite-marked-candidates
(cl-loop for entry in org-ref-ivy-cite-marked-candidates
do
(if ivy-current-prefix-arg
(let ((org-ref-default-citation-link (ivy-read "Type: " org-ref-cite-types)))
(org-ref-insert-key-at-point (list (cdr (assoc "=key=" entry)))))
(org-ref-insert-key-at-point (list (cdr (assoc "=key=" entry))))))
(if ivy-current-prefix-arg
(let ((org-ref-default-citation-link (ivy-read "Type: " org-ref-cite-types)))
(org-ref-insert-key-at-point (list (cdr (assoc "=key=" entry)))))
(org-ref-insert-key-at-point (list (cdr (assoc "=key=" entry))))))))
(defun or-ivy-bibtex-open-pdf (entry)
"Open the pdf associated with ENTRY.
ENTRY is selected from `orhc-bibtex-candidates'."
(with-ivy-window
(let ((pdf (expand-file-name
(format "%s.pdf"
(cdr (assoc "=key=" entry)))
org-ref-pdf-directory)))
(if (file-exists-p pdf)
(org-open-file pdf)
(message "No pdf found for %s" (cdr (assoc "=key=" entry)))))))
(defun or-ivy-bibtex-open-notes (entry)
"Open the notes associated with ENTRY.
ENTRY is selected from `orhc-bibtex-candidates'."
(with-ivy-window
(find-file (expand-file-name
(format "%s.org"
(cdr (assoc "=key=" entry)))
org-ref-notes-directory))))
(defun or-ivy-bibtex-open-entry (entry)
"Open the bibtex file at ENTRY.
ENTRY is selected from `orhc-bibtex-candidates'."
(find-file (cdr (assoc "bibfile" entry)))
(goto-char (cdr (assoc "position" entry)))
(bibtex-beginning-of-entry))
(defun or-ivy-bibtex-copy-entry (entry)
"Copy selected bibtex ENTRY to the clipboard."
(with-temp-buffer
(save-window-excursion
(or-ivy-bibtex-open-entry entry)
(bibtex-copy-entry-as-kill))
(bibtex-yank)
(kill-region (point-min) (point-max))))
(defun or-ivy-bibtex-open-url (entry)
"Open the URL associated with ENTRY.
ENTRY is selected from `orhc-bibtex-candidates'."
(let ((url (cdr (assoc "url" entry))))
(if url
(browse-url url)
(message "No url found for %s" (cdr (assoc "=key=" entry))))))
(defun or-ivy-bibtex-open-doi (entry)
"Open the DOI associated with ENTRY.
ENTRY is selected from `orhc-bibtex-candidates'."
(let ((doi (cdr (assoc "doi" entry))))
(if doi
(browse-url (format "http://dx.doi.org/%s" doi))
(message "No doi found for %s" (cdr (assoc "=key=" entry))))))
(defun or-ivy-bibtex-set-keywords (entry)
"Prompt for keywords, and put them on the selected ENTRY."
(let ((keywords (read-string "Keyword(s) comma-separated: " ))
entry-keywords)
(save-window-excursion
(or-ivy-bibtex-open-entry entry)
(setq entry-keywords (bibtex-autokey-get-field "keywords"))
(bibtex-set-field
"keywords"
(if (> (length entry-keywords) 0)
(concat entry-keywords ", " keywords)
keywords)))))
(defun or-ivy-bibtex-email-entry (entry)
"Insert selected ENTRY and attach pdf file to an email.
Create email unless called from an email."
(with-ivy-window
(let ((goto-to nil))
(unless (memq major-mode '(message-mode mu4e-compose-mode))
(setq goto-to t)
(compose-mail)
(message-goto-body))
(save-window-excursion
(or-ivy-bibtex-open-entry entry)
(bibtex-copy-entry-as-kill))
(insert (pop bibtex-entry-kill-ring))
(insert "\n")
(let ((pdf (expand-file-name
(format "%s.pdf"
(cdr (assoc "=key=" entry)))
org-ref-pdf-directory)))
(if (file-exists-p pdf)
(mml-attach-file pdf)))
(when goto-to
(message-goto-to)))))
(defun or-ivy-bibtex-formatted-citation (entry)
"Return string containing formatted citations for ENTRY.
This uses a citeproc library."
(let ((enable-recursive-minibuffers t))
(ivy-read "Style: " '("unsrt" "author-year")
:action 'load-library
:require-match t
:preselect "unsrt"
:caller 'or-ivy-formatted-citation)
(format "%s\n\n" (orhc-formatted-citation entry))))
(defun or-ivy-bibtex-insert-formatted-citation (_)
"Insert formatted citations at point for selected entries."
(with-ivy-window
(insert (mapconcat
'identity
(cl-loop for entry in org-ref-ivy-cite-marked-candidates
collect (org-ref-format-bibtex-entry entry))
"\n\n"))))
(defun or-ivy-bibtex-copy-formatted-citation (entry)
"Copy formatted citation to clipboard for ENTRY."
(kill-new (org-ref-format-entry entry)))
(defun or-ivy-bibtex-add-entry (_)
"Open a bibliography file and move point to the end, in order
to add a new bibtex entry. The arg is selected from
`orhc-bibtex-candidates' but ignored."
(ivy-read "bibtex file: " org-ref-bibtex-files
:require-match t
:action 'find-file
:caller 'or-ivy-bibtex-add-entry)
(widen)
(goto-char (point-max))
(unless (bolp)
(insert "\n")))
(defvar org-ref-ivy-cite-actions
'(("b" or-ivy-bibtex-open-entry "Open bibtex entry")
("B" or-ivy-bibtex-copy-entry "Copy bibtex entry")
("p" or-ivy-bibtex-open-pdf "Open pdf")
("n" or-ivy-bibtex-open-notes "Open notes")
("u" or-ivy-bibtex-open-url "Open url")
("d" or-ivy-bibtex-open-doi "Open doi")
("k" or-ivy-bibtex-set-keywords "Add keywords")
("e" or-ivy-bibtex-email-entry "Email entry")
("f" or-ivy-bibtex-insert-formatted-citation "Insert formatted citation")
("F" or-ivy-bibtex-copy-formatted-citation "Copy formatted citation")
("a" or-ivy-bibtex-add-entry "Add bibtex entry"))
"List of additional actions for `org-ref-ivy-insert-cite-link' (the default action being to insert a citation).")
(defvar org-ref-ivy-cite-re-builder 'ivy--regex-ignore-order
"Regex builder to use in `org-ref-ivy-insert-cite-link'. Can be set to nil to use Ivy's default).")
(defun org-ref-swap (i j lst)
"Swap index I and J in the list LST."
(let ((tempi (nth i lst)))
(setf (nth i lst) (nth j lst))
(setf (nth j lst) tempi))
lst)
(defun org-ref-ivy-current ()
(if (boundp 'ivy--current)
ivy--current
(ivy-state-current ivy-last)))
(defun org-ref-ivy-move-up ()
"Move ivy candidate up and update candidates."
(interactive)
(setf (ivy-state-collection ivy-last)
(org-ref-swap ivy--index (1- ivy--index) (ivy-state-collection ivy-last)))
(setf (ivy-state-preselect ivy-last) (org-ref-ivy-current))
(ivy--reset-state ivy-last))
(defun org-ref-ivy-move-down ()
"Move ivy candidate down."
(interactive)
(setf (ivy-state-collection ivy-last)
(org-ref-swap ivy--index (1+ ivy--index) (ivy-state-collection ivy-last)))
(setf (ivy-state-preselect ivy-last) (org-ref-ivy-current))
(ivy--reset-state ivy-last))
(defun org-ref-ivy-sort-year-ascending ()
"Sort entries by year in ascending order."
(interactive)
(setf (ivy-state-collection ivy-last)
(cl-sort (copy-sequence (ivy-state-collection ivy-last))
(lambda (a b)
(let ((y1 (string-to-number (or (cdr (assoc "year" a)) "0")))
(y2 (string-to-number (or (cdr (assoc "year" b)) "0"))))
(< y1 y2)))))
(setf (ivy-state-preselect ivy-last) (org-ref-ivy-current))
(ivy--reset-state ivy-last))
(defun org-ref-ivy-sort-year-descending ()
"sort entries by year in descending order."
(interactive)
(setf (ivy-state-collection ivy-last)
(cl-sort (copy-sequence (ivy-state-collection ivy-last))
(lambda (a b)
(let ((y1 (string-to-number (or (cdr (assoc "year" a)) "0")))
(y2 (string-to-number (or (cdr (assoc "year" b)) "0"))))
(> y1 y2)))))
(setf (ivy-state-preselect ivy-last) (org-ref-ivy-current))
(ivy--reset-state ivy-last))
;; * marking candidates
(defun org-ref-ivy-mark-candidate ()
"Add current candidate to `org-ref-ivy-cite-marked-candidates'.
If candidate is already in, remove it."
(interactive)
(let ((cand (or (assoc (org-ref-ivy-current) (ivy-state-collection ivy-last))
(org-ref-ivy-current))))
(if (-contains? org-ref-ivy-cite-marked-candidates cand)
;; remove it from the marked list
(setq org-ref-ivy-cite-marked-candidates
(-remove-item cand org-ref-ivy-cite-marked-candidates))
;; add to list
(setq org-ref-ivy-cite-marked-candidates
(append org-ref-ivy-cite-marked-candidates (list cand)))))
(ivy-next-line))
(defun org-ref-ivy-show-marked-candidates ()
"Show marked candidates."
(interactive)
(setf (ivy-state-collection ivy-last) org-ref-ivy-cite-marked-candidates)
(setf (ivy-state-preselect ivy-last) (org-ref-ivy-current))
(ivy--reset-state ivy-last))
(defun org-ref-ivy-show-all ()
"Show all the candidates."
(interactive)
(setf (ivy-state-collection ivy-last)
(orhc-bibtex-candidates))
(ivy--reset-state ivy-last))
;; * org-ref-cite keymap
(defvar org-ref-ivy-cite-keymap
(let ((map (make-sparse-keymap)))
(define-key map (kbd "C-<SPC>") 'org-ref-ivy-mark-candidate)
(define-key map (kbd "C-,") 'org-ref-ivy-show-marked-candidates)
(define-key map (kbd "C-.") 'org-ref-ivy-show-all)
(define-key map (kbd "C-<up>") 'org-ref-ivy-move-up)
(define-key map (kbd "C-<down>") 'org-ref-ivy-move-down)
(define-key map (kbd "C-y") 'org-ref-ivy-sort-year-ascending)
(define-key map (kbd "C-M-y") 'org-ref-ivy-sort-year-descending)
(define-key map (kbd "C-k") (lambda ()
(interactive)
(beginning-of-line)
(kill-visual-line)
(setf (ivy-state-collection ivy-last)
(orhc-bibtex-candidates))
(setf (ivy-state-preselect ivy-last) (org-ref-ivy-current))
(ivy--reset-state ivy-last)))
(define-key map (kbd "C-<return>")
(lambda ()
"Apply action and move to next/previous candidate."
(interactive)
(ivy-call)
(ivy-next-line)))
;; (define-key ivy-minibuffer-map (kbd "M-<return>")
;; (lambda ()
;; "Apply default action to all marked candidates."
;; (interactive)
;; (mapc (ivy--get-action ivy-last)
;; org-ref-ivy-cite-marked-candidates)
;; (ivy-exit-with-action (function (lambda (_) nil)))))
map)
"A key map for `org-ref-ivy-insert-cite-link'.")
(ivy-set-actions
'org-ref-ivy-insert-cite-link
org-ref-ivy-cite-actions)
(defun org-ref-ivy-insert-cite-link (&optional arg)
"ivy function for interacting with bibtex.
Uses `org-ref-find-bibliography' for bibtex sources, unless a
prefix ARG is used, which uses `org-ref-default-bibliography'."
(interactive "P")
(setq org-ref-bibtex-files (if arg
org-ref-default-bibliography
(org-ref-find-bibliography)))
(setq org-ref-ivy-cite-marked-candidates '())
(ivy-read "Open: " (orhc-bibtex-candidates)
:require-match t
:keymap org-ref-ivy-cite-keymap
:re-builder org-ref-ivy-cite-re-builder
:action 'or-ivy-bibtex-insert-cite
:caller 'org-ref-ivy-insert-cite-link))
(defun org-ref-ivy-cite-transformer (s)
"Make entry red if it is marked."
(let* ((fill-column (frame-width))
(fill-prefix " ")
(wrapped-s (with-temp-buffer
(insert s)
(fill-paragraph)
(buffer-string))))
(if (-contains?
(if (listp (car org-ref-ivy-cite-marked-candidates))
(mapcar 'car org-ref-ivy-cite-marked-candidates)
org-ref-ivy-cite-marked-candidates)
s)
(propertize wrapped-s 'face 'font-lock-warning-face)
(propertize wrapped-s 'face nil))))
(ivy-set-display-transformer
'org-ref-ivy-insert-cite-link
'org-ref-ivy-cite-transformer )
(defun org-ref-ivy-insert-label-link ()
"Insert a label with ivy."
(interactive)
(insert
(concat "label:"
(ivy-read "label: " (org-ref-get-labels)))))
(defun org-ref-ivy-insert-ref-link ()
"Insert a ref link with ivy.
Use a prefix arg to select the ref type."
(interactive)
(let ((label (ivy-read "label: " (org-ref-get-labels) :require-match t)))
(insert
(or (when (looking-at "$") " ") "")
(concat (if ivy-current-prefix-arg
(ivy-read "type: " org-ref-ref-types)
org-ref-default-ref-type)
":"
label))))
(require 'hydra)
(setq hydra-is-helpful t)
(defhydra org-ref-cite-hydra (:color blue)
"
_p_: Open pdf _w_: WOS _g_: Google Scholar _K_: Copy citation to clipboard
_u_: Open url _r_: WOS related _P_: Pubmed _k_: Copy key to clipboard
_n_: Open notes _c_: WOS citing _C_: Crossref _f_: Copy formatted entry
_o_: Open entry _e_: Email entry ^ ^ _q_: quit
"
("o" org-ref-open-citation-at-point nil)
("p" org-ref-open-pdf-at-point nil)
("n" org-ref-open-notes-at-point nil)
("u" org-ref-open-url-at-point nil)
("w" org-ref-wos-at-point nil)
("r" org-ref-wos-related-at-point nil)
("c" org-ref-wos-citing-at-point nil)
("g" org-ref-google-scholar-at-point nil)
("P" org-ref-pubmed-at-point nil)
("C" org-ref-crossref-at-point nil)
("K" org-ref-copy-entry-as-summary nil)
("k" (progn
(kill-new
(car (org-ref-get-bibtex-key-and-file))))
nil)
("f" (kill-new
(org-ref-format-entry (org-ref-get-bibtex-key-under-cursor)))
nil)
("e" (kill-new (save-excursion
(org-ref-open-citation-at-point)
(org-ref-email-bibtex-entry)))
nil)
("q" nil))
(defun org-ref-ivy-onclick-actions ()
"An alternate click function that uses ivy for action selection.
Each action is taken from `org-ref-ivy-cite-actions'. Each action
should act on a bibtex entry that matches the key in
`orhc-bibtex-candidates'. Set `org-ref-cite-onclick-function' to
this function to use it."
(interactive)
(ivy-read
"action: "
(cl-loop for i from 0
for (_ func s) in
org-ref-ivy-cite-actions
collect (cons (format "%2s. %s" i s) func))
:action (lambda (f)
(let* ((key (car (org-ref-get-bibtex-key-and-file)))
(entry (cdr (elt (orhc-bibtex-candidates)
(-elem-index
key
(cl-loop for entry in (orhc-bibtex-candidates)
collect (cdr (assoc "=key=" entry ))))))))
(funcall f entry)))))
;; * org-ref-ivy-set-keywords
(defvar org-ref-ivy-set-keywords-keymap
(let ((map (make-sparse-keymap)))
(define-key map (kbd "C-<SPC>") 'org-ref-ivy-mark-candidate)
(define-key map (kbd "C-,") 'org-ref-ivy-show-marked-candidates)
(define-key map (kbd "C-.") 'org-ref-ivy-show-all)
(define-key map (kbd "C-<up>") 'org-ref-ivy-move-up)
(define-key map (kbd "C-<down>") 'org-ref-ivy-move-down)
map)
"A key map for `org-ref-ivy-set-keywords'.")
(defun org-ref-ivy-set-keywords ()
"Add keywords to bibtex entries selected by org-ref-ivy."
(interactive)
(setq org-ref-ivy-cite-marked-candidates '())
(ivy-read "Keywords: " (org-ref-bibtex-keywords)
:keymap org-ref-ivy-set-keywords-keymap
:caller 'org-ref-ivy-set-keywords
:action (lambda (key)
(org-ref-set-bibtex-keywords
(mapconcat
'identity
(or org-ref-ivy-cite-marked-candidates (list key))
", ")))))
(ivy-set-display-transformer
'org-ref-ivy-set-keywords
'org-ref-ivy-cite-transformer)
(provide 'org-ref-ivy-cite)
;;; org-ref-ivy-cite.el ends here

View File

@@ -0,0 +1,35 @@
;;; org-ref-ivy.el --- org-ref with ivy completion -*- lexical-binding: t; -*-
;; Copyright (C) 2016 John Kitchin
;; Author: John Kitchin <jkitchin@andrew.cmu.edu>
;; URL: https://github.com/jkitchin/org-ref
;; Version: 0.8.1
;; Keywords: org-mode, cite, ref, label
;; Package-Requires: ((dash "2.11.0") (ivy "0.8.0") (hydra "0.13.2") (key-chord "0") (s "1.10.0") (f "0.18.0") (parsebib "0") (emacs "24.4"))
;; This file is not currently part of GNU Emacs.
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
(setq org-ref-completion-library 'org-ref-ivy-cite)
(require 'org-ref-ivy-cite)
(org-ref-ivy-cite-completion)
(provide 'org-ref-ivy)
;;; org-ref-ivy.el ends here

View File

@@ -0,0 +1,147 @@
;;; org-ref-latex.el --- org-ref functionality for LaTeX files -*- lexical-binding: t; -*-
;; Copyright (C) 2015 John Kitchin
;; Author: John Kitchin <jkitchin@andrew.cmu.edu>
;; Keywords: languages
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary: Make cites in LaTeX documents clickable, and with tooltips.
;; We use font-lock to add some functionality to the
;;
;;; Code:
(require 'org-ref-core)
(defvar latex-mode-map)
(defvar org-ref-cite-types)
(defvar org-ref-latex-cite-re
(concat "\\\\\\(" (mapconcat
(lambda (x)
(replace-regexp-in-string "\*" "\\\\*" x))
org-ref-cite-types
"\\|")
"\\)"
"\\(\\[[^}]*\\)?" ; optional []
"\\(\\[[^}]*\\)?" ; optional []
"{\\([^}]*\\)}")
"Regexp for LaTeX citations. \citetype[optional]{some,keys}.
The clickable part are the keys.")
(defun org-ref-latex-get-key ()
"Figure out what key the cursor is on."
(let (start end)
;; look back for , or {
(save-excursion
(re-search-backward ",\\|{")
(setq start (+ 1 (point))))
;; look forward to , or }
(save-excursion
(re-search-forward ",\\|}")
(setq end (- (point) 1)))
(buffer-substring-no-properties start end)))
;;;###autoload
(defun org-ref-latex-debug ()
(interactive)
(message-box "%S\n%S\n%S\n%S"
(org-ref-latex-get-key)
(org-ref-find-bibliography)
(org-ref-get-bibtex-key-and-file (org-ref-latex-get-key))
(ignore-errors
(org-ref-latex-help-echo nil nil (point)))))
(defun org-ref-latex-jump-to-bibtex (&optional key)
"Jump to the KEY at point."
(let ((results (org-ref-get-bibtex-key-and-file
(or key (org-ref-latex-get-key)))))
(find-file (cdr results))
(bibtex-search-entry (car results))))
;;;###autoload
(defun org-ref-latex-click ()
"Jump to entry clicked on."
(interactive)
(helm :sources '(((name . "Actions")
(candidates . (("Open Bibtex entry" . org-ref-latex-jump-to-bibtex)
("Bibtex entry menu" . (lambda ()
(org-ref-latex-jump-to-bibtex)
(org-ref-bibtex-hydra/body)))))
(action . (lambda (f)
(funcall f)))))))
(defun org-ref-latex-help-echo (_window _object position)
"Get tool tip for a key in WINDOW for OBJECT at POSITION."
(save-excursion
(goto-char position)
(let* ((key (org-ref-latex-get-key))
(results (org-ref-get-bibtex-key-and-file key))
(bibfile (cdr results))
citation
tooltip)
(setq citation
(if bibfile
(save-excursion
(with-temp-buffer
(insert-file-contents bibfile)
(bibtex-set-dialect
(parsebib-find-bibtex-dialect) t)
(bibtex-search-entry key)
(org-ref-bib-citation)))
"!!! No entry found !!!"))
(setq tooltip
(with-temp-buffer
(insert citation)
(fill-paragraph)
(buffer-string)))
tooltip)))
(defun org-ref-next-latex-cite (&optional limit)
"Font-lock function to make cites in LaTeX documents clickable."
(when (re-search-forward org-ref-latex-cite-re limit t)
(setq font-lock-extra-managed-props (delq 'help-echo font-lock-extra-managed-props))
(add-text-properties
(match-beginning 3)
(match-end 3)
`(mouse-face
highlight
local-map ,(let ((map (copy-keymap latex-mode-map)))
(define-key map [mouse-1]
'org-ref-latex-click)
map)
help-echo org-ref-latex-help-echo))))
(defun org-ref-latex-cite-on ()
"Add the font-lock on for citations."
(font-lock-add-keywords
nil
'((org-ref-next-latex-cite 3 font-lock-constant-face))))
(add-hook 'latex-mode-hook 'org-ref-latex-cite-on)
(add-hook 'LaTeX-mode-hook 'org-ref-latex-cite-on)
(provide 'org-ref-latex)
;;; org-ref-latex.el ends here

View File

@@ -0,0 +1,273 @@
;;; org-ref-pdf.el --- Drag-n-drop PDF onto bibtex files -*- lexical-binding: t; -*-
;; Copyright (C) 2015 John Kitchin
;; Author: John Kitchin <jkitchin@andrew.cmu.edu>
;; Keywords:
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;; This library provides functions to enable drag-n-drop of pdfs onto a bibtex
;; buffer to add bibtex entries to it.
;; TODO: If no DOI is found, figure out a way to do a crossref/google query to
;; get a doi. This needs a reliable title/citation.
;;; Code:
(require 'f)
(require 'pdf-tools)
(eval-when-compile
(require 'cl-lib))
(declare-function org-ref-bibtex-key-from-doi "org-ref-bibtex.el")
(defgroup org-ref-pdf nil
"Customization group for org-ref-pdf"
:tag "Org Ref PDF"
:group 'org-ref-pdf)
(defcustom pdftotext-executable
"pdftotext"
"Executable for pdftotext. Set if the executable is not on your
path, or you want to use another version."
:type 'file
:group 'org-ref-pdf)
(defcustom org-ref-pdf-doi-regex
"dx.doi.org/\\(?1:[^]\n} \"]*\\)\\|\\(?:doi\\|DOI\\):?\\s-?\\(?1:[^]}\n \"]*\\)"
"Regular expression to match DOIs in a pdf converted to text.
The DOI should be in group 1 of the regex.
The default pattern matches:
1. http://dx.do.org/doi
2. doi: doi, where the colon is optional"
:type 'regexp
:group 'org-ref-pdf)
(defun org-ref-extract-doi-from-pdf (pdf)
"Try to extract a doi from a PDF file.
There may be more than one doi in the file. This function returns
all the ones it finds based on two patterns: doi: up to a quote,
bracket, space or end of line. dx.doi.org/up to a quote, bracket,
space or end of line.
If there is a trailing . we chomp it off. Returns a list of doi
strings, or nil.
"
(with-temp-buffer
(insert (shell-command-to-string (format "%s %s -"
pdftotext-executable
(shell-quote-argument (dnd-unescape-uri pdf)))))
(goto-char (point-min))
(let ((matches '()))
(while (re-search-forward org-ref-pdf-doi-regex nil t)
;; I don't know how to avoid a trailing . on some dois with the
;; expression above, so if it is there, I chomp it off here.
(let ((doi (match-string 1)))
(when (s-ends-with? "." doi)
(setq doi (substring doi 0 (- (length doi) 1))))
(cl-pushnew doi matches :test #'equal)))
matches)))
(defun org-ref-pdf-doi-candidates (dois)
"Generate candidate list for helm source.
Used when multiple dois are found in a pdf file."
(cl-loop for doi in dois
collect
(condition-case nil
(cons
(plist-get (doi-utils-get-json-metadata doi) :title)
doi)
(error (cons (format "%s read error" doi) doi)))))
(defun org-ref-pdf-add-dois (_)
"Add all entries for CANDIDATE in `helm-marked-candidates'."
(cl-loop for doi in (helm-marked-candidates)
do
(doi-utils-add-bibtex-entry-from-doi
doi
(buffer-file-name))))
;;;###autoload
(defun org-ref-pdf-to-bibtex ()
"Add pdf of current buffer to bib file and save pdf to
`org-ref-default-bibliography'. The pdf should be open in Emacs
using the `pdf-tools' package."
(interactive)
(when (not (f-ext? (buffer-file-name) "pdf"))
(error "Buffer is not a pdf file"))
;; Get doi from pdf of current buffer
(let* ((dois (org-ref-extract-doi-from-pdf (buffer-file-name)))
(doi-utils-download-pdf nil)
(doi (if (= 1 (length dois))
(car dois)
(completing-read "Select DOI: " dois))))
;; Add bib entry from doi:
(doi-utils-add-bibtex-entry-from-doi doi)
;; Copy pdf to `org-ref-pdf-directory':
(let ((key (org-ref-bibtex-key-from-doi doi)))
(copy-file (buffer-file-name)
(expand-file-name (format "%s.pdf" key)
org-ref-pdf-directory)))))
;;;###autoload
;; (defun org-ref-pdf-dnd-func (event)
;; "Drag-n-drop support to add a bibtex entry from a pdf file."
;; (interactive "e")
;; (goto-char (nth 1 (event-start event)))
;; (x-focus-frame nil)
;; (let* ((payload (car (last event)))
;; (pdf (cadr payload))
;; (dois (org-ref-extract-doi-from-pdf pdf)))
;; (cond
;; ((null dois)
;; (message "No doi found in %s" pdf))
;; ((= 1 (length dois))
;; (doi-utils-add-bibtex-entry-from-doi
;; (car dois)
;; (buffer-file-name)))
;; ;; Multiple DOIs found
;; (t
;; (helm :sources `((name . "Select a DOI")
;; (candidates . ,(org-ref-pdf-doi-candidates dois))
;; (action . org-ref-pdf-add-dois)))))))
;; This isn't very flexible, as it hijacks all drag-n-drop events. I switched to
;; using `dnd-protocol-alist'.
;; (define-key bibtex-mode-map (kbd "<drag-n-drop>") 'org-ref-pdf-dnd-func)
;; This is what the original dnd function was.
;; (define-key bibtex-mode-map (kbd "<drag-n-drop>") 'ns-drag-n-drop)
;; I replaced the functionality above with this new approach that leverages
;; ns-drag-n-drop. An alternative approach would be to adapt the function above
;; so that if the item dragged on wasn't a pdf, it would use another function.
;; that is essentially what ns-drag-n-drop enables, multiple handlers for
;; different uris that get dropped on the windwo.
(defun org-ref-pdf-dnd-protocol (uri action)
"Drag-n-drop protocol.
PDF will be a string like file:path.
ACTION is what to do. It is required for `dnd-protocol-alist'.
This function should only apply when in a bibtex file."
(if (and (buffer-file-name)
(f-ext? (buffer-file-name) "bib"))
(let* ((path (substring uri 5))
dois)
(cond
((f-ext? path "pdf")
(setq dois (org-ref-extract-doi-from-pdf
path))
(cond
((null dois)
(message "No doi found in %s" path)
nil)
((= 1 (length dois))
;; we do not need to get the pdf, since we have one.
(let ((doi-utils-download-pdf nil))
(doi-utils-add-bibtex-entry-from-doi
(car dois)
(buffer-file-name))
;; we should copy the pdf to the pdf directory though
(let ((key (cdr (assoc "=key=" (bibtex-parse-entry)))))
(copy-file (dnd-unescape-uri path) (expand-file-name (format "%s.pdf" key) org-ref-pdf-directory))))
action)
;; Multiple DOIs found
(t
(helm :sources `((name . "Select a DOI")
(candidates . ,(org-ref-pdf-doi-candidates dois))
(action . org-ref-pdf-add-dois)))
action)))
;; drag a bib file on and add contents to the end of the file.
((f-ext? path "bib")
(goto-char (point-max))
(insert "\n")
(insert-file-contents path))))
;; ignoring. pass back to dnd. Copied from `org-download-dnd'. Apparently
;; returning nil does not do this.
(let ((dnd-protocol-alist
(rassq-delete-all
'org-ref-pdf-dnd-protocol
(copy-alist dnd-protocol-alist))))
(dnd-handle-one-url nil action uri))))
(add-to-list 'dnd-protocol-alist '("^file:" . org-ref-pdf-dnd-protocol))
;;;###autoload
(defun org-ref-pdf-dir-to-bibtex (bibfile directory)
"Create BIBFILE from pdf files in DIRECTORY."
(interactive (list
(read-file-name "Bibtex file: ")
(read-directory-name "Directory: ")))
(find-file bibfile)
(goto-char (point-max))
(cl-loop for pdf in (f-entries directory (lambda (f) (f-ext? f "pdf")))
do
(goto-char (point-max))
(let ((dois (org-ref-extract-doi-from-pdf pdf)))
(cond
((null dois)
(insert (format "%% No doi found to create entry in %s.\n" pdf)))
((= 1 (length dois))
(doi-utils-add-bibtex-entry-from-doi
(car dois)
(buffer-file-name))
(bibtex-beginning-of-entry)
(insert (format "%% [[file:%s]]\n" pdf)))
;; Multiple DOIs found
(t
(insert (format "%% Multiple dois found in %s\n" pdf))
(helm :sources `((name . "Select a DOI")
(candidates . ,(org-ref-pdf-doi-candidates dois))
(action . org-ref-pdf-add-dois))))))))
;;;###autoload
(defun org-ref-pdf-debug-pdf (pdf-file)
"Try to debug getting a doi from a pdf.
Opens a buffer with the pdf converted to text, and `occur' on the
variable `org-ref-pdf-doi-regex'."
(interactive "fPDF: ")
(switch-to-buffer (get-buffer-create "*org-ref-pdf debug*"))
(erase-buffer)
(insert (shell-command-to-string (format "%s %s -"
pdftotext-executable
(shell-quote-argument pdf-file))))
(goto-char (point-min))
(highlight-regexp org-ref-pdf-doi-regex)
(occur org-ref-pdf-doi-regex)
(switch-to-buffer-other-window "*Occur*"))
;;;###autoload
(defun org-ref-pdf-crossref-lookup ()
"Lookup highlighted text in PDFView in CrossRef."
(interactive)
(pdf-view-assert-active-region)
(let* ((txt (pdf-view-active-region-text)))
(pdf-view-deactivate-region)
(crossref-lookup (mapconcat 'identity txt " \n"))))
(provide 'org-ref-pdf)
;;; org-ref-pdf.el ends here

View File

@@ -0,0 +1,18 @@
(define-package "org-ref" "20180706.614" "citations, cross-references and bibliographies in org-mode"
'((dash "2.11.0")
(htmlize "1.51")
(helm "1.5.5")
(helm-bibtex "2.0.0")
(ivy "0.8.0")
(hydra "0.13.2")
(key-chord "0")
(s "1.10.0")
(f "0.18.0")
(emacs "24.4")
(pdf-tools "0.7"))
:keywords
'("org-mode" "cite" "ref" "label")
:url "https://github.com/jkitchin/org-ref")
;; Local Variables:
;; no-byte-compile: t
;; End:

View File

@@ -0,0 +1,259 @@
;;; org-ref-pubmed.el --- Links and functions for Pubmed and NIH databases -*- lexical-binding: t; -*-
;; Copyright (C) 2015 John Kitchin
;; Author: John Kitchin <jkitchin@andrew.cmu.edu>
;; Keywords: convenience
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;;* Introduction
;; This document is an experiment at creating a literate program to provide
;; functions for interacting with pubmed databases.
;; This library provides links that go to pubmed resources, e.g.
;; pmcid:PMC3498956
;;
;; pmid:23162369
;;
;; and nihmsid:NIHMS395714
;;
;; See http://www.ncbi.nlm.nih.gov/pmc/about/public-access-info/#p3 for details
;; of these identifiers.
;;
;; For PMID there is one interactive function that inserts a bibtex entry:
;; pubmed-insert-bibtex-from-pmid.
;; This library is complementary to [[./doi-utils.org]].
;;; Code:
;;* PMID (from PubMed) link and functions
;; A PMID is a number that identifies an entry in the Pubmed database. The PMID
;; is a unique reference number for PubMed citations. The PMID is a distinctly
;; different number from the PMCID and is used only for PubMed records.
(require 'dash)
(require 'org)
(require 'org-ref-utils)
(org-ref-link-set-parameters "pmid"
:follow (lambda (link-string) (browse-url (format "http://www.ncbi.nlm.nih.gov/pubmed/%s" link-string)))
:export (lambda (keyword desc format)
(cond
((eq format 'html)
(format "<a href=\"http://www.ncbi.nlm.nih.gov/pmc/articles/mid/%s\">pmid:%s</a>" keyword (or desc keyword))) ; no output for html
((eq format 'latex)
;; write out the latex command
(format "\\url{http://www.ncbi.nlm.nih.gov/pmc/articles/mid/%s}{%s}" keyword (or desc keyword))))))
;;** Get MEDLINE metadata
;; We can get bibliographic metadata from a pmid. Here we get the MEDLINE
;; text. The website wraps the data in <pre></pre> tags.
(defun pubmed-get-medline (pmid)
"Get MEDLINE text for PMID as a string."
(with-current-buffer
(url-retrieve-synchronously
(format "http://www.ncbi.nlm.nih.gov/pubmed/%s/?report=medline&format=text" pmid))
(goto-char (point-min))
(let ((p1 (search-forward "<pre>"))
(p2 (search-forward "</pre>")))
(buffer-substring (+ 1 p1) (- p2 6)))))
;;** Parse the PMID MEDLINE data
;; We can parse this into a data structure.
(defun pubmed-parse-medline (pmid)
"Parse the medline text for PMID and return a list of cons cells."
(let ((data '())
(p1)
(p2)
(tag)
(value))
(with-temp-buffer (insert (pubmed-get-medline pmid))
(goto-char (point-min))
(while (re-search-forward "\\(^[A-Z]\\{2,4\\}\\)\\s-*- "
nil t)
(setq tag (match-string 1))
;; point is at end of the search
(setq p1 (point))
;; now go to next tag
(re-search-forward "\\(^[A-Z]\\{2,4\\}\\)\\s-*- " nil t)
(setq p2 (- (match-beginning 1) 1))
(setq value (buffer-substring p1 p2))
(setq data (append data (list (cons tag value))))
;; now go back to last tag to get the next one
(goto-char p1)))
data))
;;** PMID to bibtex entry
;; The point of parsing the MEDLINE text is so we can make bibtex entries. We
;; only support Journal articles for now.
(defun pubmed-pmid-to-bibtex (pmid)
"Convert a PMID to a bibtex entry."
(let* ((data (pubmed-parse-medline pmid))
(type (downcase (cdr (assoc "PT" data))))
(title (cdr (assoc "TI" data)))
(authors (mapconcat 'cdr
(-filter (lambda (x)
(string= (car x) "FAU"))
data)
" and "))
(abstract (cdr (assoc "AB" data)))
(volume (cdr (assoc "VI" data)))
(issue (cdr (assoc "IP" data)))
(journal (cdr (assoc "JT" data)))
(year (cdr (assoc "DP" data)))
(pages (cdr (assoc "PG" data)))
(aid (cdr (assoc "AID" data))))
(cond
((string= type "journal article")
(concat "@article{,
author = {" authors "},
title = {" title "},
abstract = {" abstract "},
journal = {" journal "},
volume = {" volume "},
number = {" issue "},
year = {" (car (split-string year)) "},
pages = {" pages "},
doi = {" (replace-regexp-in-string " \\[doi\\]" "" aid) "},
}"))
(t
(message "No conversion for type: %s" type)))))
;; And we probably want to be able to insert a bibtex entry
;;;###autoload
(defun pubmed-insert-bibtex-from-pmid (pmid)
"Insert a bibtex entry at point derived from PMID.
You must clean the entry after insertion."
(interactive "sPMID: ")
(insert (pubmed-pmid-to-bibtex pmid)))
;;** PMID to xml
;; We can also get xml of the MEDLINE data. The web page here also wraps the xml
;; in a <pre> block and escapes the <> with &lt; and &gt;, which we have to
;; undo. I have not used this code for anything, so I am not sure how good the
;; xml code is.
;;;###autoload
(defun pubmed-get-medline-xml (pmid)
"Get MEDLINE xml for PMID as a string."
(interactive)
(with-current-buffer
(url-retrieve-synchronously
(format "http://www.ncbi.nlm.nih.gov/pubmed/%s/?report=xml&format=text" pmid))
(goto-char (point-min))
(while (search-forward "&lt;" nil t)
(replace-match "<"))
(goto-char (point-min))
(while (search-forward "&gt;" nil t)
(replace-match ">"))
(goto-char (point-min))
(let ((p1 (search-forward "<pre>"))
(p2 (search-forward "</pre>")))
(buffer-substring (+ 1 p1) (- p2 6)))))
;;* Pubmed Central (PMC) link
;; A PMCID starts with PMC and is followed by numbers. The PMCID is a unique
;; reference number or identifier that is assigned to every article that is
;; accepted into PMC. The PMCID is also used by recipients of NIH funding to
;; demonstrate compliance with the NIH Public Access policy. The PMCID can be
;; found in both PMC and PubMed.
;; Here we define a new link. Clicking on it simply opens a webpage to the
;; article.
(org-ref-link-set-parameters "pmcid"
:follow (lambda (link-string) (browse-url (format "http://www.ncbi.nlm.nih.gov/pmc/articles/%s" link-string)))
:export (lambda (keyword desc format)
(cond
((eq format 'html)
(format "<a href=\"http://www.ncbi.nlm.nih.gov/pmc/articles/%s\">pmcid:%s</a>" keyword (or desc keyword)))
((eq format 'latex)
(format "\\url{http://www.ncbi.nlm.nih.gov/pmc/articles/%s}{%s}" keyword (or desc keyword))))))
;;* NIHMSID
;; The NIHMSID is a preliminary article identifier that applies only to
;; manuscripts deposited through the NIHMS system. The NIHMSID is only valid for
;; compliance reporting for 90 days after the publication date of an
;; article. Once the Web version of the NIHMS submission is approved for
;; inclusion in PMC and the corresponding citation is in PubMed, the article
;; will also be assigned a PMCID.
(org-ref-link-set-parameters "nihmsid"
:follow (lambda (link-string) (browse-url (format "http://www.ncbi.nlm.nih.gov/pmc/articles/mid/%s" link-string)))
:export (lambda (keyword desc format)
(cond
((eq format 'html)
(format "<a href=\"http://www.ncbi.nlm.nih.gov/pmc/articles/mid//%s\">nihmsid:%s</a>" keyword (or desc keyword)))
((eq format 'latex)
;; write out the latex command
(format "\\url{http://www.ncbi.nlm.nih.gov/pmc/articles/mid/%s}{%s}" keyword (or desc keyword))))))
;;* Searching pubmed
;;;###autoload
(defun pubmed ()
"Open http://www.ncbi.nlm.nih.gov/pubmed in a browser."
(interactive)
(browse-url "http://www.ncbi.nlm.nih.gov/pubmed"))
;;;###autoload
(defun pubmed-advanced ()
"Open http://www.ncbi.nlm.nih.gov/pubmed/advanced in a browser."
(interactive)
(browse-url "http://www.ncbi.nlm.nih.gov/pubmed/advanced"))
;;;###autoload
(defun pubmed-simple-search (query)
"Open QUERY in Pubmed in a browser."
(interactive "sQuery: ")
(browse-url
(format "http://www.ncbi.nlm.nih.gov/pubmed/?term=%s" (url-hexify-string query))))
(org-ref-link-set-parameters "pubmed-search"
:follow (lambda (query)
"Open QUERY in a `pubmed-simple-search'."
(pubmed-simple-search query))
:export (lambda (query desc format)
(let ((url (format "http://www.ncbi.nlm.nih.gov/pubmed/?term=%s" (url-hexify-string query))))
(cond
((eq format 'html)
(format "<a href=\"%s\">%s</a>" url (or desc (concat "pubmed-search:" query))))
((eq format 'latex)
(format "\\href{%s}{%s}" url (or desc (concat "pubmed-search:" query))))))))
(provide 'org-ref-pubmed)
;;; org-ref-pubmed.el ends here

View File

@@ -0,0 +1,274 @@
;;; org-ref-reftex.el --- org-ref completion setup with reftex -*- lexical-binding: t; -*-
;; Copyright (C) 2016 John Kitchin
;; Author: John Kitchin <jkitchin@andrew.cmu.edu>
;; Keywords:
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary: This is a bare-bones completion engine using only org-mode and
;;; vanilla Emacs functions. It is not being further developed.
;;
;;; Code:
(require 'reftex)
(require 'reftex-cite)
(require 'org-ref-utils)
(declare-function 'org-ref-find-bibliography "org-ref-core.el")
(declare-function 'org-ref-get-bibtex-key-and-file "org-ref-core.el")
(declare-function 'org-ref-bib-citation "org-ref-core.el")
(defvar org-ref-cite-types)
(defvar org-ref-open-notes-function)
(defvar org-ref-get-pdf-filename-function)
(defvar org-ref-open-pdf-function)
;;;###autoload
(defun org-ref-reftex-completion ()
"Use reftex and org-mode for completion."
(interactive)
;; Define core functions for org-ref
(setq org-ref-insert-link-function 'org-ref-insert-cite-link
org-ref-insert-cite-function 'org-ref-insert-cite-link
org-ref-insert-label-function 'org-insert-link
org-ref-insert-ref-function 'org-insert-link
org-ref-cite-onclick-function 'org-ref-cite-onclick-minibuffer-menu)
(message "reftex completion in org-ref loaded."))
(org-ref-reftex-completion)
(define-key org-mode-map
(kbd org-ref-insert-cite-key)
org-ref-insert-link-function)
;; Messages in the minbuffer conflict with the minibuffer menu. So we turn them
;; off.
(setq org-ref-show-citation-on-enter nil)
;;* org-mode / reftex setup
(defun org-mode-reftex-setup ()
"Setup `org-mode' and reftex for `org-ref'."
(and (buffer-file-name)
(file-exists-p (buffer-file-name))
(global-auto-revert-mode t))
(make-local-variable 'reftex-cite-format)
(setq reftex-cite-format 'org))
(add-hook 'org-mode-hook 'org-mode-reftex-setup)
(eval-after-load 'reftex-vars
'(progn
(add-to-list 'reftex-cite-format-builtin
'(org "Org-mode citation"
((?\C-m . "cite:%l") ; default
(?d . ",%l") ; for appending
(?a . "autocite:%l")
(?t . "citet:%l")
(?T . "citet*:%l")
(?p . "citep:%l")
(?P . "citep*:%l")
(?h . "citeauthor:%l")
(?H . "citeauthor*:%l")
(?y . "citeyear:%l")
(?x . "citetext:%l")
(?n . "nocite:%l"))))))
(defun org-ref-insert-cite-link (alternative-cite)
"Insert a default citation link using reftex.
If you are on a link, it appends to the end of the link,
otherwise, a new link is inserted. Use a prefix
arg (ALTERNATIVE-CITE) to get a menu of citation types."
(interactive "P")
(org-ref-find-bibliography)
(let* ((object (org-element-context))
(link-string-end (org-element-property :end object)))
(if (not alternative-cite)
(cond
;; case where we are in a link
((and (equal (org-element-type object) 'link)
(-contains? org-ref-cite-types
(org-element-property :type object)))
(goto-char link-string-end)
;; sometimes there are spaces at the end of the link
;; this code moves point pack until no spaces are there
(skip-chars-backward " ")
(insert (concat "," (mapconcat
'identity
(reftex-citation t ?a) ","))))
;; We are next to a link, and we want to append
((save-excursion
(backward-char)
(and (equal (org-element-type (org-element-context)) 'link)
(-contains? org-ref-cite-types
(org-element-property
:type (org-element-context)))))
(skip-chars-backward " ")
(insert (concat "," (mapconcat
'identity
(reftex-citation t ?a) ","))))
;; insert fresh link
(t
(insert
(concat org-ref-default-citation-link
":"
(mapconcat 'identity (reftex-citation t) ",")))))
;; you pressed a C-u so we run this code
(reftex-citation))))
;;;###autoload
(defun org-ref-open-notes-from-reftex ()
"Call reftex, and open notes for selected entry."
(interactive)
;; now look for entry in the notes file
(if org-ref-bibliography-notes
(find-file-other-window org-ref-bibliography-notes)
(error "org-ref-bibliography-notes is not set to anything"))
(org-open-link-from-string
(format "[[#%s]]" (car (reftex-citation t))))
(funcall org-ref-open-notes-function))
(defalias 'ornr 'org-ref-open-notes-from-reftex)
;;*** Minibuffer menu
;;;###autoload
(defun org-ref-cite-onclick-minibuffer-menu (&optional _link-string)
"Action when a cite link is clicked on.
Provides a menu of context sensitive actions. If the bibtex entry
has a pdf, you get an option to open it. If there is a doi, you
get a lot of options. LINK-STRING is used by the link function."
(interactive)
(let* ((results (org-ref-get-bibtex-key-and-file))
(key (car results))
(pdf-file (funcall org-ref-get-pdf-filename-function key))
(bibfile (cdr results))
(url (save-excursion
(with-temp-buffer
(insert-file-contents bibfile)
(bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
(bibtex-search-entry key)
(bibtex-autokey-get-field "url"))))
(doi (save-excursion
(with-temp-buffer
(insert-file-contents bibfile)
(bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
(bibtex-search-entry key)
;; I like this better than bibtex-url which does not always find
;; the urls
(bibtex-autokey-get-field "doi")))))
(when (string= "" doi) (setq doi nil))
(when (string= "" url) (setq url nil))
(setq org-ref-cite-menu-funcs '())
;; open action
(when
bibfile
(add-to-list
'org-ref-cite-menu-funcs
'("o" "pen" org-ref-open-citation-at-point)))
;; pdf
(when (file-exists-p pdf-file)
(add-to-list
'org-ref-cite-menu-funcs
`("p" "df" ,org-ref-open-pdf-function) t))
;; notes
(add-to-list
'org-ref-cite-menu-funcs
'("n" "otes" org-ref-open-notes-at-point) t)
;; url
(when (or url doi)
(add-to-list
'org-ref-cite-menu-funcs
'("u" "rl" org-ref-open-url-at-point) t))
;; doi funcs
(when doi
(add-to-list
'org-ref-cite-menu-funcs
'("w" "os" org-ref-wos-at-point) t)
(add-to-list
'org-ref-cite-menu-funcs
'("c" "iting" org-ref-wos-citing-at-point) t)
(add-to-list
'org-ref-cite-menu-funcs
'("r" "elated" org-ref-wos-related-at-point) t)
(add-to-list
'org-ref-cite-menu-funcs
'("g" "oogle scholar" org-ref-google-scholar-at-point) t)
(add-to-list
'org-ref-cite-menu-funcs
'("P" "ubmed" org-ref-pubmed-at-point) t))
;; add user functions
(dolist (tup org-ref-user-cite-menu-funcs)
(add-to-list
'org-ref-cite-menu-funcs
tup t))
;; finally quit
(add-to-list
'org-ref-cite-menu-funcs
'("q" "uit" (lambda ())) t)
;; now we make a menu
;; construct menu string as a message
(message
(concat
(let* ((results (org-ref-get-bibtex-key-and-file))
(key (car results))
(bibfile (cdr results)))
(save-excursion
(with-temp-buffer
(insert-file-contents bibfile)
(bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
(bibtex-search-entry key)
(org-ref-bib-citation))))
"\n"
(mapconcat
(lambda (tup)
(concat "[" (elt tup 0) "]"
(elt tup 1) " "))
org-ref-cite-menu-funcs "")))
;; get the input
(let* ((input (read-char-exclusive))
(choice (assoc
(char-to-string input) org-ref-cite-menu-funcs)))
;; now run the function (2nd element in choice)
(when choice
(funcall
(elt
choice
2))))))
(provide 'org-ref-reftex)
;;; org-ref-reftex.el ends here

View File

@@ -0,0 +1,54 @@
;;; org-ref-sci-id.el --- org-mode links for scientific IDs -*- lexical-binding: t; -*-
;; Copyright (C) 2015 John Kitchin
;; Author: John Kitchin <jkitchin@andrew.cmu.edu>
;; Keywords:
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;; New org-mode links for scientific IDs like orcid (http://orcid.org) and researcherid (http://www.researcherid.com)
;; orcid:0000-0003-2625-9232
;; researcherid:A-2363-2010
;;; Code:
(require 'org)
(require 'org-ref-utils)
(org-ref-link-set-parameters "orcid"
:follow (lambda
(link-string)
(browse-url
(format "http://orcid.org/%s" link-string)))
:export (lambda (keyword desc format)
(cond
((eq format 'html)
(format "<a href=\"http://orcid.org/%s\">orcid:%s</a>" keyword (or desc keyword))))))
(org-ref-link-set-parameters "researcherid"
:follow (lambda
(link-string)
(browse-url
(format "http://www.researcherid.com/rid/%s" link-string)))
:export (lambda (keyword desc format)
(cond
((eq format 'html)
(format "<a href=\"http://www.researcherid.com/rid/%s\">ResearcherID:%s</a>"
keyword (or desc keyword))))))
(provide 'org-ref-sci-id)
;;; org-ref-sci-id.el ends here

View File

@@ -0,0 +1,35 @@
;;; org-ref-scifinder.el --- Emacs interface to SciFinder
;; Copyright (C) 2015 John Kitchin
;; Author: John Kitchin <jkitchin@andrew.cmu.edu>
;; Keywords:
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;; Hopefully this eventually integrates the Scifinder API into Emacs. For now,
;; there is just one function that opens Scifinder for you.
;;; Code:
;;;###autoload
(defun scifinder ()
"Open https://scifinder.cas.org/scifinder/view/scifinder/scifinderExplore.jsf in a browser."
(interactive)
(browse-url "https://scifinder.cas.org/scifinder/view/scifinder/scifinderExplore.jsf"))
(provide 'org-ref-scifinder)
;;; org-ref-scifinder.el ends here

View File

@@ -0,0 +1,222 @@
;;; org-ref-scopus.el --- Emacs-lisp interface to the Scopus API -*- lexical-binding: t; -*-
;; Copyright (C) 2015 John Kitchin
;; Author: John Kitchin <jkitchin@andrew.cmu.edu>
;; Keywords:
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;; See http://dev.elsevier.com/index.html for more information about the Scopus API
;;
;; New org-links:
;; eid:2-s2.0-72649092395 with a hydra menu
;; [[scopus-search:alloy Au segregation]]
;; [[scopus-advanced-search:au-id(24176978500)]]
;;; Code:
(require 'org)
(require 'hydra)
(require 'xml)
(require 'org-ref-utils)
(defvar url-request-method)
(defvar url-mime-accept-string)
(defvar url-http-end-of-headers)
(defvar url-request-extra-headers)
(defvar *scopus-api-key* nil
"Your Scopus API key.
You need to set this in your init files. Get a key here:
http://dev.elsevier.com/myapikey.html.")
;; (defun scopus-doi-to-xml (doi)
;; "Return a parsed xml from the Scopus article retrieval api for DOI.
;; This does not always seem to work for the most recent DOIs."
;; (let* ((url-request-method "GET")
;; (url-request-extra-headers (list (cons "X-ELS-APIKey" *scopus-api-key*)))
;; (url (format "http://api.elsevier.com/content/article/doi/%s" doi))
;; (xml))
;; (setq xml
;; (with-current-buffer (url-retrieve-synchronously url)
;; (xml-parse-region url-http-end-of-headers (point-max))))
;; (if (eq 'service-error (caar xml))
;; (progn (message-box "%s\n%s\n%s" doi url xml)
;; nil)
;; xml)))
(defun scopus-doi-to-eid (doi)
"Get a Scopus eid from a DOI.
Requires `*scopus-api-key*' to be defined."
(unless *scopus-api-key* (error "You must define `*scopus-api-key*'"))
(let* ((url-request-method "GET")
(url-mime-accept-string "application/xml")
(url-request-extra-headers (list (cons "X-ELS-APIKey" *scopus-api-key*)
'("field" . "eid")))
(url (format "http://api.elsevier.com/content/search/scopus?query=doi(%s)" doi))
(xml (with-current-buffer (url-retrieve-synchronously url)
(xml-parse-region url-http-end-of-headers (point-max))))
(results (car xml))
(entry (car (xml-get-children results 'entry))))
(car (xml-node-children (car (xml-get-children entry 'eid))))))
;;;###autoload
(defun scopus-related-by-keyword-url (doi)
"Return a Scopus url to articles related by keyword for DOI."
(interactive)
(unless *scopus-api-key* (error "You must define `*scopus-api-key*'"))
(let ((eid (scopus-doi-to-eid doi)))
(when eid (format "http://www.scopus.com/search/submit/mlt.url?eid=%s&src=s&all=true&origin=recordpage&method=key&zone=relatedDocuments" eid))))
;;;###autoload
(defun scopus-related-by-author-url (doi)
"Return a Scopus url to articles related by author for DOI."
(interactive)
(unless *scopus-api-key* (error "You must define `*scopus-api-key*'"))
(let ((eid (scopus-doi-to-eid doi)))
(when eid (format "http://www.scopus.com/search/submit/mlt.url?eid=%s&src=s&all=true&origin=recordpage&method=aut&zone=relatedDocuments" eid))))
;;;###autoload
(defun scopus-related-by-references-url (doi)
"Return a Scopus url to articles related by references for DOI."
(interactive)
(unless *scopus-api-key* (error "You must define `*scopus-api-key*'"))
(let ((eid (scopus-doi-to-eid doi)))
(when eid (format "http://www.scopus.com/search/submit/mlt.url?eid=%s&src=s&all=true&origin=recordpage&method=ref&zone=relatedDocuments" eid))))
(defun scopus-citing-url (doi)
"Return a Scopus url to articles citing DOI."
(format "http://www.scopus.com/results/citedbyresults.url?sort=plf-f&cite=%s&src=s&imp=t&sot=cite&sdt=a&sl=0&origin=recordpage" (scopus-doi-to-eid doi)))
;;;###autoload
(defun scopus-open-eid (eid)
"Open article with EID in browser."
(interactive "sEID: ")
(browse-url (format "http://www.scopus.com/record/display.url?eid=%s&origin=resultslist" eid)))
(defun scopus ()
"Open http://scopus.com is a browser."
(browse-url "http://www.scopus.com"))
;;;###autoload
(defun scopus-basic-search (query)
"Open QUERY as a basic title-abstract-keyword search at scopus.com."
(interactive "sQuery: ")
(browse-url
(format
"http://www.scopus.com/results/results.url?sort=plf-f&src=s&sot=b&sdt=b&sl=%s&s=TITLE-ABS-KEY%%28%s%%29&origin=searchbasic"
(length (url-unhex-string (concat "TITLE-ABS-KEY%28" (url-hexify-string query) "%29")))
(url-hexify-string query))))
;;;###autoload
(defun scopus-advanced-search (query)
"Open QUERY as an advanced search at scopus.com."
(interactive "sQuery: ")
(browse-url
(format
"http://www.scopus.com/results/results.url?sort=plf-f&src=s&sot=a&sdt=a&sl=%s&s=%s&origin=searchadvanced"
(length query)
(url-hexify-string query))))
;;; Org-mode EID link and an action menu
;; These functions use a global var *hydra-eid*
(defvar *hydra-eid* nil
"Global variable to pass an EID from an org-mode link to a hydra function.")
(defhydra scopus-hydra (:color blue)
("o" (scopus-open-eid *hydra-eid*) "Open in Scopus")
("a" (browse-url (format "http://www.scopus.com/search/submit/mlt.url?eid=%s&src=s&all=true&origin=recordpage&method=aut&zone=relatedDocuments" *hydra-eid*))
"Related by author")
("k" (browse-url (format "http://www.scopus.com/search/submit/mlt.url?eid=%s&src=s&all=true&origin=recordpage&method=key&zone=relatedDocuments" *hydra-eid*))
"Related by keyword")
("r" (browse-url (format "http://www.scopus.com/search/submit/mlt.url?eid=%s&src=s&all=true&origin=recordpage&method=ref&zone=relatedDocuments" *hydra-eid*))
"Related by references")
("c" (browse-url (format "http://www.scopus.com/results/citedbyresults.url?sort=plf-f&cite=%s&src=s&imp=t&sot=cite&sdt=a&sl=0&origin=recordpage" *hydra-eid*))
"Citing articles"))
(org-ref-link-set-parameters "eid"
:follow (lambda (eid)
"Opens the hydra menu."
(setq *hydra-eid* eid)
(scopus-hydra/body))
:export (lambda (keyword desc format)
(cond
((eq format 'html)
(format "<a href=\" http://www.scopus.com/record/display.url?eid=%s&origin=resultslist\">%s</a>" keyword (or desc keyword)))
((eq format 'latex)
(format "\\href{http://www.scopus.com/record/display.url?eid=%s&origin=resultslist}{%s}"
keyword (or desc keyword))))))
(org-ref-link-set-parameters "scopus-search"
:follow (lambda (query)
(scopus-basic-search query))
:export (lambda (query desc format)
(let ((url (format
"http://www.scopus.com/results/results.url?sort=plf-f&src=s&sot=b&sdt=b&sl=%s&s=TITLE-ABS-KEY%%28%s%%29&origin=searchbasic"
(length (url-unhex-string (concat "TITLE-ABS-KEY%28" (url-hexify-string query) "%29")))
(url-hexify-string query))))
(cond
((eq format 'html)
(format "<a href=\"%s\">%s</a>" url (or desc query)))
((eq format 'latex)
(format "\\href{%s}{%s}" url (or desc query)))))))
(org-ref-link-set-parameters "scopus-advanced-search"
:follow (lambda (query)
(scopus-advanced-search query))
:export (lambda (query desc format)
(let ((url (format
"http://www.scopus.com/results/results.url?sort=plf-f&src=s&sot=a&sdt=a&sl=%s&s=%s&origin=searchadvanced"
(length (url-hexify-string query))
(url-hexify-string query))))
(cond
((eq format 'html)
(format "<a href=\"%s\">%s</a>" url (or desc query)))
((eq format 'latex)
(format "\\href{%s}{%s}" url (or desc query)))))))
(org-ref-link-set-parameters "scopusid"
:follow (lambda
(link-string)
(browse-url
(format
"http://www.scopus.com/authid/detail.url?origin=AuthorProfile&authorId=%s"
link-string)))
:export (lambda (keyword desc format)
(cond
((eq format 'latex)
(format "\\href{http://www.scopus.com/authid/detail.url?origin=AuthorProfile&authorId=%s}{%s}"
keyword (or desc (concat "scopusid:" keyword))))
((eq format 'html)
(format "<a href=\"http://www.scopus.com/authid/detail.url?origin=AuthorProfile&authorId=%s\">%s</a>"
keyword (or desc (concat "scopusid:" keyword)))))))
(provide 'org-ref-scopus)
;;; org-ref-scopus.el ends here

View File

@@ -0,0 +1,275 @@
;;; org-ref-url-utils.el --- Utility functions to scrape DOIs from urls -*- lexical-binding: t; -*-
;; Copyright (C) 2015 John Kitchin
;; Author: John Kitchin <jkitchin@andrew.cmu.edu>
;; Keywords:
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;; Drag a webpage onto a bibtex file to insert a bibtex entry.
;; This works by scraping DOIs from the content at the URL using patterns in
;; `org-ref-doi-regexps'. If one DOI is found, it is added as an entry. If
;; multiple DOIs are found, you will get a helm selection buffer to choose what
;; you want to add. You can add new patterns to `org-ref-doi-regexps'.
;; You can press Control to "debug" a URL, which will open a buffer of the
;; content with the current DOI patterns highlighted. If you want to get all the
;; DOIs at a URL, you can press Meta during the drag-n-drop.
;;; Code:
(defvar org-ref-bibliography-entry-format)
(defvar org-ref-get-pdf-filename-function)
(defvar org-ref-notes-function)
(defvar org-ref-cite-types)
(declare-function 'org-ref-get-bibtex-key-and-file "org-ref-core.el")
(declare-function 'org-ref-find-bibliography "org-ref-core.el")
(declare-function 'org-ref-key-in-file-p "org-ref-core.el")
(declare-function 'org-ref-bib-citation "org-ref-core.el")
(declare-function 'org-ref-get-bibtex-key-under-cursor "org-ref-core.el")
(require 'doi-utils)
(require 'f)
(eval-when-compile
(require 'cl-lib))
(defgroup org-ref-url nil
"Customization group for org-ref-url-utils"
:tag "Org Ref URL"
:group 'org-ref-url-utils)
(defcustom org-ref-doi-regexps
'("scheme=\"doi\" content=\"\\([^\"]*\\)\""
"citation_doi\" content=\"\\([^\"]*\\)\""
"data-doi=\"\\([^\"]*\\)\""
"content=\"\\([^\"]*\\)\" name=\"citation_doi"
"objectDOI\" : \"\\([^\"]*\\)\""
"doi = '\\([^']*\\)'"
"\"http://dx.doi.org/\\([^\"]*\\)\""
"/doi/\\([^\"]*\\)\">"
"doi/full/\\(.*\\)&"
"doi=\\([^&]*\\)&amp")
"List of regexps to match a DOI.
The doi should be in group 1 so that (match-string 1) contains
the DOI."
:type '(repeat regexp)
:group 'org-ref-url-utils)
;;* Scrape DOIs from a URL
(defun org-ref-url-scrape-dois (url)
"Scrape all dois from a URL matching a pattern in `org-ref-doi-regexps'.
Returns a list of collected DOIs in the order found."
(let ((dois '()))
(with-current-buffer (url-retrieve-synchronously url)
(cl-loop for doi-pattern in org-ref-doi-regexps
do
(goto-char (point-min))
(while (re-search-forward doi-pattern nil t)
(cl-pushnew (match-string 1) dois :test #'equal)))
(reverse dois))))
(defun org-ref-url-add-doi-entries (_)
"Add all entries for CANDIDATE in `helm-marked-candidates'.
This is used in a helm selection command in `org-ref-url-dnd-protocol'."
(cl-loop for doi in (helm-marked-candidates)
do
(doi-utils-add-bibtex-entry-from-doi
doi
(buffer-file-name))
;; this removes two blank lines before each entry.
(bibtex-beginning-of-entry)
(delete-char -2)))
(defun org-ref-url-dnd-protocol (url action)
"Protocol function for use in `dnd-protocol-alist'.
We scrape DOIs from the url first. If there is one, we add it. If
there is more than one, we offer a helm buffer of selections. If
no DOI is found, we create a misc entry, with a prompt for a key."
;; make sure we are on a bib-file
(if (and (buffer-file-name)
(f-ext? (buffer-file-name) "bib"))
(let ((dois (org-ref-url-scrape-dois url)))
(cond
;; One doi found. Assume it is what we want.
((= 1 (length dois))
(doi-utils-add-bibtex-entry-from-doi
(car dois)
(buffer-file-name))
action)
;; Multiple DOIs found
((> (length dois) 1)
(helm :sources
`((name . "Select a DOI")
(candidates . ,(let ((dois '()))
(with-current-buffer (url-retrieve-synchronously url)
(cl-loop for doi-pattern in org-ref-doi-regexps
do
(goto-char (point-min))
(while (re-search-forward doi-pattern nil t)
(cl-pushnew
;; Cut off the doi, sometimes
;; false matches are long.
(cons (format "%40s | %s"
(substring
(match-string 1)
0 (min
(length (match-string 1))
40))
doi-pattern)
(match-string 1))
dois
:test #'equal)))
(reverse dois))))
(action . org-ref-url-add-doi-entries)))
action)
;; No DOIs found, add a misc entry.
(t
(goto-char (point-max))
(insert (format "\n@misc{,
url = {%s},
note = {Last accessed %s}
}"
url
(current-time-string)))
(bibtex-clean-entry)
action)))
;; pass back to dnd. Copied from `org-download-dnd'. Apparently
;; returning nil does not do this.
(let ((dnd-protocol-alist
(rassq-delete-all
'org-ref-url-dnd-protocol
(copy-alist dnd-protocol-alist))))
(dnd-handle-one-url nil action url))))
(add-to-list 'dnd-protocol-alist '("^https?" . org-ref-url-dnd-protocol))
;;* Enable a DOI to be dragged onto a bibtex buffer
(defun org-ref-doi-dnd-protocol (doi action)
"Protocol for when a doi is dragged onto a bibtex file.
A doi will be either doi:10.xxx or 10.xxx."
(if (and (buffer-file-name)
(f-ext? (buffer-file-name) "bib"))
(let ((doi (dnd-unescape-uri doi)))
;; Get the actual doi now
(string-match "\\(?:DOI\\|doi\\)?:? *\\(10.*\\)" doi)
(setq doi (match-string 1 doi))
(when doi
(doi-add-bibtex-entry doi (buffer-file-name))
(save-buffer)
action))
;; not on a bib file
(let ((dnd-protocol-alist
(rassq-delete-all
'org-ref-url-dnd-protocol
(copy-alist dnd-protocol-alist))))
(dnd-handle-one-url nil action doi))))
(add-to-list 'dnd-protocol-alist '("^doi" . org-ref-doi-dnd-protocol))
(add-to-list 'dnd-protocol-alist '("^10" . org-ref-doi-dnd-protocol))
;;* Debug URL in a buffer with C-dnd
;; You can use this to see if there are any DOIs in a URL, and to use re-builder
;; to add new patterns to `org-ref-doi-regexps'.
;;;###autoload
(defun org-ref-url-debug-url (url)
"Open a buffer to URL with all doi patterns highlighted."
(interactive)
(switch-to-buffer
(url-retrieve-synchronously url))
(highlight-regexp
(mapconcat 'identity org-ref-doi-regexps "\\|")))
;;;###autoload
(defun org-ref-url-dnd-debug (event)
"Drag-n-drop function to debug a url."
(interactive "e")
(org-ref-url-debug-url (cadr (car (last event)))))
(define-key bibtex-mode-map (kbd "<C-drag-n-drop>") 'org-ref-url-dnd-debug)
;;* Add all DOI bibtex entries with M-dnd
(defun org-ref-url-add-all-doi-entries (url)
"Add all DOI bibtex entries for URL."
(cl-loop for doi in (org-ref-url-scrape-dois url)
do
(ignore-errors
(doi-utils-add-bibtex-entry-from-doi
doi
(buffer-file-name))
;; this removes two blank lines before each entry.
(bibtex-beginning-of-entry)
(delete-char -2))))
;;;###autoload
(defun org-ref-url-dnd-all (event)
"Drag-n-drop function to get all DOI bibtex entries for a url.
You probably do not want to do this since the DOI patterns are
not perfect, and some hits are not actually DOIs."
(interactive "e")
(org-ref-url-add-all-doi-entries (cadr (car (last event)))))
(define-key bibtex-mode-map (kbd "<M-drag-n-drop>") 'org-ref-url-dnd-all)
;; Get first DOI if there is one with s-dnd
(defun org-ref-url-add-first-doi-entry (url)
"Add first DOI bibtex entry for URL if there is one."
(let* ((dois (org-ref-url-scrape-dois url))
(doi (car dois)))
(if doi
(progn
(doi-utils-add-bibtex-entry-from-doi
doi
(buffer-file-name))
;; this removes two blank lines before each entry.
(bibtex-beginning-of-entry)
(delete-char -2))
;; no doi, add misc
(goto-char (point-max))
(insert (format "\n@misc{,
url = {%s},
note = {Last accessed %s}
}"
url
(current-time-string)))
(bibtex-clean-entry))))
;;;###autoload
(defun org-ref-url-dnd-first (event)
"Drag-n-drop function to download the first DOI in a url."
(interactive "e")
(org-ref-url-add-first-doi-entry (cadr (car (last event)))))
(define-key bibtex-mode-map (kbd "<s-drag-n-drop>") 'org-ref-url-dnd-first)
(provide 'org-ref-url-utils)
;;; org-ref-url-utils.el ends here

View File

@@ -0,0 +1,841 @@
;;; org-ref-utils.el --- Utility functions for org-ref -*- lexical-binding: t; -*-
;; Copyright (C) 2016 John Kitchin
;; Author: John Kitchin <jkitchin@andrew.cmu.edu>
;; Keywords:
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;;
(require 'org)
(require 'org-ref-pdf) ; for pdftotext-executable
(defcustom org-ref-bib-html "<h1 class='org-ref-bib-h1'>Bibliography</h1>\n"
"HTML header to use for bibliography in HTML export."
:type 'string
:group 'org-ref)
(defvar org-ref-cite-types)
(defvar org-ref-get-pdf-filename-function)
(defvar org-ref-notes-function)
(defvar org-ref-bibliography-entry-format)
(declare-function 'org-ref-get-bibtex-key-and-file "org-ref-core.el")
(declare-function 'org-ref-key-in-file-p "org-ref-core.el")
(declare-function 'org-ref-find-bibliography "org-ref-core.el")
(declare-function 'org-ref-bib-citation "org-ref-core.el")
(declare-function 'org-ref-get-bibtex-key-under-cursor "org-ref-core.el")
;;; Code:
;;;###autoload
(defun org-ref-version ()
"Provide a version string for org-ref.
Copies the string to the clipboard."
(interactive)
;; version in the el file.
(let* ((org-ref-el (concat
(file-name-sans-extension
(locate-library "org-ref"))
".el"))
(org-ref-dir (file-name-directory org-ref-el))
org-version
git-commit
version-string)
(setq org-version (with-temp-buffer
(insert-file-contents org-ref-el)
(goto-char (point-min))
(re-search-forward ";; Version:")
(s-trim (buffer-substring (point)
(line-end-position)))))
(setq git-commit
;; If in git, get current commit
(let ((default-directory org-ref-dir))
(when (= 0 (shell-command "git rev-parse --git-dir"))
(s-trim (shell-command-to-string "git rev-parse HEAD")))))
(setq version-string (format "org-ref: Version %s%s" org-version
(if git-commit
(format " (git-commit %s)" git-commit)
"")))
(kill-new version-string)
(message version-string)))
(defun org-ref-report-issue ()
"Report an issue in org-ref.
Opens https://github.com/jkitchin/org-ref/issues/new."
(save-window-excursion
(org-ref-debug)
(kill-new (buffer-string)))
(message "org-ref-debug has been run. You can paste the results in the issue website if you like.")
(browse-url "https://github.com/jkitchin/org-ref/issues/new"))
;;* Debug(require 'org-ref-pdf)
(defmacro ords (&rest body)
"Evaluate BODY and return a string."
`(format "%s" (progn ,@body)))
;;;###autoload
(defun org-ref-debug ()
"Print some debug information to a buffer."
(interactive)
(switch-to-buffer "*org-ref-debug*")
(erase-buffer)
(org-mode)
(insert
(s-format "#+TITLE: org-ref debug
${org-ref-version}
* Variables
1. org-ref-completion-library: ${org-ref-completion-library}
2. org-ref-bibliography-notes: ${org-ref-bibliography-notes} (exists ${orbn-p})
3. org-ref-default-bibliography: ${org-ref-default-bibliography} (exists ${ordb-p}) (listp ${ordb-listp})
4. org-ref-pdf-directory: ${org-ref-pdf-directory} (exists ${orpd-p})
* System
system-type: ${system}
system-configuration: ${system-configuration}
window system: ${window-system}
Emacs: ${emacs-version}
org-version: ${org-version}
* about org-ref
org-ref installed in ${org-ref-location}.
** Dependencies
helm-bibtex ${helm-bibtex-path}
* org-ref-pdf (loaded: ${org-ref-pdf-p})
system pdftotext: ${pdftotext}
You set pdftotext-executable to ${pdftotext-executable} (exists: ${pdftotext-executable-p})
* org-ref-url-utils (loaded: ${org-ref-url-p})
* export variables
org-latex-pdf-process:
${org-latex-pdf-process}
"
'aget
`(("org-ref-completion-library" . ,(format "%s" org-ref-completion-library))
("org-ref-bibliography-notes" . ,(format "%s" org-ref-bibliography-notes))
("orbn-p" . ,(format "%s" (file-exists-p org-ref-bibliography-notes)))
("org-ref-version" . ,(org-ref-version))
("org-latex-pdf-process" . ,(format "%S" org-latex-pdf-process))
("org-ref-default-bibliography" . ,(format "%s" org-ref-default-bibliography))
("ordb-p" . ,(format "%s" (mapcar 'file-exists-p org-ref-default-bibliography)))
("ordb-listp" . ,(ords (listp org-ref-default-bibliography)))
("org-ref-pdf-directory" . ,(format "%s" org-ref-pdf-directory))
("orpd-p" . ,(format "%s" (file-exists-p org-ref-pdf-directory)))
("org-ref-location" . ,(format "%s" (locate-library "org-ref")))
("system" . ,(format "System: %s" system-type))
("system-configuration" . ,(ords system-configuration))
("window-system" . ,(format "Window system: %s" window-system))
("emacs-version" . ,(ords (emacs-version)))
("org-version" . ,(org-version))
("helm-bibtex-path" . ,(ords (locate-library "helm-bibtex")))
("org-ref-pdf-p" . ,(ords (featurep 'org-ref-pdf)))
("pdftotext" . ,(ords (if (featurep 'org-ref-pdf)
(executable-find "pdftotext")
"org-ref-pdf not loaded")))
("pdftotext-executable" . ,(ords (if (featurep 'org-ref-pdf)
pdftotext-executable
"org-ref-pdf not loaded")))
("pdftotext-executable-p" . ,(ords (if (featurep 'org-ref-pdf)
(or
(executable-find pdftotext-executable)
(file-exists-p pdftotext-executable))
"org-ref-pdf not loaded")))
("org-ref-url-p" . ,(ords (featurep 'org-ref-url)))))))
(defun org-ref-reftex-get-bib-field (field entry &optional format)
"Get FIELD from a bibtex ENTRY in optional FORMAT.
Similar to `reftex-get-bib-field', but removes enclosing braces
and quotes in FIELD in the bibtex ENTRY."
(let ((result))
(setq result (reftex-get-bib-field field entry format))
(when (and (not (string= result "")) (string= "{" (substring result 0 1)))
(setq result (substring result 1 -1)))
(when (and (not (string= result "")) (string= "\"" (substring result 0 1)))
(setq result (substring result 1 -1)))
result))
(defun org-ref-reftex-format-citation (entry format)
"Format the bibtex ENTRY according to the FORMAT argument.
ENTRY is from `bibtex-parse-entry'
The FORMAT is a string with these percent escapes.
In the format, the following percent escapes will be expanded.
%l The BibTeX label of the citation.
%a List of author names, see also `reftex-cite-punctuation'.
%2a Like %a, but abbreviate more than 2 authors like Jones et al.
%A First author name only.
%e Works like %a, but on list of editor names. (%2e and %E work as well)
It is also possible to access all other BibTeX database fields:
%b booktitle %c chapter %d edition %h howpublished
%i institution %j journal %k key %m month
%n number %o organization %p pages %P first page
%r address %s school %u publisher %t title
%v volume %y year
%B booktitle, abbreviated %T title, abbreviated
%U url
%D doi
%S series %N note
%f pdf filename
%F absolute pdf filename
Usually, only %l is needed. The other stuff is mainly for the echo area
display, and for (setq reftex-comment-citations t).
%< as a special operator kills punctuation and space around it after the
string has been formatted.
A pair of square brackets indicates an optional argument, and RefTeX
will prompt for the values of these arguments.
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
(string-match "%l" reftex-cite-comment-format))
(error "Reftex-cite-comment-format contains invalid %%l"))
(while (string-match
"\\(\\`\\|[^%]\\)\\(\\(%\\([0-9]*\\)\\([a-zA-Z]\\)\\)[.,;: ]*\\)"
format)
(let ((n (string-to-number (match-string 4 format)))
(l (string-to-char (match-string 5 format)))
rpl b e)
(save-match-data
(setq rpl
(cond
((= l ?l) (concat
(org-ref-reftex-get-bib-field "&key" entry)
(if reftex-comment-citations
reftex-cite-comment-format
"")))
((= l ?a) (replace-regexp-in-string
"\n\\|\t\\|\s+" " "
(reftex-format-names
(reftex-get-bib-names "author" entry)
(or n 2))))
((= l ?A) (replace-regexp-in-string
"\n\\|\t\\|\s+" " "
(car (reftex-get-bib-names "author" entry))))
((= l ?b) (org-ref-reftex-get-bib-field "booktitle" entry "in: %s"))
((= l ?B) (reftex-abbreviate-title
(org-ref-reftex-get-bib-field "booktitle" entry "in: %s")))
((= l ?c) (org-ref-reftex-get-bib-field "chapter" entry))
((= l ?d) (org-ref-reftex-get-bib-field "edition" entry))
((= l ?D) (org-ref-reftex-get-bib-field "doi" entry))
((= l ?e) (reftex-format-names
(reftex-get-bib-names "editor" entry)
(or n 2)))
((= l ?E) (car (reftex-get-bib-names "editor" entry)))
((= l ?f) (concat (org-ref-reftex-get-bib-field "=key=" entry) ".pdf"))
((= l ?F) (concat org-ref-pdf-directory (org-ref-reftex-get-bib-field "=key=" entry) ".pdf"))
((= l ?h) (org-ref-reftex-get-bib-field "howpublished" entry))
((= l ?i) (org-ref-reftex-get-bib-field "institution" entry))
((= l ?j) (let ((jt (reftex-get-bib-field "journal" entry)))
(if (string= "" jt)
(reftex-get-bib-field "journaltitle" entry)
jt)))
((= l ?k) (org-ref-reftex-get-bib-field "=key=" entry))
((= l ?m) (org-ref-reftex-get-bib-field "month" entry))
((= l ?n) (org-ref-reftex-get-bib-field "number" entry))
((= l ?N) (org-ref-reftex-get-bib-field "note" entry))
((= l ?o) (org-ref-reftex-get-bib-field "organization" entry))
((= l ?p) (org-ref-reftex-get-bib-field "pages" entry))
((= l ?P) (car (split-string
(org-ref-reftex-get-bib-field "pages" entry)
"[- .]+")))
((= l ?s) (org-ref-reftex-get-bib-field "school" entry))
((= l ?S) (org-ref-reftex-get-bib-field "series" entry))
((= l ?u) (org-ref-reftex-get-bib-field "publisher" entry))
((= l ?U) (org-ref-reftex-get-bib-field "url" entry))
((= l ?r) (org-ref-reftex-get-bib-field "address" entry))
;; strip enclosing brackets from title if they are there
((= l ?t) (replace-regexp-in-string
"\n\\|\t\\|\s+" " "
(org-ref-reftex-get-bib-field "title" entry)))
((= l ?T) (reftex-abbreviate-title
(replace-regexp-in-string
"\n\\|\t\\|\s+" " "
(org-ref-reftex-get-bib-field "title" entry))))
((= l ?v) (org-ref-reftex-get-bib-field "volume" entry))
((= l ?y) (org-ref-reftex-get-bib-field "year" entry)))))
(if (string= rpl "")
(setq b (match-beginning 2) e (match-end 2))
(setq b (match-beginning 3) e (match-end 3)))
(setq format (concat (substring format 0 b) rpl (substring format e)))))
(while (string-match "%%" format)
(setq format (replace-match "%" t t format)))
(while (string-match "[ ,.;:]*%<" format)
(setq format (replace-match "" t t format)))
format)
(defun org-ref-get-bibtex-entry-citation (key)
"Return a string for the bibliography entry corresponding to KEY.
Format according to the type in `org-ref-bibliography-entry-format'."
(let ((org-ref-bibliography-files (org-ref-find-bibliography))
(file) (entry) (bibtex-entry) (entry-type) (format))
(setq file (catch 'result
(cl-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))))))
(with-temp-buffer
(insert-file-contents file)
(bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
(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)))))
entry))
(defun org-ref-get-bibtex-entry (key)
"Return the bibtex entry as a string."
(let ((org-ref-bibliography-files (org-ref-find-bibliography))
(file) (entry))
(setq file (catch 'result
(cl-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))))))
(with-temp-buffer
(insert-file-contents file)
(bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
(bibtex-search-entry key nil 0)
(save-restriction
(bibtex-narrow-to-entry)
(setq entry (buffer-string)))
entry)))
;;*** key at point functions
(defun org-ref-get-pdf-filename (key)
"Return the pdf filename associated with a bibtex KEY.
If `org-ref-pdf-directory' is non-nil, put filename there."
(if org-ref-pdf-directory
(let ((pdf (-first 'f-file?
(--map (f-join it (concat key ".pdf"))
(-flatten (list org-ref-pdf-directory))))))
(format "%s" pdf))
(format "%s.pdf" key)))
(defun org-ref-get-mendeley-filename (key)
"Return the pdf filename indicated by mendeley file field.
Falls back to `org-ref-get-pdf-filename' if file field does not exist.
Contributed by https://github.com/autosquid.
Argument KEY is the bibtex key."
(let* ((results (org-ref-get-bibtex-key-and-file key))
(bibfile (cdr results))
entry)
(with-temp-buffer
(insert-file-contents bibfile)
(bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
(bibtex-search-entry key nil 0)
(setq entry (bibtex-parse-entry))
(let ((e (org-ref-reftex-get-bib-field "file" entry)))
(if (> (length e) 4)
(let ((clean-field (replace-regexp-in-string "{\\|}\\|\\\\" "" e)))
(let ((first-file (car (split-string clean-field ";" t))))
(format "/%s" (substring first-file 1
(- (length first-file) 4)))))
(format (concat
(file-name-as-directory org-ref-pdf-directory)
"%s.pdf")
key))))))
(defun org-ref-get-pdf-filename-helm-bibtex (key)
"Use helm-bibtex to retrieve a PDF filename for KEY.
helm-bibtex looks in both the configured directory
`bibtex-completion-library-path' and in the fields of the bibtex
item for a filename. It understands file fields exported by
Jabref, Mendeley and Zotero. See `bibtex-completion-find-pdf'."
(let ((bibtex-completion-bibliography (org-ref-find-bibliography)))
(or (car (bibtex-completion-find-pdf key)) "")))
;;;###autoload
(defun org-ref-open-pdf-at-point ()
"Open the pdf for bibtex key under point if it exists."
(interactive)
(let* ((results (org-ref-get-bibtex-key-and-file))
(key (car results))
(pdf-file (funcall org-ref-get-pdf-filename-function key)))
(if (file-exists-p pdf-file)
(org-open-file pdf-file)
(message "no pdf found for %s" key))))
;;;###autoload
(defun org-ref-open-url-at-point ()
"Open the url for bibtex key under point."
(interactive)
(let* ((results (org-ref-get-bibtex-key-and-file))
(key (car results))
(bibfile (cdr results)))
(save-excursion
(with-temp-buffer
(insert-file-contents bibfile)
(bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
(bibtex-search-entry key)
;; I like this better than bibtex-url which does not always find
;; the urls
(catch 'done
(let ((url (s-trim (bibtex-autokey-get-field "url"))))
(unless (s-blank? url)
(browse-url url)
(throw 'done nil)))
(let ((doi (s-trim (bibtex-autokey-get-field "doi"))))
(unless (s-blank? doi)
(if (string-match "^http" doi)
(browse-url doi)
(browse-url (format "http://dx.doi.org/%s" doi)))
(throw 'done nil))))))))
;;;###autoload
(defun org-ref-open-notes-at-point (&optional thekey)
"Open the notes for bibtex key under point in a cite link in a buffer.
Can also be called with THEKEY in a program."
(interactive)
(funcall org-ref-notes-function thekey))
;;;###autoload
(defun org-ref-citation-at-point ()
"Give message of current citation at point."
(interactive)
(org-ref-format-entry (org-ref-get-bibtex-key-under-cursor))
;; (let* ((results (org-ref-get-bibtex-key-and-file))
;; (key (car results))
;; (bibfile (cdr results)))
;; (message "%s" (progn
;; (with-temp-buffer
;; (insert-file-contents bibfile)
;; (bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
;; (bibtex-search-entry key)
;; (org-ref-bib-citation)))))
)
;;;###autoload
(defun org-ref-open-citation-at-point ()
"Open bibtex file to key at point."
(interactive)
(let* ((results (org-ref-get-bibtex-key-and-file))
(key (car results))
(bibfile (cdr results)))
(find-file bibfile)
(bibtex-search-entry key)))
;;*** cite menu
(defvar org-ref-cite-menu-funcs '()
"Functions to run on cite click menu.
Each entry is a list of (key menu-name function). The function
must take no arguments and work on the key at point. Do not
modify this variable, it is set to empty in the menu click
function, and functions are conditionally added to it.")
(defvar org-ref-user-cite-menu-funcs
'(("C" "rossref" org-ref-crossref-at-point)
("y" "Copy entry to file" org-ref-copy-entry-at-point-to-file)
("s" "Copy summary" org-ref-copy-entry-as-summary))
"User-defined functions to run on bibtex key at point.")
;;;###autoload
(defun org-ref-copy-entry-as-summary ()
"Copy the bibtex entry for the citation at point as a summary."
(interactive)
(kill-new (org-ref-bib-citation)))
;;;###autoload
(defun org-ref-copy-entry-at-point-to-file ()
"Copy the bibtex entry for the citation at point to NEW-FILE.
Prompt for NEW-FILE includes bib files in
`org-ref-default-bibliography', and bib files in current working
directory. You can also specify a new file."
(interactive)
(let ((new-file (completing-read
"Copy to bibfile: "
(append org-ref-default-bibliography
(f-entries "." (lambda (f) (f-ext? f "bib"))))))
(key (org-ref-get-bibtex-key-under-cursor)))
(save-window-excursion
(org-ref-open-citation-at-point)
(bibtex-copy-entry-as-kill))
(let ((bibtex-files (list (file-truename new-file))))
(if (assoc key (bibtex-global-key-alist))
(message "That key already exists in %s" new-file)
;; add to file
(save-window-excursion
(find-file new-file)
(goto-char (point-max))
;; make sure we are at the beginning of a line.
(unless (looking-at "^") (insert "\n\n"))
(bibtex-yank)
(save-buffer))))))
(defun org-ref-get-doi-at-point ()
"Get doi for key at point."
(let* ((results (org-ref-get-bibtex-key-and-file))
(key (car results))
(bibfile (cdr results))
doi)
(save-excursion
(with-temp-buffer
(insert-file-contents bibfile)
(bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
(bibtex-search-entry key)
(setq doi (bibtex-autokey-get-field "doi"))
;; in case doi is a url, remove the url part.
(replace-regexp-in-string "^http://dx.doi.org/" "" doi)))))
;;**** functions that operate on key at point for click menu
;;;###autoload
(defun org-ref-wos-at-point ()
"Open the doi in wos for bibtex key under point."
(interactive)
(doi-utils-wos (org-ref-get-doi-at-point)))
;;;###autoload
(defun org-ref-wos-citing-at-point ()
"Open the doi in wos citing articles for bibtex key under point."
(interactive)
(doi-utils-wos-citing (org-ref-get-doi-at-point)))
;;;###autoload
(defun org-ref-wos-related-at-point ()
"Open the doi in wos related articles for bibtex key under point."
(interactive)
(doi-utils-wos-related (org-ref-get-doi-at-point)))
;;;###autoload
(defun org-ref-google-scholar-at-point ()
"Search google scholar for bibtex key under point using the title."
(interactive)
(browse-url
(format
"http://scholar.google.com/scholar?q=%s"
(let* ((key-file (org-ref-get-bibtex-key-and-file))
(key (car key-file))
(file (cdr key-file))
entry)
(with-temp-buffer
(insert-file-contents file)
(bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
(bibtex-search-entry key nil 0)
(setq entry (bibtex-parse-entry))
(org-ref-reftex-get-bib-field "title" entry))))))
;;;###autoload
(defun org-ref-pubmed-at-point ()
"Open the doi in pubmed for bibtex key under point."
(interactive)
(doi-utils-pubmed (org-ref-get-doi-at-point)))
;;;###autoload
(defun org-ref-crossref-at-point ()
"Open the doi in crossref for bibtex key under point."
(interactive)
(doi-utils-crossref (org-ref-get-doi-at-point)))
;;* General org-ref utilities
(defun org-ref-strip-string (string)
"Strip leading and trailing whitespace from the STRING."
(replace-regexp-in-string
(concat search-whitespace-regexp "$" ) ""
(replace-regexp-in-string
(concat "^" search-whitespace-regexp ) "" string)))
(defun org-ref-split-and-strip-string (string)
"Split key-string and strip keys in STRING.
Assumes the key-string is comma delimited."
(mapcar 'org-ref-strip-string (split-string string ",")))
(defun org-ref-get-bibtex-keys (&optional sort)
"Return a list of unique keys in the buffer.
Use SORT to specify alphabetical order by key."
(let ((keys '()))
(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 (-contains? keys key))
(setq keys (append keys (list key))))))))
;; set with-affiliated to get keys in captions
nil nil nil t)
(when sort
;; Sort keys alphabetically
(setq keys (cl-sort keys 'string-lessp :key 'downcase)))
keys))
;;;###autoload
(defun org-ref-bibliography (&optional sort)
"Create a new buffer with a bibliography.
If SORT is non-nil it is alphabetically sorted by key
This is mostly for convenience to see what has been cited.
Entries are formatted according to the bibtex entry type in
`org-ref-bibliography-entry-format', and the actual entries are
generated by `org-ref-reftex-format-citation'."
(interactive)
(let ((bib (mapconcat
'identity
(cl-loop for i from 1
for citation in
(mapcar
(lambda (key)
(let* ((results (org-ref-get-bibtex-key-and-file key))
(key (car results))
(bibfile (cdr results)))
(format "cite:%s %s" key
(if bibfile
(save-excursion
(with-temp-buffer
(insert-file-contents bibfile)
(bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
(bibtex-search-entry key)
(org-ref-bib-citation)))
"!!! No entry found !!!"))))
(org-ref-get-bibtex-keys sort))
collect (format "%3s. %s" i citation))
"\n\n")))
(switch-to-buffer-other-window (format "%s-bibliography" (buffer-file-name)))
(erase-buffer)
(insert bib)
(org-mode)))
(defun org-ref-get-bibtex-entry-html (key)
"Return an html string for the bibliography entry corresponding to KEY."
(let ((output))
(setq output (concat (format "<a name=\"%s\"></a>" key)
(org-ref-get-bibtex-entry-citation key)))
(setq output (org-ref-clean-unused-entry-html output))
(format "<li><a id=\"%s\">[%s]</a> %s</li>"
key key output)))
(defun org-ref-clean-unused-entry-html (entry-html)
"Return from the html string ENTRY-HTML a cleaner version"
;; unescape the &
(setq entry-html (replace-regexp-in-string "\\\\&" "&" entry-html))
;; hack to replace {} around text
(setq entry-html (replace-regexp-in-string "{" "" entry-html))
(setq entry-html (replace-regexp-in-string "}" "" entry-html))
;; get rid of empty parens
(setq entry-html (replace-regexp-in-string "()" "" entry-html))
;; Remove empty volume, number field if empty
(setq entry-html (replace-regexp-in-string "<b></b>," "" entry-html))
;; get rid of empty link and doi
(setq entry-html (replace-regexp-in-string " <a href=\"\">link</a>\\." "" entry-html))
;; change double dash to single dash
(setq entry-html (replace-regexp-in-string "--" "-" entry-html))
(setq entry-html (replace-regexp-in-string " <a href=\"http://dx\\.doi\\.org/\">doi</a>\\." "" entry-html))
entry-html)
(defun org-ref-get-html-bibliography (&optional sort)
"Create an html bibliography when there are keys.
If SORT is non-nil the bibliography is alphabetically sorted."
(let ((keys (org-ref-get-bibtex-keys sort)))
(when keys
(concat org-ref-bib-html "<ul class='org-ref-bib'>"
(mapconcat (lambda (x) (org-ref-get-bibtex-entry-html x)) keys "\n")
"\n</ul>"))))
(defun org-ref-get-bibtex-entry-org (key)
"Return an org string for the bibliography entry corresponding to KEY."
(let ((org-ref-bibliography-files (org-ref-find-bibliography))
file entry)
(setq file (catch 'result
(cl-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))))))
(with-temp-buffer
(insert-file-contents file)
(bibtex-set-dialect (parsebib-find-bibtex-dialect) t)
(bibtex-search-entry key nil 0)
(setq entry (bibtex-parse-entry))
(format "** %s - %s
:PROPERTIES:
%s
:END:
" (org-ref-reftex-get-bib-field "author" entry)
(org-ref-reftex-get-bib-field "title" entry)
(concat " :CUSTOM_ID: " (org-ref-reftex-get-bib-field "=key=" entry) "\n"
(mapconcat
(lambda (element) (format " :%s: %s"
(upcase (car element))
(cdr element)))
entry
"\n"))))))
(defun org-ref-get-org-bibliography (&optional sort)
"Create an org bibliography when there are keys.
If SORT is non-nil the bibliography is sorted alphabetically by key."
(let ((keys (org-ref-get-bibtex-keys sort)))
(when keys
(concat "* Bibliography\n"
(mapconcat (lambda (x)
(org-ref-get-bibtex-entry-org x)) keys "\n")
"\n"))))
(defun org-ref-get-bibtex-entry-ascii (key)
"Return an ascii string for the bibliography entry corresponding to KEY."
(format "[%s] %s" key (org-ref-get-bibtex-entry-citation key)))
(defun org-ref-get-bibtex-entry-md (key)
"Return a md string for the bibliography entry corresponding to KEY."
;; We create an anchor to the key that we can jump to, and provide a jump back
;; link with the md5 of the key.
(format "<a id=\"%s\"></a>[%s] %s%s [↩](#%s)"
key key
(org-ref-clean-unused-entry-html (org-ref-get-bibtex-entry-citation key))
""
;; Note: This is to temporarily resolve issue #558. This worked fine
;; for me earlier, so I don't know why it doesn't work in this issue.
;; (if (plist-get info :md-publish-bibtex)
;; (format
;; " <a href=\"data:text/plain;charset=US-ASCII;base64,%s\" title=\"%s\">[bib]</a>"
;; (base64-encode-string (org-ref-get-bibtex-entry key))
;; (concat "Right-click to open\n" (xml-escape-string
;; (org-ref-get-bibtex-entry key))))
;; "")
(md5 key)))
(defun org-ref-get-ascii-bibliography (&optional sort)
"Create an ascii bibliography when there are keys.
if SORT is non-nil the bibliography is sorted alphabetically by key."
(let ((keys (org-ref-get-bibtex-keys sort)))
(when keys
(concat
"\n\nBibliography\n=============\n\n"
(mapconcat (lambda (x) (org-ref-get-bibtex-entry-ascii x)) keys "\n")
"\n"))))
(defun org-ref-get-md-bibliography (&optional sort)
"Create an md bibliography when there are keys.
if SORT is non-nil the bibliography is sorted alphabetically by key."
(let ((keys (org-ref-get-bibtex-keys sort)))
(when keys
(concat
"# Bibliography\n"
(mapconcat (lambda (x) (org-ref-get-bibtex-entry-md x)) keys "\n\n")
"\n"))))
(defun org-ref-get-odt-bibliography (&optional sort)
"Create an ascii bibliography ofr odt export when there are keys.
if SORT is non-nil the bibliography is sorted alphabetically by
key. This is a variant of `org-ref-get-ascii-bibliography' where
some things are escaped since odt is an xml format."
(let ((keys (org-ref-get-bibtex-keys sort)))
(when keys
(mapconcat (lambda (x)
(xml-escape-string (org-ref-get-bibtex-entry-ascii x)))
keys "\n"))))
(defun org-ref-pdf-p (filename)
"Check if FILENAME is PDF file.
From the PDF specification 1.7:
The first line of a PDF file shall be a header consisting of
the 5 characters %PDF- followed by a version number of the
form 1.N, where N is a digit between 0 and 7."
(let ((header (with-temp-buffer
(set-buffer-multibyte nil)
(insert-file-contents-literally filename nil 0 5)
(buffer-string))))
(string-equal (encode-coding-string header 'utf-8) "%PDF-")))
;;;###autoload
(defmacro org-ref-link-set-parameters (type &rest parameters)
"Set link TYPE properties to PARAMETERS."
(declare (indent 1))
(if (fboundp 'org-link-set-parameters)
`(org-link-set-parameters ,type ,@parameters)
`(org-add-link-type ,type ,(plist-get parameters :follow) ,(plist-get parameters :export))))
(provide 'org-ref-utils)
;;; org-ref-utils.el ends here

View File

@@ -0,0 +1,20 @@
;;; org-ref-worldcat.el --- Worldcat library
;;; Commentary:
;; Provides a function to query world cat
;; See:
;; https://www.worldcat.org/wcpa/content/affiliate/default.jsp
;; https://www.worldcat.org/affiliate/tools?atype=text
;;; Code:
(defun worldcat-query-all (query)
"Open browser to Worldcat QUERY."
(browse-url
(format
"http://www.worldcat.org/search?qt=worldcat_org_all&q=%s"
query)))
(provide 'org-ref-worldcat)
;;; org-ref-worldcat.el ends here

View File

@@ -0,0 +1,107 @@
;;; org-ref-wos.el --- Web of Science functions -*- lexical-binding: t; -*-
;; Copyright (C) 2015 John Kitchin
;; Author: John Kitchin <jkitchin@andrew.cmu.edu>
;; Keywords:
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;; Adds a new org-mode link for a search in Web of Science.
;;; and an org-mode link for a link to an Accession number.
(require 'org)
(require 's)
(require 'org-ref-utils)
;;; Code:
(org-ref-link-set-parameters "wos"
:follow (lambda (accession-number)
(browse-url
(concat
"http://ws.isiknowledge.com/cps/openurl/service?url_ver=Z39.88-2004&rft_id=info:ut/"
accession-number)))
:export (lambda (accession-number desc format)
(cond
((eq format 'html)
(format "<a href=\"http://ws.isiknowledge.com/cps/openurl/service?url_ver=Z39.88-2004&rft_id=info:ut/%s\">%s</a>"
accession-number
(or desc (concat "wos:" accession-number)))))))
(org-ref-link-set-parameters "wos-search"
:follow (lambda (path)
(browse-url
(format "http://gateway.webofknowledge.com/gateway/Gateway.cgi?topic=%s&GWVersion=2&SrcApp=WEB&SrcAuth=HSB&DestApp=UA&DestLinkType=GeneralSearchSummary"
(s-join "+" (split-string path)))))
:export (lambda (link desc format)
(cond
((eq format 'html)
(format "<a href=\"%s\">%s</a>"
(format "http://gateway.webofknowledge.com/gateway/Gateway.cgi?topic=%s&GWVersion=2&SrcApp=WEB&SrcAuth=HSB&DestApp=UA&DestLinkType=GeneralSearchSummary"
(s-join "+" (split-string link)))
(or desc link))))))
;;;###autoload
(defun wos-search ()
"Open the word at point or selection in Web of Science as a topic query."
;; the url was derived from this page: http://wokinfo.com/webtools/searchbox/
(interactive)
(browse-url
(format "http://gateway.webofknowledge.com/gateway/Gateway.cgi?topic=%s&GWVersion=2&SrcApp=WEB&SrcAuth=HSB&DestApp=UA&DestLinkType=GeneralSearchSummary"
(if (region-active-p)
(mapconcat 'identity (split-string
(buffer-substring (region-beginning)
(region-end))) "+")
(thing-at-point 'word)))))
;;;###autoload
(defun wos ()
"Open Web of Science search page in a browser."
(interactive)
(browse-url "http://apps.webofknowledge.com"))
;;* Accession numbers
;; see http://kitchingroup.cheme.cmu.edu/blog/2015/06/08/Getting-a-WOS-Accession-number-from-a-DOI/
(defvar *wos-redirect* nil
"Holds the redirect from a `url-retrieve' callback function.")
(defvar *wos-waiting* nil
"Non-nil when waiting for a `url-retrieve' redirect.")
(defun wos-get-wos-redirect (url)
"Return final redirect URL for open-url."
(setq *wos-waiting* t)
(url-retrieve
url
(lambda (status)
(setq *wos-redirect* (car (last status)))
(setq *wos-waiting* nil)))
(while *wos-waiting* (sleep-for 0.1))
(url-unhex-string *wos-redirect*))
(defun wos-doi-to-accession-number (doi)
"Return a WOS Accession number for a DOI."
(let* ((open-url (concat "http://ws.isiknowledge.com/cps/openurl/service?url_ver=Z39.88-2004&rft_id=info:doi/" doi))
(redirect (wos-get-wos-redirect open-url)))
(message redirect)
(string-match "&KeyUT=WOS:\\([^&]*\\)&" redirect)
(match-string 1 redirect)))
(provide 'org-ref-wos)
;;; org-ref-wos.el ends here

View File

@@ -0,0 +1,332 @@
@book{Dominik201408,
keywords = {org-mode},
url = {http://amazon.com/o/ASIN/9881327709/},
isbn = 9789881327703,
year = 2014,
publisher = {Samurai Media Limited},
author = {Carsten Dominik},
title = {The Org Mode 8 Reference Manual - Organize your life with GNU
Emacs},
}
@article{xu-2015-relat-between,
title = {Relationships Between the Surface Electronic and Chemical
Properties of Doped 4d and 5d Late Transition Metal Dioxides},
eid = 104703,
url =
"http://scitation.aip.org/content/aip/journal/jcp/142/10/10.1063/1.4914093",
doi = {10.1063/1.4914093},
year = 2015,
pages = 104703,
number = 10,
volume = 142,
journal = "The Journal of Chemical Physics",
keywords = {DESC0004031, early-career, orgmode},
author = "Xu, Zhongnan and Kitchin, John R.",
}
@article{xu-2015-linear-respon,
title = {A Linear Response {DFT}+{U} Study of Trends in the Oxygen
Evolution Activity of Transition Metal Rutile Dioxides},
eprint = { http://dx.doi.org/10.1021/jp511426q },
url = { http://dx.doi.org/10.1021/jp511426q },
doi = {10.1021/jp511426q},
year = 2015,
pages = {4827-4833},
number = 9,
volume = 119,
journal = {The Journal of Physical Chemistry C},
keywords = {DESC0004031, early-career, orgmode, },
author = {Xu, Zhongnan and Rossmeisl, Jan and Kitchin, John R.},
}
@article{boes-2015-suppor-infor,
title = {Supporting Information: Estimating Bulk-Composition-Dependent
\ce{H2} Adsorption Energies on \ce{Cu_{x}Pd_{1-x}} Alloy (111)
Surfaces},
url =
{http://pubs.acs.org/doi/suppl/10.1021/cs501585k/suppl_file/cs501585k_si_001.pdf},
doi = {10.1021/cs501585k},
year = 2015,
pages = {1020-1026},
volume = 5,
journal = {ACS Catalysis},
keywords = {orgmode},
author = {Jacob R. Boes and Gamze Gumuslu and James B. Miller and Andrew
J. Gellman and John R. Kitchin},
}
@article{boes-2015-estim-bulk,
title = {Estimating Bulk-Composition-Dependent \ce{H2} Adsorption
Energies on \ce{Cu_{x}Pd_{1-x}} Alloy (111) Surfaces},
url = {http://dx.doi.org/10.1021/cs501585k},
doi = {10.1021/cs501585k},
year = 2015,
pages = {1020-1026},
volume = 5,
keywords = {orgmode},
journal = {ACS Catalysis},
author = {Jacob R. Boes and Gamze Gumuslu and James B. Miller and Andrew
J. Gellman and John R. Kitchin},
}
@article{curnan-2014-effec-concen,
title = {Effects of Concentration, Crystal Structure, Magnetism, and
Electronic Structure Method on First-Principles Oxygen Vacancy
Formation Energy Trends in Perovskites},
eprint = { http://dx.doi.org/10.1021/jp507957n },
url = {http://dx.doi.org/10.1021/jp507957n},
doi = {10.1021/jp507957n},
year = 2014,
pages = {28776-28790},
number = 49,
volume = 118,
journal = {The Journal of Physical Chemistry C},
keywords = {orgmode, },
author = {Curnan, Matthew T. and Kitchin, John R.},
}
@article{miller-2014-simul-temper,
title = {Simulating Temperature Programmed Desorption of Oxygen on
{P}t(111) Using {DFT} Derived Coverage Dependent Desorption
Barriers},
url = {http://dx.doi.org/10.1007/s11244-013-0166-3},
doi = {10.1007/s11244-013-0166-3},
year = 2014,
pages = {106-117},
number = {1-4},
volume = 57,
journal = {Topics in Catalysis},
keywords = {DESC0004031, early-career, orgmode, },
author = {Spencer D. Miller and Vladimir V. Pushkarev and Andrew
J. Gellman and John R. Kitchin},
}
@article{xu-2014-probin-cover,
title = {Probing the Coverage Dependence of Site and Adsorbate
Configurational Correlations on (111) Surfaces of Late
Transition Metals},
url = {http://dx.doi.org/10.1021/jp508805h},
doi = {10.1021/jp508805h},
year = 2014,
pages = {25597-25602},
number = 44,
volume = 118,
journal = {J. Phys. Chem. C},
keywords = {DESC0004031, early-career, orgmode, },
author = {Zhongnan Xu and John R. Kitchin},
}
@article{xu-2014-relat-elect,
title = {Relating the Electronic Structure and Reactivity of the 3d
Transition Metal Monoxide Surfaces},
abstract = "Abstract We performed a series of density functional theory
calculations of dissociative oxygen adsorption on fcc metals
and their corresponding rocksalt monoxides to elucidate the
relationship between the oxide electronic structure and its
corresponding reactivity. We decomposed the dissociative
adsorption energy of oxygen on an oxide surface into a sum of
the adsorption energy on the metal and a change in adsorption
energy caused by both expanding and oxidizing the lattice. We
were able to identify the key features of the electronic
structure that explains the trends in adsorption energies on
3d transition metal monoxide surfaces. ",
issn = "1566-7367",
url = {http://dx.doi.org/10.1016/j.catcom.2013.10.028},
doi = {10.1016/j.catcom.2013.10.028},
year = 2014,
pages = {60-64},
volume = 52,
journal = {Catalysis Communications},
keywords = {DESC0004031, early-career, orgmode, },
author = {Zhongnan Xu and John R. Kitchin},
}
@article{mehta-2014-ident-poten,
title = {Identifying Potential \ce{BO2} Oxide Polymorphs for Epitaxial
Growth Candidates},
eprint = {http://pubs.acs.org/doi/pdf/10.1021/am4059149},
url = {http://dx.doi.org/10.1021/am4059149},
doi = {10.1021/am4059149},
year = 2014,
pages = {3630-3639},
number = 5,
volume = 6,
journal = {ACS Appl. Mater. Interfaces},
keywords = {orgmode, },
author = {Prateek Mehta and Paul A. Salvador and John R. Kitchin},
}
@article{hallenbeck-2013-effec,
title = {Effects of \ce{O_2} and \ce{SO_2} on the Capture Capacity of a
Primary-Amine Based Polymeric \ce{CO_2} Sorbent},
eprint = "http://pubs.acs.org/doi/pdf/10.1021/ie400582a",
url = "http://pubs.acs.org/doi/abs/10.1021/ie400582a",
doi = "10.1021/ie400582a",
year = 2013,
pages = "10788-10794",
journal = "Industrial \& Engineering Chemistry Research",
keywords = {RUA, orgmode},
author = "Hallenbeck, Alexander P. and Kitchin, John R.",
}
@article{kitchin-2016-autom-data,
abstract = "In the current scientific publishing landscape, there is a
need for an authoring workflow that easily integrates data and
code into manuscripts and that enables the data and code to be
published in reusable form. Automated embedding of data and
code into published output will enable superior communication
and data archiving. In this work, we demonstrate a proof of
concept for a workflow, org-mode, which successfully provides
this authoring capability and workflow integration. We
illustrate this concept in a series of examples for potential
uses of this workflow. First, we use data on citation counts
to compute the h-index of an author, and show two code
examples for calculating the h-index. The source for each
example is automatically embedded in the PDF during the export
of the document. We demonstrate how data can be embedded in
image files, which themselves are embedded in the document.
Finally, metadata about the embedded files can be
automatically included in the exported PDF, and accessed by
computer programs. In our customized export, we embedded
metadata about the attached files in the PDF in an Info field.
A computer program could parse this output to get a list of
embedded files and carry out analyses on them. Authoring tools
such as Emacs + org-mode can greatly facilitate the
integration of data and code into technical writing. These
tools can also automate the embedding of data into document
formats intended for consumption.",
author = "Kitchin, John R. and Van Gulick, Ana E. and Zilinski, Lisa D.",
keywords = {orgmode},
doi = "10.1007/s00799-016-0173-7",
issn = "1432-1300",
journal = "International Journal on Digital Libraries",
pages = "1--6",
title = {Automating Data Sharing Through Authoring Tools},
url = "http://dx.doi.org/10.1007/s00799-016-0173-7",
year = 2016,
}
@article{kitchin-2015-data-surfac-scien,
author = "John R. Kitchin",
title = {Data Sharing in Surface Science},
journal = "Surface Science ",
volume = {647},
pages = {103-107},
year = 2015,
doi = {10.1016/j.susc.2015.05.007},
url =
"http://www.sciencedirect.com/science/article/pii/S0039602815001326",
issn = "0039-6028",
keywords = {DESC0004031, early-career, orgmode, Data sharing },
}
@article{kitchin-2015-examp,
author = {Kitchin, John R.},
title = {Examples of Effective Data Sharing in Scientific Publishing},
journal = {ACS Catalysis},
volume = {5},
number = {6},
pages = {3894-3899},
year = 2015,
doi = {10.1021/acscatal.5b00538},
url = { http://dx.doi.org/10.1021/acscatal.5b00538 },
keywords = {DESC0004031, early-career, orgmode, Data sharing },
eprint = { http://dx.doi.org/10.1021/acscatal.5b00538 },
}
@online{jkitchin76:online,
title = {jkitchin/org-ref: org-mode modules for citations,
cross-references, bibliographies in org-mode and useful bibtex
tools to go with it.},
url = {https://github.com/jkitchin/org-ref},
urldate = {12/04/2016}
}
@book{chen-2006-handb-data-visual,
author = {Hrsg. Chun-houh Chen ; Hrsg. Wolfgang H{\"a}rdle ; Hrsg.
Antony Unwin},
title = {Handbook of Data Visualization},
year = 2006,
publisher = {Springer Berlin},
url = {http://www.worldcat.org/oclc/150289486?referer=xid},
city = {Berlin},
ed = {1. Ed.},
form = {BA},
isbn = 9783540330363,
lang = {eng},
lccn = 2007931825,
oclcnum = {150289486 214357554 232302403 314615038 474712418 494787249
645208009 743424036 751135412 76799021 804152581 849253364
873514520 612218650},
}
@article{geng-2017-first-princ,
author = {Feiyang Geng and Jacob R. Boes and John R. Kitchin},
title = {First-Principles Study of the {Cu-Pd} Phase Diagram},
journal = {Calphad},
volume = 56,
pages = {224-229},
year = 2017,
doi = {10.1016/j.calphad.2017.01.009},
url = {https://doi.org/10.1016/j.calphad.2017.01.009},
DATE_ADDED = {Wed Feb 22 09:13:55 2017},
}
@article{boes-2017-model-segreg,
author = {Boes, Jacob Russell and Kitchin, John R.},
title = {Modeling Segregation on {AuPd}(111) Surfaces With Density
Functional Theory and Monte Carlo Simulations},
journal = {The Journal of Physical Chemistry C},
volume = {121},
number = {6},
pages = {3479-3487},
year = 2017,
doi = {10.1021/acs.jpcc.6b12752},
url = {https://doi.org/10.1021/acs.jpcc.6b12752},
eprint = { http://dx.doi.org/10.1021/acs.jpcc.6b12752 },
}
@article{xu-2017-first-princ,
author = {Xu, Zhongnan and Salvador, Paul A. and Kitchin, John R.},
title = {First-Principles Investigation of the Epitaxial Stabilization
of Oxide Polymorphs: \ce{TiO2} on \ce{(Sr,Ba)TiO3}},
journal = {ACS Applied Materials \& Interfaces},
volume = {9},
number = {4},
pages = {4106-4118},
year = 2017,
doi = {10.1021/acsami.6b11791},
url = {https://doi.org/10.1021/acsami.6b11791},
eprint = { http://dx.doi.org/10.1021/acsami.6b11791 },
note = {PMID: 28004912},
}
@article{boes-2017-neural-networ,
author = {Jacob R. Boes and John R. Kitchin},
title = {Neural Network Predictions of Oxygen Interactions on a Dynamic
{Pd} Surface},
journal = {Molecular Simulation},
pages = {1-9},
year = 2017,
doi = {10.1080/08927022.2016.1274984},
url = {https://doi.org/10.1080/08927022.2016.1274984},
keywords = {CBET-1506770, orgmode},
}
@article{boes-2016-neural-networ,
author = {Jacob R. Boes and Mitchell C. Groenenboom and John A. Keith
and John R. Kitchin},
title = {Neural Network and {Reaxff} Comparison for {Au} Properties},
journal = {Int. J. Quantum Chem.},
volume = 116,
number = 13,
pages = {979-987},
year = 2016,
doi = {10.1002/qua.25115},
url = {http://dx.doi.org/10.1002/qua.25115},
issn = {1097-461X},
keywords = {Kohn-Sham density functional theory, neural networks, reactive
force fields, potential energy surfaces, machine learning},
}

View File

@@ -0,0 +1,45 @@
;;; org-ref.el --- citations, cross-references and bibliographies in org-mode
;; Copyright(C) 2014-2016 John Kitchin
;; Author: John Kitchin <jkitchin@andrew.cmu.edu>
;; URL: https://github.com/jkitchin/org-ref
;; Version: 1.1.1
;; Keywords: org-mode, cite, ref, label
;; Package-Requires: ((dash "2.11.0") (htmlize "1.51") (helm "1.5.5") (helm-bibtex "2.0.0") (ivy "0.8.0") (hydra "0.13.2") (key-chord "0") (s "1.10.0") (f "0.18.0") (emacs "24.4") (pdf-tools "0.7"))
;; This file is not currently part of GNU Emacs.
;; This program is free software; you can redistribute it and/or
;; modify it under the terms of the GNU General Public License as
;; published by the Free Software Foundation; either version 2, or (at
;; your option) any later version.
;; This program is distributed in the hope that it will be useful, but
;; WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;; General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program ; see the file COPYING. If not, write to
;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
;;; Commentary:
;;
;; Lisp code to setup bibliography, cite, ref and label org-mode links.
;; Also sets up reftex and helm for org-mode citations. The links are
;; clickable and do things that are useful.
;;
;; The default setup uses helm-bibtex.
;; You should really read org-ref.org in this package for details.
;;
;;; Code:
(require 'org-ref-core)
(require org-ref-completion-library)
;;* The end
(provide 'org-ref)
;;; org-ref.el ends here

View File

@@ -0,0 +1,951 @@
#+TITLE: The org-ref manual
#+AUTHOR: John Kitchin
#+DATE: 2015-03-15 Sun
#+OPTIONS: toc:nil ^:{}
#+LATEX_HEADER: \usepackage{natbib}
#+LATEX_HEADER: \usepackage[version=3]{mhchem}
#+latex_header: \usepackage{glossaries}
#+latex_header: \makeglossaries
#+latex_header_extra: \newglossaryentry{acronym}{name={acronym},description={An acronym is an abbreviation used as a word which is formed from the initial components in a phrase or a word. Usually these components are individual letters (as in NATO or laser) or parts of words or names (as in Benelux)}}
#+latex_header_extra: \newacronym{tla}{TLA}{Three Letter Acronym}
\maketitle
\tableofcontents
* Introduction to org-ref
Org-ref is a library for org-mode cite:Dominik201408 that provides rich support for citations, labels and cross-references in org-mode. org-ref is especially suitable for org-mode documents destined for LaTeX export and scientific publication. org-ref is also extremely useful for research documents and notes. org-ref bundles several other libraries that provide functions to create and modify bibtex entries from a variety of sources, but most notably from a DOI.
The basic idea of org-ref is that it defines a convenient interface to insert citations from a reference database (e.g. from a bibtex file(s)), and a set of functional org-mode links for citations, cross-references and labels that export properly to LaTeX, and that provide clickable functionality to the user. org-ref interfaces with helm-bibtex to facilitate citation entry, and it can also use reftex.
org-ref provides a fairly large number of utilities for finding bad citations, extracting bibtex entries from citations in an org-file, and functions for interacting with bibtex entries. We find these utilities indispensable in scientific writing.
org-ref is [[*Customizing org-ref][customizable]].
org-ref has been in development since sometime in 2013. It was written to aid in the preparation of scientific manuscripts. We have published over a dozen scientific articles with it so far:
- cite:hallenbeck-2013-effec
- cite:mehta-2014-ident-poten
- cite:xu-2014-relat-elect
- cite:xu-2014-probin-cover
- cite:miller-2014-simul-temper
- cite:curnan-2014-effec-concen
- cite:boes-2015-estim-bulk
- cite:xu-2015-linear-respon
- cite:xu-2015-relat-between
- cite:boes-2016-neural-networ
- cite:boes-2017-neural-networ
- cite:xu-2017-first-princ
- cite:geng-2017-first-princ
Be sure to check out the supporting information files for each of these. The org source for the supporting information is usually embedded in the supporting information. You may also find these two perspective articles cite:kitchin-2015-examp,kitchin-2015-data-surfac-scien interesting, as well as this article on data sharing cite:kitchin-2016-autom-data we wrote.
There has been a lot of recent discussion on the org-mode mailing list about a citation syntax for org-mode. It is not clear what the impact of this on org-ref will be. The new syntax will more cleanly support pre/post text, and it will be separate from the links used in org-ref. It is not clear if the new syntax will support all of the citation types, especially those in biblatex, that are supported in org-ref. The new citations are likely to be clickable, and could share functionality with org-ref. The new citation syntax will not cover labels and cross-references though, so these links from org-ref will still exist. We anticipate a long life for org-ref.
Biblatex users should read this [[id:212B487E-CC38-4BDF-9F0E-6993845AF49B][section]].
If you want to export this document to another format like PDF or HTML, see [[id:5BBB8F29-3C82-4C7B-8FDB-9D146751D187][Other forms of this document]].
** Basic usage of org-ref
*** Bibliography links
index:bibliography index:bibliographystyle
org-ref provides a bibliography link to specify which bibtex files to use in the document. You should use the filename with extension, and separate filenames by commas. This link is clickable; clicking on a filename will open the file. Also, if your cursor is on a filename, you will see a minibuffer message about whether the file exists or not. On export, the bibliography will appear at the position where the link is defined. Usually this link goes near the end of your document, e.g. like [[bibliography link][here]].
There is also a nobibliography link, which is useful for specifying a bibliography file, but not listing a bibliography in the exported document.
There is also a bibliographystyle link that specifies the style. This link does nothing but export to a LaTeX command. For LaTeX export a bibliography and bibliographystyle link is /required/ if you use bibtex. If you use biblatex see [[id:212B487E-CC38-4BDF-9F0E-6993845AF49B][biblatex users]].
*** Citations
:PROPERTIES:
:CUSTOM_ID: citations
:END:
index:cite
org-ref uses the [[bibliography link]] to determine which bibtex files to get citations from, and falls back to the bibtex files defined in the variable ~reftex-default-bibliography~ or ~org-ref-default-bibliography~ if no bibliography link is found.
For simple citation needs, org-ref is simple to use. At the point you want to insert a citation, you select the "Org -> org-ref -> Insert citation" menu (or use the key-binding ~C-c ]~ by default), select the reference(s) you want in the helm-bibtex buffer and press enter. The citation will be inserted automatically into your org-file. You "select" an entry by using the arrow keys (or ~C-n~ and ~C-p~) to move up and down to the entry you want. You can also narrow the selection by typing a pattern to match, e.g. author name, title words, year, BibTeX key and entry types. For any other field (e.g. keywords), you will need to add it to the variable ~bibtex-completion-additional-search-fields~. You can select multiple entries by pressing ~C-SPC~ to mark entries in the helm-bibtex buffer.
If the cursor is on a citation key, you should see a message in the minibuffer that summarizes which citation it refers to. If you click on a key, you should see a helm selection buffer with some actions to choose, including opening the bibtex entry, opening/getting a pdf for the entry, searching the entry in Web of Science, etc...
The default citation type is [[*Customizing org-ref][customizable]], and set to "cite". If you want another type of citation type, then type ~C-u~ before pressing enter in the helm-bibtex selection buffer. You will be prompted for the type of citation you actually want.
Here is a list of supported citation types. You can customize this if you want. If you do not know what all these types are, you probably do not need them. The default cite is what you need. See http://tug.ctan.org/macros/latex/contrib/natbib/natnotes.pdf
for the cite commands supported in bibtex index:natbib, and http://ctan.mirrorcatalogs.com/macros/latex/contrib/biblatex/doc/biblatex.pdf
for the commands supported in biblatex. For most scientific journals, only bibtex is supported. index:biblatex
#+BEGIN_SRC emacs-lisp
org-ref-cite-types
#+END_SRC
#+RESULTS:
| cite | nocite | citet | citet* | citep | citep* | citealt | citealt* | citealp | citealp* | citenum | citetext | citeauthor | citeauthor* | citeyear | citeyear* | Citet | Citep | Citealt | Citealp | Citeauthor | Cite | parencite | Parencite | footcite | footcitetext | textcite | Textcite | smartcite | Smartcite | cite* | parencite* | supercite | autocite | Autocite | autocite* | Autocite* | Citeauthor* | citetitle | citetitle* | citedate | citedate* | citeurl | fullcite | footfullcite | notecite | Notecite | pnotecite | Pnotecite | fnotecite | cites | Cites | parencites | Parencites | footcites | footcitetexts | smartcites | Smartcites | textcites | Textcites | supercites | autocites | Autocites | bibentry |
If the cursor is on a citation, or at the end of the citation, and you add another citation, it will be appended to the current citation.
index:cite!replace
If you want to /replace/ an existing key in a citation, put the cursor on the key, run the insert citation command, and type ~C-u C-u~ before pressing enter in the helm-bibtex selection buffer. The key will be replaced. Of course, you can just delete it yourself, and add a new key.
[[index:cite!shift]]
Finally, if you do not like the order of the keys in a citation, you can put your cursor on a key and use shift-arrows (left or right) to move the key around. Alternatively, you can run the command ~org-ref-sort-citation-link~ which will sort the keys by year, oldest to newest.
You may want to bind a hydra menu to a key-binding or key-chord. For example:
#+BEGIN_SRC emacs-lisp
(key-chord-define-global "kk" 'org-ref-cite-hydra/body)
#+END_SRC
This will allow you to quickly press ~kk~ while on a cite link to access functions that can act on the link.
Alternatively, there is now a keymap defined on cite links. By default this map is defined in the variable ~org-ref-cite-keymap~. Note if you change any of these, you have to either restart emacs or run ~org-ref-generate-cite-links~. I am a fan of the [[http://ergoemacs.org/emacs/emacs_hyper_super_keys.html][hyper]] key, so the following are defined by default:
| H-b | Open the citation to the bibtex entry |
| H-u | Open the citation URL |
| H-p | Open the citation PDF (if it exists) |
| H-n | Open the citation notes |
| H-c | Open Web of Science citing articles |
| H-e | Email the bibtex entry and pdf |
| H-f | Copy a formatted entry string |
| H-g | Open Google Scholar |
| H-w | Copy the key at point |
| H-y | Paste the key in an existing link |
There are navigation bindings:
| C-left | Jump to previous key |
| C-right | Jump to next key |
| S-left | move key to the left |
| S-right | move key to the right |
You can also sort
| S-up | sort keys by ascending year |
*** Pre/post text support
org-ref has basic and limited support for pre/post text in citations. You can get pre/post text by using a description in a cite link, with pre/post text separated by ::. For example, [[cite:Dominik201408][See page 20::, for example]]. It is not easy (maybe not possible) to extend this for the humanities style of citations (e.g. harvard) with nested pre/post text on multiple citations. If anyone knows how to do it, pull requests are welcome! There is an ongoing effort in org-mode for a new citation syntax that may make this more feasible.
If you use helm-bibtex and would like pre/post text support enabled, you can add ~org-ref-format-citation~ to ~bibtex-completion-format-citation-functions~:
#+BEGIN_SRC emacs-lisp
(setf (cdr (assoc 'org-mode bibtex-completion-format-citation-functions)) 'org-ref-format-citation)
#+END_SRC
See also: [[https://github.com/tmalsburg/helm-bibtex#format-of-citations][Format of citations]] and [[https://github.com/tmalsburg/helm-bibtex#latex-citation-commands][Insert LaTeX cite commands]]. Note that pre/post prompt can also be switched off by setting the variable ~bibtex-completion-cite-prompt-for-optional-arguments~ to nil.
*** label links
index:label
LaTeX uses labels to define places you can refer to. These can be labels in the captions of figures and tables, or labels in sections. We illustrate some uses here.
label links are "functional" if you put your cursor on the link, you will get a message in the minibuffer showing you the number of occurrences of that label in the buffer. That number should be one! It is most preferable to put a label link into a caption like this.
#+caption: Another simple table. label:tab-ydata
| y |
| 4 |
| 5 |
org-ref can help you insert unique labels with the command elisp:org-ref-helm-insert-label-link. This will show you the existing labels, and insert your new label as a link. There is no default key-binding for this.
*** ref links
:PROPERTIES:
:ID: 290260A1-F07C-4852-B4B3-CEE3E768AA3B
:CUSTOM_ID: ref-links
:END:
index:ref
A ref link refers to a label of some sort. For example, you can refer to a table name, e.g. Table ref:table-1. You have to provide the context before the ref link, e.g. Table, Figure, Equation, Section, and so on.
#+name: table-1
#+caption: A simple table.
| x |
| 1 |
| 2 |
Or you can refer to an org-mode label as in Table ref:table-3.
Note: You may need to set org-latex-prefer-user-labels to t if you refer to times by their "name" for the export to use the name you create.
#+BEGIN_SRC emacs-lisp
(setq org-latex-prefer-user-labels t)
#+END_SRC
#+RESULTS:
: t
#+caption: Another simple table. label:table-3
| y |
|---|
| 3 |
| 2 |
You can also refer to an org-ref label link as in Table ref:tab-ydata.
To help you insert ref links, use the "Org -> org-ref -> Insert ref" menu, or run the command elisp:org-ref-helm-insert-ref-link. There is no default key-binding for this.
ref links are functional. If you put the cursor on a ref link, you should see a message in the minibuffer with some context of the corresponding label. If you click on the ref link, the cursor will jump to the label.
A brief note about references to a section. You can make a ref link to a CUSTOM_ID. Section ref:sec-misc has a label link in the headline. That works, but is not too pretty. Section ref:ref-links uses the CUSTOM_ID property. For this to work, you should set ~org-latex-prefer-user-labels~ to t.
Also note that "#+tblname:" and "#+label:" are deprecated in org-mode now, and "#+name:" is preferred.
**** Miscellaneous ref links label:sec-misc
index:ref!pageref index:ref!nameref index:ref!eqref
org-ref also provides these links:
- pageref :: The page a label is on
- nameref :: The name of a section a label is in
- eqref :: Puts the equation number in parentheses
- autoref :: A command from hyperref that automatically prefixes the reference number.
- cref & Cref :: [[https://www.ctan.org/tex-archive/macros/latex/contrib/cleveref?lang=en][cleveref Intelligent cross-referencing]] (crefrange is not supported)
Note for eqref, you must use a LaTeX label like this:
\begin{equation}
e^x = 4 \label{eq:1}
\end{equation}
Then you can refer to Eq. eqref:eq:1 in your documents.
Autoref works like this: autoref:table-3, autoref:sec-misc.
You can specify the default ref link type in `org-ref-default-ref-type'.
*** Some other links
[[index:list of tables]] [[index:list of figures]]
org-ref provides clickable links for a list-of-tables:nil and list-of-figures:nil. We have to put some text in the link, anything will do. These export as listoftables and listoffigures LaTeX commands, and they are clickable links that open a mini table of contents with links to the tables and figures in the buffer. There are also interactive commands for this: elisp:org-ref-list-of-tables and elisp:org-ref-list-of-figures.
*** Controlling link messages and tooltips
Org-ref is setup to provide messages in the minibuffer when your cursor is on a link, and tooltips when your mouse hovers over a link. If this is distracting you can turn it off by putting this in your init file:
#+BEGIN_SRC emacs-lisp
(setq org-ref-show-citation-on-enter nil)
#+END_SRC
Alternatively, you can turn this on and off interactively with the commands:
- org-ref-mouse-messages-on
- org-ref-mouse-messages-off
Org-ref can also be configured to show bad label,ref and cite links by setting this in your init files:
#+BEGIN_SRC emacs-lisp
(setq org-ref-show-broken-links t)
#+END_SRC
#+RESULTS:
: t
This may be slow in large files, so you can turn it off by setting that variable to nil.
** org-ref customization of helm-bibtex
index:helm-bibtex
org-ref adds a few new features to helm-bibtex. First, we add keywords as a searchable field. Second, org-ref modifies the helm-bibtex search buffer to include the keywords. Since keywords now can have a central role in searching, we add some functionality to add keywords from the helm-bibtex buffer as a new action.
We change the order of the actions in helm-bibtex to suit our work flow, and add some new actions as well. We define a format function for org-mode that is compatible with the usage defined in section [[#citations]]. Finally, we add some new fallback options for additional scientific search engines.
** Some basic org-ref utilities
[[index:bibtex!clean entry]]
The command ~org-ref~ does a lot for you automatically. It will check the buffer for errors, e.g. multiply-defined labels, bad citations or ref links, and provide easy access to a few commands through a helm buffer.
~org-ref-clean-bibtex-entry~ will sort the fields of a bibtex entry, clean it, and give it a bibtex key. By default, this function does a lot of cleaning:
1. adds a comma if needed in the first line of the entry
2. makes sure the DOI field is an actual DOI, and not a URL
3. fixes bad year entries
4. fixes empty pages
5. escapes ampersand and percentage signs
6. generate a key according to your setup
7. runs your hook functions
8. sorts the fields in the entry
9. checks the entry for non-ascii characters
10. converts article title to title case (note: see below to convert titles in other entry types)
This function has a hook ~org-ref-clean-bibtex-entry-hook~, which you can add functions to of your own. Each function must work on a bibtex entry at point. (Note: the default behavior can be changed by removing the relevant functions from the initial value of ~org-ref-clean-bibtex-entry-hook~.)
#+BEGIN_SRC emacs-lisp
(add-hook 'org-ref-clean-bibtex-entry-hook 'org-ref-replace-nonascii)
#+END_SRC
~org-ref-extract-bibtex-entries~ will create a bibtex file from the citations in the current buffer.
** LaTeX export
index:export!LaTeX
All org-ref links are designed to export to the corresponding LaTeX commands for citations, labels, refs and the bibliography/bibliography style. Once you have the LaTeX file, you have to build it, using the appropriate latex and bibtex commands. You can have org-mode do this for you with a setup like:
#+BEGIN_SRC emacs-lisp
(setq org-latex-pdf-process
'("pdflatex -interaction nonstopmode -output-directory %o %f"
"bibtex %b"
"pdflatex -interaction nonstopmode -output-directory %o %f"
"pdflatex -interaction nonstopmode -output-directory %o %f"))
#+END_SRC
I have also had success with this setup:
#+BEGIN_SRC emacs-lisp
(setq org-latex-pdf-process (list "latexmk -shell-escape -bibtex -f -pdf %f"))
#+END_SRC
** Other exports
index:export!html index:export!ascii
There is some basic support for HTML and ascii export. Not all bibtex entry types are supported, but basic support exists for articles and books. For a markdown export, the cite links are exported as Pandoc style links. During HTML export, the references get the HTML class ~org-ref-reference~, the bibliography headline has the class ~org-ref-bib-h1~ and the list of references has the class ~org-ref-bib~.
* org-ref-ivy
org-ref provides an alternative to reftex and helm with ivy as the backend completion engine for searching and entering citations.
You can set this backend in your init file like this
#+BEGIN_SRC emacs-lisp
(setq org-ref-completion-library 'org-ref-ivy-cite)
(require 'org-ref)
#+END_SRC
There are some non-standard ivy features in org-ref ;)
You still use C-c ] to search for a bibtex entry, and Ret to insert it as a citation. C-c ] C-u Ret will prompt you for a different citation type.
1. You can mark entries with C-space like in helm, and pressing enter will insert the citations.
2. C-, will show you the only the marked entries, and C-. will show them all again.
3. C-up and C-down will move an entry up and down to reorder them.
4. In the selection buffer C-y will sort in increasing year, C-M-y will sort in decreasing year.
5. C-Ret will insert the current entry and move to the next one.
C-u C-c ] will insert a ref link. You will see a list of labels to select. Pres Ret to enter a ref link, or C-u Ret to select a different type of ref.
C-u C-u C-c ] will insert a label link. You should see a list of all the current labels to help you avoid duplicating them.
* Other libraries in org-ref
These are mostly functions for adding entries to bibtex files, modifying entries or for operating on bibtex files. Some new org-mode links are defined.
** doi-utils
index:doi
This library adds two extremely useful tools for getting bibtex entries and pdf files of journal manuscripts. Add this to your emacs setup:
#+BEGIN_SRC emacs-lisp
(require 'doi-utils)
#+END_SRC
This provides two important commands:
- ~doi-utils-add-bibtex-entry-from-doi~
This will prompt you for a DOI, and a bibtex file, and then try to get the bibtex entry, and pdf of the article.
- ~doi-utils-add-entry-from-crossref-query~
This will prompt you for a query string, which is usually the title of an article, or a free-form text citation of an article. Then you will get a helm buffer of matching items, which you can choose from to insert a new bibtex entry into a bibtex file.
This library also redefines the org-mode doi link. Now, when you click on this link you will get a menu of options, e.g. to open a bibtex entry or a pdf if you have it, or to search the doi in some scientific search engines. Try it out doi:10.1021/jp511426q.
*** Bibtex key format
The key is formatted according to the settings of bibtex-autokey-* variables. I use these settings. Look at the documentation of them to see how to get the format you want. The function (bibtex-generate-autokey) does this.
The settings I use are:
#+BEGIN_SRC emacs-lisp
(setq bibtex-autokey-year-length 4
bibtex-autokey-name-year-separator "-"
bibtex-autokey-year-title-separator "-"
bibtex-autokey-titleword-separator "-"
bibtex-autokey-titlewords 2
bibtex-autokey-titlewords-stretch 1
bibtex-autokey-titleword-length 5)
#+END_SRC
*** Troubleshooting doi-utils
Occasionally weird things happen with a DOI. The first thing you should check is if the json data for the DOI can be retrieved. You can do that at the command line, or in a sh block like this:
#+BEGIN_SRC sh
curl -LH "Accept: application/citeproc+json" "http://doi.org/10.1021/jp511426q"
#+END_SRC
#+RESULTS:
| indexed":{"date-parts | 12 | 19]] | 2015-12-19T19:18:29Z | timestamp:1450552709286} | reference-count:52 | American Chemical Society (ACS) | 9 | award":["DE-SC0004031 | publisher | Basic Energy Sciences | 10.13039\/100006151 | award":["DMR 0843934 | publisher | Division of Materials Research | 10.13039\/100000078 | date-parts | 3 | 5]]} | 10.1021\/jp511426q | journal-article | date-parts | 2 | 10]] | 2015-02-10T03:10:55Z | timestamp:1423537855000} | 4827-4833 | CrossRef | A Linear Response DFT+ U Study of Trends in the Oxygen Evolution Activity of Transition Metal Rutile Dioxides | [[http:\/\/id.crossref.org\/prefix\/10.1021]] | 119 | affiliation | Xu | Zhongnan | affiliation | Rossmeisl | Jan | affiliation | Kitchin | John R. | [[http:\/\/id.crossref.org\/member\/316]] | J. Phys. Chem. C | intended-application":"unspecified | vor | application\/pdf | [[http:\/\/pubs.acs.org\/doi\/pdf\/10.1021\/jp511426q]] | date-parts | 3 | 5]] | 2015-03-05T10:30:59Z | timestamp:1425551459000} | score:1.0 | subtitle:[] | date-parts | 3 | 5]]} | 10.1021\/jp511426q | [[http:\/\/dx.doi.org\/10.1021\/jp511426q]] | 1932-7447 | 1932-7455] | Energy(all) | Physical and Theoretical Chemistry | Electronic, Optical and Magnetic Materials | Surfaces, Coatings and Films]} |
If you do not get json data, doi-utils will not be able to generate the bibtex entry.
Not all PDFs can be retrieved. doi-utils uses a set of functions to attempt this. Here is the list.
#+BEGIN_SRC emacs-lisp
doi-utils-pdf-url-functions
#+END_SRC
#+RESULTS:
| aps-pdf-url | science-pdf-url | nature-pdf-url | wiley-pdf-url | springer-chapter-pdf-url | springer-pdf-url | acs-pdf-url-1 | acs-pdf-url-2 | iop-pdf-url | jstor-pdf-url | aip-pdf-url | science-direct-pdf-url | linkinghub-elsevier-pdf-url | tandfonline-pdf-url | ecs-pdf-url | ecst-pdf-url | rsc-pdf-url | pnas-pdf-url | sage-pdf-url | jneurosci-pdf-url | ieee-pdf-url | acm-pdf-url | generic-full-pdf-url |
You can check if a url for the PDF can be found like this:
#+BEGIN_SRC emacs-lisp
(doi-utils-get-pdf-url "10.1021/jp511426q")
#+END_SRC
#+RESULTS:
: http://pubs.acs.org/doi/pdf/10.1021/jp511426q
** org-ref-bibtex
These are functions I use often in bibtex files.
*** Generate new bibtex files with adapted journal names
The variable ~org-ref-bibtex-journal-abbreviations~ contains a mapping of a short string to a full journal title, and an abbreviated journal title. We can use these to create new versions of a bibtex file with full or abbreviated journal titles. You can add new strings like this:
#+BEGIN_SRC emacs-lisp
(add-to-list 'org-ref-bibtex-journal-abbreviations
'("JIR" "Journal of Irreproducible Research" "J. Irrep. Res."))
#+END_SRC
- org-ref-bibtex-generate-longtitles :: Generate a bib file with long titles as
defined in `org-ref-bibtex-journal-abbreviations'
- org-ref-bibtex-generate-shorttitles :: Generate a bib file with short titles as
defined in `org-ref-bibtex-journal-abbreviations'
*** Modifying bibtex entries
- org-ref-stringify-journal-name :: replace a journal name with a string in
`org-ref-bibtex-journal-abbreviations'
- org-ref-set-journal-string :: in a bibtex entry run this to replace the journal
with a string selected interactively.
- org-ref-title-case-article :: title case the title in an article entry.
- org-ref-title-case :: title case the title for entries listed in `org-ref-title-case-types'.
- org-ref-sentence-case-article :: sentence case the title in an article entry.
- org-ref-replace-nonascii :: replace nonascii characters in a bibtex
entry. Replacements are in `org-ref-nonascii-latex-replacements'. This
function is a hook function in org-ref-clean-bibtex-entry.
The non-ascii characters are looked up in a list of cons cells. You can add your own non-ascii replacements like this. Note backslashes must be escaped doubly, so one =\= is =\\\\= in the cons cell.
#+BEGIN_SRC emacs-lisp
(add-to-list 'org-ref-nonascii-latex-replacements
'("æ" . "{\\\\ae}"))
#+END_SRC
These functions are compatible with ~bibtex-map-entries~, so it is possible to conveniently apply them to all the entries in a file like this:
#+BEGIN_SRC emacs-lisp
(bibtex-map-entries 'org-ref-title-case-article)
#+END_SRC
*** Bibtex entry navigation
- org-ref-bibtex-next-entry :: bound to M-n
- org-ref-bibtex-previous-entry :: bound to M-p
*** Hydra menus for bibtex entries and files
- Functions to act on a bibtex entry or file
- org-ref-bibtex-hydra/body :: gives a hydra menu to a lot of useful functions
like opening the pdf, or the entry in a browser, or searching in a
variety of scientific search engines.
- org-ref-bibtex-new-entry/body :: gives a hydra menu to add new bibtex entries.
- org-ref-bibtex-file/body :: gives a hydra menu of actions for the bibtex file.
You will want to bind the hydra menus to a key. You only need to bind the first one, as the second and third can be accessed from the first hydra. You can do that like this before you require ~org-ref-bibtex~:
#+BEGIN_SRC emacs-lisp
(setq org-ref-bibtex-hydra-key-binding "\C-cj")
#+END_SRC
Or this if you like key-chord:
#+BEGIN_SRC emacs-lisp
(key-chord-define-global "jj" 'org-ref-bibtex-hydra/body)
#+END_SRC
*** Formatted bibtex entry citations
org-ref has some limited capability to make formatted bibliography entries from a bibtex entry or citation link. This is generally a hard problem, and the first solution is not a replacement for a dedicated citation processor like BibTeX. Two variable determine the behavior of formatted citations:
- Formats are from `org-ref-formatted-citation-formats' is an a-list of (backend . formats). formats is an alist of (entry-type . format-string).
- The variable `org-ref-formatted-citation-backend' determines which set of format strings is used. The default is "text", and "org" format strings are also defined.
So, if you click on a citation link, there should be a menu option to copy a formatted citation, which will copy the citation string to the clipboard.
If you are on a bibtex entry, the `org-ref-bibtex-hydra/body' has an option to copy a formatted citation for the entry your cursor is in.
Finally, depending on your org-ref backend, there may be an action in the org-ref-insert-link command.
For the second approach see [[./citeproc/readme.org]]. It is more advanced in someways, but it is currently limited to a few formats, and is a long-term work in progress.
** org-ref-wos
This is a small utility for Web of Science/Knowledge (WOK) (http://apps.webofknowledge.com).
#+BEGIN_SRC emacs-lisp
(require 'org-ref-wos)
#+END_SRC
#+RESULTS:
: org-ref-wos
- wos :: Convenience function to open WOK in a browser.
- wos-search :: Search WOK with the selected text or word at point
There is also a new org-mode link that opens a search: [[wos-search:alloy and segregation]]
** org-ref-scopus
This is a small utility to interact with Scopus (http://www.scopus.com). Scopus is search engine for scientific literature. It is owned by Elsevier. You must have a license to use it (usually provided by your research institution).
#+BEGIN_SRC emacs-lisp
(require 'org-ref-scopus)
#+END_SRC
#+RESULTS:
: org-ref-scopus
Interactive functions:
- scopus :: Convenience function to open Scopus in a browser.
- scopus-basic-search :: Prompts for a query and opens it in a browser.
- scopus-advanced-search :: Prompts for an advanced query and opens it in a browser.
Some new links:
Open a basic search in Scopus: [[scopus-search:alloy Au segregation]]
Open an advanced search in Scopus: scopus-advanced-search:au-id(7004212771). See http://www.scopus.com/search/form.url?display=advanced&clear=t for details on the codes and syntax, and http://help.elsevier.com/app/answers/detail/a_id/2347/p/8150/incidents.c$portal_account_name/26389.
A functional link to a document in Scopus by its "EID": eid:2-s2.0-72649092395. Clicking on this link will open a hydra menu to open the document in Scopus, find different kinds of related documents by keywords, authors or references, and to open a page in Scopus of citing documents.
There is also a scopusid link for authors that will open their author page in Scopus: scopusid:7004212771
** org-ref-isbn
index:isbn
#+BEGIN_SRC emacs-lisp
(require 'org-ref-isbn)
#+END_SRC
#+RESULTS:
: org-ref-isbn
This library provides some functions to get bibtex entries for books from their ISBN.
- isbn-to-bibtex
- isbn-to-bibtex-lead
It also provides some variables for customizing the bibtex entry.
- org-ref-isbn-clean-bibtex-entry-hook
- org-ref-isbn-exclude-fields
- org-ref-isbn-field-name-replacements
** org-ref-pubmed
index:pubmed
[[http://www.ncbi.nlm.nih.gov/pubmed][PubMed]] comprises more than 24 million citations for biomedical literature from MEDLINE, life science journals, and online books. Citations may include links to full-text content from PubMed Central and publisher web sites. This library provides some functions to initiate searches of PubMed from Emacs, and to link to PubMed content.
#+BEGIN_SRC emacs-lisp
(require 'org-ref-pubmed)
#+END_SRC
#+RESULTS:
: org-ref-pubmed
This library provides a number of new org-mode links to PubMed entries. See http://www.ncbi.nlm.nih.gov/pmc/about/public-access-info/#p3 for details of these identifiers. These links open the page in PubMed for the identifier.
pmcid:PMC3498956
pmid:23162369
nihmsid:NIHMS395714
Also, you can retrieve a bibtex entry for a PMID with
- ~pubmed-insert-bibtex-from-pmid~
There are some utility functions that may be helpful.
- pubmed :: Open [[http://www.ncbi.nlm.nih.gov/pubmed][PubMed]] in a browser
- pubmed-advanced :: Open [[http://www.ncbi.nlm.nih.gov/pubmed/advanced][PubMed]] at advanced search page.
- pubmed-simple-search :: Prompts you for a simple query and opens it in PubMed.
There is a new org-mode link to PubMed searches: [[pubmed-search:alloy segregation]]
** org-ref-arxiv
index:arxiv
This library provides an org-mode link to http://arxiv.org entries: arxiv:cond-mat/0410285, and a function to get a bibtex entry and pdfs for arxiv entries:
#+BEGIN_SRC emacs-lisp
(require 'org-ref-arxiv)
#+END_SRC
#+RESULTS:
: org-ref-arxiv
- ~arxiv-add-bibtex-entry~
- ~arxiv-get-pdf~
** org-ref-sci-id
:PROPERTIES:
:ID: AD7C70CF-1BB8-4610-B9AD-580790250459
:END:
index:orcid [[index:researcher id]]
#+BEGIN_SRC emacs-lisp
(require 'org-ref-sci-id)
#+END_SRC
#+RESULTS:
: org-ref-sci-id
This package just defines two new org-mode links for http://www.orcid.org, and http://www.researcherid.com. Here are two examples:
orcid:0000-0003-2625-9232
researcherid:A-2363-2010
** x2bib
index:bibtex!conversion
#+BEGIN_SRC emacs-lisp
(require 'x2bib)
#+END_SRC
#+RESULTS:
: x2bib
If you find you need to convert some bibliographies in some format into bibtex, this library is a starting point. This code is mostly wrappers around the command line utilities at http://sourceforge.net/p/bibutils/home/Bibutils. I thankfully have not had to use this often, but it is here when I need it again.
- ris2bib :: Convert an RIS file to a bibtex file.
- medxml2bib :: Convert PubMed XML to bibtex.
- clean-entries :: Map over a converted bibtex file and "clean it".
** org-ref-latex
This provides some org-ref like capabilities in LaTeX files, e.g. the links are clickable with tooltips.
** org-ref-pdf
=org-ref-pdf= allows Emacs to get bibliography information from pdf files that contain a DOI. You must have =pdftotext= installed where Emacs can find it. This library is known to not work on Windows very well.
- Drag and drop a PDF onto a bibtex file to add a bibtex entry
- If you have a pdf file open in Emacs (from, for example, an email attachment), use ~org-ref-pdf-to-bibtex~ to try to extract and write the bibliography information to a bib file, (defaulting to ~org-ref-default-bibliography~) and save the pdf to ~org-ref-pdf-directory~.
** org-ref-url-utils
Allows you to drag-n-drop a webpage from a browser onto a bibtex file to add a bibtex entry (as long as it is from a recognized publisher that org-ref knows about). This library does not work well on Windows.
* Appendix
** Customizing org-ref
:PROPERTIES:
:ID: 32B558A3-7B48-4581-982B-082017B0AEE8
:END:
index:customization
You will probably want to customize a few variables before using org-ref. One way to do this is through the Emacs customization interface: [[elisp:(customize-group "org-ref")]].
Also see: [[elisp:(customize-group "org-ref-bibtex")]].
Here is my minimal setup:
#+BEGIN_SRC emacs-lisp
(setq reftex-default-bibliography '("~/Dropbox/bibliography/references.bib"))
(setq org-ref-bibliography-notes "~/Dropbox/bibliography/notes.org"
org-ref-default-bibliography '("~/Dropbox/bibliography/references.bib")
org-ref-pdf-directory "~/Dropbox/bibliography/bibtex-pdfs/")
#+END_SRC
You can also specify different completion backends. The default is `org-ref-helm-bibtex'.
- org-ref-helm-bibtex :: The default backend that uses helm-bibtex
- org-ref-reftex :: A backend that uses reftex
- org-ref-helm-cite :: An alternative helm completion backend (does not use helm-bibtex)
- org-ref-ivy-cite :: uses ivy for the backend
To use one of these, add a line like this before you "require" org-ref.
#+BEGIN_SRC emacs-lisp
(setq org-ref-completion-library 'org-ref-ivy-cite)
#+END_SRC
** Customizing how PDFs are opened
*** Using doc-view or pdf-tools
There are a few different ways in which PDFs can be opened from org-ref. By default, org-ref uses the function ~org-ref-open-pdf-at-point~, which looks for the corresponding file in the directory specified in ~org-ref-library-path~. If the file was found, it opens it externally with ~org-open-file~. To open the PDF from within Emacs, using doc-view or pdf-tools, you will need to modify the function slightly and assign it to the variable ~org-ref-open-pdf-function~, as in the example below.
#+begin_src emacs-lisp
(defun my/org-ref-open-pdf-at-point ()
"Open the pdf for bibtex key under point if it exists."
(interactive)
(let* ((results (org-ref-get-bibtex-key-and-file))
(key (car results))
(pdf-file (funcall org-ref-get-pdf-filename-function key)))
(if (file-exists-p pdf-file)
(find-file pdf-file)
(message "No PDF found for %s" key))))
(setq org-ref-open-pdf-function 'my/org-ref-open-pdf-at-point)
#+end_src
An alternative approach adapted from https://github.com/jkitchin/org-ref/issues/184 to use pdfview is described here. First, unstall org-pdfview (on MELPA).
Add this to your init file:
#+BEGIN_SRC emacs-lisp
;; PDF links for org-mode
(with-eval-after-load "pdf-tools"
(use-package org-pdfview
:config
;; https://lists.gnu.org/archive/html/emacs-orgmode/2016-11/msg00169.html
;; Before adding, remove it (to avoid clogging)
(delete '("\\.pdf\\'" . default) org-file-apps)
;; https://lists.gnu.org/archive/html/emacs-orgmode/2016-11/msg00176.html
(add-to-list 'org-file-apps
'("\\.pdf\\'" . (lambda (file link)
(org-pdfview-open link))))))
#+END_SRC
*** A note for Mendeley, JabRef and Zotero users
If ~bibtex-completion-pdf-field~ is defined, the function below should work with JabRef and Zotero. For more information, see https://github.com/tmalsburg/helm-bibtex#pdf-files.
#+begin_src emacs-lisp
(defun my/org-ref-open-pdf-at-point ()
"Open the pdf for bibtex key under point if it exists."
(interactive)
(let* ((results (org-ref-get-bibtex-key-and-file))
(key (car results))
(pdf-file (car (bibtex-completion-find-pdf key))))
(if (file-exists-p pdf-file)
(org-open-file pdf-file)
(message "No PDF found for %s" key))))
(setq org-ref-open-pdf-function 'my/org-ref-open-pdf-at-point)
#+end_src
Mendeley users should set to:
#+BEGIN_SRC emacs-lisp
(setq org-ref-open-pdf-function 'org-ref-get-mendeley-filename)
#+END_SRC
** Setting up notes to work with multiple notes.org files
Adapted from https://github.com/jkitchin/org-ref/issues/443. This setup lets helm-bibtex find the note file for an entry.
#+BEGIN_SRC emacs-lisp
;; Tell org-ref to let helm-bibtex find notes for it
(setq org-ref-notes-function
(lambda (thekey)
(let ((bibtex-completion-bibliography (org-ref-find-bibliography)))
(bibtex-completion-edit-notes
(list (car (org-ref-get-bibtex-key-and-file thekey)))))))
#+END_SRC
** Customizing the notes format
A user asked about customizing note formats in https://github.com/jkitchin/org-ref/issues/225. The issue is that helm-bibtex command creates notes as defined in `bibtex-completion-notes-template-one-file' and org-ref creates the notes as defined in `org-ref-open-bibtex-notes'. They wanted some consistency so they got the same results either way they open the notes. @jagrg suggested this approach:
#+BEGIN_SRC emacs-lisp
(defun my/org-ref-notes-function (candidates)
(let ((key (helm-marked-candidates)))
(funcall org-ref-notes-function (car key))))
(helm-delete-action-from-source "Edit notes" helm-source-bibtex)
;; Note that 7 is a magic number of the index where you want to insert the command. You may need to change yours.
(helm-add-action-to-source "Edit notes" 'my/org-ref-notes-function helm-source-bibtex 7)
#+END_SRC
** Other things org-ref supports
*** org-completion
index:completion index:link!completion
Most org-ref links support org-mode completion. You can type ~C-c C-l~ to insert a link. You will get completion of the link type, type some characters and press tab. When you select the type, press tab to see the completion options. This works for the following link types:
- bibliography
- bibliographystyle
- all cite types
- ref
*** Storing org-links to labels
:PROPERTIES:
:ID: AD9663C7-1369-413F-842A-157916D4BB75
:CUSTOM_ID: sec-store-links
:END:
index:link!storing
If you are on a label link, or on a table name, or on an org-mode label you can "store" a link to it by typing C-c l. Then you can insert the corresponding ref link with ~C-c C-l~. This will insert a ref link or custom_id link as needed. This usually works, but it is not used by me too often, so it is not tested too deeply.
*** Storing links to bibtex entries
If you have a bibtex file open, you type ~C-c C-l~ with your cursor in a bibtex entry to store a link to that entry. In an org buffer if you then type ~C-c l~, you can enter a cite link.
*** Indexes
index:index
org-ref provides links to support making an index in LaTeX. (http://en.wikibooks.org/wiki/LaTeX/Indexing).
- index :: creates an index entry.
- printindex :: Generates a temporary index of clickable entries. Exports to the LaTeX command.
You will need to use the makeidx package, and use this in the LaTeX header.
#+begin_example
#+LATEX_HEADER: \usepackage{makeidx}
#+LATEX_HEADER: \makeindex
#+end_example
You will have to incorporate running makeindex into your PDF build command.
This is not supported in anything but LaTeX export.
*** Glossaries
index:glossary
org-ref provides some support for glossary and acronym definitions.
- gls :: a reference to a term
- glspl :: plural reference to a term
- Gsl :: capitalized reference to a term
- Glspl :: capitalized plural reference to a term
- gslink :: Link to alternative text in the link description.
- glssymbol :: The symbol term
- glsdesc :: The description of the term
- acrshort :: Short version of the acroynm
- acrfull :: The full definition of the acronym
- acrlong :: The full definition of the acronym with (abbrv).
There are two useful commands:
- org-ref-add-glossary-entry :: Add a new entry to the file
- org-ref-add-acronym-entry :: Add a new acronym to the file
Here is an example of glossary link for an [[gls:acronym][acronym]] and an actual [[acrshort:tla][TLA]]. Each link has a tool tip on it that shows up when you hover the mouse over it. These links will export as the LaTeX commands need by the glossaries package.
You will need to incorporate running the command makeglossaries into your PDF build command. You also need use the glossaries LaTeX package.
Here is a minimal working example of an org file that makes a glossary.
#+BEGIN_EXAMPLE
#+latex_header: \usepackage{glossaries}
#+latex_header: \makeglossaries
#+latex_header_extra: \newglossaryentry{computer}{name=computer,description={A machine}}
A gls:computer is good for computing. Gls:computer is capitalized. We can also use a bunch of glspl:computer to make a cluster. Glspl:computer are the wave of the future.
\printglossaries
#+END_EXAMPLE
This is not supported in anything but LaTeX export.
** biblatex users
:PROPERTIES:
:ID: 212B487E-CC38-4BDF-9F0E-6993845AF49B
:END:
In the latex header you specify the style and bibliography file using addbibresource. Here is an example:
#+BEGIN_EXAMPLE
#+latex_header: \usepackage[citestyle=authoryear-icomp,bibstyle=authoryear, hyperref=true,backref=true,maxcitenames=3,url=true,backend=biber,natbib=true] {biblatex}
#+latex_header: \addbibresource{tests/test-1.bib}
#+END_EXAMPLE
Sometimes it is necessary to tell bibtex what dialect you are using to support the different bibtex entries that are possible in biblatex. You can do it like this globally.
#+BEGIN_SRC emacs-lisp
(setq bibtex-dialect 'biblatex)
#+END_SRC
#+RESULTS:
: biblatex
Or like this in a bibtex file:
#+BEGIN_EXAMPLE
% -*- mode:bibtex; eval: (bibtex-set-dialect 'biblatex); -*-
#+END_EXAMPLE
Make sure you invoke biblatex in the org-latex-pdf-process. Here is one way to do it.
#+BEGIN_SRC emacs-lisp :results silent
(setq org-latex-pdf-process
'("latexmk -shell-escape -bibtex -pdf %f"))
#+END_SRC
Finally, where you want the bibliography put this command:
#+BEGIN_EXAMPLE
\printbibliography
#+END_EXAMPLE
** Prelude users
An issue related to using org-ref with prelude was [[https://github.com/jkitchin/org-ref/issues/583][reported]], along with a solution that loads org-ref before loading prelude. The solution was to create a file like ~/.emacs.d/personal/preload/preload.el with these contents.
#+BEGIN_SRC emacs-lisp
(package-initialize)
(setq reftex-default-bibliography '("~/bibliography/references.bib"))
(setq org-ref-bibliography-notes "~/bibliography/notes.org"
org-ref-default-bibliography '("~/bibliography/references.bib")
org-ref-pdf-directory "~/bibliography/bibtex-pdfs/")
(require 'org-ref)
(provide 'preload)
;;; preload.el ends here
#+END_SRC
** Other forms of this document
:PROPERTIES:
:ID: 5BBB8F29-3C82-4C7B-8FDB-9D146751D187
:END:
*** Build notes
Before building this file you need to require the following libraries so the links will be resolved.
#+BEGIN_SRC emacs-lisp
(require 'org-id)
(require 'org-ref-wos)
(require 'org-ref-scopus)
(require 'org-ref-pubmed)
#+END_SRC
#+RESULTS:
: org-ref-pubmed
*** PDF
You may want to build a pdf of this file. Here is an emacs-lisp block that will create and open the PDF.
#+BEGIN_SRC emacs-lisp
(org-open-file (org-latex-export-to-pdf))
#+END_SRC
*** HTML
You may want to build an html version of this file. Here is an emacs-lisp block that will create and open the html in your browser. You will see the bibliography is not perfect, but it is pretty functional.
#+BEGIN_SRC emacs-lisp
(browse-url (org-html-export-to-html))
#+END_SRC
* Index
This is a functional link that will open a buffer of clickable index entries:
printindex:nil
* References
<<bibliography link>>
bibliographystyle:unsrt
bibliography:org-ref.bib

View File

@@ -0,0 +1,132 @@
;;; x2bib.el --- Bibliography conversion to Bibtex
;;; Header:
;;; Commentary:
;; This module is more for my convenience to convert bibliography files to
;; bibtex. This can be done at the command line, for example, but I want to do
;; it in Emacs. There are a few scenarios where this happens.
;; 1. Someone sends me a non-Bibtex file (Endnote, etc...)
;; 2. From some online search I select many references and there is no export to
;; Bibtex option, e.g. from Web of Science.
;; This code is mostly wrappers around the command line utilities at
;; http://sourceforge.net/p/bibutils/home/Bibutils.
;; Here are the commands that are available.
;; bib2xml - convert BibTeX to MODS XML intermediate
;; biblatex2xml - convert BibLaTeX to MODS XML intermediate
;; copac2xml - convert COPAC format references to MODS XML intermediate
;; end2xml - convert EndNote (Refer format) to MODS XML intermediate
;; endx2xml - convert EndNote XML to MODS XML intermediate
;; isi2xml - convert ISI web of science to MODS XML intermediate
;; med2xml - convert Pubmed XML references to MODS XML intermediate
;; modsclean - a MODS to MODS converter for testing puposes mostly
;; ris2xml - convert RIS format to MODS XML intermediate
;; xml2ads - convert MODS XML intermediate into Smithsonian Astrophysical
;; Observatory (SAO)/National Aeronautics and Space
;; Administration (NASA) Astrophyics Data System or ADS
;; reference format (converter submitted by Richard Mathar)
;; xml2bib - convert MODS XML intermediate into BibTeX
;; xml2end - convert MODS XML intermediate into format for EndNote
;; xml2isi - convert MODS XML intermediate to ISI format
;; xml2ris - convert MODS XML intermediate into RIS format
;; xml2wordbib - convert MODS XML intermediate into Word 2007 bibliography format
;;; Code:
(require 'bibtex)
(require 'org-ref-core)
;;* RIS to bibtex
;; RIS can be pretty easily exported from Endnote. Here is a function to read an
;; RIS file and convert it to bibtex which is inserted at point. Note that there
;; is often other output from the commands. We try to comment them out here, but
;; you should probably inspect the entries, and do other bibtex file compliance
;; checks.
;;;###autoload
(defun ris2bib (risfile &optional verbose)
"Convert RISFILE to bibtex and insert at point.
Without a prefix arg, stderr is diverted.
If VERBOSE is non-nil show command output."
(interactive
(list (read-file-name "RIS file:")
(prefix-numeric-value current-prefix-arg)))
(let ((result (shell-command-to-string
(concat
(format
"ris2xml %s | xml2bib -w"
risfile)
(unless verbose " 2> /dev/null")))))
;; make some lines into comments.
(setq result (replace-regexp-in-string
"^xml2bib:"
"% xml2bib:"
result))
(setq result (replace-regexp-in-string
"^ris2xml:"
"% ris2xml"
result))
(setq result (replace-regexp-in-string
"^ Defaulting"
"% Defaulting"
result))
(insert result)))
;;* Pubmed XML to bibtex
;; In http://www.ncbi.nlm.nih.gov/pubmed/ you can select entries, and then send
;; them to a file. If you choose Pubmed XML as the format, then you can use this
;; function to convert it to bibtex.
;;;###autoload
(defun medxml2bib (medfile &optional verbose)
"Convert MEDFILE (in Pubmed xml) to bibtex and insert at point.
Without a prefix arg, stderr is diverted.
Display output if VERBOSE is non-nil."
(interactive
(list (read-file-name "MED file:")
(prefix-numeric-value current-prefix-arg)))
(let ((result (shell-command-to-string
(concat
(format
"med2xml %s | xml2bib -w"
medfile)
(unless verbose " 2> /dev/null")))))
;; make some lines into comments.
(setq result (replace-regexp-in-string
"^xml2bib:"
"% xml2bib:"
result))
(setq result (replace-regexp-in-string
"^med2xml:"
"% med2xml"
result))
(setq result (replace-regexp-in-string
"^ Defaulting"
"% Defaulting"
result))
(insert result)))
;;* Clean up all the entries
;; Finally, after you put the new entries in, you probably need to do some clean
;; up actions. This little function does that.
;;;###autoload
(defun clean-entries ()
"Map over bibtex entries and clean them."
(interactive)
(bibtex-map-entries
(lambda (a b c)
(ignore-errors
(org-ref-clean-bibtex-entry)))))
(provide 'x2bib)
;;; x2bib.el ends here