Skip to main content

chronicle/cli/
read.rs

1use crate::error::Result;
2use crate::git::CliOps;
3use crate::read::{execute, ReadQuery};
4use crate::schema::LineRange;
5
6pub fn run(path: String, anchor: Option<String>, lines: Option<String>) -> Result<()> {
7    let line_range = match lines {
8        Some(ref s) => Some(parse_line_range(s)?),
9        None => None,
10    };
11
12    let repo_dir = std::env::current_dir().map_err(|e| crate::error::ChronicleError::Io {
13        source: e,
14        location: snafu::Location::default(),
15    })?;
16    let git_ops = CliOps::new(repo_dir);
17
18    let query = ReadQuery {
19        file: path,
20        anchor,
21        lines: line_range,
22    };
23
24    let result = execute(&git_ops, &query)?;
25
26    let json =
27        serde_json::to_string_pretty(&result).map_err(|e| crate::error::ChronicleError::Json {
28            source: e,
29            location: snafu::Location::default(),
30        })?;
31    println!("{json}");
32
33    Ok(())
34}
35
36/// Parse a "start:end" line range string.
37fn parse_line_range(s: &str) -> Result<LineRange> {
38    let parts: Vec<&str> = s.split(':').collect();
39    if parts.len() != 2 {
40        return Err(crate::error::ChronicleError::Config {
41            message: format!("invalid line range '{s}', expected format 'start:end'"),
42            location: snafu::Location::default(),
43        });
44    }
45    let start: u32 = parts[0]
46        .parse()
47        .map_err(|_| crate::error::ChronicleError::Config {
48            message: format!("invalid start line number '{}'", parts[0]),
49            location: snafu::Location::default(),
50        })?;
51    let end: u32 = parts[1]
52        .parse()
53        .map_err(|_| crate::error::ChronicleError::Config {
54            message: format!("invalid end line number '{}'", parts[1]),
55            location: snafu::Location::default(),
56        })?;
57    Ok(LineRange { start, end })
58}