diff --git a/src/bin/alpha_id.rs b/src/bin/alpha_id.rs index a781f8c..e7d771b 100644 --- a/src/bin/alpha_id.rs +++ b/src/bin/alpha_id.rs @@ -1,4 +1,4 @@ -use alpha_id::model::{Config, Filter, Mode}; +use alpha_id::model::{normalize_chapters, Config, Filter, Mode}; use alpha_id::pipeline::Pipeline; use clap::{Parser, Subcommand}; use std::io::Read; @@ -126,9 +126,16 @@ fn main() { Cmd::Suggest { input, mode, top, billable_only, valid_only, exclude_exotic, chapters, json } => { let p = Pipeline::load(&cfg).expect("load"); let m: Mode = mode.parse().expect("mode"); + let chapters = chapters.map(|c| { + let (padded, unknown) = normalize_chapters(&c); + for tok in &unknown { + eprintln!("warning: --chapters token '{tok}' matches no known chapter (01..22); ignored"); + } + padded + }); let filter = Filter { billable_only, valid_only, exclude_exotic, - chapters: chapters.map(|c| c.split(',').map(|s| s.trim().to_string()).collect()), + chapters, }; let text = read_input(&input); let res = p.suggest(&text, m, &filter, top); diff --git a/src/model.rs b/src/model.rs index e6347ee..4c48fe2 100644 --- a/src/model.rs +++ b/src/model.rs @@ -42,6 +42,29 @@ pub struct Filter { pub exclude_exotic: bool, } +/// Normalize a raw `--chapters` token list to the zero-padded chapter-tag form +/// ("01".."22") that `Filter::accepts` compares against. Splits on ',', trims +/// each token, and classifies: a token that parses as one of the 22 known +/// ICD-10-GM chapters (1..=22) goes — zero-padded to two digits — into the first +/// returned vec (in input order); every other non-empty token goes verbatim +/// (trimmed) into the second (unrecognised) vec. Empty-after-trim tokens are +/// skipped. Both "4" and "04" yield "04". +pub fn normalize_chapters(raw: &str) -> (Vec, Vec) { + let mut known = Vec::new(); + let mut unknown = Vec::new(); + for tok in raw.split(',') { + let tok = tok.trim(); + if tok.is_empty() { + continue; + } + match tok.parse::() { + Ok(n) if (1..=22).contains(&n) => known.push(format!("{n:02}")), + _ => unknown.push(tok.to_string()), + } + } + (known, unknown) +} + impl Filter { pub fn accepts(&self, t: &Tags) -> bool { if self.billable_only && !t.billable { return false; }