Skip to content

Commit

Permalink
wip Store to history file
Browse files Browse the repository at this point in the history
  • Loading branch information
kyu08 committed Jan 20, 2024
1 parent efe1437 commit 1817b22
Show file tree
Hide file tree
Showing 2 changed files with 225 additions and 30 deletions.
187 changes: 187 additions & 0 deletions src/model/histories.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use simple_home_dir::home_dir;
use std::path::PathBuf;

#[derive(Clone, PartialEq, Debug)]
Expand All @@ -22,6 +23,22 @@ impl Histories {
.map(|h| h.executed_targets.clone())
}

pub fn append(&self, path: &PathBuf, executed_target: &str) -> Option<Self> {
let mut new_histories = self.histories.clone();

new_histories
.iter()
.position(|h| h.path == *path)
.map(|index| {
let new_history = new_histories[index].append(executed_target.to_string());
new_histories[index] = new_history;

Self {
histories: new_histories,
}
})
}

fn default(path: PathBuf) -> Self {
let histories = vec![History::default(path)];
Self { histories }
Expand All @@ -39,6 +56,14 @@ impl Histories {
}
}

pub fn history_file_path() -> Option<PathBuf> {
home_dir().map(|mut h| {
let base_path: &'static str = ".config/fzf-make/history.toml";
h.push(PathBuf::from(base_path));
h.clone()
})
}

#[derive(Clone, PartialEq, Debug)]
struct History {
path: PathBuf,
Expand All @@ -59,6 +84,17 @@ impl History {
executed_targets: histories.1,
}
}

fn append(&self, executed_target: String) -> Self {
let mut executed_targets = self.executed_targets.clone();
executed_targets.retain(|t| *t != executed_target);
executed_targets.insert(0, executed_target.clone());

Self {
path: self.path.clone(),
executed_targets,
}
}
}

#[cfg(test)]
Expand Down Expand Up @@ -122,4 +158,155 @@ mod test {
)
}
}

#[test]
fn histories_append_test() {
struct Case {
title: &'static str,
path: PathBuf,
appending_target: &'static str,
histories: Histories,
expect: Option<Histories>,
}
let cases = vec![
Case {
title: "Success",
path: PathBuf::from("/Users/user/code/fzf-make".to_string()),
appending_target: "history1",
histories: Histories {
histories: vec![
History {
path: PathBuf::from("/Users/user/code/rustc".to_string()),
executed_targets: vec!["history0".to_string(), "history1".to_string()],
},
History {
path: PathBuf::from("/Users/user/code/fzf-make".to_string()),
executed_targets: vec![
"history0".to_string(),
"history1".to_string(),
"history2".to_string(),
],
},
],
},
expect: Some(Histories {
histories: vec![
History {
path: PathBuf::from("/Users/user/code/rustc".to_string()),
executed_targets: vec!["history0".to_string(), "history1".to_string()],
},
History {
path: PathBuf::from("/Users/user/code/fzf-make".to_string()),
executed_targets: vec![
"history1".to_string(),
"history0".to_string(),
"history2".to_string(),
],
},
],
}),
},
Case {
title: "Returns None when path is not found",
path: PathBuf::from("/Users/user/code/non-existent-dir".to_string()),
appending_target: "history1",
histories: Histories {
histories: vec![
History {
path: PathBuf::from("/Users/user/code/rustc".to_string()),
executed_targets: vec!["history0".to_string(), "history1".to_string()],
},
History {
path: PathBuf::from("/Users/user/code/fzf-make".to_string()),
executed_targets: vec![
"history0".to_string(),
"history1".to_string(),
"history2".to_string(),
],
},
],
},
expect: None,
},
];

for case in cases {
assert_eq!(
case.expect,
case.histories.append(&case.path, case.appending_target),
"\nFailed: 🚨{:?}🚨\n",
case.title,
)
}
}

#[test]
fn history_append_test() {
struct Case {
title: &'static str,
appending_target: &'static str,
history: History,
expect: History,
}
let path = PathBuf::from("/Users/user/code/fzf-make".to_string());
let cases = vec![
Case {
title: "Append to head",
appending_target: "history2",
history: History {
path: path.clone(),
executed_targets: vec!["history0".to_string(), "history1".to_string()],
},
expect: History {
path: path.clone(),
executed_targets: vec![
"history2".to_string(),
"history0".to_string(),
"history1".to_string(),
],
},
},
Case {
title: "Append to head(Append to empty)",
appending_target: "history0",
history: History {
path: path.clone(),
executed_targets: vec![],
},
expect: History {
path: path.clone(),
executed_targets: vec!["history0".to_string()],
},
},
Case {
title: "Append to head(Remove duplicated)",
appending_target: "history1",
history: History {
path: path.clone(),
executed_targets: vec![
"history0".to_string(),
"history1".to_string(),
"history2".to_string(),
],
},
expect: History {
path: path.clone(),
executed_targets: vec![
"history1".to_string(),
"history0".to_string(),
"history2".to_string(),
],
},
},
];

for case in cases {
assert_eq!(
case.expect,
case.history.append(case.appending_target.to_string()),
"\nFailed: 🚨{:?}🚨\n",
case.title,
)
}
}
}
68 changes: 38 additions & 30 deletions src/usecase/fzf_make/app.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use crate::{
file::{path_to_content, toml},
model::{histories::Histories, makefile::Makefile},
model::{
histories::{history_file_path, Histories},
makefile::Makefile,
},
};

use super::ui::ui;
Expand All @@ -18,12 +21,9 @@ use ratatui::{
widgets::ListState,
Terminal,
};
use simple_home_dir::home_dir;
use std::{
io::{self, Stderr},
panic,
path::PathBuf,
process,
panic, process,
};
use tui_textarea::TextArea;

Expand Down Expand Up @@ -100,6 +100,15 @@ impl Model<'_> {
})
}

pub fn append_history(&self) -> Option<Histories> {
match (&self.histories.clone(), &self.app_state.clone()) {
(Some(histories), AppState::ExecuteTarget(Some(target))) => {
histories.append(&self.makefile.path, target)
}
_ => None,
}
}

pub fn narrow_down_targets(&self) -> Vec<String> {
if self.search_text_area.0.is_empty() {
return self.makefile.to_targets_string();
Expand Down Expand Up @@ -131,25 +140,18 @@ impl Model<'_> {
}

fn get_histories() -> Option<Histories> {
let path = match home_dir() {
None => return None,
Some(mut h) => {
let base_path: &'static str = ".config/fzf-make/history.toml";
h.push(PathBuf::from(base_path));
h.clone()
}
};

let content = match path_to_content::path_to_content(path.clone()) {
Err(_) => return Some(Histories::new(path, vec![])), // NOTE: Show error message on message pane https://github.com/kyu08/fzf-make/issues/152
Ok(c) => c,
};
let histories = match toml::parse_history(content.to_string()) {
Err(_) => vec![], // NOTE: Show error message on message pane https://github.com/kyu08/fzf-make/issues/152
Ok(h) => h,
};
history_file_path().map(|path| {
let content = match path_to_content::path_to_content(path.clone()) {
Err(_) => return Histories::new(path, vec![]), // NOTE: Show error message on message pane https://github.com/kyu08/fzf-make/issues/152
Ok(c) => c,
};
let histories = match toml::parse_history(content.to_string()) {
Err(_) => vec![], // NOTE: Show error message on message pane https://github.com/kyu08/fzf-make/issues/152
Ok(h) => h,
};

Some(Histories::new(path, histories))
Histories::new(path, histories)
})
}

fn next_target(&mut self) {
Expand Down Expand Up @@ -415,14 +417,20 @@ fn update(model: &mut Model, message: Option<Message>) {
Some(Message::PreviousTarget) => model.previous_target(),
Some(Message::NextHistory) => model.next_history(),
Some(Message::PreviousHistory) => model.previous_history(),
Some(Message::ExecuteTarget) => match model.current_pane {
CurrentPane::Main => {
model.app_state = AppState::ExecuteTarget(model.selected_target());
}
CurrentPane::History => {
model.app_state = AppState::ExecuteTarget(model.selected_history());
Some(Message::ExecuteTarget) => {
let target = match model.current_pane {
CurrentPane::Main => model.selected_target(),
CurrentPane::History => model.selected_history(),
};
model.app_state = AppState::ExecuteTarget(target);
if let Some(h) = model.append_history() {
model.histories = Some(h)
}
},

// TODO: store to history file
// toml.rsとの関わり方が初期化時と同様かチェックする
}

Some(Message::SearchTextAreaKeyInput(key_event)) => {
if let KeyCode::Char(_) = key_event.code {
model.reset_selection();
Expand Down

0 comments on commit 1817b22

Please sign in to comment.