Skip to content

Commit

Permalink
feat: add citations and bibliography support
Browse files Browse the repository at this point in the history
  • Loading branch information
kmaasrud committed Apr 17, 2023
1 parent 2e5e527 commit b511a84
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 17 deletions.
22 changes: 11 additions & 11 deletions src/bib/bibliography.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
use std::{io, path::Path};
use std::io;

use hayagriva::Entry;
use hayagriva::{io::from_biblatex_str, Entry};

use crate::{utils::find_root, walk::Walker};
use crate::walk::Walker;

pub fn get_bib_entries<P: AsRef<Path>>(path: Option<P>) -> io::Result<Vec<Entry>> {
let bibtex_content = match path {
Some(path) => Walker::new(path)?.filter_extensions(&["bib", "bibtex"]),
_ => Walker::new(".")?.filter_extensions(&["bib", "bibtex"]),
}
.map(std::fs::read_to_string)
.collect::<Result<String, io::Error>>()?;
pub fn get_bib_entries() -> io::Result<Vec<Entry>> {
let bibtex_content = Walker::new(".")?
.max_nesting(5)
.filter_extensions(&["bib", "bibtex"])
.map(std::fs::read_to_string)
.collect::<Result<String, io::Error>>()?;

// TODO: Handle error(s)
Ok(hayagriva::io::from_biblatex_str(&bibtex_content).unwrap())
let entries = from_biblatex_str(&bibtex_content).unwrap();
Ok(entries)
}
4 changes: 2 additions & 2 deletions src/bib/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
mod bibliography;
mod csl;
// mod csl;

pub use bibliography::get_bib_entries;
pub use csl::get_csl;
// pub use csl::get_csl;
7 changes: 6 additions & 1 deletion src/builder.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use std::path::PathBuf;

use crate::manifest::BuilderManifest;
use hayagriva::Entry;

use crate::{bib, manifest::BuilderManifest};

const DEFAULT_LOCALE: &str = "en_US";

Expand All @@ -12,6 +14,7 @@ pub struct Builder {
pub(crate) number_sections: bool,
pub(crate) build_dir: Option<PathBuf>,
pub(crate) locale: String,
pub(crate) bib: Vec<Entry>,
}

impl Default for Builder {
Expand All @@ -20,6 +23,7 @@ impl Default for Builder {
number_sections: false,
build_dir: Some(PathBuf::from("build")),
locale: DEFAULT_LOCALE.to_string(),
bib: Vec::new(),
}
}
}
Expand All @@ -33,6 +37,7 @@ impl Builder {
.build_dir
.clone()
.or_else(|| Some(PathBuf::from("build"))),
bib: bib::get_bib_entries().unwrap(),
}
}

Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
//! ```

mod author;
mod bib;
mod builder;
mod date;
mod document;
Expand Down
44 changes: 41 additions & 3 deletions src/pdf/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ use std::{
fs,
io::{self, Write},
path::PathBuf,
sync::{Arc, Mutex},
time::SystemTime,
};

use jotdown::{Parser, Render};
use hayagriva::style::{Citation, Database, Ieee, Numerical};
use jotdown::{Container, Event, Parser, Render};
use rayon::prelude::*;

use super::Builder;
Expand Down Expand Up @@ -101,7 +103,11 @@ impl Builder {
/// .write_latex(&document, &mut std::io::stdout())
/// .unwrap();
/// ```
pub fn write_latex<W: Write>(&self, document: &Document, mut w: W) -> Result<(), PdfError> {
pub fn write_latex<'s, W: Write>(
&self,
document: &'s Document,
mut w: W,
) -> Result<(), PdfError> {
let mut inner = || -> Result<(), PdfError> {
writeln!(w, r"\documentclass{{{}}}", document.document_type.as_ref())?;

Expand Down Expand Up @@ -137,19 +143,51 @@ impl Builder {
writeln!(w, "}}")?;
}

let db = Arc::new(Mutex::new(Database::from_entries(self.bib.iter())));
let bib_style = Arc::new(Mutex::new(Numerical::new()));
writeln!(w, r"\begin{{document}}")?;
document
.texts
.par_iter()
.try_fold_with(Vec::new(), |mut buf, text| {
let mut cite = None;
let citations = |event: Event<'s>| -> Event<'s> {
match event {
Event::Start(Container::Span, ref attrs) => {
if let Some(key) = attrs.get("cite") {
let mut db = db.lock().unwrap();
// TODO: Should avoid this clone
if let Some(record) =
db.records.clone().get(key.to_string().as_str())
{
let citation = db.citation(
&mut *bib_style.lock().unwrap(),
&[Citation::new(record.entry, None)],
);
cite = Some(citation.display.value);
}
}
}
Event::Str(ref s) if cite.is_some() && s == "@" => {
return Event::Str(cite.take().unwrap().into())
}
_ => {}
}
event
};
latex::Renderer::default()
.number_sections(self.number_sections)
.write(Parser::new(text), &mut buf)?;
.write(Parser::new(text).map(citations), &mut buf)?;
Ok(buf)
})
.collect::<Result<Vec<Vec<u8>>, PdfError>>()?
.into_iter()
.try_for_each(|s| w.write_all(&s))?;

for reference in db.lock().unwrap().bibliography(&Ieee::new(), None) {
writeln!(w, "{}", reference.display.value)?;
}

writeln!(w, r"\end{{document}}")?;

Ok(())
Expand Down
6 changes: 6 additions & 0 deletions src/walk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ impl Walker {
})
}

/// Sets the maximum nesting level.
pub fn max_nesting(mut self, max_nesting: usize) -> Self {
self.max_nesting = max_nesting;
self
}

/// Returns a new iterator that only yields paths with the given extensions.
pub fn filter_extensions(self, extensions: &'static [&'static str]) -> FilteredWalker {
FilteredWalker {
Expand Down

0 comments on commit b511a84

Please sign in to comment.