diff --git a/Cargo.lock b/Cargo.lock index 5a59a1a..6f6ccc7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -50,6 +50,54 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "anstream" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" + +[[package]] +name = "anstyle-parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" +dependencies = [ + "anstyle", + "windows-sys", +] + [[package]] name = "anyhow" version = "1.0.75" @@ -235,6 +283,52 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "clap" +version = "4.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +dependencies = [ + "heck", + "proc-macro2 1.0.66", + "quote 1.0.33", + "syn 2.0.29", +] + +[[package]] +name = "clap_lex" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" + +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + [[package]] name = "console_error_panic_hook" version = "0.1.7" @@ -937,6 +1031,12 @@ version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + [[package]] name = "hermit-abi" version = "0.1.19" @@ -1525,6 +1625,8 @@ dependencies = [ name = "notmuch" version = "0.1.0" dependencies = [ + "anyhow", + "clap", "itertools", "log 0.4.20", "pretty_assertions", @@ -2592,6 +2694,12 @@ dependencies = [ "quote 1.0.33", ] +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "syn" version = "0.15.44" @@ -3050,6 +3158,12 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + [[package]] name = "uuid" version = "1.4.1" diff --git a/notmuch/Cargo.toml b/notmuch/Cargo.toml index 24442f1..9741551 100644 --- a/notmuch/Cargo.toml +++ b/notmuch/Cargo.toml @@ -6,6 +6,8 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +anyhow = "1.0.75" +clap = { version = "4.4.7", features = ["derive"] } log = "0.4.14" serde = { version = "1.0", features = ["derive"] } serde_json = { version = "1.0", features = ["unbounded_depth"] } diff --git a/notmuch/src/main.rs b/notmuch/src/main.rs new file mode 100644 index 0000000..1d063a9 --- /dev/null +++ b/notmuch/src/main.rs @@ -0,0 +1,46 @@ +use std::path::PathBuf; + +use clap::{Parser, Subcommand}; +use notmuch::Notmuch; + +#[derive(Parser)] +#[command(author, version, about, long_about = None)] +#[command(propagate_version = true)] +struct Cli { + /// Optional notmuch config file + #[arg(short, long)] + config: Option, + + #[command(subcommand)] + command: Commands, +} + +#[derive(Subcommand)] +enum Commands { + /// Show given search term + Show { search_term: String }, + /// Search for given search term + Search { search_term: String }, +} + +fn main() -> anyhow::Result<()> { + let cli = Cli::parse(); + + let nm = if let Some(config_path) = cli.config { + Notmuch::with_config(config_path) + } else { + Notmuch::default() + }; + + // You can check for the existence of subcommands, and if found use their + // matches just as you would the top level cmd + match &cli.command { + Commands::Search { search_term } => { + println!("{:#?}", nm.search(&search_term, 0, 10)?); + } + Commands::Show { search_term } => { + println!("{:#?}", nm.show(&search_term)?); + } + } + Ok(()) +} diff --git a/server/src/nm.rs b/server/src/nm.rs index 11098b8..89d6f8d 100644 --- a/server/src/nm.rs +++ b/server/src/nm.rs @@ -7,7 +7,9 @@ pub fn threadset_to_messages( thread_set: notmuch::ThreadSet, ) -> Result, error::ServerError> { for t in thread_set.0 { - for tn in t.0 {} + for tn in t.0 { + todo!() + } } Ok(Vec::new()) } diff --git a/shared/src/lib.rs b/shared/src/lib.rs index d3a12e7..c96082e 100644 --- a/shared/src/lib.rs +++ b/shared/src/lib.rs @@ -9,3 +9,5 @@ pub struct SearchResult { pub results_per_page: usize, pub total: usize, } +#[derive(Serialize, Deserialize, Debug)] +pub struct Message {} diff --git a/web/src/lib.rs b/web/src/lib.rs index 37fb5d4..6ecbf2d 100644 --- a/web/src/lib.rs +++ b/web/src/lib.rs @@ -97,7 +97,7 @@ mod urls { enum Context { None, Search(shared::SearchResult), - Thread(ThreadSet), + Thread(Vec), } // `Model` describes our app state. @@ -136,7 +136,7 @@ enum Msg { ShowRequest(String), ShowResult(fetch::Result), ShowPrettyRequest(String), - ShowPrettyResult(fetch::Result), + ShowPrettyResult(fetch::Result>), NextPage, PreviousPage, } @@ -185,9 +185,10 @@ fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders) { .skip() .perform_cmd(async move { Msg::ShowResult(show_request(&tid).await) }); } + // TODO(wathiede): remove Msg::ShowResult(Ok(response_data)) => { debug!("fetch ok {:#?}", response_data); - model.context = Context::Thread(response_data); + //model.context = Context::Thread(response_data); } Msg::ShowResult(Err(fetch_error)) => { error!("fetch failed {:?}", fetch_error); @@ -199,7 +200,7 @@ fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders) { .perform_cmd(async move { Msg::ShowPrettyResult(show_pretty_request(&tid).await) }); } Msg::ShowPrettyResult(Ok(response_data)) => { - debug!("fetch ok {:#?}", response_data); + info!("fetch ok {:#?}", response_data); model.context = Context::Thread(response_data); } Msg::ShowPrettyResult(Err(fetch_error)) => { @@ -288,7 +289,7 @@ async fn show_request(tid: &str) -> fetch::Result { .map_err(|_| FetchError::JsonError(fetch::JsonError::Serde(JsValue::NULL)))?) } -async fn show_pretty_request(tid: &str) -> fetch::Result { +async fn show_pretty_request(tid: &str) -> fetch::Result> { Request::new(api::show_pretty(tid)) .method(Method::Get) .fetch() @@ -602,29 +603,32 @@ fn view_search_pager(start: usize, count: usize, total: usize) -> Node { ] } -fn view_thread(thread_set: &ThreadSet) -> Node { - assert_eq!(thread_set.0.len(), 1); - let thread = &thread_set.0[0]; - assert_eq!(thread.0.len(), 1); - let thread_node = &thread.0[0]; - let subject = first_subject(&thread_node).unwrap_or("".to_string()); - set_title(&subject); +fn view_thread(messages: &[shared::Message]) -> Node { + div!["TODO(wathiede): view_thread(messages)"] + /* + assert_eq!(thread_set.0.len(), 1); + let thread = &thread_set.0[0]; + assert_eq!(thread.0.len(), 1); + let thread_node = &thread.0[0]; + let subject = first_subject(&thread_node).unwrap_or("".to_string()); + set_title(&subject); + div![ + C!["container"], + h1![C!["title"], subject], + view_message(&thread_node), + a![ + attrs! {At::Href=>api::original(&thread_node.0.as_ref().expect("message missing").id)}, + "Original" + ], + /* div![ - C!["container"], - h1![C!["title"], subject], - view_message(&thread_node), - a![ - attrs! {At::Href=>api::original(&thread_node.0.as_ref().expect("message missing").id)}, - "Original" - ], - /* - div![ - C!["debug"], - "Add zippy for debug dump", - view_debug_thread_set(thread_set) - ] /* pre![format!("Thread: {:#?}", thread_set).replace(" ", " ")] */ - */ + C!["debug"], + "Add zippy for debug dump", + view_debug_thread_set(thread_set) + ] /* pre![format!("Thread: {:#?}", thread_set).replace(" ", " ")] */ + */ ] + */ } fn view_debug_thread_set(thread_set: &ThreadSet) -> Node { @@ -732,7 +736,7 @@ fn view_footer(render_time_ms: u128) -> Node { fn view_desktop(model: &Model) -> Node { let content = match &model.context { Context::None => div![h1!["Loading"]], - Context::Thread(thread_set) => view_thread(thread_set), + Context::Thread(messages) => view_thread(messages), Context::Search(search_results) => view_search_results(&model.query, search_results), }; div![ @@ -745,7 +749,7 @@ fn view_desktop(model: &Model) -> Node { fn view_mobile(model: &Model) -> Node { let content = match &model.context { Context::None => div![h1!["Loading"]], - Context::Thread(thread_set) => view_thread(thread_set), + Context::Thread(messages) => view_thread(messages), Context::Search(search_results) => view_mobile_search_results(&model.query, search_results), }; div![