summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDenis Isidoro <denisidoro@users.noreply.github.com>2022-07-29 18:53:18 -0300
committerGitHub <noreply@github.com>2022-07-29 18:53:18 -0300
commit8b78d5486351ee9f3849ebe59f6f9f46c72de9a3 (patch)
treebb0b2450961d5b6d85e47c820ed0b70b3ece1f76 /src
parentd68c4437a1efad575bd0d3cdae6daba14bfe472e (diff)
Improve error handling for cheatsh and tldr (#766)
Fixes #695 and #703
Diffstat (limited to 'src')
-rw-r--r--src/clients/cheatsh.rs80
-rw-r--r--src/clients/tldr.rs48
-rw-r--r--src/commands/core/mod.rs39
-rw-r--r--src/commands/temp.rs5
-rw-r--r--src/config/mod.rs16
-rw-r--r--src/structures/fetcher.rs17
-rw-r--r--src/welcome.rs7
7 files changed, 98 insertions, 114 deletions
diff --git a/src/clients/cheatsh.rs b/src/clients/cheatsh.rs
index f039b0c..13ffaf7 100644
--- a/src/clients/cheatsh.rs
+++ b/src/clients/cheatsh.rs
@@ -1,26 +1,22 @@
-use crate::parser::Parser;
use crate::prelude::*;
-
-use crate::structures::fetcher;
-use std::process::{self, Command};
+use std::process::Command;
fn map_line(line: &str) -> String {
line.trim().trim_end_matches(':').to_string()
}
-fn lines(query: &str, markdown: &str) -> impl Iterator<Item = Result<String>> {
+fn as_lines(query: &str, markdown: &str) -> Vec<String> {
format!(
"% {}, cheat.sh
{}",
query, markdown
)
.lines()
- .map(|line| Ok(map_line(line)))
- .collect::<Vec<Result<String>>>()
- .into_iter()
+ .map(map_line)
+ .collect()
}
-pub fn fetch(query: &str) -> Result<String> {
+pub fn call(query: &str) -> Result<Vec<String>> {
let args = ["-qO-", &format!("cheat.sh/{}", query)];
let child = Command::new("wget")
@@ -32,19 +28,34 @@ pub fn fetch(query: &str) -> Result<String> {
let child = match child {
Ok(x) => x,
Err(_) => {
- eprintln!(
- "navi was unable to call wget.
-Make sure wget is correctly installed."
- );
- process::exit(34)
+ let msg = "navi was unable to call wget.
+Make sure wget is correctly installed.";
+ return Err(anyhow!(msg));
}
};
let out = child.wait_with_output().context("Failed to wait for wget")?;
if let Some(0) = out.status.code() {
+ let stdout = out.stdout;
+ let plain_bytes = strip_ansi_escapes::strip(&stdout)?;
+
+ let markdown = String::from_utf8(plain_bytes).context("Output is invalid utf8")?;
+ if markdown.starts_with("Unknown topic.") {
+ let msg = format!(
+ "`{}` not found in cheatsh.
+Output:
+{}
+",
+ &query, markdown,
+ );
+ return Err(anyhow!(msg));
+ }
+
+ let lines = as_lines(query, &markdown);
+ Ok(lines)
} else {
- eprintln!(
+ let msg = format!(
"Failed to call:
wget {}
@@ -58,43 +69,6 @@ Error:
String::from_utf8(out.stdout).unwrap_or_else(|_e| "Unable to get output message".to_string()),
String::from_utf8(out.stderr).unwrap_or_else(|_e| "Unable to get error message".to_string())
);
- process::exit(35)
- }
-
- let stdout = out.stdout;
- let plain_bytes = strip_ansi_escapes::strip(&stdout)?;
-
- String::from_utf8(plain_bytes).context("Output is invalid utf8")
-}
-
-pub struct Fetcher {
- query: String,
-}
-
-impl Fetcher {
- pub fn new(query: String) -> Self {
- Self { query }
- }
-}
-
-impl fetcher::Fetcher for Fetcher {
- fn fetch(&self, parser: &mut Parser) -> Result<bool> {
- let cheat = &fetch(&self.query)?;
-
- if cheat.starts_with("Unknown topic.") {
- eprintln!(
- "`{}` not found in cheatsh.
-
-Output:
-{}
-",
- &self.query, cheat
- );
- process::exit(35)
- }
-
- parser.read_lines(lines(&self.query, cheat), "cheat.sh", None)?;
-
- Ok(true)
+ Err(anyhow!(msg))
}
}
diff --git a/src/clients/tldr.rs b/src/clients/tldr.rs
index f164534..6783fdc 100644
--- a/src/clients/tldr.rs
+++ b/src/clients/tldr.rs
@@ -1,6 +1,4 @@
-use crate::parser::Parser;
use crate::prelude::*;
-use crate::structures::fetcher;
use std::process::{self, Command, Stdio};
lazy_static! {
@@ -42,19 +40,18 @@ fn convert_tldr(line: &str) -> String {
}
}
-fn markdown_lines(query: &str, markdown: &str) -> impl Iterator<Item = Result<String>> {
+fn markdown_lines(query: &str, markdown: &str) -> Vec<String> {
format!(
"% {}, tldr
{}",
query, markdown
)
.lines()
- .map(|line| Ok(convert_tldr(line)))
- .collect::<Vec<Result<String>>>()
- .into_iter()
+ .map(convert_tldr)
+ .collect()
}
-pub fn fetch(query: &str) -> Result<String> {
+pub fn call(query: &str) -> Result<Vec<String>> {
let args = [query, "--markdown"];
let child = Command::new("tldr")
@@ -67,7 +64,7 @@ pub fn fetch(query: &str) -> Result<String> {
let child = match child {
Ok(x) => x,
Err(_) => {
- eprintln!(
+ let msg = format!(
"navi was unable to call tldr.
Make sure tldr is correctly installed.
Refer to https://github.com/tldr-pages/tldr for more info.
@@ -77,15 +74,20 @@ Note:
",
VERSION_DISCLAIMER
);
- process::exit(34)
+ return Err(anyhow!(msg));
}
};
let out = child.wait_with_output().context("Failed to wait for tldr")?;
if let Some(0) = out.status.code() {
+ let stdout = out.stdout;
+
+ let markdown = String::from_utf8(stdout).context("Output is invalid utf8")?;
+ let lines = markdown_lines(query, &markdown);
+ Ok(lines)
} else {
- eprintln!(
+ let msg = format!(
"Failed to call:
tldr {}
@@ -103,30 +105,8 @@ If you are already using a supported version you can ignore this message.
args.join(" "),
String::from_utf8(out.stdout).unwrap_or_else(|_e| "Unable to get output message".to_string()),
String::from_utf8(out.stderr).unwrap_or_else(|_e| "Unable to get error message".to_string()),
- VERSION_DISCLAIMER
+ VERSION_DISCLAIMER,
);
- process::exit(35)
- }
-
- let stdout = out.stdout;
-
- String::from_utf8(stdout).context("Output is invalid utf8")
-}
-
-pub struct Fetcher {
- query: String,
-}
-
-impl Fetcher {
- pub fn new(query: String) -> Self {
- Self { query }
- }
-}
-
-impl fetcher::Fetcher for Fetcher {
- fn fetch(&self, parser: &mut Parser) -> Result<bool> {
- let markdown = fetch(&self.query)?;
- parser.read_lines(markdown_lines(&self.query, &markdown), "markdown", None)?;
- Ok(true)
+ Err(anyhow!(msg))
}
}
diff --git a/src/commands/core/mod.rs b/src/commands/core/mod.rs
index f212880..74e2852 100644
--- a/src/commands/core/mod.rs
+++ b/src/commands/core/mod.rs
@@ -1,20 +1,23 @@
mod actor;
mod extractor;
+use crate::clients::cheatsh;
+use crate::config::Source;
+use crate::filesystem;
use crate::finder::structures::Opts as FinderOpts;
use crate::parser::Parser;
use crate::prelude::*;
+use crate::structures::fetcher::{Fetcher, StaticFetcher};
use crate::welcome;
-pub fn main() -> Result<()> {
+pub fn init(fetcher: Box<dyn Fetcher>) -> Result<()> {
let config = &CONFIG;
let opts = FinderOpts::snippet_default();
+ // let fetcher = config.fetcher();
let (raw_selection, (variables, files)) = config
.finder()
.call(opts, |writer| {
- let fetcher = config.fetcher();
-
let mut parser = Parser::new(writer, true);
let found_something = fetcher
@@ -32,10 +35,38 @@ pub fn main() -> Result<()> {
let extractions = extractor::extract_from_selections(&raw_selection, config.best_match());
if extractions.is_err() {
- return main();
+ return init(fetcher);
}
actor::act(extractions, files, variables)?;
Ok(())
}
+
+pub fn get_fetcher() -> Result<Box<dyn Fetcher>> {
+ match CONFIG.source() {
+ Source::Cheats(query) => {
+ let lines = cheatsh::call(&query)?;
+ let fetcher = Box::new(StaticFetcher::new(lines));
+ Ok(fetcher)
+ }
+ Source::Tldr(query) => {
+ let lines = cheatsh::call(&query)?;
+ let fetcher = Box::new(StaticFetcher::new(lines));
+ Ok(fetcher)
+ }
+ Source::Filesystem(path) => {
+ let fetcher = Box::new(filesystem::Fetcher::new(path));
+ Ok(fetcher)
+ }
+ Source::Welcome => {
+ let fetcher = Box::new(welcome::Fetcher::new());
+ Ok(fetcher)
+ }
+ }
+}
+
+pub fn main() -> Result<()> {
+ let fetcher = get_fetcher()?;
+ init(fetcher)
+}
diff --git a/src/commands/temp.rs b/src/commands/temp.rs
index 35a1ac3..efcdd16 100644
--- a/src/commands/temp.rs
+++ b/src/commands/temp.rs
@@ -1,3 +1,4 @@
+use crate::commands::core::get_fetcher;
use crate::common::shell::{self, ShellSpawnError};
use crate::finder::structures::Opts as FinderOpts;
use crate::parser::Parser;
@@ -8,7 +9,7 @@ pub fn main() -> Result<()> {
let config = &CONFIG;
let _opts = FinderOpts::snippet_default();
- let fetcher = config.fetcher();
+ let fetcher = get_fetcher()?;
let hash: u64 = 2087294461664323320;
let mut buf = vec![];
@@ -50,7 +51,7 @@ pub fn main() -> Result<()> {
pub fn _main0() -> Result<()> {
let config = &CONFIG;
- let fetcher = config.fetcher();
+ let fetcher = get_fetcher()?;
let mut stdout = io::stdout();
let mut writer: Box<&mut dyn Write> = Box::new(&mut stdout);
diff --git a/src/config/mod.rs b/src/config/mod.rs
index 43f97ca..1126b05 100644
--- a/src/config/mod.rs
+++ b/src/config/mod.rs
@@ -2,15 +2,8 @@ mod cli;
mod env;
mod yaml;
-use crate::clients::cheatsh;
-use crate::clients::tldr;
-
use crate::commands::func::Func;
-use crate::config::Source;
-use crate::filesystem;
use crate::finder::FinderChoice;
-use crate::structures::fetcher::Fetcher;
-use crate::welcome;
pub use cli::*;
use crossterm::style::Color;
use env::EnvConfig;
@@ -62,15 +55,6 @@ impl Config {
}
}
- pub fn fetcher(&self) -> Box<dyn Fetcher> {
- match self.source() {
- Source::Cheats(query) => Box::new(cheatsh::Fetcher::new(query)),
- Source::Tldr(query) => Box::new(tldr::Fetcher::new(query)),
- Source::Filesystem(path) => Box::new(filesystem::Fetcher::new(path)),
- Source::Welcome => Box::new(welcome::Fetcher::new()),
- }
- }
-
pub fn path(&self) -> Option<String> {
self.clap
.path
diff --git a/src/structures/fetcher.rs b/src/structures/fetcher.rs
index 4488ef7..f6c8437 100644
--- a/src/structures/fetcher.rs
+++ b/src/structures/fetcher.rs
@@ -8,3 +8,20 @@ pub trait Fetcher {
vec![]
}
}
+
+pub struct StaticFetcher {
+ lines: Vec<String>,
+}
+
+impl StaticFetcher {
+ pub fn new(lines: Vec<String>) -> Self {
+ Self { lines }
+ }
+}
+
+impl Fetcher for StaticFetcher {
+ fn fetch(&self, parser: &mut Parser) -> Result<bool> {
+ parser.read_lines(self.lines.clone().into_iter().map(Ok), "static", None)?;
+ Ok(true)
+ }
+}
diff --git a/src/welcome.rs b/src/welcome.rs
index 62e41bc..bf3e618 100644
--- a/src/welcome.rs
+++ b/src/welcome.rs
@@ -4,12 +4,9 @@ use crate::structures::fetcher;
pub fn populate_cheatsheet(parser: &mut Parser) -> Result<()> {
let cheatsheet = include_str!("../docs/navi.cheat");
+ let lines = cheatsheet.split('\n').into_iter().map(|s| Ok(s.to_string()));
- parser.read_lines(
- cheatsheet.split('\n').into_iter().map(|s| Ok(s.to_string())),
- "welcome",
- None,
- )?;
+ parser.read_lines(lines, "welcome", None)?;
Ok(())
}