summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSam Tay <sam.chong.tay@gmail.com>2020-06-18 12:43:19 -0700
committerSam Tay <sam.chong.tay@gmail.com>2020-06-18 12:43:19 -0700
commit5f88657a75c4443ba93936e0f14bb3be0435fd41 (patch)
tree1dd3629bb9707fb84985b5a075fced48b0552edb /src
parentec92f930344d364e3be359a41aebea78f8205fa7 (diff)
Fetch q/a in the background while viewing --luckyv0.2.1
Diffstat (limited to 'src')
-rw-r--r--src/main.rs15
-rw-r--r--src/stackexchange.rs32
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"),