mirror of
https://git.pumpin.online/funkpower/catena.git
synced 2026-10-23 03:07:13 +00:00
colophon: file a book's printed subjects onto a shelf someone has
A cataloguing block states subjects in Library of Congress form, which is precise, deep and no use for browsing. Real blocks from this library read 'Political science – Early works to 1800' and 'English literature—Middle English, 1100–1500—History and criticism'. Nobody has a shelf called that. --shelf takes the closed list the library is actually browsed by and files the printed headings onto it, longest term first so a period of thought does not collapse into its parent. Matching is on whole words after folding punctuation away, because a cataloguing block separates with em dashes, en dashes, full stops and plain hyphens, often three in one heading, and OCR turns any of those into any other. What matches nothing comes back under unshelved rather than being dropped: a subject silently discarded is indistinguishable from a book that printed none, and the difference is the whole value of reading the block.
This commit is contained in:
@@ -53,6 +53,16 @@ struct Args {
|
||||
/// How many pages in from the front to read.
|
||||
#[arg(long, value_name = "COUNT", default_value_t = colophon::PAGES)]
|
||||
pages: usize,
|
||||
|
||||
/// A closed list of headings to file the book's printed subjects under.
|
||||
///
|
||||
/// One heading per line, optionally `Heading = term, term` to give the
|
||||
/// words that should match it; a heading with no terms matches its own
|
||||
/// name. A cataloguing block states subjects in Library of Congress form,
|
||||
/// which is no use as a shelf, so this says what the shelf is. What
|
||||
/// matches nothing comes back under `unshelved` rather than being dropped.
|
||||
#[arg(long, value_name = "FILE")]
|
||||
shelf: Option<PathBuf>,
|
||||
}
|
||||
|
||||
fn main() -> ExitCode {
|
||||
@@ -73,6 +83,26 @@ fn main() -> ExitCode {
|
||||
return ExitCode::from(exit::USAGE);
|
||||
}
|
||||
|
||||
// Read the shelf before any book, so a bad path fails at once rather than
|
||||
// after the whole library has been read with no shelf applied.
|
||||
let shelf = match args.shelf.as_deref() {
|
||||
None => None,
|
||||
Some(path) => match std::fs::read_to_string(path) {
|
||||
Ok(text) => {
|
||||
let s = colophon::shelf::Shelf::parse(&text);
|
||||
if s.is_empty() {
|
||||
eprintln!("colophon: {} lists no headings", path.display());
|
||||
return ExitCode::from(exit::USAGE);
|
||||
}
|
||||
Some(s)
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("colophon: {}: {e}", path.display());
|
||||
return ExitCode::from(exit::USAGE);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
let inputs: Vec<Option<PathBuf>> = if args.paths.is_empty() {
|
||||
vec![None]
|
||||
} else {
|
||||
@@ -89,7 +119,7 @@ fn main() -> ExitCode {
|
||||
return ExitCode::from(code);
|
||||
}
|
||||
};
|
||||
let mut record = colophon::read(&text, args.pages);
|
||||
let mut record = colophon::read_onto(&text, args.pages, shelf.as_ref());
|
||||
record.path = path.as_deref().map(|p| p.display().to_string());
|
||||
records.push(record);
|
||||
last_text = text;
|
||||
|
||||
Reference in New Issue
Block a user