mirror of
https://github.com/denisidoro/navi
synced 2024-11-25 13:00:20 +00:00
Add navi repo browse
(#280)
This commit is contained in:
parent
cc8982f014
commit
0b91a374fe
10 changed files with 84 additions and 21 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -245,7 +245,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[[package]]
|
||||
name = "navi"
|
||||
version = "2.1.3"
|
||||
version = "2.1.4"
|
||||
dependencies = [
|
||||
"dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"git2 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "navi"
|
||||
version = "2.1.3"
|
||||
version = "2.1.4"
|
||||
authors = ["Denis Isidoro <denis_isidoro@live.com>"]
|
||||
edition = "2018"
|
||||
description = "An interactive cheatsheet tool for the command-line"
|
||||
|
|
|
@ -91,16 +91,11 @@ fn prompt_with_suggestions(
|
|||
..Default::default()
|
||||
};
|
||||
|
||||
let mut column: Option<u8> = None;
|
||||
let mut delimiter = r"\s\s+";
|
||||
|
||||
if let Some(o) = &suggestion_options {
|
||||
opts.suggestion_type = o.suggestion_type;
|
||||
opts.header_lines = o.header_lines;
|
||||
column = o.column;
|
||||
if let Some(d) = o.delimiter.as_ref() {
|
||||
delimiter = d.as_str();
|
||||
}
|
||||
opts.column = o.column;
|
||||
opts.delimiter = o.delimiter.as_deref();
|
||||
};
|
||||
|
||||
let (output, _) = fzf::call(opts, |stdin| {
|
||||
|
@ -108,16 +103,7 @@ fn prompt_with_suggestions(
|
|||
None
|
||||
});
|
||||
|
||||
if let Some(c) = column {
|
||||
let re = regex::Regex::new(delimiter).unwrap();
|
||||
let mut parts = re.split(output.as_str());
|
||||
for _ in 0..(c - 1) {
|
||||
parts.next().unwrap();
|
||||
}
|
||||
parts.next().unwrap().to_string()
|
||||
} else {
|
||||
output
|
||||
}
|
||||
output
|
||||
}
|
||||
|
||||
fn prompt_without_suggestions(variable_name: &str) -> String {
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use crate::handler;
|
||||
use crate::option;
|
||||
use std::error::Error;
|
||||
use std::process::Command;
|
||||
|
||||
|
@ -13,6 +15,11 @@ pub fn main(func: String, args: Vec<String>) -> Result<(), Box<dyn Error>> {
|
|||
.unwrap();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
"welcome" => handler::handle_config(option::config_from_iter(
|
||||
"navi --path /tmp/irrelevant".split(' ').collect(),
|
||||
)),
|
||||
|
||||
_ => unreachable!(""),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,11 +8,42 @@ use std::fs;
|
|||
use std::io::Write;
|
||||
use walkdir::WalkDir;
|
||||
|
||||
pub fn browse() -> Result<(), Box<dyn Error>> {
|
||||
let repo_path_str = format!("{}/featured", filesystem::tmp_path_str());
|
||||
|
||||
filesystem::remove_dir(&repo_path_str);
|
||||
filesystem::create_dir(&repo_path_str);
|
||||
|
||||
match Repository::clone("https://github.com/denisidoro/cheats", &repo_path_str) {
|
||||
Ok(r) => r,
|
||||
Err(e) => panic!("failed to clone: {}", e),
|
||||
};
|
||||
|
||||
let repos = fs::read_to_string(format!("{}/featured_repos.txt", &repo_path_str))
|
||||
.expect("Unable to fetch featured repos");
|
||||
|
||||
let opts = fzf::Opts {
|
||||
column: Some(1),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let (repo, _) = fzf::call(opts, |stdin| {
|
||||
stdin
|
||||
.write_all(repos.as_bytes())
|
||||
.expect("Unable to prompt featured repos");
|
||||
None
|
||||
});
|
||||
|
||||
filesystem::remove_dir(&repo_path_str);
|
||||
|
||||
add(repo)
|
||||
}
|
||||
|
||||
pub fn add(uri: String) -> Result<(), Box<dyn Error>> {
|
||||
let (actual_uri, user, repo) = git::meta(uri.as_str());
|
||||
|
||||
let cheat_path_str = filesystem::pathbuf_to_string(filesystem::cheat_pathbuf().unwrap());
|
||||
let tmp_path_str = format!("{}/tmp", cheat_path_str);
|
||||
let tmp_path_str = filesystem::tmp_path_str();
|
||||
let tmp_path_str_with_trailing_slash = format!("{}/", &tmp_path_str);
|
||||
|
||||
filesystem::remove_dir(&tmp_path_str);
|
||||
|
|
|
@ -83,3 +83,8 @@ pub fn create_dir(path: &str) {
|
|||
pub fn remove_dir(path: &str) {
|
||||
fs::remove_dir_all(path).unwrap_or(());
|
||||
}
|
||||
|
||||
pub fn tmp_path_str() -> String {
|
||||
let cheat_path_str = pathbuf_to_string(cheat_pathbuf().unwrap());
|
||||
format!("{}/tmp", cheat_path_str)
|
||||
}
|
||||
|
|
27
src/fzf.rs
27
src/fzf.rs
|
@ -16,6 +16,8 @@ pub struct Opts<'a> {
|
|||
pub header_lines: u8,
|
||||
pub header: Option<String>,
|
||||
pub suggestion_type: SuggestionType,
|
||||
pub delimiter: Option<&'a str>,
|
||||
pub column: Option<u8>,
|
||||
}
|
||||
|
||||
impl Default for Opts<'_> {
|
||||
|
@ -30,10 +32,25 @@ impl Default for Opts<'_> {
|
|||
header: None,
|
||||
prompt: None,
|
||||
suggestion_type: SingleSelection,
|
||||
column: None,
|
||||
delimiter: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_column(text: String, column: Option<u8>, delimiter: Option<&str>) -> String {
|
||||
if let Some(c) = column {
|
||||
let re = regex::Regex::new(delimiter.unwrap_or(r"\s\s+")).unwrap();
|
||||
let mut parts = re.split(text.as_str());
|
||||
for _ in 0..(c - 1) {
|
||||
parts.next().unwrap();
|
||||
}
|
||||
parts.next().unwrap().to_string()
|
||||
} else {
|
||||
text
|
||||
}
|
||||
}
|
||||
|
||||
pub fn call<F>(opts: Opts, stdin_fn: F) -> (String, Option<HashMap<String, cheat::Suggestion>>)
|
||||
where
|
||||
F: Fn(&mut process::ChildStdin) -> Option<HashMap<String, cheat::Suggestion>>,
|
||||
|
@ -134,7 +151,15 @@ where
|
|||
panic!("External command failed:\n {}", err)
|
||||
}
|
||||
};
|
||||
(parse_output_single(text, opts.suggestion_type), result)
|
||||
|
||||
(
|
||||
get_column(
|
||||
parse_output_single(text, opts.suggestion_type),
|
||||
opts.column,
|
||||
opts.delimiter,
|
||||
),
|
||||
result,
|
||||
)
|
||||
}
|
||||
|
||||
fn parse_output_single(mut text: String, suggestion_type: SuggestionType) -> String {
|
||||
|
|
|
@ -15,6 +15,7 @@ pub fn handle_config(mut config: Config) -> Result<(), Box<dyn Error>> {
|
|||
Fn { func, args } => cmds::func::main(func.clone(), args.to_vec()),
|
||||
Repo { cmd } => match cmd {
|
||||
RepoCommand::Add { uri } => cmds::repo::add(uri.clone()),
|
||||
RepoCommand::Browse => cmds::repo::browse(),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -92,6 +92,8 @@ pub enum RepoCommand {
|
|||
/// A URI to a git repository containing .cheat files ("user/repo" will download cheats from github.com/user/repo)
|
||||
uri: String,
|
||||
},
|
||||
/// Browses for featured cheatsheet repos
|
||||
Browse,
|
||||
}
|
||||
|
||||
pub enum InternalCommand {
|
||||
|
|
|
@ -14,5 +14,11 @@ pub fn cheatsheet(stdin: &mut std::process::ChildStdin) {
|
|||
"navi repo add denisidoro/cheats",
|
||||
stdin,
|
||||
);
|
||||
add_msg(
|
||||
"cheatsheets",
|
||||
"Browse for cheatsheet repos",
|
||||
"navi repo browse",
|
||||
stdin,
|
||||
);
|
||||
add_msg("more info", "Read --help message", "navi --help", stdin);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue