mod delete;
mod errors;
mod parser;
mod query;
mod set;
use std::path::PathBuf;
use std::str;
use clap::{Parser, Subcommand};
use errors::TomliError;
use toml_edit::DocumentMut;
#[derive(Parser)]
#[command(version)]
struct Cli {
#[arg(short, long, global = true)]
filepath: Option<PathBuf>,
#[command(subcommand)]
command: Commands,
}
#[derive(Subcommand)]
enum Commands {
Query {
query: String,
},
Set {
query: String,
value: String,
#[arg(value_enum, short = 't', long = "type", default_value_t = ValueType::Str)]
value_type: ValueType,
},
Delete {
query: String,
},
}
#[derive(clap::ValueEnum, Clone, Debug)]
enum ValueType {
Str,
Int,
Float,
Bool,
}
fn read_input(filepath: &Option<PathBuf>) -> Result<DocumentMut, TomliError> {
let input = if let Some(filepath) = filepath {
std::fs::read_to_string(filepath)?
} else {
std::io::read_to_string(std::io::stdin())?
};
Ok(input.parse::<DocumentMut>()?)
}
fn main() {
let cli = Cli::parse();
let document = read_input(&cli.filepath).unwrap_or_else(|err| {
eprintln!("{}", err);
std::process::exit(1);
});
let (query, result) = match cli.command {
Commands::Query { query } => (query.clone(), query::exec(document, &query)),
Commands::Set {
query,
value,
value_type,
} => (
query.clone(),
set::exec(document, &query, &value, value_type),
),
Commands::Delete { query } => (query.clone(), delete::exec(document, &query)),
};
result.unwrap_or_else(|err| {
match err {
TomliError::QuerySyntaxError(position) => {
eprintln!(
"{}:\n\n{}\n{}--^-",
err,
query,
" ".repeat(position.saturating_sub(2)),
);
}
_ => eprintln!("{}", err),
}
std::process::exit(1);
})
}