From 63aa4c4f35191134ef79cb5c2598fa73069d7d28 Mon Sep 17 00:00:00 2001 From: bin liu Date: Thu, 24 Nov 2022 16:00:35 +0800 Subject: [PATCH] support edit file in place add two opitons for set sub command: - overwrite: save the result to the TOML file. - backup: create a backup file before overwrite. Both of them are false by default. Signed-off-by: bin liu --- Cargo.lock | 262 ++++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + README.md | 10 +- src/main.rs | 39 ++++++-- 4 files changed, 302 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 78f01d3..77638a6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,15 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "ansi_term" version = "0.12.1" @@ -70,6 +79,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bumpalo" +version = "3.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" + [[package]] name = "bytes" version = "1.3.0" @@ -88,6 +103,21 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" +dependencies = [ + "iana-time-zone", + "js-sys", + "num-integer", + "num-traits", + "time", + "wasm-bindgen", + "winapi", +] + [[package]] name = "clap" version = "2.34.0" @@ -103,6 +133,16 @@ dependencies = [ "vec_map", ] +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + [[package]] name = "combine" version = "4.6.6" @@ -113,6 +153,56 @@ dependencies = [ "memchr", ] +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + +[[package]] +name = "cxx" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4a41a86530d0fe7f5d9ea779916b7cadd2d4f9add748b99c2c029cbbdfaf453" +dependencies = [ + "cc", + "cxxbridge-flags", + "cxxbridge-macro", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06416d667ff3e3ad2df1cd8cd8afae5da26cf9cec4d0825040f88b5ca659a2f0" +dependencies = [ + "cc", + "codespan-reporting", + "once_cell", + "proc-macro2", + "quote", + "scratch", + "syn", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "820a9a2af1669deeef27cb271f476ffd196a2c4b6731336011e0ba63e2c7cf71" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a08a6e2fcc370a089ad3b4aaf54db3b1b4cee38ddabce5896b33eb693275f470" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "either" version = "1.8.0" @@ -171,6 +261,30 @@ dependencies = [ "libc", ] +[[package]] +name = "iana-time-zone" +version = "0.1.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "winapi", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" +dependencies = [ + "cxx", + "cxx-build", +] + [[package]] name = "indexmap" version = "1.9.2" @@ -196,6 +310,15 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" +[[package]] +name = "js-sys" +version = "0.3.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" +dependencies = [ + "wasm-bindgen", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -221,6 +344,24 @@ version = "0.2.137" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" +[[package]] +name = "link-cplusplus" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9272ab7b96c9046fbc5bc56c06c117cb639fe2d509df0c421cad82d2915cf369" +dependencies = [ + "cc", +] + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + [[package]] name = "memchr" version = "2.5.0" @@ -247,6 +388,25 @@ dependencies = [ "version_check", ] +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + [[package]] name = "object" version = "0.29.0" @@ -256,6 +416,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "once_cell" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -310,6 +476,12 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" +[[package]] +name = "scratch" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898" + [[package]] name = "serde" version = "1.0.148" @@ -386,6 +558,15 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "termcolor" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +dependencies = [ + "winapi-util", +] + [[package]] name = "textwrap" version = "0.11.0" @@ -395,10 +576,22 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "time" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" +dependencies = [ + "libc", + "wasi", + "winapi", +] + [[package]] name = "toml-cli" version = "0.2.0" dependencies = [ + "chrono", "failure", "nom", "serde", @@ -461,6 +654,66 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + +[[package]] +name = "wasm-bindgen" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" + [[package]] name = "winapi" version = "0.3.9" @@ -477,6 +730,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" diff --git a/Cargo.toml b/Cargo.toml index cbd9d32..5ca8ecc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,3 +24,4 @@ serde = "1.0" serde_json = "1.0" structopt = "0.3" toml_edit = "0.15" +chrono = "0.4" diff --git a/README.md b/README.md index 297fe6b..e07bc18 100644 --- a/README.md +++ b/README.md @@ -103,7 +103,7 @@ SUBCOMMANDS: check Check if a key exists get Print some data from the file help Prints this message or the help of the given subcommand(s) - set Edit the file to set some data (currently, just print modified version) + set Edit the file to set some data ``` ### `toml check` @@ -164,14 +164,16 @@ ARGS: ``` $ toml set --help toml-set 0.2.0 -Edit the file to set some data (currently, just print modified version) +Edit the file to set some data USAGE: toml set FLAGS: - -h, --help Prints help information - -V, --version Prints version information + --backup Create a backup file when `overwrite` is set(default: doesn't create a backup file) + -h, --help Prints help information + --overwrite Overwrite the TOML file (default: print to stdout) + -V, --version Prints version information ARGS: Path to the TOML file to read diff --git a/src/main.rs b/src/main.rs index dff67f0..4b37af6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,9 @@ mod query_parser; +use chrono::{DateTime, Utc}; use std::fs; +use std::fs::OpenOptions; +use std::io::Write; use std::path::PathBuf; use std::str; @@ -34,7 +37,7 @@ enum Args { #[structopt(flatten)] opts: GetOpts, }, - /// Edit the file to set some data (currently, just print modified version) + /// Edit the file to set some data Set { /// Path to the TOML file to read #[structopt(parse(from_os_str))] @@ -43,6 +46,8 @@ enum Args { query: String, /// String value to place at the given spot (bool, array, etc. are TODO) value_str: String, // TODO more forms + #[structopt(flatten)] + opts: SetOpts, }, // TODO: append/add (name TBD) } @@ -54,6 +59,16 @@ struct GetOpts { output_toml: bool, } +#[derive(StructOpt)] +struct SetOpts { + /// Overwrite the TOML file (default: print to stdout) + #[structopt(long)] + overwrite: bool, + /// Create a backup file when `overwrite` is set(default: doesn't create a backup file) + #[structopt(long)] + backup: bool, +} + #[derive(Debug, Fail)] enum CliError { #[fail(display = "bad query")] @@ -73,7 +88,8 @@ fn main() -> Result<(), Error> { path, query, value_str, - } => set(path, &query, &value_str)?, + opts, + } => set(path, &query, &value_str, opts)?, } Ok(()) } @@ -177,9 +193,9 @@ fn print_toml_fragment(doc: &Document, tpath: &[TpathSegment]) { print!("{}", doc); } -fn set(path: PathBuf, query: &str, value_str: &str) -> Result<(), Error> { +fn set(path: PathBuf, query: &str, value_str: &str, opts: SetOpts) -> Result<(), Error> { let tpath = parse_query_cli(query)?.0; - let mut doc = read_parse(path)?; + let mut doc = read_parse(path.clone())?; let mut item = doc.as_item_mut(); let mut already_inline = false; @@ -222,8 +238,19 @@ fn set(path: PathBuf, query: &str, value_str: &str) -> Result<(), Error> { } *item = detect_value(value_str); - // TODO actually write back - print!("{}", doc); + if opts.overwrite { + // write content to path + if opts.backup { + let now: DateTime = Utc::now(); + let ext = now.format("%Y%m%d-%H%M%S-%f"); + let backup_file = format!("{}.{}", path.display(), ext); + fs::copy(path.clone(), backup_file)?; + } + let mut output = OpenOptions::new().write(true).truncate(true).open(path)?; + write!(output, "{}", doc)?; + } else { + print!("{}", doc); + } Ok(()) }