-
Notifications
You must be signed in to change notification settings - Fork 37
/
org-ebib.el
170 lines (148 loc) · 7.29 KB
/
org-ebib.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
;;; org-ebib.el --- Support for links to Ebib entries in Org -*- lexical-binding: t -*-
;; Copyright (c) 2014-2020 Grégoire Jadi, Joost Kremers
;; Al rights reserved
;; Author: Grégoire Jadi <daimrod@gmail.com>
;; Maintainer: Joost Kremers <joostkremers@fastmail.fm>
;; This file is not 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, 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 GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;; This file provides two functions to integrate Ebib with org-mode.
;; `org-ebib-open' can be called with a BibTeX key as argument. It opens Ebib
;; and shows the entry corresponding to the key. `org-ebib-store-link' creates
;; a link that when followed opens Ebib.
;;; Code:
(require 'org)
;; This is to silence the byte-compiler and flycheck.
(defvar ebib--cur-db)
(defvar ebib--databases)
(defvar ebib-citation-description-function)
(defvar ebib-citation-insert-multiple)
(declare-function ebib "ebib" (&optional file key))
(declare-function ebib--get-key-at-point "ebib" ())
(declare-function ebib--get-local-bibfiles "ebib" ())
(declare-function ebib--get-or-open-db "ebib" file)
(declare-function ebib-read-entry-ivy "ebib" databases)
(declare-function ebib-read-entry-helm "ebib" databases)
(declare-function ebib-read-entry-multiple "ebib" databases)
(declare-function ebib-read-entry-single "ebib" databases)
(declare-function ebib-db-get-entry "ebib-db" (key db &optional noerror))
(declare-function ebib-db-get-filename "ebib-db" (db &optional shortened))
(declare-function org-link-set-parameters "org" (type &rest parameters))
(declare-function org-element-context "org-element" (&optional element))
(declare-function org-element-property "org-element" (property element))
(defvar reftex-cite-punctuation)
(declare-function reftex-format-citation "reftex-cite" (entry format))
(defcustom org-ebib-help-echo-format "%2a (%y), %t, %b, %j %<"
"Citation format used to display citation info in the message area.
Must NOT contain %l. See the variable `reftex-cite-format' for
possible percent escapes."
:group 'ebib
:type 'string)
(defcustom org-ebib-link-type 'key
"Type of link created by `org-ebib-store-link'.
This can be `key', which creates a link with the key of the
entry, `key+filename', which adds the file name of the `.bib'
file containing the key, or `key+filepath', which adds the full
path to the `.bib' file. If the file name or path is added, it
is separated from the key with an @-sign."
:group 'ebib
:type '(choice (const :tag "Key only" key)
(const :tag "Key and file name" key+filename)
(const :tag "Key and file path" key+filepath)))
(org-link-set-parameters "ebib" :follow #'org-ebib-open :store #'org-ebib-store-link)
;;;###autoload
(defun org-ebib-open (entry)
"Open Ebib and jump to ENTRY."
(save-match-data
(string-match "^\\(.*?\\)\\(?:@\\(.*?\\)\\)?$" entry)
(let ((key (match-string 1 entry))
(db (match-string 2 entry)))
(ebib db key))))
(defun org-ebib-store-link ()
"Store a link to an Ebib entry.
This function is called when executing `org-store-link' in Ebib's
entry buffer."
(when (memq major-mode '(ebib-index-mode ebib-entry-mode))
;; This is an Ebib entry
(let* ((key (ebib--get-key-at-point))
(link (concat "ebib:" (pcase org-ebib-link-type
('key key)
('key+filename (format "%s@%s" key (ebib-db-get-filename ebib--cur-db :shortened)))
('key+filepath (format "%s@%s" key (ebib-db-get-filename ebib--cur-db))))))
(description (ignore-errors (funcall ebib-citation-description-function key ebib--cur-db))))
(org-link-store-props :type "ebib"
:link link
:description description))))
(defun org-ebib-insert-link ()
"Insert a link to an Ebib entry.
This function can be called in an Org mode buffer to insert a
link to an Ebib entry."
(interactive)
(let* ((database-files (ebib--get-local-bibfiles))
(databases (or (delq nil (mapcar #'ebib--get-or-open-db database-files))
ebib--databases))
(entries (cond
((and (boundp 'ivy-mode) ivy-mode) (ebib-read-entry-ivy databases))
((and (boundp 'helm-mode) helm-mode) (ebib-read-entry-helm databases))
(ebib-citation-insert-multiple (ebib-read-entry-multiple databases))
(t (ebib-read-entry-single databases))))
(separator (if (> (length entries) 1)
(read-string "Separator: ")
"")))
(mapc (lambda (entry)
(let ((link (pcase org-ebib-link-type
('key (car entry))
('key+filename (format "%s@%s" (car entry) (ebib-db-get-filename (cdr entry) :shortened)))
('key+filepath (format "%s@%s" (car entry) (ebib-db-get-filename (cdr entry))))))
(description (ignore-errors (funcall ebib-citation-description-function (car entry) ebib--cur-db))))
(insert (format "[[ebib:%s][%s]]%s" link description separator))))
entries)))
(with-eval-after-load "reftex-cite"
(org-link-set-parameters "ebib" :help-echo #'org-ebib-show-citation-info))
(defun org-ebib-show-citation-info (window _object position)
"Help echo function for org-ebib links.
WINDOW is the window displaying the link, POSITION the link's
position in the relevant buffer."
(with-selected-window window
(save-excursion
(goto-char position)
(goto-char (org-element-property :begin (org-element-context)))
(cond
((looking-at org-link-bracket-re)
(mapconcat 'org-ebib-make-help-echo-string
(split-string
(cadr (split-string (match-string-no-properties 1)
":" t "[[:punct:]]*"))
"," t)
"\n"))
((looking-at org-link-plain-re)
(mapconcat 'org-ebib-make-help-echo-string
(split-string
(cadr (split-string (match-string-no-properties 0)
":" t "[[:punct:]]*"))
"," t)
"\n"))
(t "Not a link?")))))
(defun org-ebib-make-help-echo-string (key &optional format)
"Return the citation string of KEY according to FORMAT.
It is adapted from `reftex-make-cite-echo-string'."
(let ((entry (ebib-db-get-entry key ebib--cur-db 'noerror))
(reftex-cite-punctuation '(" " " & " " et al.")))
(or format (setq format org-ebib-help-echo-format))
(if entry
(replace-regexp-in-string
"[\"{}]" ""
(reftex-format-citation entry format))
(format "Key %s is not found in current database." key))))
(provide 'org-ebib)
;;; org-ebib.el ends here