navi/src/cheat.rs

288 lines
8.6 KiB
Rust
Raw Normal View History

2020-03-04 21:01:23 +00:00
use crate::display;
use crate::filesystem;
use crate::fnv::HashLine;
2020-03-04 21:01:23 +00:00
use crate::option::Config;
Initial cheat repo support (#258) This PR makes navi stop bundling `.cheat` files and makes it able to download from repos on GitHub, using a standardized config directory. - it fixes #233 and #237 - it makes #52, #256 and #257 much easier to implement - it makes #40 harder to implement - it's an alternate solution to #140 - it's influenced by #238 and #254. This PR ended up being much bigger than I would like so if you could review only this description it would be already very nice! When navi is started for the first time, a welcome cheatsheet is shown: ![Screenshot at 2020-03-15 10-20-04](https://user-images.githubusercontent.com/3226564/76702240-19fffd80-66a7-11ea-884f-97c565bc1ead.png) If the user selects the first option, the user is prompted to download `.cheat`s from https://github.com/denisidoro/cheats: ![Screenshot at 2020-03-15 10-20-35](https://user-images.githubusercontent.com/3226564/76702239-19fffd80-66a7-11ea-8f69-324f669b1e01.png) ![Screenshot at 2020-03-15 10-22-59](https://user-images.githubusercontent.com/3226564/76702236-18363a00-66a7-11ea-8ff4-53b497f85888.png) The config folder is populated: ![Screenshot at 2020-03-15 10-21-11](https://user-images.githubusercontent.com/3226564/76702238-19676700-66a7-11ea-8367-3e7b5733f2b4.png) When run again, cheats are available: ![Screenshot at 2020-03-15 10-21-34](https://user-images.githubusercontent.com/3226564/76702237-19676700-66a7-11ea-9c2a-d8829340f3e9.png) ### Breaking changes In order to make navi stop bundling shell widgets as well, a breaking change has been introduced: `source $(navi widget bash)` won't work anymore. It should be `source <(navi widget bash)` now. Any ideas on how to make this transition more graceful?
2020-03-15 16:46:58 +00:00
use crate::welcome;
2020-03-04 21:01:23 +00:00
use regex::Regex;
use std::collections::{HashMap, HashSet};
2020-03-04 21:01:23 +00:00
use std::fs;
use std::io::Write;
2020-03-14 08:09:09 +00:00
#[derive(Debug, PartialEq)]
2020-03-04 21:01:23 +00:00
pub struct SuggestionOpts {
pub header_lines: u8,
pub column: Option<u8>,
2020-03-11 14:30:25 +00:00
pub delimiter: Option<String>,
2020-03-14 12:33:07 +00:00
pub suggestion_type: SuggestionType,
2020-03-04 21:01:23 +00:00
}
2020-03-14 12:33:07 +00:00
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum SuggestionType {
2020-03-18 11:38:13 +00:00
/// fzf will not print any suggestions
Disabled,
2020-03-14 12:41:28 +00:00
/// fzf will only select one of the suggestions
SingleSelection,
2020-03-18 11:38:13 +00:00
/// fzf will select multiple suggestions
MultipleSelections,
2020-03-18 11:38:13 +00:00
/// fzf will select one of the suggestions or use the query
SingleRecommendation,
2020-03-14 12:41:28 +00:00
/// initial snippet selection
SnippetSelection,
}
pub type Suggestion = (String, Option<SuggestionOpts>);
2020-03-04 21:01:23 +00:00
2020-03-18 11:38:13 +00:00
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))
}
}
Initial cheat repo support (#258) This PR makes navi stop bundling `.cheat` files and makes it able to download from repos on GitHub, using a standardized config directory. - it fixes #233 and #237 - it makes #52, #256 and #257 much easier to implement - it makes #40 harder to implement - it's an alternate solution to #140 - it's influenced by #238 and #254. This PR ended up being much bigger than I would like so if you could review only this description it would be already very nice! When navi is started for the first time, a welcome cheatsheet is shown: ![Screenshot at 2020-03-15 10-20-04](https://user-images.githubusercontent.com/3226564/76702240-19fffd80-66a7-11ea-884f-97c565bc1ead.png) If the user selects the first option, the user is prompted to download `.cheat`s from https://github.com/denisidoro/cheats: ![Screenshot at 2020-03-15 10-20-35](https://user-images.githubusercontent.com/3226564/76702239-19fffd80-66a7-11ea-8f69-324f669b1e01.png) ![Screenshot at 2020-03-15 10-22-59](https://user-images.githubusercontent.com/3226564/76702236-18363a00-66a7-11ea-8ff4-53b497f85888.png) The config folder is populated: ![Screenshot at 2020-03-15 10-21-11](https://user-images.githubusercontent.com/3226564/76702238-19676700-66a7-11ea-8367-3e7b5733f2b4.png) When run again, cheats are available: ![Screenshot at 2020-03-15 10-21-34](https://user-images.githubusercontent.com/3226564/76702237-19676700-66a7-11ea-9c2a-d8829340f3e9.png) ### Breaking changes In order to make navi stop bundling shell widgets as well, a breaking change has been introduced: `source $(navi widget bash)` won't work anymore. It should be `source <(navi widget bash)` now. Any ideas on how to make this transition more graceful?
2020-03-15 16:46:58 +00:00
fn remove_quotes(txt: &str) -> String {
2020-03-12 22:04:47 +00:00
txt.replace('"', "").replace('\'', "")
}
2020-03-04 21:01:23 +00:00
fn parse_opts(text: &str) -> SuggestionOpts {
let mut header_lines: u8 = 0;
let mut column: Option<u8> = None;
let mut multi = false;
2020-03-17 15:39:38 +00:00
let mut prevent_extra = false;
2020-03-11 14:30:25 +00:00
let mut delimiter: Option<String> = None;
2020-03-04 21:01:23 +00:00
let mut parts = text.split(' ');
while let Some(p) = parts.next() {
match p {
"--multi" => multi = true,
2020-03-17 15:39:38 +00:00
"--prevent-extra" => prevent_extra = true,
2020-03-11 14:30:25 +00:00
"--header" | "--headers" | "--header-lines" => {
Initial cheat repo support (#258) This PR makes navi stop bundling `.cheat` files and makes it able to download from repos on GitHub, using a standardized config directory. - it fixes #233 and #237 - it makes #52, #256 and #257 much easier to implement - it makes #40 harder to implement - it's an alternate solution to #140 - it's influenced by #238 and #254. This PR ended up being much bigger than I would like so if you could review only this description it would be already very nice! When navi is started for the first time, a welcome cheatsheet is shown: ![Screenshot at 2020-03-15 10-20-04](https://user-images.githubusercontent.com/3226564/76702240-19fffd80-66a7-11ea-884f-97c565bc1ead.png) If the user selects the first option, the user is prompted to download `.cheat`s from https://github.com/denisidoro/cheats: ![Screenshot at 2020-03-15 10-20-35](https://user-images.githubusercontent.com/3226564/76702239-19fffd80-66a7-11ea-8f69-324f669b1e01.png) ![Screenshot at 2020-03-15 10-22-59](https://user-images.githubusercontent.com/3226564/76702236-18363a00-66a7-11ea-8ff4-53b497f85888.png) The config folder is populated: ![Screenshot at 2020-03-15 10-21-11](https://user-images.githubusercontent.com/3226564/76702238-19676700-66a7-11ea-8367-3e7b5733f2b4.png) When run again, cheats are available: ![Screenshot at 2020-03-15 10-21-34](https://user-images.githubusercontent.com/3226564/76702237-19676700-66a7-11ea-9c2a-d8829340f3e9.png) ### Breaking changes In order to make navi stop bundling shell widgets as well, a breaking change has been introduced: `source $(navi widget bash)` won't work anymore. It should be `source <(navi widget bash)` now. Any ideas on how to make this transition more graceful?
2020-03-15 16:46:58 +00:00
header_lines = remove_quotes(parts.next().unwrap()).parse::<u8>().unwrap()
}
"--column" => {
column = Some(remove_quotes(parts.next().unwrap()).parse::<u8>().unwrap())
2020-03-04 21:01:23 +00:00
}
Initial cheat repo support (#258) This PR makes navi stop bundling `.cheat` files and makes it able to download from repos on GitHub, using a standardized config directory. - it fixes #233 and #237 - it makes #52, #256 and #257 much easier to implement - it makes #40 harder to implement - it's an alternate solution to #140 - it's influenced by #238 and #254. This PR ended up being much bigger than I would like so if you could review only this description it would be already very nice! When navi is started for the first time, a welcome cheatsheet is shown: ![Screenshot at 2020-03-15 10-20-04](https://user-images.githubusercontent.com/3226564/76702240-19fffd80-66a7-11ea-884f-97c565bc1ead.png) If the user selects the first option, the user is prompted to download `.cheat`s from https://github.com/denisidoro/cheats: ![Screenshot at 2020-03-15 10-20-35](https://user-images.githubusercontent.com/3226564/76702239-19fffd80-66a7-11ea-8f69-324f669b1e01.png) ![Screenshot at 2020-03-15 10-22-59](https://user-images.githubusercontent.com/3226564/76702236-18363a00-66a7-11ea-8ff4-53b497f85888.png) The config folder is populated: ![Screenshot at 2020-03-15 10-21-11](https://user-images.githubusercontent.com/3226564/76702238-19676700-66a7-11ea-8367-3e7b5733f2b4.png) When run again, cheats are available: ![Screenshot at 2020-03-15 10-21-34](https://user-images.githubusercontent.com/3226564/76702237-19676700-66a7-11ea-9c2a-d8829340f3e9.png) ### Breaking changes In order to make navi stop bundling shell widgets as well, a breaking change has been introduced: `source $(navi widget bash)` won't work anymore. It should be `source <(navi widget bash)` now. Any ideas on how to make this transition more graceful?
2020-03-15 16:46:58 +00:00
"--delimiter" => delimiter = Some(remove_quotes(parts.next().unwrap()).to_string()),
2020-03-04 21:01:23 +00:00
_ => (),
}
}
2020-03-14 12:41:28 +00:00
SuggestionOpts {
2020-03-04 21:01:23 +00:00
header_lines,
column,
2020-03-11 14:30:25 +00:00
delimiter,
2020-03-17 15:39:38 +00:00
suggestion_type: match (multi, prevent_extra) {
2020-03-14 12:33:07 +00:00
(true, _) => SuggestionType::MultipleSelections, // multi wins over allow-extra
2020-03-17 15:39:38 +00:00
(false, false) => SuggestionType::SingleRecommendation,
(false, true) => SuggestionType::SingleSelection,
2020-03-14 08:09:09 +00:00
},
2020-03-14 12:41:28 +00:00
}
2020-03-04 21:01:23 +00:00
}
fn parse_variable_line(line: &str) -> (&str, &str, Option<SuggestionOpts>) {
let re = Regex::new(r"^\$\s*([^:]+):(.*)").unwrap();
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("---");
2020-03-14 15:46:33 +00:00
let command = command_plus_opts.next().unwrap();
let command_options = command_plus_opts.next().map(parse_opts);
2020-03-14 08:09:09 +00:00
(variable, command, command_options)
2020-03-04 21:01:23 +00:00
}
fn write_cmd(
tags: &str,
comment: &str,
snippet: &str,
tag_width: usize,
comment_width: usize,
stdin: &mut std::process::ChildStdin,
) -> bool {
if snippet.is_empty() {
true
} else {
stdin
.write_all(
2020-03-18 11:38:13 +00:00
display::format_line(&tags, &comment, &snippet, tag_width, comment_width)
.as_bytes(),
)
.is_ok()
}
}
2020-03-18 11:38:13 +00:00
fn gen_key(tags: &str, variable: &str) -> u64 {
format!("{};{}", tags, variable).hash_line()
}
2020-03-04 21:01:23 +00:00
fn read_file(
path: &str,
2020-03-18 11:38:13 +00:00
variables: &mut VariableMap,
2020-03-04 21:01:23 +00:00
stdin: &mut std::process::ChildStdin,
set: &mut HashSet<u64>,
Initial cheat repo support (#258) This PR makes navi stop bundling `.cheat` files and makes it able to download from repos on GitHub, using a standardized config directory. - it fixes #233 and #237 - it makes #52, #256 and #257 much easier to implement - it makes #40 harder to implement - it's an alternate solution to #140 - it's influenced by #238 and #254. This PR ended up being much bigger than I would like so if you could review only this description it would be already very nice! When navi is started for the first time, a welcome cheatsheet is shown: ![Screenshot at 2020-03-15 10-20-04](https://user-images.githubusercontent.com/3226564/76702240-19fffd80-66a7-11ea-884f-97c565bc1ead.png) If the user selects the first option, the user is prompted to download `.cheat`s from https://github.com/denisidoro/cheats: ![Screenshot at 2020-03-15 10-20-35](https://user-images.githubusercontent.com/3226564/76702239-19fffd80-66a7-11ea-8f69-324f669b1e01.png) ![Screenshot at 2020-03-15 10-22-59](https://user-images.githubusercontent.com/3226564/76702236-18363a00-66a7-11ea-8ff4-53b497f85888.png) The config folder is populated: ![Screenshot at 2020-03-15 10-21-11](https://user-images.githubusercontent.com/3226564/76702238-19676700-66a7-11ea-8367-3e7b5733f2b4.png) When run again, cheats are available: ![Screenshot at 2020-03-15 10-21-34](https://user-images.githubusercontent.com/3226564/76702237-19676700-66a7-11ea-9c2a-d8829340f3e9.png) ### Breaking changes In order to make navi stop bundling shell widgets as well, a breaking change has been introduced: `source $(navi widget bash)` won't work anymore. It should be `source <(navi widget bash)` now. Any ideas on how to make this transition more graceful?
2020-03-15 16:46:58 +00:00
) -> bool {
2020-03-04 21:01:23 +00:00
let mut tags = String::from("");
let mut comment = String::from("");
let mut snippet = String::from("");
2020-03-18 11:38:13 +00:00
let mut should_break = false;
2020-03-04 21:01:23 +00:00
2020-03-07 21:03:51 +00:00
let (tag_width, comment_width) = *display::WIDTHS;
2020-03-04 21:01:23 +00:00
if let Ok(lines) = filesystem::read_lines(path) {
for l in lines {
2020-03-18 11:38:13 +00:00
if should_break {
break;
}
2020-03-04 21:01:23 +00:00
let line = l.unwrap();
let hash = line.hash_line();
if set.contains(&hash) {
continue;
}
set.insert(hash);
2020-03-04 21:01:23 +00:00
2020-03-14 21:14:30 +00:00
// blank
if line.is_empty() {
}
2020-03-04 21:01:23 +00:00
// tag
2020-03-14 21:14:30 +00:00
else if line.starts_with('%') {
if !write_cmd(&tags, &comment, &snippet, tag_width, comment_width, stdin) {
2020-03-18 11:38:13 +00:00
should_break = true
}
snippet = String::from("");
2020-03-04 21:01:23 +00:00
tags = String::from(&line[2..]);
}
// metacomment
else if line.starts_with(';') {
}
2020-03-04 21:01:23 +00:00
// comment
else if line.starts_with('#') {
if !write_cmd(&tags, &comment, &snippet, tag_width, comment_width, stdin) {
2020-03-18 11:38:13 +00:00
should_break = true
}
snippet = String::from("");
2020-03-04 21:01:23 +00:00
comment = String::from(&line[2..]);
}
// variable
else if line.starts_with('$') {
if !write_cmd(&tags, &comment, &snippet, tag_width, comment_width, stdin) {
2020-03-18 11:38:13 +00:00
should_break = true
}
snippet = String::from("");
2020-03-14 08:09:09 +00:00
let (variable, command, opts) = parse_variable_line(&line);
2020-03-18 11:38:13 +00:00
variables.insert(&tags, &variable, (String::from(command), opts));
2020-03-04 21:01:23 +00:00
}
2020-03-18 11:38:13 +00:00
// first snippet line
else if (&snippet).is_empty() {
snippet.push_str(&line);
}
// other snippet lines
2020-03-04 21:01:23 +00:00
else {
snippet.push_str(display::LINE_SEPARATOR);
snippet.push_str(&line);
2020-03-04 21:01:23 +00:00
}
}
Initial cheat repo support (#258) This PR makes navi stop bundling `.cheat` files and makes it able to download from repos on GitHub, using a standardized config directory. - it fixes #233 and #237 - it makes #52, #256 and #257 much easier to implement - it makes #40 harder to implement - it's an alternate solution to #140 - it's influenced by #238 and #254. This PR ended up being much bigger than I would like so if you could review only this description it would be already very nice! When navi is started for the first time, a welcome cheatsheet is shown: ![Screenshot at 2020-03-15 10-20-04](https://user-images.githubusercontent.com/3226564/76702240-19fffd80-66a7-11ea-884f-97c565bc1ead.png) If the user selects the first option, the user is prompted to download `.cheat`s from https://github.com/denisidoro/cheats: ![Screenshot at 2020-03-15 10-20-35](https://user-images.githubusercontent.com/3226564/76702239-19fffd80-66a7-11ea-8f69-324f669b1e01.png) ![Screenshot at 2020-03-15 10-22-59](https://user-images.githubusercontent.com/3226564/76702236-18363a00-66a7-11ea-8ff4-53b497f85888.png) The config folder is populated: ![Screenshot at 2020-03-15 10-21-11](https://user-images.githubusercontent.com/3226564/76702238-19676700-66a7-11ea-8367-3e7b5733f2b4.png) When run again, cheats are available: ![Screenshot at 2020-03-15 10-21-34](https://user-images.githubusercontent.com/3226564/76702237-19676700-66a7-11ea-9c2a-d8829340f3e9.png) ### Breaking changes In order to make navi stop bundling shell widgets as well, a breaking change has been introduced: `source $(navi widget bash)` won't work anymore. It should be `source <(navi widget bash)` now. Any ideas on how to make this transition more graceful?
2020-03-15 16:46:58 +00:00
2020-03-18 11:38:13 +00:00
if !should_break {
write_cmd(&tags, &comment, &snippet, tag_width, comment_width, stdin);
}
Initial cheat repo support (#258) This PR makes navi stop bundling `.cheat` files and makes it able to download from repos on GitHub, using a standardized config directory. - it fixes #233 and #237 - it makes #52, #256 and #257 much easier to implement - it makes #40 harder to implement - it's an alternate solution to #140 - it's influenced by #238 and #254. This PR ended up being much bigger than I would like so if you could review only this description it would be already very nice! When navi is started for the first time, a welcome cheatsheet is shown: ![Screenshot at 2020-03-15 10-20-04](https://user-images.githubusercontent.com/3226564/76702240-19fffd80-66a7-11ea-884f-97c565bc1ead.png) If the user selects the first option, the user is prompted to download `.cheat`s from https://github.com/denisidoro/cheats: ![Screenshot at 2020-03-15 10-20-35](https://user-images.githubusercontent.com/3226564/76702239-19fffd80-66a7-11ea-8f69-324f669b1e01.png) ![Screenshot at 2020-03-15 10-22-59](https://user-images.githubusercontent.com/3226564/76702236-18363a00-66a7-11ea-8ff4-53b497f85888.png) The config folder is populated: ![Screenshot at 2020-03-15 10-21-11](https://user-images.githubusercontent.com/3226564/76702238-19676700-66a7-11ea-8367-3e7b5733f2b4.png) When run again, cheats are available: ![Screenshot at 2020-03-15 10-21-34](https://user-images.githubusercontent.com/3226564/76702237-19676700-66a7-11ea-9c2a-d8829340f3e9.png) ### Breaking changes In order to make navi stop bundling shell widgets as well, a breaking change has been introduced: `source $(navi widget bash)` won't work anymore. It should be `source <(navi widget bash)` now. Any ideas on how to make this transition more graceful?
2020-03-15 16:46:58 +00:00
return true;
2020-03-04 21:01:23 +00:00
}
Initial cheat repo support (#258) This PR makes navi stop bundling `.cheat` files and makes it able to download from repos on GitHub, using a standardized config directory. - it fixes #233 and #237 - it makes #52, #256 and #257 much easier to implement - it makes #40 harder to implement - it's an alternate solution to #140 - it's influenced by #238 and #254. This PR ended up being much bigger than I would like so if you could review only this description it would be already very nice! When navi is started for the first time, a welcome cheatsheet is shown: ![Screenshot at 2020-03-15 10-20-04](https://user-images.githubusercontent.com/3226564/76702240-19fffd80-66a7-11ea-884f-97c565bc1ead.png) If the user selects the first option, the user is prompted to download `.cheat`s from https://github.com/denisidoro/cheats: ![Screenshot at 2020-03-15 10-20-35](https://user-images.githubusercontent.com/3226564/76702239-19fffd80-66a7-11ea-8f69-324f669b1e01.png) ![Screenshot at 2020-03-15 10-22-59](https://user-images.githubusercontent.com/3226564/76702236-18363a00-66a7-11ea-8ff4-53b497f85888.png) The config folder is populated: ![Screenshot at 2020-03-15 10-21-11](https://user-images.githubusercontent.com/3226564/76702238-19676700-66a7-11ea-8367-3e7b5733f2b4.png) When run again, cheats are available: ![Screenshot at 2020-03-15 10-21-34](https://user-images.githubusercontent.com/3226564/76702237-19676700-66a7-11ea-9c2a-d8829340f3e9.png) ### Breaking changes In order to make navi stop bundling shell widgets as well, a breaking change has been introduced: `source $(navi widget bash)` won't work anymore. It should be `source <(navi widget bash)` now. Any ideas on how to make this transition more graceful?
2020-03-15 16:46:58 +00:00
false
2020-03-04 21:01:23 +00:00
}
2020-03-18 11:38:13 +00:00
pub fn read_all(config: &Config, stdin: &mut std::process::ChildStdin) -> VariableMap {
let mut variables = VariableMap::new();
Initial cheat repo support (#258) This PR makes navi stop bundling `.cheat` files and makes it able to download from repos on GitHub, using a standardized config directory. - it fixes #233 and #237 - it makes #52, #256 and #257 much easier to implement - it makes #40 harder to implement - it's an alternate solution to #140 - it's influenced by #238 and #254. This PR ended up being much bigger than I would like so if you could review only this description it would be already very nice! When navi is started for the first time, a welcome cheatsheet is shown: ![Screenshot at 2020-03-15 10-20-04](https://user-images.githubusercontent.com/3226564/76702240-19fffd80-66a7-11ea-884f-97c565bc1ead.png) If the user selects the first option, the user is prompted to download `.cheat`s from https://github.com/denisidoro/cheats: ![Screenshot at 2020-03-15 10-20-35](https://user-images.githubusercontent.com/3226564/76702239-19fffd80-66a7-11ea-8f69-324f669b1e01.png) ![Screenshot at 2020-03-15 10-22-59](https://user-images.githubusercontent.com/3226564/76702236-18363a00-66a7-11ea-8ff4-53b497f85888.png) The config folder is populated: ![Screenshot at 2020-03-15 10-21-11](https://user-images.githubusercontent.com/3226564/76702238-19676700-66a7-11ea-8367-3e7b5733f2b4.png) When run again, cheats are available: ![Screenshot at 2020-03-15 10-21-34](https://user-images.githubusercontent.com/3226564/76702237-19676700-66a7-11ea-9c2a-d8829340f3e9.png) ### Breaking changes In order to make navi stop bundling shell widgets as well, a breaking change has been introduced: `source $(navi widget bash)` won't work anymore. It should be `source <(navi widget bash)` now. Any ideas on how to make this transition more graceful?
2020-03-15 16:46:58 +00:00
let mut found_something = false;
let paths = filesystem::cheat_paths(config);
let folders = paths.split(':');
let mut set = HashSet::new();
2020-03-04 21:01:23 +00:00
for folder in folders {
if let Ok(paths) = fs::read_dir(folder) {
for path in paths {
let path = path.unwrap().path();
let path_str = path.to_str().unwrap();
Initial cheat repo support (#258) This PR makes navi stop bundling `.cheat` files and makes it able to download from repos on GitHub, using a standardized config directory. - it fixes #233 and #237 - it makes #52, #256 and #257 much easier to implement - it makes #40 harder to implement - it's an alternate solution to #140 - it's influenced by #238 and #254. This PR ended up being much bigger than I would like so if you could review only this description it would be already very nice! When navi is started for the first time, a welcome cheatsheet is shown: ![Screenshot at 2020-03-15 10-20-04](https://user-images.githubusercontent.com/3226564/76702240-19fffd80-66a7-11ea-884f-97c565bc1ead.png) If the user selects the first option, the user is prompted to download `.cheat`s from https://github.com/denisidoro/cheats: ![Screenshot at 2020-03-15 10-20-35](https://user-images.githubusercontent.com/3226564/76702239-19fffd80-66a7-11ea-8f69-324f669b1e01.png) ![Screenshot at 2020-03-15 10-22-59](https://user-images.githubusercontent.com/3226564/76702236-18363a00-66a7-11ea-8ff4-53b497f85888.png) The config folder is populated: ![Screenshot at 2020-03-15 10-21-11](https://user-images.githubusercontent.com/3226564/76702238-19676700-66a7-11ea-8367-3e7b5733f2b4.png) When run again, cheats are available: ![Screenshot at 2020-03-15 10-21-34](https://user-images.githubusercontent.com/3226564/76702237-19676700-66a7-11ea-9c2a-d8829340f3e9.png) ### Breaking changes In order to make navi stop bundling shell widgets as well, a breaking change has been introduced: `source $(navi widget bash)` won't work anymore. It should be `source <(navi widget bash)` now. Any ideas on how to make this transition more graceful?
2020-03-15 16:46:58 +00:00
if path_str.ends_with(".cheat")
&& read_file(path_str, &mut variables, stdin, &mut set)
Initial cheat repo support (#258) This PR makes navi stop bundling `.cheat` files and makes it able to download from repos on GitHub, using a standardized config directory. - it fixes #233 and #237 - it makes #52, #256 and #257 much easier to implement - it makes #40 harder to implement - it's an alternate solution to #140 - it's influenced by #238 and #254. This PR ended up being much bigger than I would like so if you could review only this description it would be already very nice! When navi is started for the first time, a welcome cheatsheet is shown: ![Screenshot at 2020-03-15 10-20-04](https://user-images.githubusercontent.com/3226564/76702240-19fffd80-66a7-11ea-884f-97c565bc1ead.png) If the user selects the first option, the user is prompted to download `.cheat`s from https://github.com/denisidoro/cheats: ![Screenshot at 2020-03-15 10-20-35](https://user-images.githubusercontent.com/3226564/76702239-19fffd80-66a7-11ea-8f69-324f669b1e01.png) ![Screenshot at 2020-03-15 10-22-59](https://user-images.githubusercontent.com/3226564/76702236-18363a00-66a7-11ea-8ff4-53b497f85888.png) The config folder is populated: ![Screenshot at 2020-03-15 10-21-11](https://user-images.githubusercontent.com/3226564/76702238-19676700-66a7-11ea-8367-3e7b5733f2b4.png) When run again, cheats are available: ![Screenshot at 2020-03-15 10-21-34](https://user-images.githubusercontent.com/3226564/76702237-19676700-66a7-11ea-9c2a-d8829340f3e9.png) ### Breaking changes In order to make navi stop bundling shell widgets as well, a breaking change has been introduced: `source $(navi widget bash)` won't work anymore. It should be `source <(navi widget bash)` now. Any ideas on how to make this transition more graceful?
2020-03-15 16:46:58 +00:00
&& !found_something
{
found_something = true;
}
2020-03-04 21:01:23 +00:00
}
}
}
Initial cheat repo support (#258) This PR makes navi stop bundling `.cheat` files and makes it able to download from repos on GitHub, using a standardized config directory. - it fixes #233 and #237 - it makes #52, #256 and #257 much easier to implement - it makes #40 harder to implement - it's an alternate solution to #140 - it's influenced by #238 and #254. This PR ended up being much bigger than I would like so if you could review only this description it would be already very nice! When navi is started for the first time, a welcome cheatsheet is shown: ![Screenshot at 2020-03-15 10-20-04](https://user-images.githubusercontent.com/3226564/76702240-19fffd80-66a7-11ea-884f-97c565bc1ead.png) If the user selects the first option, the user is prompted to download `.cheat`s from https://github.com/denisidoro/cheats: ![Screenshot at 2020-03-15 10-20-35](https://user-images.githubusercontent.com/3226564/76702239-19fffd80-66a7-11ea-8f69-324f669b1e01.png) ![Screenshot at 2020-03-15 10-22-59](https://user-images.githubusercontent.com/3226564/76702236-18363a00-66a7-11ea-8ff4-53b497f85888.png) The config folder is populated: ![Screenshot at 2020-03-15 10-21-11](https://user-images.githubusercontent.com/3226564/76702238-19676700-66a7-11ea-8367-3e7b5733f2b4.png) When run again, cheats are available: ![Screenshot at 2020-03-15 10-21-34](https://user-images.githubusercontent.com/3226564/76702237-19676700-66a7-11ea-9c2a-d8829340f3e9.png) ### Breaking changes In order to make navi stop bundling shell widgets as well, a breaking change has been introduced: `source $(navi widget bash)` won't work anymore. It should be `source <(navi widget bash)` now. Any ideas on how to make this transition more graceful?
2020-03-15 16:46:58 +00:00
if !found_something {
welcome::cheatsheet(stdin);
}
2020-03-04 21:01:23 +00:00
variables
}
2020-03-14 08:09:09 +00:00
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_variable_line() {
2020-03-14 12:33:07 +00:00
let (variable, command, command_options) =
parse_variable_line("$ user : echo -e \"$(whoami)\\nroot\" --- --allow-extra");
2020-03-14 08:09:09 +00:00
assert_eq!(command, " echo -e \"$(whoami)\\nroot\" ");
assert_eq!(variable, "user");
2020-03-14 12:33:07 +00:00
assert_eq!(
command_options,
Some(SuggestionOpts {
header_lines: 0,
column: None,
delimiter: None,
suggestion_type: SuggestionType::SingleRecommendation
})
);
2020-03-14 08:09:09 +00:00
}
use std::process::{Command, Stdio};
#[test]
fn test_read_file() {
let path = "tests/cheats/ssh.cheat";
2020-03-18 11:38:13 +00:00
let mut variables = VariableMap::new();
2020-03-14 12:33:07 +00:00
let mut child = Command::new("cat").stdin(Stdio::piped()).spawn().unwrap();
2020-03-14 08:09:09 +00:00
let child_stdin = child.stdin.as_mut().unwrap();
2020-03-18 11:38:13 +00:00
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(&(
2020-03-14 15:46:33 +00:00
r#" echo -e "$(whoami)\nroot" "#.to_string(),
2020-03-14 12:33:07 +00:00
Some(SuggestionOpts {
header_lines: 0,
column: None,
delimiter: None,
suggestion_type: SuggestionType::SingleRecommendation,
}),
2020-03-18 11:38:13 +00:00
)),
actual_suggestion
2020-03-14 08:09:09 +00:00
);
}
}