Skip to content

Commit

Permalink
Minor fixes (#285)
Browse files Browse the repository at this point in the history
  • Loading branch information
denisidoro authored Mar 18, 2020
1 parent a08f3cd commit a0bba94
Show file tree
Hide file tree
Showing 8 changed files with 141 additions and 103 deletions.
98 changes: 65 additions & 33 deletions src/cheat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,36 @@ pub struct SuggestionOpts {

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum SuggestionType {
/// fzf will not print any suggestions.
/// fzf will not print any suggestions
Disabled,
/// fzf will only select one of the suggestions
SingleSelection,
/// fzf will select multiple ones of the suggestions
/// fzf will select multiple suggestions
MultipleSelections,
/// fzf will select one of the suggestions or use the Query
/// fzf will select one of the suggestions or use the query
SingleRecommendation,
/// initial snippet selection
SnippetSelection,
}

pub type Suggestion = (String, Option<SuggestionOpts>);

pub struct VariableMap(HashMap<u64, Suggestion>);

impl VariableMap {
pub fn new() -> Self {
Self(HashMap::new())
}

pub fn insert(&mut self, tags: &str, variable: &str, value: Suggestion) -> Option<Suggestion> {
self.0.insert(gen_key(tags, variable), value)
}

pub fn get(&self, tags: &str, variable: &str) -> Option<&Suggestion> {
self.0.get(&gen_key(tags, variable))
}
}

fn remove_quotes(txt: &str) -> String {
txt.replace('"', "").replace('\'', "")
}
Expand Down Expand Up @@ -95,33 +111,36 @@ fn write_cmd(
} else {
stdin
.write_all(
display::format_line(
&tags[..],
&comment[..],
&snippet[3..],
tag_width,
comment_width,
)
.as_bytes(),
display::format_line(&tags, &comment, &snippet, tag_width, comment_width)
.as_bytes(),
)
.is_ok()
}
}

fn gen_key(tags: &str, variable: &str) -> u64 {
format!("{};{}", tags, variable).hash_line()
}

fn read_file(
path: &str,
variables: &mut HashMap<String, Suggestion>,
variables: &mut VariableMap,
stdin: &mut std::process::ChildStdin,
set: &mut HashSet<u64>,
) -> bool {
let mut tags = String::from("");
let mut comment = String::from("");
let mut snippet = String::from("");
let mut should_break = false;

let (tag_width, comment_width) = *display::WIDTHS;

if let Ok(lines) = filesystem::read_lines(path) {
for l in lines {
if should_break {
break;
}

let line = l.unwrap();
let hash = line.hash_line();
if set.contains(&hash) {
Expand All @@ -135,7 +154,7 @@ fn read_file(
// tag
else if line.starts_with('%') {
if !write_cmd(&tags, &comment, &snippet, tag_width, comment_width, stdin) {
break;
should_break = true
}
snippet = String::from("");
tags = String::from(&line[2..]);
Expand All @@ -146,41 +165,43 @@ fn read_file(
// comment
else if line.starts_with('#') {
if !write_cmd(&tags, &comment, &snippet, tag_width, comment_width, stdin) {
break;
should_break = true
}
snippet = String::from("");
comment = String::from(&line[2..]);
}
// variable
else if line.starts_with('$') {
if !write_cmd(&tags, &comment, &snippet, tag_width, comment_width, stdin) {
break;
should_break = true
}
snippet = String::from("");
let (variable, command, opts) = parse_variable_line(&line);
variables.insert(
format!("{};{}", tags, variable),
(String::from(command), opts),
);
variables.insert(&tags, &variable, (String::from(command), opts));
}
// snippet
// first snippet line
else if (&snippet).is_empty() {
snippet.push_str(&line);
}
// other snippet lines
else {
snippet.push_str(display::LINE_SEPARATOR);
snippet.push_str(&line);
}
}

if !should_break {
write_cmd(&tags, &comment, &snippet, tag_width, comment_width, stdin);
}

return true;
}

false
}

pub fn read_all(
config: &Config,
stdin: &mut std::process::ChildStdin,
) -> HashMap<String, Suggestion> {
let mut variables: HashMap<String, Suggestion> = HashMap::new();
pub fn read_all(config: &Config, stdin: &mut std::process::ChildStdin) -> VariableMap {
let mut variables = VariableMap::new();
let mut found_something = false;
let paths = filesystem::cheat_paths(config);
let folders = paths.split(':');
Expand Down Expand Up @@ -233,23 +254,34 @@ mod tests {
#[test]
fn test_read_file() {
let path = "tests/cheats/ssh.cheat";
let mut variables: HashMap<String, Suggestion> = HashMap::new();
let mut variables = VariableMap::new();
let mut child = Command::new("cat").stdin(Stdio::piped()).spawn().unwrap();
let child_stdin = child.stdin.as_mut().unwrap();
read_file(path, &mut variables, child_stdin);
let mut result: HashMap<String, (String, std::option::Option<_>)> = HashMap::new();
result.insert(
"ssh;user".to_string(),
(
let mut set: HashSet<u64> = HashSet::new();
read_file(path, &mut variables, child_stdin, &mut set);
let mut result = VariableMap::new();
let suggestion = (
r#" echo -e "$(whoami)\nroot" "#.to_string(),
Some(SuggestionOpts {
header_lines: 0,
column: None,
delimiter: None,
suggestion_type: SuggestionType::SingleRecommendation,
}),
);
result.insert("ssh", "user", suggestion);
let actual_suggestion = result.get("ssh", "user");
assert_eq!(
Some(&(
r#" echo -e "$(whoami)\nroot" "#.to_string(),
Some(SuggestionOpts {
header_lines: 0,
column: None,
delimiter: None,
suggestion_type: SuggestionType::SingleRecommendation,
}),
),
)),
actual_suggestion
);
assert_eq!(variables, result);
}
}
43 changes: 17 additions & 26 deletions src/cmds/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,18 +119,10 @@ fn prompt_without_suggestions(variable_name: &str) -> String {
output
}

fn gen_replacement(value: &str) -> String {
if value.contains(' ') {
format!("\"{}\"", value)
} else {
value.to_string()
}
}

fn replace_variables_from_snippet(
snippet: &str,
tags: &str,
variables: HashMap<String, cheat::Suggestion>,
variables: cheat::VariableMap,
config: &Config,
) -> String {
let mut interpolated_snippet = String::from(snippet);
Expand All @@ -141,23 +133,22 @@ fn replace_variables_from_snippet(
let bracketed_variable_name = &captures[0];
let variable_name = &bracketed_variable_name[1..bracketed_variable_name.len() - 1];

if values.get(variable_name).is_none() {
let key = format!("{};{}", tags, variable_name);

let value = match variables.get(&key[..]) {
Some(suggestion) => {
prompt_with_suggestions(variable_name, &config, suggestion, &values)
}
None => prompt_without_suggestions(variable_name),
};

values.insert(variable_name.to_string(), value.clone());

interpolated_snippet = interpolated_snippet.replace(
bracketed_variable_name,
gen_replacement(&value[..]).as_str(),
);
}
let value = values
.get(variable_name)
.map(|s| s.to_string())
.unwrap_or_else(|| {
variables
.get(&tags, &variable_name)
.map(|suggestion| {
prompt_with_suggestions(variable_name, &config, suggestion, &values)
})
.unwrap_or_else(|| prompt_without_suggestions(variable_name))
});

values.insert(variable_name.to_string(), value.clone());

interpolated_snippet =
interpolated_snippet.replacen(bracketed_variable_name, value.as_str(), 1);
}

interpolated_snippet
Expand Down
4 changes: 2 additions & 2 deletions src/cmds/preview.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ fn extract_elements(argstr: &str) -> (&str, &str, &str) {
(tags, comment, snippet)
}

pub fn main(line: String) -> Result<(), Box<dyn Error>> {
let (tags, comment, snippet) = extract_elements(&line[..]);
pub fn main(line: &str) -> Result<(), Box<dyn Error>> {
let (tags, comment, snippet) = extract_elements(line);
display::preview(comment, tags, snippet);
process::exit(0)
}
5 changes: 2 additions & 3 deletions src/fzf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use crate::cheat;
use crate::cheat::SuggestionType;
use crate::cheat::SuggestionType::SingleSelection;
use crate::display;
use std::collections::HashMap;
use std::process;
use std::process::{Command, Stdio};

Expand Down Expand Up @@ -51,9 +50,9 @@ fn get_column(text: String, column: Option<u8>, delimiter: Option<&str>) -> Stri
}
}

pub fn call<F>(opts: Opts, stdin_fn: F) -> (String, Option<HashMap<String, cheat::Suggestion>>)
pub fn call<F>(opts: Opts, stdin_fn: F) -> (String, Option<cheat::VariableMap>)
where
F: Fn(&mut process::ChildStdin) -> Option<HashMap<String, cheat::Suggestion>>,
F: Fn(&mut process::ChildStdin) -> Option<cheat::VariableMap>,
{
let mut fzf_command = Command::new("fzf");

Expand Down
11 changes: 3 additions & 8 deletions src/handler.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
use crate::cmds;
use crate::cmds::core::Variant;
use crate::option::Command::{Best, Fn, Query, Repo, Search, Widget};
use crate::option::{Config, InternalCommand, RepoCommand};
use crate::option::Command::{Best, Fn, Preview, Query, Repo, Search, Widget};
use crate::option::{Config, RepoCommand};
use std::error::Error;

pub fn handle_config(mut config: Config) -> Result<(), Box<dyn Error>> {
match config.cmd.as_mut() {
None => cmds::core::main(Variant::Core, config, true),
Some(c) => match c {
Preview { line } => cmds::preview::main(&line[..]),
Query { query } => cmds::query::main(query.clone(), config),
Best { query, args } => cmds::best::main(query.clone(), args.to_vec(), config),
Search { query } => cmds::search::main(query.clone(), config),
Expand All @@ -20,9 +21,3 @@ pub fn handle_config(mut config: Config) -> Result<(), Box<dyn Error>> {
},
}
}

pub fn handle_internal_command(cmd: InternalCommand) -> Result<(), Box<dyn Error>> {
match cmd {
InternalCommand::Preview { line } => cmds::preview::main(line),
}
}
7 changes: 1 addition & 6 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,5 @@ mod welcome;
use std::error::Error;

fn main() -> Result<(), Box<dyn Error>> {
let internal_cmd = option::internal_command_from_env();
if let Some(cmd) = internal_cmd {
handler::handle_internal_command(cmd)
} else {
handler::handle_config(option::config_from_env())
}
handler::handle_config(option::config_from_env())
}
26 changes: 8 additions & 18 deletions src/option.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use std::env;
use structopt::StructOpt;
use structopt::{clap::AppSettings, StructOpt};

#[derive(Debug, StructOpt)]
#[structopt(after_help = r#"EXAMPLES:
Expand All @@ -14,6 +13,7 @@ use structopt::StructOpt;
navi --fzf-overrides ' --with-nth 1,2' # shows only the comment and tag columns
navi --fzf-overrides ' --nth 1,2' # search will consider only the first two columns
navi --fzf-overrides ' --no-exact' # looser search algorithm"#)]
#[structopt(setting = AppSettings::AllowLeadingHyphen)]
pub struct Config {
/// List of :-separated paths containing .cheat files
#[structopt(short, long, env = "NAVI_PATH")]
Expand Down Expand Up @@ -78,6 +78,12 @@ pub enum Command {
#[structopt(subcommand)]
cmd: RepoCommand,
},
/// Used for fzf's preview window
#[structopt(setting = AppSettings::Hidden)]
Preview {
/// Selection line
line: String,
},
/// Shows the path for shell widget files
Widget {
/// bash, zsh or fish
Expand All @@ -96,26 +102,10 @@ pub enum RepoCommand {
Browse,
}

pub enum InternalCommand {
Preview { line: String },
}

pub fn config_from_env() -> Config {
Config::from_args()
}

pub fn config_from_iter(args: Vec<&str>) -> Config {
Config::from_iter(args)
}

pub fn internal_command_from_env() -> Option<InternalCommand> {
let mut args = env::args();
args.next();
if args.next() == Some(String::from("preview")) {
Some(InternalCommand::Preview {
line: args.next().unwrap(),
})
} else {
None
}
}
Loading

0 comments on commit a0bba94

Please sign in to comment.