;;; org-ref-scopus.el --- Emacs-lisp interface to the Scopus API -*- lexical-binding: t; -*- ;; Copyright (C) 2015 John Kitchin ;; Author: John Kitchin ;; 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 . ;;; 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 "%s" 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 "%s" 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 "%s" 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 "%s" keyword (or desc (concat "scopusid:" keyword))))))) (provide 'org-ref-scopus) ;;; org-ref-scopus.el ends here