diff options
-rw-r--r-- | Cargo.lock | 198 | ||||
-rw-r--r-- | Cargo.toml | 3 | ||||
-rw-r--r-- | src/main.rs | 131 |
3 files changed, 175 insertions, 157 deletions
@@ -1,10 +1,16 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "adler32" -version = "1.1.0" +name = "adler" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccc9a9dd069569f212bc4330af9f17c4afb5e8ce185e83dbb14f1349dda18b10" + +[[package]] +name = "anyhow" +version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567b077b825e468cc974f0020d4082ee6e03132512f207ef1a02fd5d00d1f32d" +checksum = "85bb70cc08ec97ca5450e6eba421deeea5f172c0fc61f78b5357b2a8e8be195f" [[package]] name = "arc-swap" @@ -42,6 +48,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1ba68f4276a778591e36a0c348a269888f3a177c8d2054969389e3b59611ff5" [[package]] +name = "base64" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" + +[[package]] name = "bitflags" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -51,9 +63,12 @@ checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" name = "bk" version = "0.2.0" dependencies = [ + "anyhow", "argh", "crossterm", + "ron", "roxmltree", + "serde", "zip", ] @@ -83,9 +98,9 @@ dependencies = [ [[package]] name = "crossterm" -version = "0.17.5" +version = "0.17.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9851d20b9809e561297ec3ca85d7cba3a57507fe8d01d07ba7b52469e1c89a11" +checksum = "b1f397c213f41eae56e512bb3bec44ac044650e30f1a15357d9d8495a01906cb" dependencies = [ "bitflags", "crossterm_winapi", @@ -94,7 +109,7 @@ dependencies = [ "mio", "parking_lot", "signal-hook", - "winapi 0.3.8", + "winapi", ] [[package]] @@ -103,14 +118,14 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "057b7146d02fb50175fd7dbe5158f6097f33d02831f43b4ee8ae4ddf67b68f5c" dependencies = [ - "winapi 0.3.8", + "winapi", ] [[package]] name = "flate2" -version = "1.0.14" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cfff41391129e0a856d6d822600b8d71179d46879e310417eb9c762eb178b42" +checksum = "68c90b0fc46cf89d227cc78b40e494ff81287a92dd07631e5af0d06fe3cf885e" dependencies = [ "cfg-if", "crc32fast", @@ -119,22 +134,6 @@ dependencies = [ ] [[package]] -name = "fuchsia-zircon" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" -dependencies = [ - "bitflags", - "fuchsia-zircon-sys", -] - -[[package]] -name = "fuchsia-zircon-sys" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" - -[[package]] name = "heck" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -144,25 +143,6 @@ dependencies = [ ] [[package]] -name = "iovec" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" -dependencies = [ - "libc", -] - -[[package]] -name = "kernel32-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] - -[[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -170,9 +150,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.71" +version = "0.2.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49" +checksum = "a9f8082297d534141b30c8d39e9b1773713ab50fdbe4ff30f750d063b3bfd701" [[package]] name = "lock_api" @@ -194,53 +174,44 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.3.7" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435" +checksum = "be0f75932c1f6cfae3c04000e40114adf955636e19040f9c0a2c380702aa1c7f" dependencies = [ - "adler32", + "adler", ] [[package]] name = "mio" -version = "0.6.22" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fce347092656428bc8eaf6201042cb551b8d67855af7374542a92a0fbfcac430" +checksum = "6e9971bc8349a361217a8f2a41f5d011274686bd4436465ba51730921039d7fb" dependencies = [ - "cfg-if", - "fuchsia-zircon", - "fuchsia-zircon-sys", - "iovec", - "kernel32-sys", + "lazy_static", "libc", "log", "miow", - "net2", - "slab", - "winapi 0.2.8", + "ntapi", + "winapi", ] [[package]] name = "miow" -version = "0.2.1" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" +checksum = "07b88fb9795d4d36d62a012dfbf49a8f5cf12751f36d31a9dbe66d528e58979e" dependencies = [ - "kernel32-sys", - "net2", - "winapi 0.2.8", - "ws2_32-sys", + "socket2", + "winapi", ] [[package]] -name = "net2" -version = "0.2.34" +name = "ntapi" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ba7c918ac76704fb42afcbbb43891e72731f3dcca3bef2a19786297baf14af7" +checksum = "7a31937dea023539c72ddae0e3571deadc1414b300483fa7aaec176168cfa9d2" dependencies = [ - "cfg-if", - "libc", - "winapi 0.3.8", + "winapi", ] [[package]] @@ -264,7 +235,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "winapi 0.3.8", + "winapi", ] [[package]] @@ -298,6 +269,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" [[package]] +name = "ron" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a91260f321dbf3b5a16ff91c451dc9eb644ce72775a6812f9c3dfffe63818f8f" +dependencies = [ + "base64", + "bitflags", + "serde", +] + +[[package]] name = "roxmltree" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -313,6 +295,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] +name = "serde" +version = "1.0.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5317f7588f0a5078ee60ef675ef96735a1442132dc645eb1d12c018620ed8cd3" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a0be94b04690fbaed37cddffc5c134bf537c8e3329d53e982fe04c374978f8e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] name = "signal-hook" version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -334,22 +336,28 @@ dependencies = [ ] [[package]] -name = "slab" -version = "0.4.2" +name = "smallvec" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" +checksum = "3757cb9d89161a2f24e1cf78efa0c1fcff485d18e3f55e0aa3480824ddaa0f3f" [[package]] -name = "smallvec" -version = "1.4.0" +name = "socket2" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7cb5678e1615754284ec264d9bb5b4c27d2018577fd90ac0ceb578591ed5ee4" +checksum = "03088793f677dce356f3ccc2edb1b314ad191ab702a5de3faf49304f7e104918" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "winapi", +] [[package]] name = "syn" -version = "1.0.32" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a994520748611c17d163e81b6c4a4b13d11b7f63884362ab2efac3aa9cf16d00" +checksum = "e8d5d96e8cbb005d6959f119f773bfaebb5684296108fb32600c00cde305b2cd" dependencies = [ "proc-macro2", "quote", @@ -364,33 +372,21 @@ checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" [[package]] name = "unicode-xid" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" - -[[package]] -name = "winapi" -version = "0.2.8" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" +checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" [[package]] name = "winapi" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" dependencies = [ "winapi-i686-pc-windows-gnu", "winapi-x86_64-pc-windows-gnu", ] [[package]] -name = "winapi-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" - -[[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -403,16 +399,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "ws2_32-sys" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] - -[[package]] name = "xmlparser" version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -11,9 +11,12 @@ readme = "README.md" repository = "https://github.com/aeosynth/bk" [dependencies] +anyhow = "1" argh = "0" crossterm = "0" +ron = "0" roxmltree = "0" +serde = "1" [dependencies.zip] version = "0" diff --git a/src/main.rs b/src/main.rs index bf8baf1..f07ba1e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,12 @@ +use anyhow::Result; +use crossterm::{ + cursor, + event::{self, Event, KeyCode}, + queue, + style::{Attribute, Print}, + terminal, +}; +use serde::{Deserialize, Serialize}; use std::{ cmp::{max, min}, collections::HashMap, @@ -7,14 +16,6 @@ use std::{ process::exit, }; -use crossterm::{ - cursor, - event::{self, Event, KeyCode}, - queue, - style::{Attribute, Print}, - terminal, -}; - mod epub; // XXX assumes a char is i unit wide @@ -674,74 +675,102 @@ struct Props { toc: bool, } -fn init(save_path: &str) -> Option<(String, bool, Props)> { +#[derive(Default, Deserialize, Serialize)] +struct Save { + last: String, + files: HashMap<String, (usize, usize)>, +} + +struct State { + save: Save, + save_path: String, + path: String, + meta: bool, + bk: Props, +} + +fn init() -> Result<State> { + let save_path = if cfg!(windows) { + format!("{}\\bk", env::var("APPDATA")?) + } else { + format!("{}/.local/share/bk", env::var("HOME")?) + }; + // XXX will silently create a new default save if ron errors but path arg works. + // revisit if/when stabilizing. ez file format upgrades + let save = fs::read_to_string(&save_path) + .map_err(|e| anyhow::Error::new(e)) + .and_then(|s| { + let save: Save = ron::from_str(&s)?; + Ok(save) + }); let args: Args = argh::from_env(); - // TODO nice error message instead of panic - let path = args - .path - .map(|s| fs::canonicalize(s).unwrap().to_str().unwrap().to_string()); - let save = fs::read_to_string(save_path).and_then(|s| { - let mut lines = s.lines(); - Ok(( - lines.next().unwrap().to_string(), - lines.next().unwrap().parse::<usize>().unwrap(), - lines.next().unwrap().parse::<usize>().unwrap(), - )) - }); - let (path, chapter, byte) = match (save, path) { - (Err(_), None) => return None, - (Err(_), Some(path)) => (path, 0, 0), - (Ok(save), None) => save, - (Ok(save), Some(path)) => { - if save.0 == path { - save + let mut path = args.path; + // abort on path error + if path.is_some() { + path = Some( + fs::canonicalize(path.unwrap())? + .to_str() + .unwrap() + .to_string(), + ); + } + + let (path, chapter, byte) = match (&save, &path) { + (Err(_), None) => return Err(anyhow::anyhow!("no path arg and no or invalid save file")), + (Err(_), Some(p)) => (p, 0, 0), + (Ok(save), None) => { + let &(chapter, byte) = save.files.get(&save.last).unwrap(); + (&save.last, chapter, byte) + } + (Ok(save), Some(p)) => { + if save.files.contains_key(p) { + let &(chapter, byte) = save.files.get(p).unwrap(); + (p, chapter, byte) } else { - (path, 0, 0) + (p, 0, 0) } } }; - Some(( - path, - args.meta, - Props { + Ok(State { + save_path, + path: path.clone(), + save: save.unwrap_or_default(), + meta: args.meta, + bk: Props { chapter, byte, width: args.width, toc: args.toc, }, - )) + }) } fn main() { - let save_path = if cfg!(windows) { - format!("{}\\bk", env::var("APPDATA").unwrap()) - } else { - format!("{}/.local/share/bk", env::var("HOME").unwrap()) - }; - - let (path, meta, args) = init(&save_path).unwrap_or_else(|| { - println!("error: need a path"); + let mut state = init().unwrap_or_else(|e| { + println!("init error: {}", e); exit(1); }); - - let epub = epub::Epub::new(&path, meta).unwrap_or_else(|e| { - println!("error reading epub: {}", e); + let epub = epub::Epub::new(&state.path, state.meta).unwrap_or_else(|e| { + println!("epub error: {}", e); exit(1); }); - - if meta { + if state.meta { println!("{}", epub.meta); exit(0); } - - let mut bk = Bk::new(epub, args); - // i have never seen crossterm error + let mut bk = Bk::new(epub, state.bk); bk.run().unwrap(); let byte = bk.chap().lines[bk.line].0; - fs::write(save_path, format!("{}\n{}\n{}", path, bk.chapter, byte)).unwrap_or_else(|e| { + state + .save + .files + .insert(state.path.clone(), (bk.chapter, byte)); + state.save.last = state.path; + let serialized = ron::to_string(&state.save).unwrap(); + fs::write(state.save_path, serialized).unwrap_or_else(|e| { println!("error saving state: {}", e); exit(1); }); |