mod delete;
mod errors;
mod parser;
mod query;
mod set;
use std::str;
use std::{fs, path::PathBuf};
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>,
#[arg(short = 'i', long, global = true)]
in_place: bool,
#[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,
#[arg(verbatim_doc_comment, long, default_value_t = false)]
dotted_key: bool,
},
Delete {
#[arg(short = 'e', long)]
if_exists: bool,
query: String,
},
}
#[derive(clap::ValueEnum, Clone, Debug)]
enum ValueType {
Str,
Int,
Float,
Bool,
Datetime,
}
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 mut document = read_input(&cli.filepath).unwrap_or_else(|err| {
eprintln!("{}", err);
std::process::exit(1);
});
let (query, result, can_write) = match cli.command {
Commands::Query { query } => (query.clone(), query::exec(&document, &query), false),
Commands::Set {
query,
value,
value_type,
dotted_key,
} => (
query.clone(),
set::exec(&mut document, &query, &value, value_type, dotted_key),
true,
),
Commands::Delete { if_exists, query } => {
let mut result = delete::exec(&mut document, &query);
if if_exists {
result = Ok(document.to_string())
}
(query.clone(), result, true)
}
};
match result {
Err(error) => {
match error {
TomliError::QuerySyntaxError(position) => eprintln!(
"{}:\n\n{}\n{}--^-",
error,
query,
" ".repeat(position.saturating_sub(2)),
),
_ => eprintln!("{}", error),
};
std::process::exit(1);
}
Ok(result) => {
if can_write
&& cli.in_place
&& let Some(filepath) = cli.filepath
{
fs::write(filepath, result.as_bytes())
.expect("An error occured when trying to save the file");
} else {
println!("{result}");
}
}
};
}