Skip to content

Commit

Permalink
feat: add del command
Browse files Browse the repository at this point in the history
Closes #11
  • Loading branch information
Logarithmus committed Jun 23, 2023
1 parent 6a41f2d commit 2c1f5fe
Showing 1 changed file with 59 additions and 0 deletions.
59 changes: 59 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,16 @@ enum Args {
/// String value to place at the given spot (bool, array, etc. are TODO)
value_str: String, // TODO more forms
},

/// Edit the file to delete some data (currently, just print modified version)
Del {
/// Path to the TOML file to read
#[structopt(parse(from_os_str))]
path: PathBuf,

/// Query within the TOML data (e.g. `dependencies.serde`, `foo[0].bar`)
query: String,
},
//
// TODO: append/add (name TBD)
}
Expand Down Expand Up @@ -96,6 +106,7 @@ fn main() {
query,
value_str,
} => set(&path, &query, &value_str),
Args::Del { path, query } => del(&path, &query),
};
result.unwrap_or_else(|err| {
match err.downcast::<SilentError>() {
Expand Down Expand Up @@ -234,6 +245,40 @@ fn set(path: &PathBuf, query: &str, value_str: &str) -> Result<(), Error> {
Ok(())
}

fn del(path: &PathBuf, query: &str) -> Result<(), Error> {
let tpath = parse_query_cli(query)?.0;
let mut doc = read_parse(path)?;

let (parent, last) = match &tpath[..] {
[] => Err(SilentError::KeyNotFound { key: query.into() }),
[parent_path @ .., last] => Ok((walk_tpath_mut(doc.as_item_mut(), parent_path), last)),
}?;
let parent = parent.ok_or(SilentError::KeyNotFound { key: query.into() })?;
match parent {
Item::None | Item::Value(_) => Err(SilentError::KeyNotFound { key: query.into() })?,
Item::Table(table) => match last {
TpathSegment::Name(key) => {
table.remove(key);
Ok(())
}
TpathSegment::Num(_) => Err(CliError::NotArray()),
}
Item::ArrayOfTables(array) => match last {
TpathSegment::Num(i) => {
if *i < array.len() {
Ok(array.remove(*i))
} else {
Err(CliError::ArrayIndexOob())
}
}
TpathSegment::Name(_) => Err(CliError::ArrayIndexOob()),
}
}?;
// TODO actually write back
print!("{}", doc);
Ok(())
}

fn parse_query_cli(query: &str) -> Result<Query, CliError> {
parse_query(query).map_err(|_err| {
CliError::QuerySyntaxError(query.into()) // TODO: perhaps use parse-error details?
Expand All @@ -254,6 +299,20 @@ fn walk_tpath<'a>(
Some(item)
}

fn walk_tpath_mut<'a>(
mut item: &'a mut toml_edit::Item,
tpath: &[TpathSegment],
) -> Option<&'a mut toml_edit::Item> {
use TpathSegment::{Name, Num};
for seg in tpath {
match seg {
Name(n) => item = item.get_mut(n)?,
Num(n) => item = item.get_mut(n)?,
}
}
Some(item)
}

// TODO Can we do newtypes more cleanly than this?
struct JsonItem<'a>(&'a toml_edit::Item);

Expand Down

0 comments on commit 2c1f5fe

Please sign in to comment.