pkg update and first config fix
org-brain not working, add org-roam
This commit is contained in:
457
lisp/parsebib.el
457
lisp/parsebib.el
@@ -1,14 +1,14 @@
|
||||
;;; parsebib.el --- A library for parsing bib files -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright (c) 2014-2021 Joost Kremers
|
||||
;; Copyright (c) 2014-2022 Joost Kremers
|
||||
;; All rights reserved.
|
||||
|
||||
;; Author: Joost Kremers <joostkremers@fastmail.fm>
|
||||
;; Maintainer: Joost Kremers <joostkremers@fastmail.fm>
|
||||
;; Created: 2014
|
||||
;; Version: 3.0
|
||||
;; Package-Version: 20211208.2335
|
||||
;; Package-Commit: 3d46fb939371664682c711750367de088aa66f92
|
||||
;; Version: 4.3
|
||||
;; Package-Version: 20221007.1402
|
||||
;; Package-Commit: 1efca921cbb49380396df9d81308b32e55fc8b63
|
||||
;; Keywords: text bibtex
|
||||
;; URL: https://github.com/joostkremers/parsebib
|
||||
;; Package-Requires: ((emacs "25.1"))
|
||||
@@ -49,6 +49,8 @@
|
||||
(require 'json)
|
||||
(defvar json-object-type)))
|
||||
|
||||
(declare-function json-read "json.el")
|
||||
|
||||
(define-error 'parsebib-entry-type-error "[Parsebib] Illegal entry type at point" 'error)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
@@ -62,96 +64,96 @@ id is stored in the entry in the special field `=hashid='.")
|
||||
|
||||
(defvar parsebib--biblatex-inheritances '(;; Source Target
|
||||
("all" "all"
|
||||
(("ids" . none)
|
||||
("crossref" . none)
|
||||
("xref" . none)
|
||||
("entryset" . none)
|
||||
("entrysubtype" . none)
|
||||
("execute" . none)
|
||||
("label" . none)
|
||||
("options" . none)
|
||||
("presort" . none)
|
||||
("related" . none)
|
||||
("relatedoptions" . none)
|
||||
("relatedstring" . none)
|
||||
("relatedtype" . none)
|
||||
("shorthand" . none)
|
||||
("shorthandintro" . none)
|
||||
("sortkey" . none)))
|
||||
(("ids" . none)
|
||||
("crossref" . none)
|
||||
("xref" . none)
|
||||
("entryset" . none)
|
||||
("entrysubtype" . none)
|
||||
("execute" . none)
|
||||
("label" . none)
|
||||
("options" . none)
|
||||
("presort" . none)
|
||||
("related" . none)
|
||||
("relatedoptions" . none)
|
||||
("relatedstring" . none)
|
||||
("relatedtype" . none)
|
||||
("shorthand" . none)
|
||||
("shorthandintro" . none)
|
||||
("sortkey" . none)))
|
||||
|
||||
;; Source Target
|
||||
("mvbook, book" "inbook, bookinbook, suppbook"
|
||||
(("author" . "author")
|
||||
("author" . "bookauthor")))
|
||||
("mvbook, book" "inbook, bookinbook, suppbook"
|
||||
(("author" . "author")
|
||||
("author" . "bookauthor")))
|
||||
|
||||
;; Source Target
|
||||
("mvbook" "book, inbook, bookinbook, suppbook"
|
||||
(("title" . "maintitle")
|
||||
("subtitle" . "mainsubtitle")
|
||||
("titleaddon" . "maintitleaddon")
|
||||
("shorttitle" . none)
|
||||
("sorttitle" . none)
|
||||
("indextitle" . none)
|
||||
("indexsorttitle" . none)))
|
||||
("mvbook" "book, inbook, bookinbook, suppbook"
|
||||
(("title" . "maintitle")
|
||||
("subtitle" . "mainsubtitle")
|
||||
("titleaddon" . "maintitleaddon")
|
||||
("shorttitle" . none)
|
||||
("sorttitle" . none)
|
||||
("indextitle" . none)
|
||||
("indexsorttitle" . none)))
|
||||
|
||||
;; Source Target
|
||||
("mvcollection, mvreference" "collection, reference, incollection, inreference, suppcollection"
|
||||
(("title" . "maintitle")
|
||||
("subtitle" . "mainsubtitle")
|
||||
("titleaddon" . "maintitleaddon")
|
||||
("shorttitle" . none)
|
||||
("sorttitle" . none)
|
||||
("indextitle" . none)
|
||||
("indexsorttitle" . none)))
|
||||
("mvcollection, mvreference" "collection, reference, incollection, inreference, suppcollection"
|
||||
(("title" . "maintitle")
|
||||
("subtitle" . "mainsubtitle")
|
||||
("titleaddon" . "maintitleaddon")
|
||||
("shorttitle" . none)
|
||||
("sorttitle" . none)
|
||||
("indextitle" . none)
|
||||
("indexsorttitle" . none)))
|
||||
|
||||
;; Source Target
|
||||
("mvproceedings" "proceedings, inproceedings"
|
||||
(("title" . "maintitle")
|
||||
("subtitle" . "mainsubtitle")
|
||||
("titleaddon" . "maintitleaddon")
|
||||
("shorttitle" . none)
|
||||
("sorttitle" . none)
|
||||
("indextitle" . none)
|
||||
("indexsorttitle" . none)))
|
||||
("mvproceedings" "proceedings, inproceedings"
|
||||
(("title" . "maintitle")
|
||||
("subtitle" . "mainsubtitle")
|
||||
("titleaddon" . "maintitleaddon")
|
||||
("shorttitle" . none)
|
||||
("sorttitle" . none)
|
||||
("indextitle" . none)
|
||||
("indexsorttitle" . none)))
|
||||
|
||||
;; Source Target
|
||||
("book" "inbook, bookinbook, suppbook"
|
||||
(("title" . "booktitle")
|
||||
("subtitle" . "booksubtitle")
|
||||
("titleaddon" . "booktitleaddon")
|
||||
("shorttitle" . none)
|
||||
("sorttitle" . none)
|
||||
("indextitle" . none)
|
||||
("indexsorttitle" . none)))
|
||||
("book" "inbook, bookinbook, suppbook"
|
||||
(("title" . "booktitle")
|
||||
("subtitle" . "booksubtitle")
|
||||
("titleaddon" . "booktitleaddon")
|
||||
("shorttitle" . none)
|
||||
("sorttitle" . none)
|
||||
("indextitle" . none)
|
||||
("indexsorttitle" . none)))
|
||||
|
||||
;; Source Target
|
||||
("collection, reference" "incollection, inreference, suppcollection"
|
||||
(("title" . "booktitle")
|
||||
("subtitle" . "booksubtitle")
|
||||
("titleaddon" . "booktitleaddon")
|
||||
("shorttitle" . none)
|
||||
("sorttitle" . none)
|
||||
("indextitle" . none)
|
||||
("indexsorttitle" . none)))
|
||||
("collection, reference" "incollection, inreference, suppcollection"
|
||||
(("title" . "booktitle")
|
||||
("subtitle" . "booksubtitle")
|
||||
("titleaddon" . "booktitleaddon")
|
||||
("shorttitle" . none)
|
||||
("sorttitle" . none)
|
||||
("indextitle" . none)
|
||||
("indexsorttitle" . none)))
|
||||
|
||||
;; Source Target
|
||||
("proceedings" "inproceedings"
|
||||
(("title" . "booktitle")
|
||||
("subtitle" . "booksubtitle")
|
||||
("titleaddon" . "booktitleaddon")
|
||||
("shorttitle" . none)
|
||||
("sorttitle" . none)
|
||||
("indextitle" . none)
|
||||
("indexsorttitle" . none)))
|
||||
("proceedings" "inproceedings"
|
||||
(("title" . "booktitle")
|
||||
("subtitle" . "booksubtitle")
|
||||
("titleaddon" . "booktitleaddon")
|
||||
("shorttitle" . none)
|
||||
("sorttitle" . none)
|
||||
("indextitle" . none)
|
||||
("indexsorttitle" . none)))
|
||||
|
||||
;; Source Target
|
||||
("periodical" "article, suppperiodical"
|
||||
(("title" . "journaltitle")
|
||||
("subtitle" . "journalsubtitle")
|
||||
("shorttitle" . none)
|
||||
("sorttitle" . none)
|
||||
("indextitle" . none)
|
||||
("indexsorttitle" . none))))
|
||||
("periodical" "article, suppperiodical"
|
||||
(("title" . "journaltitle")
|
||||
("subtitle" . "journalsubtitle")
|
||||
("shorttitle" . none)
|
||||
("sorttitle" . none)
|
||||
("indextitle" . none)
|
||||
("indexsorttitle" . none))))
|
||||
|
||||
"Inheritance scheme for BibLaTeX cross-referencing.
|
||||
Inheritances are specified for pairs of source and target entry
|
||||
@@ -179,6 +181,231 @@ target field is set to the symbol `none'.")
|
||||
(defconst parsebib--key-regexp "[^\"@\\#%',={} \t\n\f]+" "Regexp describing a licit key.")
|
||||
(defconst parsebib--entry-start "^[ \t]*@" "Regexp describing the start of an entry.")
|
||||
|
||||
(defun parsebib--convert-tex-italics (str)
|
||||
"Return STR with face property `italic'."
|
||||
(propertize str 'face 'italic))
|
||||
|
||||
(defun parsebib--convert-tex-bold (str)
|
||||
"Return STR with face property `bold'."
|
||||
(propertize str 'face 'bold))
|
||||
|
||||
(defun parsebib--convert-tex-small-caps (str)
|
||||
"Return STR capitalised."
|
||||
(upcase str))
|
||||
|
||||
(defvar parsebib-TeX-command-replacement-alist
|
||||
'(("ddag" . "\N{DOUBLE DAGGER}")
|
||||
("textdaggerdbl" . "\N{DOUBLE DAGGER}")
|
||||
("dag" . "\N{DAGGER}")
|
||||
("textdagger" . "\N{DAGGER}")
|
||||
("textpertenthousand" . "\N{PER TEN THOUSAND SIGN}")
|
||||
("textperthousand" . "\N{PER MILLE SIGN}")
|
||||
("textquestiondown" . "\N{INVERTED QUESTION MARK}")
|
||||
("P" . "\N{PILCROW SIGN}")
|
||||
("textdollar" . "$")
|
||||
("S" . "\N{SECTION SIGN}")
|
||||
("ldots" . "\N{HORIZONTAL ELLIPSIS}")
|
||||
("dots" . "\N{HORIZONTAL ELLIPSIS}")
|
||||
("textellipsis" . "\N{HORIZONTAL ELLIPSIS}")
|
||||
("textemdash" . "\N{EM DASH}")
|
||||
("textendash" . "\N{EN DASH}")
|
||||
|
||||
;; Non-ASCII Letters (Excluding Accented Letters)
|
||||
("AA" . "\N{LATIN CAPITAL LETTER A WITH RING ABOVE}")
|
||||
("AE" . "\N{LATIN CAPITAL LETTER AE}")
|
||||
("DH" . "\N{LATIN CAPITAL LETTER ETH}")
|
||||
("DJ" . "\N{LATIN CAPITAL LETTER ETH}")
|
||||
("L" . "\N{LATIN CAPITAL LETTER L WITH STROKE}")
|
||||
("SS" . "\N{LATIN CAPITAL LETTER SHARP S}")
|
||||
("NG" . "\N{LATIN CAPITAL LETTER ENG}")
|
||||
("OE" . "\N{LATIN CAPITAL LIGATURE OE}")
|
||||
("O" . "\N{LATIN CAPITAL LETTER O WITH STROKE}")
|
||||
("TH" . "\N{LATIN CAPITAL LETTER THORN}")
|
||||
|
||||
("aa" . "\N{LATIN SMALL LETTER A WITH RING ABOVE}")
|
||||
("ae" . "\N{LATIN SMALL LETTER AE}")
|
||||
("dh" . "\N{LATIN SMALL LETTER ETH}")
|
||||
("dj" . "\N{LATIN SMALL LETTER ETH}")
|
||||
("l" . "\N{LATIN SMALL LETTER L WITH STROKE}")
|
||||
("ss" . "\N{LATIN SMALL LETTER SHARP S}")
|
||||
("ng" . "\N{LATIN SMALL LETTER ENG}")
|
||||
("oe" . "\N{LATIN SMALL LIGATURE OE}")
|
||||
("o" . "\N{LATIN SMALL LETTER O WITH STROKE}")
|
||||
("th" . "\N{LATIN SMALL LETTER THORN}")
|
||||
|
||||
("ij" . "ij")
|
||||
("i" . "\N{LATIN SMALL LETTER DOTLESS I}")
|
||||
("j" . "\N{LATIN SMALL LETTER DOTLESS J}")
|
||||
;; Formatting Commands
|
||||
("textit" . parsebib--convert-tex-italics)
|
||||
("emph" . parsebib--convert-tex-italics)
|
||||
("textbf" . parsebib--convert-tex-bold)
|
||||
("textsc" . parsebib--convert-tex-small-caps))
|
||||
"An alist of <command>-<replacement> pairs for LaTeX commands.
|
||||
<command> is the name of a TeX or LaTeX command (without
|
||||
backslash), <replacement> is the string with which it is
|
||||
replaced.
|
||||
|
||||
<replacement> can also be a function of one argument. In this
|
||||
case, <command> must take at least one obligatory argument, which
|
||||
is passed as the first argument of the replacement function. The
|
||||
return value of this function is used as the replacement string
|
||||
for <command>.
|
||||
|
||||
See `parsebib-TeX-markup-replacement-alist' and the function
|
||||
`parsebib-clean-TeX-markup' to see how this variable is used.")
|
||||
|
||||
(defvar parsebib-TeX-accent-replacement-alist
|
||||
'(("\"" . "\N{COMBINING DIAERESIS}")
|
||||
("'" . "\N{COMBINING ACUTE ACCENT}")
|
||||
("." . "\N{COMBINING DOT ABOVE}")
|
||||
("=" . "\N{COMBINING MACRON}")
|
||||
("^" . "\N{COMBINING CIRCUMFLEX ACCENT}")
|
||||
("`" . "\N{COMBINING GRAVE ACCENT}")
|
||||
("b" . "\N{COMBINING MACRON BELOW}")
|
||||
("c" . "\N{COMBINING CEDILLA}")
|
||||
("d" . "\N{COMBINING DOT BELOW}")
|
||||
("H" . "\N{COMBINING DOUBLE ACUTE ACCENT}")
|
||||
("k" . "\N{COMBINING OGONEK}")
|
||||
("U" . "\N{COMBINING DOUBLE VERTICAL LINE ABOVE}")
|
||||
("u" . "\N{COMBINING BREVE}")
|
||||
("v" . "\N{COMBINING CARON}")
|
||||
("~" . "\N{COMBINING TILDE}")
|
||||
("|" . "\N{COMBINING COMMA ABOVE}")
|
||||
("f" . "\N{COMBINING INVERTED BREVE}")
|
||||
("G" . "\N{COMBINING DOUBLE GRAVE ACCENT}")
|
||||
("h" . "\N{COMBINING HOOK ABOVE}")
|
||||
("C" . "\N{COMBINING DOUBLE GRAVE ACCENT}")
|
||||
("r" . "\N{COMBINING RING ABOVE}") )
|
||||
"Alist of <command>-<accent> pairs for LaTeX diacritics.
|
||||
<command> is the name of a TeX or LaTeX command (without
|
||||
backslash), <accent> is the Unicode combining character for the
|
||||
diacritic that <command> generates. Both <command> and <accent>
|
||||
must be strings.
|
||||
|
||||
The replacement string for <command> is composed of its
|
||||
obligatory argument (usually a single character) and the
|
||||
combining diacritic.
|
||||
|
||||
See `parsebib-TeX-markup-replacement-alist' and the function
|
||||
`parsebib-clean-TeX-markup' to see how this variable is used.")
|
||||
|
||||
(defvar parsebib-TeX-literal-replacement-alist
|
||||
;; LaTeX2 Escapable "Special" Characters
|
||||
`(("\\%" . "%") ("\\&" . "&") ("\\#" . "#") ("\\$" . "$")
|
||||
;; Quotes
|
||||
("``" . "\N{LEFT DOUBLE QUOTATION MARK}")
|
||||
("`" . "\N{LEFT SINGLE QUOTATION MARK}")
|
||||
("''" . "\N{RIGHT DOUBLE QUOTATION MARK}")
|
||||
("'" . "\N{RIGHT SINGLE QUOTATION MARK}")
|
||||
;; Dashes
|
||||
("---" . "\N{EM DASH}")
|
||||
("--" . "\N{EN DASH}")
|
||||
;; Remove all remaining {braces}
|
||||
("{" . "") ("}" . ""))
|
||||
"Alist of <literal>-<replacement> pairs. Both are strings.
|
||||
This variable contains characters that are special in LaTeX and
|
||||
single-character, non-ASCII LaTeX commands.
|
||||
|
||||
Note that adding pairs to this variable has no effect unless
|
||||
`parsebib-TeX-markup-replacement-alist' is adjusted accordingly.
|
||||
For example, after adding a <literal>-<replacement> pair, the
|
||||
following code will ensure that <literal> gets replaced with
|
||||
<replacement>.
|
||||
|
||||
(cl-callf (lambda (regex) (rx (or <literal> (regexp regex))))
|
||||
(alist-get (quote parsebib--replace-literal)
|
||||
parsebib-TeX-markup-replacement-alist))
|
||||
|
||||
See `parsebib-TeX-markup-replacement-alist' and the function
|
||||
`parsebib-clean-TeX-markup' to see how this variable is used.")
|
||||
|
||||
(defvar parsebib-TeX-markup-replacement-alist
|
||||
`((parsebib--replace-command-or-accent
|
||||
;; This regexp matches any latex command i.e. anything that
|
||||
;; starts with a backslash. The name of the command which
|
||||
;; is either a string of alphabetic characters or a single
|
||||
;; non-alphabetic character is captured by group 1. The command
|
||||
;; can have a mandatory argument enclosed by braces which is
|
||||
;; captured by group 2. If the command has no arguments in
|
||||
;; brackets or braces, the first non-white space letter after
|
||||
;; the command is captured in group 3. This is to be able to deal
|
||||
;; with accents.
|
||||
;; Note that the capturing of arguments in braces is imperfect,
|
||||
;; because doing it properly requires sexp parsing. It will fail
|
||||
;; for cases like \command{\anothercommand{an arg}some text}.
|
||||
. ,(rx "\\" (group-n 1 (or (1+ letter) nonl))
|
||||
(: (* blank) (opt (or (: (* (: "[" (* (not (any "]"))) "]"))
|
||||
"{" (group-n 2 (0+ (not (any "}")))) (opt "}"))
|
||||
(group-n 3 letter))))))
|
||||
(parsebib--replace-literal
|
||||
. ,(rx-to-string `(or ,@(mapcar #'car parsebib-TeX-literal-replacement-alist)
|
||||
(1+ blank)))))
|
||||
"Alist of replacements and strings for TeX markup.
|
||||
This is used in `parsebib-clean-TeX-markup' to make TeX markup more
|
||||
suitable for display. Each item in the list consists of a replacement
|
||||
and a regexp. The replacement can be a string (which will
|
||||
simply replace the match) or a function (the match will be
|
||||
replaced by the result of calling the function on the match
|
||||
string). Earlier elements are evaluated before later ones, so if
|
||||
one string is a subpattern of another, the second must appear
|
||||
later (e.g. \"''\" is before \"'\").
|
||||
|
||||
For the common cases of replacing a LaTeX command or a literal
|
||||
it is faster to use `parsebib-TeX-command-replacement-alist'
|
||||
and `parsebib-TeX-literal-replacement-alist' respectively.")
|
||||
|
||||
(defvar parsebib-clean-TeX-markup-excluded-fields '("file"
|
||||
"url"
|
||||
"doi")
|
||||
"List of fields that should not be passed to `parsebib-clean-TeX-markup'.")
|
||||
|
||||
(defun parsebib--replace-command-or-accent (string)
|
||||
"Return the replacement text for the command or accent matched by STRING."
|
||||
(let* ((cmd (match-string 1 string))
|
||||
;; bar is the argument in braces.
|
||||
(bar (match-string 2 string))
|
||||
;; If there is no argument in braces, consider the letter after
|
||||
;; the command as the argument. Clean this argument.
|
||||
(arg (parsebib-clean-TeX-markup (or (if bar bar (match-string 3 string)) "")))
|
||||
;; Check if the cmd is an accent that needs to be replaced
|
||||
;; and get its replacement.
|
||||
(acc (alist-get cmd parsebib-TeX-accent-replacement-alist nil nil #'equal))
|
||||
;; If it is not an accent, check if it is a command that needs to be replaced
|
||||
;; and get the replacement.
|
||||
(rep (or acc (alist-get cmd parsebib-TeX-command-replacement-alist nil nil #'equal))))
|
||||
(cond
|
||||
;; If replacement is a function call it with the argument.
|
||||
((functionp rep) (funcall rep arg))
|
||||
;; Otherwise combine the replacement with the argument. The order of combination
|
||||
;; depends on whether the command is an accent or not.
|
||||
(rep (if acc (concat arg rep) (concat rep arg)))
|
||||
;; Now we handle the fallback cases. If there is a braced argument but no
|
||||
;; replacement for the command was found, consider the replacement to be
|
||||
;; empty.
|
||||
((and bar (not (equal "" bar))) bar)
|
||||
;; Otherwise clean any optional arguments by discarding them.
|
||||
(t (replace-regexp-in-string (rx "[" (* (not (any "]"))) "]") "" string t t)))))
|
||||
|
||||
(defun parsebib--replace-literal (string)
|
||||
"Look up the replacement text for literal STRING."
|
||||
(or (alist-get string parsebib-TeX-literal-replacement-alist nil nil #'equal)
|
||||
" "))
|
||||
|
||||
(defun parsebib-clean-TeX-markup (string)
|
||||
"Return STRING without TeX markup.
|
||||
Any substring matching the car of a cell in
|
||||
`parsebib-TeX-markup-replace-alist' is replaced with the
|
||||
corresponding cdr (if the cdr is a string), or with the result of
|
||||
calling the cdr on the match (if it is a function). This is done
|
||||
with `replace-regexp-in-string', which see for details."
|
||||
(let ((case-fold-search nil))
|
||||
(cl-loop for (replacement . pattern) in parsebib-TeX-markup-replacement-alist
|
||||
do (setq string (replace-regexp-in-string
|
||||
pattern replacement string
|
||||
t t))
|
||||
finally return string)))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Matching and parsing stuff ;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
@@ -228,7 +455,7 @@ if a matching delimiter was found."
|
||||
;; If forward-sexp does not result in an error, we want to return t.
|
||||
t))
|
||||
|
||||
(defun parsebib--parse-bib-value (limit &optional strings)
|
||||
(defun parsebib--parse-bib-value (limit &optional strings replace-TeX)
|
||||
"Parse value at point.
|
||||
A value is either a field value or a @String expansion. Return
|
||||
the value as a string. No parsing is done beyond LIMIT, but note
|
||||
@@ -238,7 +465,11 @@ STRINGS, if non-nil, is a hash table of @String definitions.
|
||||
@String abbrevs in the value to be parsed are then replaced with
|
||||
their expansions. Additionally, newlines in field values are
|
||||
removed, white space is reduced to a single space and braces or
|
||||
double quotes around field values are removed."
|
||||
double quotes around field values are removed.
|
||||
|
||||
REPLACE-TEX indicates whether TeX markup should be replaced with
|
||||
ASCII/Unicode characters. See the variable
|
||||
`parsebib-TeX-markup-replace-alist' for details."
|
||||
(let (res)
|
||||
(while (and (< (point) limit)
|
||||
(not (looking-at-p ",")))
|
||||
@@ -253,9 +484,12 @@ double quotes around field values are removed."
|
||||
((looking-at "[[:space:]]*#[[:space:]]*")
|
||||
(goto-char (match-end 0)))
|
||||
(t (forward-char 1)))) ; So as not to get stuck in an infinite loop.
|
||||
(if strings
|
||||
(string-join (parsebib--expand-strings (nreverse res) strings))
|
||||
(string-join (nreverse res) " # "))))
|
||||
(setq res (if strings
|
||||
(string-join (parsebib--expand-strings (nreverse res) strings))
|
||||
(string-join (nreverse res) " # ")))
|
||||
(if replace-TeX
|
||||
(parsebib-clean-TeX-markup res)
|
||||
res)))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Expanding stuff ;;
|
||||
@@ -313,12 +547,18 @@ such an inheritance schema."
|
||||
(when (and target-entry source-entry)
|
||||
(when (eq inheritance 'biblatex)
|
||||
(setq inheritance parsebib--biblatex-inheritances))
|
||||
(let* ((inheritable-fields (unless (eq inheritance 'BibTeX)
|
||||
(append (cl-third (cl-find-if (lambda (elem)
|
||||
(and (string-match-p (concat "\\b" (cdr (assoc-string "=type=" source-entry)) "\\b") (cl-first elem))
|
||||
(string-match-p (concat "\\b" (cdr (assoc-string "=type=" target-entry)) "\\b") (cl-second elem))))
|
||||
inheritance))
|
||||
(cl-third (assoc-string "all" inheritance)))))
|
||||
(let* ((inheritable-fields
|
||||
(unless (eq inheritance 'BibTeX)
|
||||
(append
|
||||
(apply #'append (mapcar #'cl-third
|
||||
(cl-remove-if-not
|
||||
(lambda (elem)
|
||||
(and (string-match-p (concat "\\b" (cdr (assoc-string "=type=" source-entry)) "\\b")
|
||||
(cl-first elem))
|
||||
(string-match-p (concat "\\b" (cdr (assoc-string "=type=" target-entry)) "\\b")
|
||||
(cl-second elem))))
|
||||
inheritance)))
|
||||
(cl-third (assoc-string "all" inheritance)))))
|
||||
(new-fields (delq nil (mapcar (lambda (field)
|
||||
(let ((target-field (parsebib--get-target-field (car field) inheritable-fields)))
|
||||
(if (and target-field
|
||||
@@ -450,7 +690,7 @@ point."
|
||||
into hashid-fields
|
||||
finally return (mapconcat #'identity hashid-fields "")))
|
||||
|
||||
(defun parsebib-read-entry (type &optional pos strings fields)
|
||||
(defun parsebib-read-entry (type &optional pos strings fields replace-TeX)
|
||||
"Read a BibTeX entry of type TYPE at the line POS is on.
|
||||
TYPE should be a string and should not contain the @
|
||||
sign. The return value is the entry as an alist of (<field> .
|
||||
@@ -478,7 +718,11 @@ FIELDS is a list of the field names (as strings) to be read and
|
||||
included in the result. Fields not in the list are ignored,
|
||||
except \"=key=\" and \"=type=\", which are always included. Case
|
||||
is ignored when comparing fields to the list in FIELDS. If
|
||||
FIELDS is nil, all fields are returned."
|
||||
FIELDS is nil, all fields are returned.
|
||||
|
||||
REPLACE-TEX indicates whether TeX markup should be replaced with
|
||||
ASCII/Unicode characters. See the variable
|
||||
`parsebib-TeX-markup-replace-alist' for details."
|
||||
(unless (member-ignore-case type '("comment" "preamble" "string"))
|
||||
(when pos (goto-char pos))
|
||||
(beginning-of-line)
|
||||
@@ -495,7 +739,7 @@ FIELDS is nil, all fields are returned."
|
||||
(buffer-substring-no-properties beg (point)))))
|
||||
(or key (setq key "")) ; If no key was found, we pretend it's empty and try to read the entry anyway.
|
||||
(skip-chars-forward "^," limit) ; Move to the comma after the entry key.
|
||||
(let ((fields (cl-loop for field = (parsebib--parse-bibtex-field limit strings fields)
|
||||
(let ((fields (cl-loop for field = (parsebib--parse-bibtex-field limit strings fields replace-TeX)
|
||||
while field
|
||||
if (consp field) collect field)))
|
||||
(push (cons "=type=" type) fields)
|
||||
@@ -504,7 +748,7 @@ FIELDS is nil, all fields are returned."
|
||||
(push (cons "=hashid=" (secure-hash 'sha256 (parsebib--get-hashid-string fields))) fields))
|
||||
(nreverse fields))))))
|
||||
|
||||
(defun parsebib--parse-bibtex-field (limit &optional strings fields)
|
||||
(defun parsebib--parse-bibtex-field (limit &optional strings fields replace-TeX)
|
||||
"Parse the field starting at point.
|
||||
Do not search beyond LIMIT (a buffer position). Return a
|
||||
cons (FIELD . VALUE), or nil if no field was found.
|
||||
@@ -516,15 +760,21 @@ FIELDS is a list of the field names (as strings) to be read and
|
||||
included in the result. Fields not in the list are ignored,
|
||||
except \"=key=\" and \"=type=\", which are always included. Case
|
||||
is ignored when comparing fields to the list in FIELDS. If
|
||||
FIELDS is nil, all fields are returned."
|
||||
FIELDS is nil, all fields are returned.
|
||||
|
||||
REPLACE-TEX indicates whether TeX markup should be replaced with
|
||||
ASCII/Unicode characters. See the variable
|
||||
`parsebib-TeX-markup-replace-alist' for details."
|
||||
(skip-chars-forward "\"#%'(),={} \n\t\f" limit) ; Move to the first char of the field name.
|
||||
(unless (>= (point) limit) ; If we haven't reached the end of the entry.
|
||||
(let ((beg (point)))
|
||||
(if (parsebib--looking-at-goto-end (concat "\\(" parsebib--bibtex-identifier "\\)[[:space:]]*=[[:space:]]*") 1)
|
||||
(let ((field-type (buffer-substring-no-properties beg (point))))
|
||||
(let* ((field (buffer-substring-no-properties beg (point)))
|
||||
(replace-TeX (and replace-TeX
|
||||
(not (member-ignore-case field parsebib-clean-TeX-markup-excluded-fields)))))
|
||||
(if (or (not fields)
|
||||
(member-ignore-case field-type fields))
|
||||
(cons field-type (parsebib--parse-bib-value limit strings))
|
||||
(member-ignore-case field fields))
|
||||
(cons field (parsebib--parse-bib-value limit strings replace-TeX))
|
||||
(parsebib--parse-bib-value limit) ; Skip over the field value.
|
||||
:ignore)))))) ; Ignore this field but keep the `cl-loop' in `parsebib-read-entry' going.
|
||||
|
||||
@@ -644,7 +894,7 @@ file. Return nil if no dialect is found."
|
||||
(string-match (concat "bibtex-dialect: " (regexp-opt (mapcar #'symbol-name bibtex-dialect-list) t)) comment))
|
||||
(intern (match-string 1 comment))))))))
|
||||
|
||||
(cl-defun parsebib-parse-bib-buffer (&key entries strings expand-strings inheritance fields)
|
||||
(cl-defun parsebib-parse-bib-buffer (&key entries strings expand-strings inheritance fields replace-TeX)
|
||||
"Parse the current buffer and return all BibTeX data.
|
||||
Return a list of five elements: a hash table with the entries, a
|
||||
hash table with the @String definitions, a list of @Preamble
|
||||
@@ -679,7 +929,11 @@ FIELDS is a list of the field names (as strings) to be read and
|
||||
included in the result. Fields not in the list are ignored,
|
||||
except \"=key=\" and \"=type=\", which are always included. Case
|
||||
is ignored when comparing fields to the list in FIELDS. If
|
||||
FIELDS is nil, all fields are returned."
|
||||
FIELDS is nil, all fields are returned.
|
||||
|
||||
REPLACE-TEX indicates whether TeX markup should be replaced with
|
||||
ASCII/Unicode characters. See the variable
|
||||
`parsebib-TeX-markup-replace-alist' for details."
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(or (and (hash-table-p entries)
|
||||
@@ -704,7 +958,7 @@ FIELDS is nil, all fields are returned."
|
||||
((cl-equalp item "comment")
|
||||
(push (parsebib-read-comment) comments))
|
||||
((stringp item)
|
||||
(let ((entry (parsebib-read-entry item nil (if expand-strings strings) fields)))
|
||||
(let ((entry (parsebib-read-entry item nil (if expand-strings strings) fields replace-TeX)))
|
||||
(when entry
|
||||
(puthash (cdr (assoc-string "=key=" entry)) entry entries))))))
|
||||
(when inheritance (parsebib-expand-xrefs entries (if (eq inheritance t) dialect inheritance)))
|
||||
@@ -1009,7 +1263,8 @@ details. If FIELDS is nil, all fields are returned."
|
||||
:strings strings
|
||||
:expand-strings display
|
||||
:inheritance display
|
||||
:fields fields))
|
||||
:fields fields
|
||||
:replace-TeX display))
|
||||
((string= (file-name-extension file t) ".json")
|
||||
(parsebib-parse-json-buffer :entries entries
|
||||
:stringify display
|
||||
|
||||
Reference in New Issue
Block a user