diff options
author | Sam Tay <sam.chong.tay@gmail.com> | 2020-06-18 12:43:19 -0700 |
---|---|---|
committer | Sam Tay <sam.chong.tay@gmail.com> | 2020-06-18 12:43:19 -0700 |
commit | 5f88657a75c4443ba93936e0f14bb3be0435fd41 (patch) | |
tree | 1dd3629bb9707fb84985b5a075fced48b0552edb /src | |
parent | ec92f930344d364e3be359a41aebea78f8205fa7 (diff) |
Fetch q/a in the background while viewing --luckyv0.2.1
Diffstat (limited to 'src')
-rw-r--r-- | src/main.rs | 15 | ||||
-rw-r--r-- | src/stackexchange.rs | 32 |
2 files changed, 27 insertions, 20 deletions
diff --git a/src/main.rs b/src/main.rs index 27c7109..e7c0414 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,12 +7,13 @@ mod tui; mod utils; use crossterm::style::Color; -use error::Error; +use error::{Error, Result}; use lazy_static::lazy_static; use minimad::mad_inline; use stackexchange::{LocalStorage, StackExchange}; use term::mk_print_error; use termimad::{CompoundStyle, MadSkin}; +use tokio::task; #[tokio::main] async fn main() -> Result<(), Error> { @@ -77,19 +78,21 @@ async fn run(skin: &mut MadSkin) -> Result<(), Error> { } if let Some(q) = opts.query { - let se = StackExchange::new(config); - // TODO get the rest of the results in the background + let se = StackExchange::new(config, q); if lucky { // TODO this needs preprocessing; all the more reason to do it at SE level - let md = se.search_lucky(&q).await?; + let md = se.search_lucky().await?; skin.print_text(&md); skin.print_text("\nPress **[SPACE]** to see more results, or any other key to exit"); + // Kick off the rest of the search in the background + let qs = task::spawn(async move { se.search().await }); if !utils::wait_for_char(' ')? { return Ok(()); } + tui::run(qs.await.unwrap()?)?; + } else { + tui::run(se.search().await?)?; } - let qs = se.search(&q).await?; - tui::run(qs)?; } Ok(()) } diff --git a/src/stackexchange.rs b/src/stackexchange.rs index 2b4da67..f86c8c0 100644 --- a/src/stackexchange.rs +++ b/src/stackexchange.rs @@ -27,11 +27,12 @@ const SE_SITES_PAGESIZE: u16 = 10000; pub struct StackExchange { client: Client, config: Config, + query: String, } /// This structure allows interacting with locally cached StackExchange metadata. pub struct LocalStorage { - sites: Option<Vec<Site>>, + sites: Option<Vec<Site>>, // TODO this should be a hashmap! filename: PathBuf, } @@ -75,16 +76,20 @@ struct ResponseWrapper<T> { } impl StackExchange { - pub fn new(config: Config) -> Self { + pub fn new(config: Config, query: String) -> Self { let client = Client::new(); - StackExchange { client, config } + StackExchange { + client, + config, + query, + } } // TODO also return a future with the rest of the questions /// Search query at stack exchange and get the top answer body - pub async fn search_lucky(&self, q: &str) -> Result<String> { - let ans = self - .search_advanced(q, 1) + pub async fn search_lucky(&self) -> Result<String> { + Ok(self + .search_advanced(1) .await? .into_iter() .next() @@ -92,28 +97,27 @@ impl StackExchange { .answers .into_iter() .next() - .ok_or_else(|| { - Error::StackExchange(String::from("Received question with no answers")) - })?; - Ok(ans.body) + .ok_or_else(|| Error::StackExchange(String::from("Received question with no answers")))? + .body) } /// Search query at stack exchange and get a list of relevant questions - pub async fn search(&self, q: &str) -> Result<Vec<Question>> { - self.search_advanced(q, self.config.limit).await + pub async fn search(&self) -> Result<Vec<Question>> { + self.search_advanced(self.config.limit).await } + /// Search against the search/advanced endpoint with a given query. /// Only fetches questions that have at least one answer. /// TODO async /// TODO parallel requests over multiple sites - async fn search_advanced(&self, q: &str, limit: u16) -> Result<Vec<Question>> { + async fn search_advanced(&self, limit: u16) -> Result<Vec<Question>> { Ok(self .client .get(stackexchange_url("search/advanced")) .header("Accepts", "application/json") .query(&self.get_default_opts()) .query(&[ - ("q", q), + ("q", self.query.as_str()), ("pagesize", &limit.to_string()), ("page", "1"), ("answers", "1"), |