;; Functions supporting aux-file parsing. ;; ;; This file is part of Beastie ;; SPDX-FileCopyrightText: 2024 Norman Gray ;; SPDX-License-Identifier: BSD-2-Clause (define *requires-implementation-functions* '(parse-aux-source**)) (define-macro (%module-verbosity-flag%) 8) ;; A helper function, tidying up after parse-aux.y. ;; ;; The argument is a list of the contents of the aux file; the order doesn't matter, ;; This comprises a list (("command" "arg" ...) ...). ;; We ignore all of the commands apart from "citation", "bibstyle" and "bibdata". ;; We return a list of (list-of-strings list-of-strings string) ;; which are in order the list of citations, or 'all if we see \citation{*}, ;; the list of .bib databases to consult, ;; and the style-file to use. ;; The databases and style-file elements are returned as #f if they're absent (define (preen-auxparse-output auxfile-elements) (let loop ((aux auxfile-elements) (citations '()) (databases '()) (style-file #f)) (if (null? aux) (list citations (if (null? databases) #f databases) style-file) (let ((cmd (caar aux)) (arg (if (null? (cdar aux)) #f (cadar aux)))) (cond ((string=? cmd "citation") (if (string=? arg "*") (loop (cdr aux) 'all databases style-file) (loop (cdr aux) (if (list? citations) ;citation is either '("key"...) or 'all (append (map string->symbol (string-split arg #\,)) citations) citations) databases style-file))) ((string=? cmd "bibdata") (loop (cdr aux) citations (append databases (string-split arg #\,)) style-file)) ((string=? cmd "bibstyle") (when style-file ;; we are processing these in the reverse order to the order ;; they appear in the .aux file, so if we override this here, ;; we are ignoring 'later' ones. (print-warning "Duplicate style file command in aux; later ones ignored")) (loop (cdr aux) citations databases arg)) (else (loop (cdr aux) citations databases style-file))))))) (define/provide (parse-aux-file fn) #"""`parse-aux-file : string? -> (list (listof symbol?) (listof string?) string?` : In `(parse-aux-file filename)` parse the aux file `filename`, and return relevant contents. We return a list `(list-of-symbols list-of-strings string)` which are in order the list of citations, or `'all` if we see `\citation{*}`; the list of .bib databases to consult; and the style-file to use. The databases and style-file elements are returned as `#f` if they're absent. We recognise the following commands in the `.aux` file: * `\citation{foo}` : cite an object with BibTeX key `foo`. * `\citation{*}` : include _all_ of the entries in the database. * `\bibdata{bib}` : names the BibTeX database to consult; this command can appear more than once, the argument can be a single file or a list separated by commas, and the `.bib` extension is optional. * `\bibstyle{plain}` : the style file to be used. If the [kpathsea](https://tug.org/kpathsea/) library was available when `beastie` was built (it usually is) then it will be used to look up the values of the `\bibdata` and `\bibstyle` commands. If the `fn` is passed as `#f`, then parse stdin. Returns `#f` if the file can't be parsed as an aux-file.""" (cond ((parse-aux-source** #t fn) => preen-auxparse-output) (else #f))) (define/provide (parse-aux-string str) "Like parse-aux-file, mostly for debugging." (cond ((parse-aux-source** #f str) => preen-auxparse-output) (else #f))) (define* (call-with-aux-file fn processor (parse-aux-file parse-aux-file)) #"""`call-with-aux-file : string? ((listof symbol?) (listof string?) string? [:parse-aux-file fn] -> unspecified`: In `(call-with-aux-file fn processor)`, the aux-file `fn` is opened, parsed, and the contents processed with the function `processor`, called with the results from `parse-aux-file`. The given processor function is called with three arguments: * citations: a list of citation keys, as symbols, or the special symbol `'all` * bibdata: a list of paths to the .bib files to read from, as indicated by `\bibdata` * bibstyle: a style file indicated by the `\bibstyle` command If the `fn` is passed as `#f`, then parse stdin. If the aux file can't be opened, or it can't be parsed, then return `#f`. For a suitable processor, see the function `process-bibs/bst` in the `bst` module. If the keyword argument `:parse-aux-file` is present, then that function is used, instead of the default `parse-aux-file` function, to parse the file. A suitable alternative function might be, for example, (define (parse-aux-file/nobst fn) (let ((result (parse-aux-file fn))) (list (car result) (cadr result) #f))) will have the same effect as `parse-aux-file`, but discarding the style-file found there.""" (let ((aux (parse-aux-file fn))) (if (null? aux) #f (let ((citations (if (eqv? (car aux) 'all) 'all (car aux))) (bibdata (and (cadr aux) (map (lambda (f) (resolve-file f ".bib")) (cadr aux)))) (bibstyle (and (caddr aux) (resolve-file (caddr aux) ".bst")))) (processor citations bibdata bibstyle))))) (module-provide call-with-aux-file)