add --allow-extra option

This commit is contained in:
Ingolf Wagner 2020-03-14 16:09:09 +08:00
parent 8669ba9829
commit 0a22398a47
No known key found for this signature in database
GPG key ID: 76BF5F1928B9618B
4 changed files with 110 additions and 27 deletions

View file

@ -7,6 +7,7 @@ use std::collections::HashMap;
use std::fs;
use std::io::Write;
#[derive(Debug, PartialEq)]
pub struct SuggestionOpts {
pub header_lines: u8,
pub column: Option<u8>,
@ -14,7 +15,7 @@ pub struct SuggestionOpts {
pub suggestion_type : SuggestionType,
}
#[derive(PartialEq)]
#[derive(Clone,Copy,Debug,PartialEq)]
pub enum SuggestionType {
Disabled,
SingleSelection,
@ -41,6 +42,7 @@ fn parse_opts(text: &str) -> SuggestionOpts {
let mut header_lines: u8 = 0;
let mut column: Option<u8> = None;
let mut multi = false;
let mut allow_extra = false;
let mut delimiter: Option<String> = None;
let mut parts = text.split(' ');
@ -48,6 +50,7 @@ fn parse_opts(text: &str) -> SuggestionOpts {
while let Some(p) = parts.next() {
match p {
"--multi" => multi = true,
"--allow-extra" => allow_extra = true,
"--header" | "--headers" | "--header-lines" => {
header_lines = remove_quote(parts.next().unwrap()).parse::<u8>().unwrap()
}
@ -57,12 +60,18 @@ fn parse_opts(text: &str) -> SuggestionOpts {
}
}
SuggestionOpts {
let result = SuggestionOpts {
header_lines,
column,
delimiter,
suggestion_type: if multi { SuggestionType::MultipleSelections } else { SuggestionType::SingleSelection},
}
suggestion_type: match (multi, allow_extra) {
(true,_) => SuggestionType::MultipleSelections , // multi wins over allow-extra
(false,true) => SuggestionType::SingleRecommendation,
(false,false) => SuggestionType::SingleSelection
},
};
result
}
fn parse_variable_line(line: &str) -> (&str, &str, Option<SuggestionOpts>) {
@ -70,12 +79,10 @@ fn parse_variable_line(line: &str) -> (&str, &str, Option<SuggestionOpts>) {
let caps = re.captures(line).unwrap();
let variable = caps.get(1).unwrap().as_str().trim();
let mut command_plus_opts = caps.get(2).unwrap().as_str().split("---");
let command = command_plus_opts.next().unwrap();
let opts = match command_plus_opts.next() {
Some(o) => Some(parse_opts(o)),
None => None,
};
(variable, command, opts)
let command : &str = command_plus_opts.next().unwrap();
let command_option_string : Option<&str>= command_plus_opts.next();
let command_options = command_option_string.map(parse_opts);
(variable, command, command_options)
}
fn read_file(
@ -106,7 +113,7 @@ fn read_file(
}
// variable
else if line.starts_with('$') {
let (variable, command, opts) = parse_variable_line(&line[..]);
let (variable, command, opts) = parse_variable_line(&line);
variables.insert(
format!("{};{}", tags, variable),
(String::from(command), opts),
@ -170,3 +177,46 @@ pub fn read_all(config: &Config, stdin: &mut std::process::ChildStdin) -> HashMa
variables
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_variable_line() {
let( variable, command, command_options ) = parse_variable_line("$ user : echo -e \"$(whoami)\\nroot\" --- --allow-extra" );
assert_eq!(command, " echo -e \"$(whoami)\\nroot\" ");
assert_eq!(variable, "user");
assert_eq!(command_options, Some(SuggestionOpts{
header_lines: 0,
column: None,
delimiter: None,
suggestion_type: SuggestionType::SingleRecommendation
}));
}
use std::process::{Command, Stdio};
#[test]
fn test_read_file() {
let path = "tests/cheats/ssh.cheat";
let mut variables: HashMap<String, Suggestion> = HashMap::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(),
(" echo -e \"$(whoami)\\nroot\" ".to_string(), Some(SuggestionOpts { header_lines: 0, column: None, delimiter: None, suggestion_type: SuggestionType::SingleRecommendation }))
);
assert_eq!(variables, result);
}
}

View file

@ -90,7 +90,7 @@ fn prompt_with_suggestions(
let mut delimiter = r"\s\s+";
if let Some(o) = &suggestion_options {
opts.suggestion_type = if o.suggestion_type == SuggestionType::Disabled { SuggestionType::SingleSelection} else { SuggestionType::SingleSelection};
opts.suggestion_type = o.suggestion_type;
opts.header_lines = o.header_lines;
column = o.column;
if let Some(d) = o.delimiter.as_ref() {

View file

@ -16,7 +16,6 @@ pub struct Opts<'a> {
pub autoselect: bool,
pub overrides: Option<&'a String>, // TODO: remove &'a
pub header_lines: u8,
pub copyable: bool,
pub suggestion_type : SuggestionType,
}
@ -31,7 +30,6 @@ impl Default for Opts<'_> {
overrides: None,
header_lines: 0,
prompt: None,
copyable: false,
suggestion_type: SingleSelection,
}
}
@ -68,10 +66,12 @@ where
SuggestionType::SnippetSelection =>{
fzf_command.args(&["--expect", "ctrl-y,enter"]);
}
SuggestionType::SingleRecommendation =>{
fzf_command.args(&["--print-query", "--expect", "tab,enter"]);
}
_ => {}
}
if opts.preview {
fzf_command.args(&[
"--preview",
@ -125,7 +125,7 @@ where
let out = child.wait_with_output().unwrap();
let mut text = match out.status.code() {
let text = match out.status.code() {
Some(0) | Some(1) => String::from_utf8(out.stdout).unwrap(),
Some(130) => process::exit(130),
_ => {
@ -153,13 +153,19 @@ fn parse_output_single(mut text: String, suggestion_type: SuggestionType) -> St
return text;
}
SuggestionType::SingleRecommendation => {
let lines : Vec<&str>= text.lines().collect();
match *(lines.get(1).unwrap()) {
input_string if input_string == "enter" =>
return lines.get(2).unwrap().to_string(),
_ =>
return lines.get(0).unwrap().to_string(),
}
let lines: Vec<&str> = text.lines().collect();
match (lines.get(0), lines.get(1), lines.get(2)) {
(Some(one), Some(termination), Some(two)) if *termination == "enter" =>
if two.is_empty() {
one.to_string()
} else {
two.to_string()
},
(Some(one), Some(termination), None)if *termination == "enter" => one.to_string(),
(Some(one), Some(termination), _)if *termination == "tab" => one.to_string(),
_ => "".to_string(),
}
}
}
}
@ -170,28 +176,49 @@ mod tests {
#[test]
fn test_parse_output1() {
let mut text = "palo\n".to_string();
let text = "palo\n".to_string();
let output = parse_output_single(text, SuggestionType::SingleSelection);
assert_eq!(output, "palo");
}
#[test]
fn test_parse_output2() {
let mut text = "\nenter\npalo".to_string();
let text = "\nenter\npalo".to_string();
let output = parse_output_single(text, SuggestionType::SingleRecommendation);
assert_eq!(output, "palo");
}
#[test]
fn test_parse_recommendation_output_1() {
let text = "\nenter\npalo".to_string();
let output = parse_output_single(text, SuggestionType::SingleRecommendation);
assert_eq!(output, "palo");
}
#[test]
fn test_parse_recommendation_output_2() {
let text = "p\nenter\npalo".to_string();
let output = parse_output_single(text, SuggestionType::SingleRecommendation);
assert_eq!(output, "palo");
}
#[test]
fn test_parse_recommendation_output_3() {
let text = "peter\nenter\n".to_string();
let output = parse_output_single(text, SuggestionType::SingleRecommendation);
assert_eq!(output, "peter");
}
#[test]
fn test_parse_output3() {
let mut text = "p\ntab\npalo".to_string();
let text = "p\ntab\npalo".to_string();
let output = parse_output_single(text, SuggestionType::SingleRecommendation);
assert_eq!(output, "p");
}
#[test]
fn test_parse_snippet_request() {
let mut text = "enter\nssh login to a server and forward to ssh key (d… ssh -A <user>@<server> ssh login to a server and forward to ssh key (dangerous but usefull for bastion hosts) ssh -A <user>@<server> \n".to_string();
let text = "enter\nssh login to a server and forward to ssh key (d… ssh -A <user>@<server> ssh login to a server and forward to ssh key (dangerous but usefull for bastion hosts) ssh -A <user>@<server> \n".to_string();
let output = parse_output_single(text, SuggestionType::SnippetSelection);
assert_eq!(output, "enter\nssh login to a server and forward to ssh key (d… ssh -A <user>@<server> ssh login to a server and forward to ssh key (dangerous but usefull for bastion hosts) ssh -A <user>@<server> ");
}

6
tests/cheats/ssh.cheat Normal file
View file

@ -0,0 +1,6 @@
% ssh
# login to a server with a key and port
ssh -i <sshkey> -p <port> <user>@<server>
$ user : echo -e "$(whoami)\nroot" --- --allow-extra