Emacs-zotero is a GNU Emacs interface to the Zotero Web API v3. It provides wrapper functions to access the API, functions to cache and sync emacs-zotero with the Zotero server, and a browser to interact with the cache.
Emacs-zotero is now available from MELPA.
To follow or contribute to emacs-zotero development, you can browse or clone the Git repository on GitLab:
git clone https://gitlab.com/fvdbeek/emacs-zotero.git
If you are installing manually, make sure that Emacs can find it by adding the following line to your startup file:
(add-to-list 'load-path "/path/to/emacs-zotero")
To use emacs-zotero, include the following in your init.el
or .emacs
file:
(require 'zotero)
(require 'zotero-browser)
If you use use-package
, you can do the below instead:
(use-package zotero
:ensure t
:commands (zotero-browser)
:init
(require 'zotero-browser))
Accessing non-public libraries requires the use of an Zotero account. An account can be created via the Zotero website. Authentication is not required for read access to public libraries.
Requests for data in a specific library require a user ID or group ID. User
IDs are different from usernames and can be found on the API Keys page. M-x
zotero-auth-username
, M-x zotero-auth-userid
, and M-x zotero-auth-api-key
return the username, userid and API key, respectively. When you haven’t
authorized emacs-zotero already, you will be redirected to authorize.
Group IDs are different from group names and can be retrieved with the
zotero-groups
.
The Zotero API uses OAuth 1.0 to authenticate requests. A token can be
requested with zotero-auth-authorize
:
(zotero-auth-authorize)
The token is stored in a structure of type zotero-auth-token
. It is saved
for future sessions, by default to your initialization file. The token will
be valid indefinitely, unless it is revoked by the user manually.
For manual authentication without OAuth, you will need a userid, username,
token, and secret (the token and secret are the same) from Zotero, and
store it in the zotero-auth-token
struct:
- The userid is mentioned on the [Zotero feeds/API settings page](https://www.zotero.org/settings/keys):
- The username is mentioned on the [Zotero account settings page](https://www.zotero.org/settings/account):
- Create a new API key on the [Zotero feeds/API settings page](https://www.zotero.org/settings/keys/new). You will be presented a new API key:
- Create a Zotero token:
(setq zotero-auth-token (zotero-auth-token-create :token <api-key>
:token-secret <api-key>
:userid <userid>
:username <username>))
- Save the token for future sessions:
(customize-save-variable 'zotero-auth-token zotero-auth-token)
All requests available in the Zotero Web API can be constructed with the
zotero-request
function. This function is rather complicated, so for your
convenience the most common Zotero requests have specialised functions with less
options.
Function: zotero-request METHOD RESOURCE &optional KEY &key TYPE ID API-KEY HOST HEADERS PARAMS DATA NO-AUTH
Return the response of the Zotero request.
METHOD is the method to use for the request, i.e. “GET”, “HEAD” “POST”, “PUT”, “PATCH”, or “DELETE”.
RESOURCE is one of:
- “collections”: collections in the library
- “collections-top”: top level collections in the library
- “collection”: a specific collection in the library
- “subcollections”: subcollections within a specific collection in the library
- “items”: all items in the library, excluding trashed items
- “items-top”: top level items in the library, excluding trashed items
- “trash-items”: items in the trash
- “item”: a specific item in the library
- “item-children”: child items under a specific item
- “publication-items”: items in My Publications
- “collection-items”: items within a specific collection in the library
- “collection-items-top”: top level items within a specific collection in the library
- “searches”: all saved searches in the library
- “search”: a specific saved search in the library
- “tags”: all tags in the library, or tags of all types matching a specific name when an url encoded tag is provided
- “item-tags”: tags associated with a specific item
- “collection-tags”: tags within a specific collection in the library
- “items-tags”: all tags in the library, with the ability to filter based on the items
- “items-top-tags”: tags assigned to top level items
- “trash-items-tags”: tags assigned to items in the trash
- “collection-items-tags”: tags assigned to items in a given collection
- “collection-items-top-tags”: tags assigned to top level items in a given collection
- “publication-items-tags”: tags assigned to items in My Publications
- “keys”: the user id and privileges of the given API key
- “groups”: all groups the current API key has access to, including public groups the key owner belongs to even if the key doesn’t have explicit permissions for them
- “group”: group metadata
- “all-fulltext”: all full-text content
- “item-fulltext”: an item’s full-text content
- “file”: an item’s attachment file
- “deleted”: all deleted data.
KEY is the item key, collection key, or search key. Which key is needed varies by resource.
Keyword TYPE is “user” for your personal library, and “group” for the group libraries.
ID is the ID of the personal or group library you want to access, that is the user ID or group ID. Your personal library ID is available at URL ‘https://www.zotero.org/settings/keys/’. For group libraries, the ID can be found by opening the group’s page at URL ‘https://www.zotero.org/groups/’.
API-KEY is the Zotero API key.
If HOST is non-nil, use that instead of zotero-base-url
.
HEADERS is an alist of extra headers. The CAR of each cons cell is the field name and the CDR is the field value. HEADERS has the form:
(("Content-Type" . "application/x-www-form-urlencoded"))
PARAMS is an alist of the query string that is part of the URL. The CAR of each cons cell is the parameter, CAR of the CDR is the value. PARAMS has the form:
((key1 val1) (key2 val2) (key3 val1 val2) (key4) (key5 ""))
DATA is the data to be sent to the server.
If NO-AUTH is non-nil, no authentication is used. Authentication is not required for read access to public libraries.
Below are several examples of web API request URLs taken from the Zotero Web API Documentation and their equivalent emacs-zotero requests:
https://api.zotero.org/users/475425/collections/9KH9TNSJ/items/top?v=3
(zotero-request "GET"
"collection-items-top" "475425"
:type "user"
:id "475425"
:no-auth t)
https://api.zotero.org/users/475425/items/X42A7DEE?v=3
(zotero-request "GET"
"item" "X42A7DEE"
:type "user"
:id "475425"
:no-auth t)
https://api.zotero.org/users/475425/collections?v=3
(zotero-request "GET"
"collections" "X42A7DEE"
:type "user"
:id "475425"
:no-auth t)
https://api.zotero.org/users/475425/items?format=atom&v=3
(zotero-request "GET"
"items" nil
:type "user"
:id "475425"
:params '(("format" "atom"))
:no-auth t)
https://api.zotero.org/users/475425/collections/9KH9TNSJ/items?format=bib
(zotero-request "GET"
"collection-items" "9KH9TNSJ"
:type "user"
:id "475425"
:params '(("format" "bib"))
:no-auth t)
All request functions return a record of type zotero-response
, which
contains the following slots:
status-code
: status code of the responseheaders
: alist of response headers. The CAR of each cons cell is the field name and the CDR is the field value.version
: current library version, as returned by the “Last-Modified-Version” header in the response.etag
: attachment item’s md5 value, as returned by the “ETag” header in the response.data
: data returned in the response. The data is returned as a property list, converted from JSON. The value:json-empty
(instead ofnil
) is used for an empty object to differentiate an empty value and an empty object.
Given a zotero-response
object response
, you can access the slots by
calling (zotero-response-status-code response)
, (zotero-response-headers
response)
, (zotero-response-version response)
, (zotero-response-etag
response)
, and (zotero-response-data response)
. For example:
(setq response (zotero-request "GET"
"item" "E4TD9XGL"
:type "user"
:id "475425"
:no-auth t))
(zotero-response-status-code response) ; => 200
(zotero-response-version response) ; => 3662
(zotero-response-data response) ; => (:key "E4TD9XGL" :version 3662 :library (:type "user" :id 475425 :name "Z public library" :links (:alternate (:href "https://www.zotero.org/z_public_library" :type "text/html"))) :links (:self (:href "https://api.zotero.org/users/475425/items/E4TD9XGL" :type "application/json") :alternate (:href "https://www.zotero.org/z_public_library/items/E4TD9XGL" :type "text/html") :up (:href "https://api.zotero.org/users/475425/items/7VLLCTW7" :type "application/json")) :meta (:numChildren :json-false) :data (:key "E4TD9XGL" :version 3662 :parentItem "7VLLCTW7" :itemType "attachment" :linkMode "imported_file" :title "Zotero Blog » Blog Archive » A Unified Zotero Experience.pdf" :accessDate "" :url "" :note "" :contentType "application/pdf" :charset "" :filename "Zotero Blog » Blog Archive » A Unified Zotero Experience.pdf" :md5 "fb8537e562048fc14b4fc9b637e195de" :mtime 1503415007000 :inPublications t :tags [] :relations :json-empty :dateAdded "2017-08-22T15:16:47Z" :dateModified "2017-08-22T15:16:47Z"))
The most common Zotero requests are provided in the specialised functions outlined below.
The request functions accept one or more of the following arguments:
- TYPE (string): a valid Zotero API library type: “user” or “group”. Defaults to “user”.
- ID (string): a valid Zotero API user or group ID. Defaults to the user ID
stored in
zotero-auth-token
. - API-KEY (string): a valid Zotero API user key. Defaults to the API key
stored in
zotero-auth-token
. - LOCALE (string): the locale, allowing retrieval of localised item types, field types, and creator types. Defaults to “en-US”.
- KEY (string): a valid item key, collection key, or search key, depending on the resource.
- OBJECT (plist): a plist of an object. Instead of a plist, OBJECT may be:
- buffer (read one Lisp expression from the beginning)
- a function (call it with no arguments)
- a file (read one Lisp expression from the beginning)
- a string (takes text from string, starting at the beginning).
- VERSION (string or number): the last known version number of the object, as returned by the “Last-Modified-Version” response header.
Timeout in seconds. Default=30.
Locale used in translations. Default=”en-US”.
Return Zotero library items.
Return top level Zotero library items.
Return the publications from the “My Publications” collection of a user’s library. Only available on user libraries.
Return library items from the library’s trash.
Return a specific item.
Return the child items of a specific item.
Return items from the specified collection. This includes sub-collection items.
Return top level items from the specified collection.
Return a library’s collections. This includes subcollections.
Return a library’s top level collections.
Return a specific collection.
Return the sub-collections of a specific collection.
Return a library’s tags.
Return tags from a specific item.
Return tags in a specific collection.
Return info about the user and group library permissions, based on the API-KEY.
Together with zotero-groups
, this allows all accessible resources to be
determined.
Delete the API-KEY.
Return the Zotero group data to which the current library ID and API-KEY has access.
Return the metadata of the Zotero group.
Create a new group. The Zotero API doesn’t support creating groups, so this function invokes a browser to open a link.
Change the group settings of group ID. The Zotero API doesn’t support changing the group settings, so this function invokes a browser to open a link.
Search all items.
Search all tags.
Create an item.
Create multiple items.
Update an existing item.
Update multiple existing items.
Partially update an existing item.
Delete an item.
Delete multiple items.
Create a collection.
Create multiple collections.
Update an existing collection.
Update multiple existing collections.
Delete a collection.
Delete multiple collections.
Create a saved search.
Create multiple searches.
Update existing searches.
Delete multiple searches.
Delete multiple tags.
Return all available item types.
Return all available item fields.
Return all valid fields for the specified item type.
Return all valid creator types for the specified item type.
Return all creator fields.
Return the attachment linkmode types.
Return a template for a new collection.
Return the template for a new item of an item type.
Return a template for a new attachment item of a linkmode.
Return the attributes of an attachment file.
Get the attributes of a file. The result is a plist with :filename
, :filesize
,
:content-type
, :md5
, :mtime
, and :accessdate
props to be passed to
zotero-authorize-upload
.
Authorize, upload and register an attachment to an item. This is a convenient
wrapper around zotero-authorize-upload
, zotero-upload-file
, and
zotero-register-upload
.
Return the raw file content of an item.
A convenient wrapper around zotero-file
. Download an attachment using the
optional path and filename. If neither are supplied, the file is written to the
current working directory, and zotero-item
is called to determine the attachment
filename.
Webpage snapshots prior to Zotero 5.0.93 were saved as zip files. The downloaded file will be given a zip extension.
PDFs are recognized using an undocumented Zotero web service that operates on the first few pages of text using extraction algorithms and known metadata from CrossRef. The Zotero lookup service doesn’t require a Zotero account, and data about the content or results of searches are not logged.
The metadata can be used to create a parent item for the PDF attachment, by looking up item metadata when supplied with a standard identifier.
Install the PDF tools modified by Zotero. The executables are modified to output a preprocessed JSON that contains rich and structured information about the PDF and the text extracted from it, for use with the PDF recognizer.
This function downloads and extracts the binaries available for macOS, Windows
and Linux. You can change the installation directory by setting
zotero-recognize-pdftools-dir
to an appropriate value before calling this
function.
If there are no binaries available for your operating system, you should
compile them from source and set the variables zotero-recognize-pdftotext
,
zotero-recognize-pdfinfo
, and zotero-recognize-pdfdata
to the corresponding
paths. The source is available at https://github.com/zotero/cross-poppler.
Return metadata recognized from a PDF.
While Zotero is only able to index PDF documents, emacs-zotero can index far
more file types. To index documents external dependencies are needed. The
pdftotext executable is needed for PDFs, the antiword executable for
Microsoft Word documents until version 2003, and the pandoc executable for
pandoc compatible markup formats. See the variable
zotero-fulltext-pandoc-mimetypes
for a list of formats understood by pandoc.
Return fulltext content of an item.
Create full-text content for an item.
Create full-text content for an item.
This is a convenient wrapper around zotero-fulltext-create-item
that is able to
index a variety of file formats, including but not limited to:
- Portable Document Format (PDF)
- OpenDocument (ODT)
- Microsoft Word version 2, 6, 7, 97, 2000 and 2003 (DOC)
- Office Open XML (DOCX)
- EPUB
- LaTeX
- Org-mode.
Executable for pdftotext. Needed for fulltext indexing of PDF documents. It is freely available and included by default with many Linux distributions, and is also available for Windows as part of the Xpdf Windows port. Default=”pdftotext”.
Executable for pdfinfo. Needed for fulltext indexing of PDF documents. It
is freely available and included by default with many Linux distributions,
and is also available for Windows as part of the Xpdf Windows port. This
variable is set by zotero-fulltext-install-pdftools
after downloading the
PDF tools modified by Zotero. If you compile the PDF tools from source, it
should point to the “pdfinfo-*” binary for your operating system.
Default=”pdfinfo”.
Executable for pandoc executable. Pandoc is an open-source document converter that supports many formats and is freely available for most operating systems. Default=”pandoc”.
Executable for antiword executable. Antiword is an open source reader for proprietary Microsoft Word documents and is freely available for most operating systems. Default=”antiword”.
How much text is indexed. Default: 500000 characters.
How much text is indexed. Default: 100 pages.
Zotero provides a user interface to the Zotero library with zotero-browser
.
The browser allows you to interact with the cache. You can add the browser to
your setup by loading it with:
(require 'zotero-browser)
To use the browser, you should do M-x zotero-browser-sync
to synchronize the
cache with the Zotero server.
The default layout is shown in the screenshot below. It can be changed by using window parameters as explained in the Elisp reference manual accessible from Emacs or online.
The browser is interactive an has its own keybindings.
Key | Binding |
---|---|
n | Move to next library |
p | Move to previous library |
C-c C-u | Move to parent collection |
C-c C-n | Move to next collection |
C-c C-p | Move to previous collection |
RET | Display library |
e | Change group settings |
+ | Create new group |
g | Reload the current buffer |
q | Quit current window |
Key | Binding |
---|---|
n | Move to next collection |
p | Move to previous collection |
u | Move to parent collection |
C-c C-f | Move to next collection on same level |
C-c C-b | Move to previous collection on same level |
TAB | Expand or collapse the children of the current item |
S-TAB | Cycle the visibility of children |
$ | Expand all children |
M-$ | Collapse all children |
RET | Display collection |
e | Edit collection |
+ | Create new collection |
D | Delete collection |
g | Reload the current buffer |
q | Quit current window |
Key | Binding |
---|---|
n | Move to next item |
p | Move to previous item |
u | Move to parent item |
C-c C-f | Move to next item on same level |
C-c C-b | Move to previous item on same level |
C-c C-n | Move to next collection |
C-c C-p | Move to previous collection |
C-c C-u | Move to parent collection |
TAB | Expand or collapse the children of the current item |
S-TAB | Cycle the visibility of children |
$ | Expand all children |
M-$ | Collapse all children |
RET | Open attachment |
e | Edit current entry |
+ | Create new item |
D | Delete item |
R | Remove item from collection |
C | Copy item to a collection |
M | Move item to a parent item |
g | Reload the current buffer |
Key | Binding |
---|---|
TAB | Forward |
S-TAB | Backward |
RET | Invoke button |
C-x C-s | Save item |
C-c C-k | Reset item |
C-c C-c | Edit text for the current text field in a separate buffer |
M-TAB or C-M-i | Complete field |
q | Quit current window |
Serialize the memory cache to the hard drive.
Serialize the hard drive to the memory cache.
Erase the cache. If optional argument NO-CONFIRM is non-nil, don’t ask for confirmation.
Initialize the cache if needed.
Caching is automatically enabled by default.
Storage of attachment files is automatically enabled by default.
The cache file. By default “zotero-cache” in user-emacs-directory
.
Attachment storage directory. By default “zotero-storage” in
user-emacs-directory
.
Number of seconds before the cache expires. Default=86400 (one day).
Sync the Zotero library, templates, schemas and file storage. When optional
argument FULL-SYNC is non-nil, or with a C-u
prefix, force a full sync.
Seconds to wait before stopping sync retries; set to 0 to disable retrying. Default=3600.
Maximum sync retries. Set to 0 to disable retrying. Default=100.
Create a new Zotero browser buffer.
Display current library or collection.
Open attachment at point.
Check if the current buffer is a Zotero browser buffer.
Check if the current buffer is a Zotero items buffer.
Check if the library in the current buffer has write access.
Check if there is an item at point.
Reload the current buffer.
Move point to the next item.
Move point to the previous item.
Move point to the parent item.
Move point to the next collection.
Move point to the previous collection.
Move point to the parent collection.
Show all items.
Show unfiled items.
Show trashed items.
Expand or collapse the children of the current item.
Cycle the visibility of children.
Expand all children.
Collapse all children.
Expand children till level NUM. If NUM is omitted or nil, expand till level 1.
Edit current entry.
Move current entry to a parent item. With a C-u
prefix, move to top
level.
Move current entry to a collection.
Copy current entry to another collection.
Remove current entry from the collection.
Move current entry to trash. If region is active, trash entries in active region instead.
Restore current entry from trash. If region is active, restore entries in active region instead.
Delete current entry. If region is active, delete entries in active region instead.
Create a new collection or item.
Create a new note. With a C-u
prefix, create a new top level note.
Create a new attachment with the current entry as parent. With a C-u
prefix, create a new top level attachment.
Only file attachments (imported_file/linked_file) and PDF imported web attachments (imported_url with content type application/pdf) are allowed as top level items, as in the Zotero client.
Update the attachment of the current entry.
Rename the attachment of the current entry to match the metadata.
Import a PDF file and create a new attachment. Retrieve the metadata automatically, create an appropriate parent item, and rename the associated file based on the metadata.
Link to a PDF file and create a new attachment. Retrieve the metadata automatically and create an appropriate xparent item.
Create a new item by providing an identifier. Argument STRING is a ISBN, DOI, PMID, or arXiv ID.
Recognize content of the current entry.
Index the full-text content of the current entry.
Return the path of the attachment of the current entry.
Download the attachment of the current entry.
Optional argument DIR is the directory. If DIR is omitted or nil, the
attachment is downloaded to the default storage directory
zotero-cache-storage-dir
and a subdirectory named as the item key.
The default buffer name. Default=”\*Zotero Libraries\*”.
The default buffer name. Default=”\*Zotero Collections\*”.
The default name of the items buffer. Default=”\*Zotero Items\*”.
The default expansion level for collections. Default=1.
The default expansion level for items. Default=1.
When t show browser icons. Icons are enabled by default.
Sort field for the collections buffer. If nil, no sorting is performed. Otherwise, this should be a cons cell (FIELD . FLIP). FIELD is the prop of the object plist to be sorted. FLIP, if non-nil, means to invert the resulting sort. Default=:name.
Sort field for the collections buffer. If nil, no sorting is performed. Otherwise, this should be a cons cell (FIELD . FLIP). FIELD is the prop of the object plist to be sorted. FLIP, if non-nil, means to invert the resulting sort. Default=:name.
Sort field for the items buffer. If nil, no sorting is performed. Otherwise, this should be a cons cell (FIELD . FLIP). FIELD is the prop of the object plist to be sorted. FLIP, if non-nil, means to invert the resulting sort. Default=:title.
Fields to show in the libraries buffer. This should be a list of cons cells (FIELD . WIDTH), where:
- FIELD is the prop of the object plist to be sorted.
- WIDTH is the width to reserve for the column.
Fields to show in the collections buffer. This should be a list of cons cells (FIELD . WIDTH), where:
- FIELD is the prop of the object plist to be sorted.
- WIDTH is the width to reserve for the column.
Fields to show in the items buffer. This should be a list of cons cells (FIELD . WIDTH), where:
- FIELD is the prop of the object plist to be sorted.
- WIDTH is the width to reserve for the column.
Fields to show in the attachment filename. Join all the key values with the separator in between.
Maximum length of fields in attachment filenames. Fields exceeding the maximum length are truncated. Default=50.
Preferred application to open files. The default is mailcap.
Emacs-zotero provides a few helper functions that are used internally, but could prove useful elsewhere as well.
Convert KEYWORD to a string. Strip the leading “:” from the keyword.
Convert STRING to a keyword. Add a leading “:” to the string.
Recursively extract a value from a property list. This function returns the value corresponding to the given PROPS in a nested PLIST. The lookup for each prop should return another plist, except for the final prop, which may return any value.
Delete PROPS from PLIST.
Return non-nil if PLIST1 and PLIST2 can be merged without conflicts. Two plists are considered mergable when the same keys don’t have different values.
Merge PLIST2 into PLIST1.
Check if STRING is a valid ISBN. Return the ISBN if it is valid, else return nil. Argument STRING can be in either the older ISBN-10 or the current ISBN-13 format. A leading “ISBN” identifier is allowed, and ISBN parts can optionally be separated by hyphens or spaces. The format is validated by a regexp and the validity of the final digit is checked using a checksum algorithm.
Check if STRING is a valid arXiv identifier. Return the arXiv identifier if it is valid, else return nil. The scheme used by arXiv was changed in April 2007. Argument STRING can be in either the old scheme (from 1999 to March 2007) or the new scheme (since 1 April 2007). A leading “arXiv” identifier is allowed. The format is validated by a regexp.
Check if STRING is a valid Crossref DOI. Return the DOI if it is valid, else return nil. A leading “doi” identifier or a link (for example, https://doi.org/10.1000/182) is allowed. The format is validated by a regexp.
Check if STRING is a valid PubMed ID (PMID). Return the PMID if it is valid, else return nil. A leading “PMID” identifier is allowed. The format is validated by a regexp.
Replace HTML entities with unicode in STRING.
Remove all HTML tags from STRING.