mirror of
https://git.pumpin.online/funkpower/catena.git
synced 2026-10-23 03:07:13 +00:00
mdsplit: the works inside one file, and the books inside scripture
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
//! Splits one markdown file into the works inside it.
|
||||
|
||||
use std::path::PathBuf;
|
||||
use std::process::ExitCode;
|
||||
|
||||
use clap::Parser;
|
||||
use corpus_core::exit;
|
||||
|
||||
/// Split a collection into the works inside it, one record per line.
|
||||
///
|
||||
/// A collected edition is one file holding forty books, and indexed whole a
|
||||
/// query for any of them returns a passage that could be from any other. This
|
||||
/// finds the seams.
|
||||
///
|
||||
/// Scripture is recognised and grouped by book rather than by chapter, since
|
||||
/// every chapter there is its own heading and splitting on those would give a
|
||||
/// thousand fragments instead of the books.
|
||||
#[derive(Parser)]
|
||||
#[command(
|
||||
version,
|
||||
about,
|
||||
after_help = "\
|
||||
Exit codes: 0 it split, 1 it is not a collection, 65 the input was not text,
|
||||
74 the file could not be read.
|
||||
|
||||
Example:
|
||||
|
||||
mdsplit --into sections/ complete-works.md
|
||||
mdsplit complete-works.md | jq -r '\"\\(.idx)\\t\\(.title)\"'"
|
||||
)]
|
||||
struct Args {
|
||||
/// Markdown file to read. Reads stdin when absent.
|
||||
path: Option<PathBuf>,
|
||||
|
||||
/// Write one file per section into this directory instead of writing
|
||||
/// records. Each is named for its position and its title.
|
||||
#[arg(long, value_name = "DIR")]
|
||||
into: Option<PathBuf>,
|
||||
}
|
||||
|
||||
fn main() -> ExitCode {
|
||||
let args: Args = match catena_cli::parse() {
|
||||
Ok(args) => args,
|
||||
Err(code) => return code,
|
||||
};
|
||||
|
||||
let markdown = match catena_cli::read_text(args.path.as_deref()) {
|
||||
Ok(markdown) => markdown,
|
||||
Err((code, why)) => {
|
||||
eprintln!("mdsplit: {why}");
|
||||
return ExitCode::from(code);
|
||||
}
|
||||
};
|
||||
|
||||
let sections = match mdsplit::split(&markdown) {
|
||||
Ok(sections) => sections,
|
||||
Err(why) => {
|
||||
// Not a failure: "this is one work, not a collection" is an
|
||||
// answer, and the usual one.
|
||||
eprintln!("mdsplit: {why}");
|
||||
return ExitCode::from(exit::NO);
|
||||
}
|
||||
};
|
||||
|
||||
match args.into.as_deref() {
|
||||
None => catena_cli::stream("mdsplit", §ions),
|
||||
Some(dir) => match write_files(dir, §ions) {
|
||||
Ok(()) => ExitCode::from(exit::OK),
|
||||
Err((code, why)) => {
|
||||
eprintln!("mdsplit: {why}");
|
||||
ExitCode::from(code)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Write each section as its own file, named so a directory listing is in
|
||||
/// reading order.
|
||||
fn write_files(dir: &std::path::Path, sections: &[mdsplit::Section]) -> Result<(), (u8, String)> {
|
||||
std::fs::create_dir_all(dir).map_err(|e| (exit::IO, format!("{}: {e}", dir.display())))?;
|
||||
|
||||
for section in sections {
|
||||
let path = dir.join(format!("{:03}-{}.md", section.idx, section.slug));
|
||||
std::fs::write(&path, §ion.text)
|
||||
.map_err(|e| (exit::IO, format!("{}: {e}", path.display())))?;
|
||||
println!("{}", path.display());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user