mirror of
https://github.com/denisidoro/navi
synced 2024-11-21 19:13:07 +00:00
parent
d68c4437a1
commit
8b78d54863
7 changed files with 98 additions and 114 deletions
|
@ -1,26 +1,22 @@
|
||||||
use crate::parser::Parser;
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use std::process::Command;
|
||||||
use crate::structures::fetcher;
|
|
||||||
use std::process::{self, Command};
|
|
||||||
|
|
||||||
fn map_line(line: &str) -> String {
|
fn map_line(line: &str) -> String {
|
||||||
line.trim().trim_end_matches(':').to_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!(
|
format!(
|
||||||
"% {}, cheat.sh
|
"% {}, cheat.sh
|
||||||
{}",
|
{}",
|
||||||
query, markdown
|
query, markdown
|
||||||
)
|
)
|
||||||
.lines()
|
.lines()
|
||||||
.map(|line| Ok(map_line(line)))
|
.map(map_line)
|
||||||
.collect::<Vec<Result<String>>>()
|
.collect()
|
||||||
.into_iter()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fetch(query: &str) -> Result<String> {
|
pub fn call(query: &str) -> Result<Vec<String>> {
|
||||||
let args = ["-qO-", &format!("cheat.sh/{}", query)];
|
let args = ["-qO-", &format!("cheat.sh/{}", query)];
|
||||||
|
|
||||||
let child = Command::new("wget")
|
let child = Command::new("wget")
|
||||||
|
@ -32,19 +28,34 @@ pub fn fetch(query: &str) -> Result<String> {
|
||||||
let child = match child {
|
let child = match child {
|
||||||
Ok(x) => x,
|
Ok(x) => x,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
eprintln!(
|
let msg = "navi was unable to call wget.
|
||||||
"navi was unable to call wget.
|
Make sure wget is correctly installed.";
|
||||||
Make sure wget is correctly installed."
|
return Err(anyhow!(msg));
|
||||||
);
|
|
||||||
process::exit(34)
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let out = child.wait_with_output().context("Failed to wait for wget")?;
|
let out = child.wait_with_output().context("Failed to wait for wget")?;
|
||||||
|
|
||||||
if let Some(0) = out.status.code() {
|
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 {
|
} else {
|
||||||
eprintln!(
|
let msg = format!(
|
||||||
"Failed to call:
|
"Failed to call:
|
||||||
wget {}
|
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.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())
|
String::from_utf8(out.stderr).unwrap_or_else(|_e| "Unable to get error message".to_string())
|
||||||
);
|
);
|
||||||
process::exit(35)
|
Err(anyhow!(msg))
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
use crate::parser::Parser;
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::structures::fetcher;
|
|
||||||
use std::process::{self, Command, Stdio};
|
use std::process::{self, Command, Stdio};
|
||||||
|
|
||||||
lazy_static! {
|
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!(
|
format!(
|
||||||
"% {}, tldr
|
"% {}, tldr
|
||||||
{}",
|
{}",
|
||||||
query, markdown
|
query, markdown
|
||||||
)
|
)
|
||||||
.lines()
|
.lines()
|
||||||
.map(|line| Ok(convert_tldr(line)))
|
.map(convert_tldr)
|
||||||
.collect::<Vec<Result<String>>>()
|
.collect()
|
||||||
.into_iter()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fetch(query: &str) -> Result<String> {
|
pub fn call(query: &str) -> Result<Vec<String>> {
|
||||||
let args = [query, "--markdown"];
|
let args = [query, "--markdown"];
|
||||||
|
|
||||||
let child = Command::new("tldr")
|
let child = Command::new("tldr")
|
||||||
|
@ -67,7 +64,7 @@ pub fn fetch(query: &str) -> Result<String> {
|
||||||
let child = match child {
|
let child = match child {
|
||||||
Ok(x) => x,
|
Ok(x) => x,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
eprintln!(
|
let msg = format!(
|
||||||
"navi was unable to call tldr.
|
"navi was unable to call tldr.
|
||||||
Make sure tldr is correctly installed.
|
Make sure tldr is correctly installed.
|
||||||
Refer to https://github.com/tldr-pages/tldr for more info.
|
Refer to https://github.com/tldr-pages/tldr for more info.
|
||||||
|
@ -77,15 +74,20 @@ Note:
|
||||||
",
|
",
|
||||||
VERSION_DISCLAIMER
|
VERSION_DISCLAIMER
|
||||||
);
|
);
|
||||||
process::exit(34)
|
return Err(anyhow!(msg));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let out = child.wait_with_output().context("Failed to wait for tldr")?;
|
let out = child.wait_with_output().context("Failed to wait for tldr")?;
|
||||||
|
|
||||||
if let Some(0) = out.status.code() {
|
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 {
|
} else {
|
||||||
eprintln!(
|
let msg = format!(
|
||||||
"Failed to call:
|
"Failed to call:
|
||||||
tldr {}
|
tldr {}
|
||||||
|
|
||||||
|
@ -103,30 +105,8 @@ If you are already using a supported version you can ignore this message.
|
||||||
args.join(" "),
|
args.join(" "),
|
||||||
String::from_utf8(out.stdout).unwrap_or_else(|_e| "Unable to get output message".to_string()),
|
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()),
|
String::from_utf8(out.stderr).unwrap_or_else(|_e| "Unable to get error message".to_string()),
|
||||||
VERSION_DISCLAIMER
|
VERSION_DISCLAIMER,
|
||||||
);
|
);
|
||||||
process::exit(35)
|
Err(anyhow!(msg))
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,23 @@
|
||||||
mod actor;
|
mod actor;
|
||||||
mod extractor;
|
mod extractor;
|
||||||
|
|
||||||
|
use crate::clients::cheatsh;
|
||||||
|
use crate::config::Source;
|
||||||
|
use crate::filesystem;
|
||||||
use crate::finder::structures::Opts as FinderOpts;
|
use crate::finder::structures::Opts as FinderOpts;
|
||||||
use crate::parser::Parser;
|
use crate::parser::Parser;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use crate::structures::fetcher::{Fetcher, StaticFetcher};
|
||||||
use crate::welcome;
|
use crate::welcome;
|
||||||
|
|
||||||
pub fn main() -> Result<()> {
|
pub fn init(fetcher: Box<dyn Fetcher>) -> Result<()> {
|
||||||
let config = &CONFIG;
|
let config = &CONFIG;
|
||||||
let opts = FinderOpts::snippet_default();
|
let opts = FinderOpts::snippet_default();
|
||||||
|
// let fetcher = config.fetcher();
|
||||||
|
|
||||||
let (raw_selection, (variables, files)) = config
|
let (raw_selection, (variables, files)) = config
|
||||||
.finder()
|
.finder()
|
||||||
.call(opts, |writer| {
|
.call(opts, |writer| {
|
||||||
let fetcher = config.fetcher();
|
|
||||||
|
|
||||||
let mut parser = Parser::new(writer, true);
|
let mut parser = Parser::new(writer, true);
|
||||||
|
|
||||||
let found_something = fetcher
|
let found_something = fetcher
|
||||||
|
@ -32,10 +35,38 @@ pub fn main() -> Result<()> {
|
||||||
let extractions = extractor::extract_from_selections(&raw_selection, config.best_match());
|
let extractions = extractor::extract_from_selections(&raw_selection, config.best_match());
|
||||||
|
|
||||||
if extractions.is_err() {
|
if extractions.is_err() {
|
||||||
return main();
|
return init(fetcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
actor::act(extractions, files, variables)?;
|
actor::act(extractions, files, variables)?;
|
||||||
|
|
||||||
Ok(())
|
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)
|
||||||
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::commands::core::get_fetcher;
|
||||||
use crate::common::shell::{self, ShellSpawnError};
|
use crate::common::shell::{self, ShellSpawnError};
|
||||||
use crate::finder::structures::Opts as FinderOpts;
|
use crate::finder::structures::Opts as FinderOpts;
|
||||||
use crate::parser::Parser;
|
use crate::parser::Parser;
|
||||||
|
@ -8,7 +9,7 @@ pub fn main() -> Result<()> {
|
||||||
let config = &CONFIG;
|
let config = &CONFIG;
|
||||||
let _opts = FinderOpts::snippet_default();
|
let _opts = FinderOpts::snippet_default();
|
||||||
|
|
||||||
let fetcher = config.fetcher();
|
let fetcher = get_fetcher()?;
|
||||||
let hash: u64 = 2087294461664323320;
|
let hash: u64 = 2087294461664323320;
|
||||||
|
|
||||||
let mut buf = vec![];
|
let mut buf = vec![];
|
||||||
|
@ -50,7 +51,7 @@ pub fn main() -> Result<()> {
|
||||||
pub fn _main0() -> Result<()> {
|
pub fn _main0() -> Result<()> {
|
||||||
let config = &CONFIG;
|
let config = &CONFIG;
|
||||||
|
|
||||||
let fetcher = config.fetcher();
|
let fetcher = get_fetcher()?;
|
||||||
|
|
||||||
let mut stdout = io::stdout();
|
let mut stdout = io::stdout();
|
||||||
let mut writer: Box<&mut dyn Write> = Box::new(&mut stdout);
|
let mut writer: Box<&mut dyn Write> = Box::new(&mut stdout);
|
||||||
|
|
|
@ -2,15 +2,8 @@ mod cli;
|
||||||
mod env;
|
mod env;
|
||||||
mod yaml;
|
mod yaml;
|
||||||
|
|
||||||
use crate::clients::cheatsh;
|
|
||||||
use crate::clients::tldr;
|
|
||||||
|
|
||||||
use crate::commands::func::Func;
|
use crate::commands::func::Func;
|
||||||
use crate::config::Source;
|
|
||||||
use crate::filesystem;
|
|
||||||
use crate::finder::FinderChoice;
|
use crate::finder::FinderChoice;
|
||||||
use crate::structures::fetcher::Fetcher;
|
|
||||||
use crate::welcome;
|
|
||||||
pub use cli::*;
|
pub use cli::*;
|
||||||
use crossterm::style::Color;
|
use crossterm::style::Color;
|
||||||
use env::EnvConfig;
|
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> {
|
pub fn path(&self) -> Option<String> {
|
||||||
self.clap
|
self.clap
|
||||||
.path
|
.path
|
||||||
|
|
|
@ -8,3 +8,20 @@ pub trait Fetcher {
|
||||||
vec![]
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -4,12 +4,9 @@ use crate::structures::fetcher;
|
||||||
|
|
||||||
pub fn populate_cheatsheet(parser: &mut Parser) -> Result<()> {
|
pub fn populate_cheatsheet(parser: &mut Parser) -> Result<()> {
|
||||||
let cheatsheet = include_str!("../docs/navi.cheat");
|
let cheatsheet = include_str!("../docs/navi.cheat");
|
||||||
|
let lines = cheatsheet.split('\n').into_iter().map(|s| Ok(s.to_string()));
|
||||||
|
|
||||||
parser.read_lines(
|
parser.read_lines(lines, "welcome", None)?;
|
||||||
cheatsheet.split('\n').into_iter().map(|s| Ok(s.to_string())),
|
|
||||||
"welcome",
|
|
||||||
None,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue