diff --git a/Cargo.lock b/Cargo.lock index 7d039f8..0aac4c1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12,6 +12,9 @@ version = "0.2.9" dependencies = [ "getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "terminal_size 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -22,6 +25,11 @@ name = "getopts" version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "itoa" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "kernel32-sys" version = "0.2.2" @@ -49,6 +57,22 @@ dependencies = [ "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "proc-macro2" +version = "0.4.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quote" +version = "0.6.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "regex" version = "0.2.10" @@ -69,6 +93,46 @@ dependencies = [ "ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ryu" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde_derive" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.23 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_json" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syn" +version = "0.15.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "terminal_size" version = "0.1.7" @@ -103,6 +167,11 @@ name = "unicode-width" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "unreachable" version = "1.0.0" @@ -134,17 +203,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] "checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4" "checksum getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)" = "65922871abd2f101a2eb0eaebadc66668e54a87ad9c3dd82520b5f86ede5eff9" +"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" "checksum libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)" = "f54263ad99207254cf58b5f701ecb432c717445ea2ee8af387334bdd1a03fdff" "checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" +"checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09" +"checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c" "checksum regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "aec3f58d903a7d2a9dc2bf0e41a746f4530e0cab6b615494e058f67a3ef947fb" "checksum regex-syntax 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b2550876c31dc914696a6c2e01cbce8afba79a93c8ae979d2fe051c0230b3756" +"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" +"checksum serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)" = "6fa52f19aee12441d5ad11c9a00459122bd8f98707cadf9778c540674f1935b6" +"checksum serde_derive 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)" = "96a7f9496ac65a2db5929afa087b54f8fc5008dcfbe48a8874ed20049b0d6154" +"checksum serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)" = "c37ccd6be3ed1fdf419ee848f7c758eb31b054d7cd3ae3600e3bae0adf569811" +"checksum syn 0.15.23 (registry+https://github.com/rust-lang/crates.io-index)" = "9545a6a093a3f0bd59adb472700acc08cad3776f860f16a897dfce8c88721cbc" "checksum terminal_size 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "ef4f7fdb2a063032d361d9a72539380900bc3e0cd9ffc9ca8b677f8c855bae0f" "checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963" "checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d" "checksum unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8083c594e02b8ae1654ae26f0ade5158b119bd88ad0e8227a5d8fcd72407946" "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f" +"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" diff --git a/Cargo.toml b/Cargo.toml index 0b95f55..1302b40 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,3 +15,6 @@ terminal_size = "0.1.7" regex = "0.2" unicode-width = "0.1.1" unicode-segmentation = "1.2.0" +serde = "1.0" +serde_derive = "1.0" +serde_json = "1.0" diff --git a/README.md b/README.md index 469059e..777418e 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,8 @@ Options: -s, --summary equivalent to -da, or -d1 -a1M -u, --usage report real disk usage instead of file size -b, --bytes print sizes in bytes + -w, --write FILE write data to file + -r, --read FILE read data from file -f, --files-only skip directories for a fast local overview -x, --exclude NAME exclude matching files or directories -H, --no-hidden exclude hidden files diff --git a/src/lib.rs b/src/lib.rs index 554ae1b..0602598 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,6 +13,8 @@ //! -s, --summary equivalent to -da, or -d1 -a1M //! -u, --usage report real disk usage instead of file size //! -b, --bytes print sizes in bytes +//! -w, --write FILE write data to file +//! -r, --read FILE read data from file //! -x, --exclude NAME exclude matching files or directories //! -H, --no-hidden exclude hidden files //! -A, --ascii ASCII characters only, no colors @@ -49,9 +51,14 @@ use terminal_size::{Width, Height, terminal_size}; extern crate regex; use regex::Regex; -use std::io; +#[macro_use] +extern crate serde_derive; +extern crate serde; +extern crate serde_json; + +use std::io::{self, Read}; use std::path::{Path, PathBuf}; -use std::fs; +use std::fs::{self, File}; #[cfg(target_os = "linux")] use std::os::linux::fs::MetadataExt; #[cfg(target_os = "macos")] @@ -69,6 +76,7 @@ pub enum XResult { } use XResult::{XOk, XExit, XErr}; +#[derive(Serialize, Deserialize)] struct Entry<'a> { name : String, bytes : u64, @@ -89,6 +97,8 @@ pub struct Config { no_dir_flg : bool, aggr : u64, exclude : Vec, + read_files : Vec, + write_file : Option, } fn init_opts() -> Options { @@ -99,6 +109,8 @@ fn init_opts() -> Options { options.optflag( "s", "summary" , "equivalent to -da, or -d1 -a1M" ); options.optflag( "u", "usage" , "report real disk usage instead of file size" ); options.optflag( "b", "bytes" , "print sizes in bytes" ); + options.optopt( "w", "write" , "write data to file", "FILE" ); + options.optmulti( "r", "read" , "read data from file", "FILE" ); options.optflag( "f", "files-only","skip directories for a fast local overview" ); options.optmulti( "x", "exclude" , "exclude matching files or directories", "NAME" ); options.optflag( "H", "no-hidden", "exclude hidden files" ); @@ -131,8 +143,11 @@ impl Config { let color_dict = create_color_dict(); + let read_file_paths = opt.opt_strs("r"); + let write_file_path = opt.opt_str("w"); + let mut paths : Vec = Vec::new(); - if opt.free.len() == 0 { + if opt.free.len() == 0 && read_file_paths.len() == 0 { let mut path = std::path::PathBuf::new(); path.push( ".".to_string() ); paths.push( path ); @@ -150,6 +165,28 @@ impl Config { } } + let mut read_files: Vec = Vec::new(); + for file_path in read_file_paths { + let mut path = std::path::PathBuf::new(); + path.push( &file_path ); + read_files.push( path ); + }; + for p in &read_files { + if !p.exists() { + return XErr( format!( "read-file {} doesn't exist", p.display() ) ); + } + } + + let mut write_file = None; + if let Some(file) = &write_file_path { + let mut path = std::path::PathBuf::new(); + path.push( &file ); + if path.exists() { + return XErr( format!( "write-file {} exist", path.display() ) ); + } + write_file = Some(path); + } + let mut depth_flag = opt.opt_present("d"); let depth_opt = opt.opt_str("d"); let mut depth = depth_opt.unwrap_or("1".to_string()).parse().unwrap_or(1); @@ -194,7 +231,7 @@ impl Config { } XOk( Config{ paths, color_dict, depth, depth_flag, bytes_flag, - usage_flag, hiddn_flag, ascii_flag, no_dir_flg, aggr, exclude } ) + usage_flag, hiddn_flag, ascii_flag, no_dir_flg, aggr, exclude, read_files, write_file } ) } } @@ -551,7 +588,15 @@ fn create_color_dict() -> HashMap { } pub fn run( cfg: &Config ) { - let entry = if cfg.paths.len() == 1 { + let mut files: Vec> = Vec::new(); + for file in &cfg.read_files { + let mut contents = String::new(); + let mut file = File::open( file ).expect( "file not found" ); + file.read_to_string( &mut contents ).expect( "read failed" ); + files.push( Box::new( contents ) ); + } + + let entry = if cfg.paths.len() == 1 && cfg.read_files.len() == 0{ Entry::new( cfg.paths[0].as_path(), &cfg, cfg.depth + 1 ) } else { let mut bytes = 0; @@ -562,12 +607,17 @@ pub fn run( cfg: &Config ) { bytes += e.bytes; entries.push( e ); } + files.iter().for_each( |file| { + let e: Entry = serde_json::from_str( file ).expect( "error while reading json" ); + bytes += e.bytes; + entries.push( e ); + }); entries.sort_unstable_by( |a, b| b.bytes.cmp( &a.bytes ) ); let len = entries.len(); if len > 0 { entries[len-1].last = true; } - Entry { + Entry { name : "".to_string(), bytes, color : None, @@ -575,6 +625,11 @@ pub fn run( cfg: &Config ) { entries : Some(entries) } }; + if let Some(file) = &cfg.write_file { + let json_file_path = Path::new( &file ); + let json_file = File::create( json_file_path ).expect( "file not writable" ); + serde_json::to_writer( json_file, &entry ).expect( "error while writing json" ); + } entry.print( cfg.bytes_flag, cfg.ascii_flag ); }