Merge pull request #981 from soar/feature/variables-history

feat: Variables history
This commit is contained in:
Alexis Opolka 2025-05-18 09:20:17 +02:00 committed by GitHub
commit 6db8eff492
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 67 additions and 2 deletions

View file

@ -5,6 +5,7 @@ use crate::common::shell::ShellSpawnError;
use crate::config::Action;
use crate::deser;
use crate::env_var;
use crate::filesystem;
use crate::finder::structures::{Opts as FinderOpts, SuggestionType};
use crate::prelude::*;
use crate::structures::cheat::{Suggestion, VariableMap};
@ -22,6 +23,7 @@ fn prompt_finder(
env_var::remove(env_var::PREVIEW_MAP);
let mut extra_preview: Option<String> = None;
let mut variable_history = vec![];
let (suggestions, initial_opts) = if let Some(s) = suggestion {
let (suggestion_command, suggestion_opts) = s;
@ -58,7 +60,13 @@ fn prompt_finder(
(text, suggestion_opts)
} else {
('\n'.to_string(), &None)
variable_history = filesystem::get_variable_history(variable_name);
if !variable_history.is_empty() {
variable_history.insert(0, "".to_string());
(variable_history.join("\n"), &None)
} else {
('\n'.to_string(), &None)
}
};
let exe = fs::exe_string();
@ -131,7 +139,9 @@ fn prompt_finder(
});
}
if suggestion.is_none() {
if !variable_history.is_empty() {
opts.suggestion_type = SuggestionType::SingleRecommendation;
} else if suggestion.is_none() {
opts.suggestion_type = SuggestionType::Disabled;
};
@ -145,6 +155,10 @@ fn prompt_finder(
})
.context("finder was unable to prompt with suggestions")?;
if suggestion.is_none() && !variable_history.contains(&output) {
filesystem::save_variable_history(variable_name, &output);
}
Ok(output)
}

View file

@ -19,6 +19,8 @@ pub const FINDER: &str = "NAVI_FINDER";
pub const CONFIG: &str = "NAVI_CONFIG";
pub const CONFIG_YAML: &str = "NAVI_CONFIG_YAML";
pub const VAR_HISTORY: &str = "NAVI_VAR_HISTORY";
pub fn parse<T: FromStr>(varname: &str) -> Option<T> {
if let Ok(x) = env::var(varname) {
x.parse::<T>().ok()

View file

@ -2,12 +2,14 @@ pub use crate::common::fs::{create_dir, exe_string, read_lines, remove_dir};
use crate::env_var;
use crate::parser::Parser;
use crate::prelude::*;
use std::io::Write;
use crate::structures::fetcher;
use etcetera::BaseStrategy;
use regex::Regex;
use std::cell::RefCell;
use std::env;
use std::path::MAIN_SEPARATOR;
use walkdir::WalkDir;
@ -88,6 +90,53 @@ pub fn cheat_paths(path: Option<String>) -> Result<String> {
}
}
pub fn variables_history_pathbuf() -> Option<PathBuf> {
if let Ok(v) = env::var(env_var::VAR_HISTORY) {
let pathbuf = PathBuf::from(v);
if !pathbuf.exists() {
File::create(&pathbuf).unwrap_or_else(|_| panic!("Unable to create file: {}", pathbuf.display()));
}
Some(pathbuf)
} else {
None
}
}
pub fn get_variable_history(variable: &str) -> Vec<String> {
if let Some(pathbuf) = variables_history_pathbuf() {
let file = std::fs::File::open(pathbuf).expect("Unable to open history file");
let reader = std::io::BufReader::new(file);
reader
.lines()
.map_while(|line| line.ok())
.filter_map(|line| {
let parts: Vec<&str> = line.splitn(2, ':').collect();
if parts.len() == 2 && parts[0] == variable {
Some(parts[1].to_string())
} else {
None
}
})
.collect()
} else {
vec![]
}
}
pub fn save_variable_history(variable: &str, value: &str) {
if let Some(pathbuf) = variables_history_pathbuf() {
let mut file = std::fs::OpenOptions::new()
.append(true)
.create(true)
.open(pathbuf)
.expect("Unable to open history file");
writeln!(file, "{}:{}", variable, value).expect("Unable to write to history file");
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Here are other functions, unrelated to CLI commands (or at least not directly related)