summaryrefslogtreecommitdiff
path: root/lisp/init-bib.el
blob: 1c44bbec7e153a9897e2a5939d49bed5296f093b (plain)
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
;; Make cite key have form <last author last name><year><first word>.
(setq bibtex-autokey-titlewords 1
      bibtex-autokey-titleword-ignore '("A" "An" "On" "The"  "[0-9].*")
      bibtex-autokey-titleword-length nil
      bibtex-autokey-titlewords-stretch 0
      bibtex-autokey-year-length 4
      bibtex-autokey-year-title-separator "")

(setq bibtex-align-at-equal-sign t)  ; Used by `bibtex-fill-entry'.

(after 'bibtex
  (setq bibtex-entry-format
        (append '(realign whitespace last-comma delimiters sort-fields)
                bibtex-entry-format)))

(add-hook 'bibtex-clean-entry-hook 'km/bibtex-use-title-case)
(add-hook 'bibtex-clean-entry-hook 'km/bibtex-single-space-author-list)
(add-hook 'bibtex-clean-entry-hook 'km/bibtex-pages-use-double-hyphen)
(add-hook 'bibtex-clean-entry-hook 'km/bibtex-remove-doi-leader)

(defvar km/bibtex-unimportant-title-words
  '("a" "aboard" "about" "above" "absent" "across" "after" "against"
    "along" "alongside" "amid" "amidst" "among" "amongst" "an" "and"
    "around" "as" "aslant" "astride" "at" "athwart" "atop"
    "barring" "before" "behind" "below" "beneath" "beside" "besides" "between"
    "beyond" "but" "by" "despite" "down" "during" "except" "failing"
    "following" "for" "from" "in" "inside" "into" "like"
    "mid" "minus" "near" "next" "nor" "notwithstanding" "of" "off"
    "on" "onto" "opposite" "or" "out" "outside" "over" "past"
    "per" "plus" "regarding" "round" "save" "since" "so" "than"
    "the" "through" "throughout" "till" "times" "to" "toward" "towards"
    "under" "underneath" "unlike" "until" "up" "upon" "via" "vs."
    "when" "with" "within" "without" "worth" "yet")
  "Words to ignore when running `km/bibtex-use-title-case'.
These are taken from
http://lanecc.libguides.com/content.php?pid=38483&sid=295540 and
have only been modified to remove duplicates. This means that
there are some unlikely words in there, but you never know when
the next article you read will have \"athwart\" in the title.")

(defun km/bibtex-use-title-case ()
  "Convert title of current BibTeX entry to title case.
Change words in `km/bibtex-unimportant-title-words' to lower
case, unless the word is the first word in the title.  Capitalize
all other words unless they are protected by brackets."
  (interactive)
  (save-excursion
    (bibtex-beginning-of-entry)
    (let* ((text-bounds (cdr (bibtex-search-forward-field "title" t)))
           (beg (car text-bounds))
           (end (cadr text-bounds)))
      (goto-char (1- beg))
      (while (re-search-forward "\\(\\W\\)\\(\\w+\\)\\(\\W\\)" end t)
        (cond
         ((and (string= (match-string 1) "{")
               (string= (match-string 3) "}"))
          ;; Go to previous character in case '}' is within the word.
          (backward-char))
         ;; Leave commands alone.
         ((string= (match-string 1) "\\"))
         ;; Capitalize the first word of the title.  This will fail if
         ;; there is a space after '{'.
         ((= (match-beginning 1) beg)
          (backward-word)
          (capitalize-word 1))
         ;; Subword is separated by '-' or '{'.
         ((or (string= (match-string 1) "-")
              (string= (match-string 1) "}"))
          (backward-word)
          (downcase-word 1))
         (t
          (backward-word)
          (if (member (downcase (match-string-no-properties 2))
                      km/bibtex-unimportant-title-words)
              (downcase-word 1)
            (capitalize-word 1))))))))

(defun km/bibtex-single-space-author-list ()
  "Convert multiple spaces in author list to single space."
  (interactive)
  (save-excursion
    (bibtex-beginning-of-entry)
    (let* ((text-bounds (cdr (bibtex-search-forward-field "author" t)))
           (beg (car text-bounds))
           (end (cadr text-bounds)))
      (goto-char beg)
      (while (re-search-forward "\\(\\s-+\\) and" end t)
        (replace-match "" nil nil nil 1))
      (goto-char beg)
      (fill-paragraph))))

(defun km/bibtex-pages-use-double-hyphen ()
  "Use double hyphen for page range."
  (interactive)
  (save-excursion
    (bibtex-beginning-of-entry)
    (let* ((text-bounds (cdr (bibtex-search-forward-field "pages" t)))
           (beg (car text-bounds))
           (end (cadr text-bounds)))
      (when text-bounds
        (goto-char beg)
        (and (re-search-forward "[^A-z0-9]*-[^A-z0-9]*" end t)
             (replace-match "--"))))))

(defun km/bibtex-remove-doi-leader ()
  "Remove leading part (http:...) of doi URL."
  (interactive)
  (save-excursion
    (bibtex-beginning-of-entry)
    (let* ((text-bounds (cdr (bibtex-search-forward-field "doi" t)))
           (beg (car text-bounds))
           (end (cadr text-bounds)))
      (when text-bounds
        (goto-char beg)
        (and (re-search-forward "http://dx.doi.org/" end t)
             (replace-match ""))))))

(defun km/browse-doi (doi)
  "Open DOI in browser.
When called interactively, take the DOI from the text under
point.  The link is opened using the settings of
`org-doi-server-url'."
  (interactive (list (km/doi-at-point)))
  (browse-url (org-link-escape-browser (concat org-doi-server-url doi))))

(defun km/copy-doi-as-kill ()
  "Copy DOI at point to kill ring."
  (interactive)
  (-when-let (doi (km/doi-at-point))
    (kill-new (message "%s" (concat "doi:" doi)))))

(defun km/doi-at-point ()
  "Return DOI at point."
  (save-excursion
    (skip-chars-backward "-.A-z0-9/")
    (and (looking-at "\\(doi:[ \t\n]*\\)*\\([-./A-z0-9]+[A-z0-9]\\)\\b")
         (match-string-no-properties 2))))

(provide 'init-bib)