aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock198
-rw-r--r--Cargo.toml3
-rw-r--r--src/main.rs131
3 files changed, 175 insertions, 157 deletions
diff --git a/Cargo.lock b/Cargo.lock
index d548319..5aa9be0 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -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"
diff --git a/Cargo.toml b/Cargo.toml
index d204c03..09d7b1f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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);
});