added undo + dynamic status bar
All checks were successful
Version Check / check-version (pull_request) Successful in 3s
All checks were successful
Version Check / check-version (pull_request) Successful in 3s
This commit is contained in:
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -853,7 +853,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mould"
|
||||
version = "0.4.1"
|
||||
version = "0.4.2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
|
||||
@@ -64,6 +64,7 @@ mould config.template.json -o config.json
|
||||
- `o`: Append a new item to the current array
|
||||
- `O`: Prepend a new item to the current array
|
||||
- `dd`: Delete the currently selected variable or group
|
||||
- `u`: Undo the last change
|
||||
- `a`: Add missing value from template to active config
|
||||
- `/`: Search for configuration keys (Jump to matches)
|
||||
- `n`: Jump to the next search match
|
||||
|
||||
@@ -44,3 +44,4 @@ jump_bottom = "G"
|
||||
append_item = "o"
|
||||
prepend_item = "O"
|
||||
delete_item = "dd"
|
||||
undo = "u"
|
||||
|
||||
29
src/app.rs
29
src/app.rs
@@ -33,6 +33,8 @@ pub struct App {
|
||||
pub input: Input,
|
||||
/// The current search query for filtering keys.
|
||||
pub search_query: String,
|
||||
/// Stack of previous variable states for undo functionality.
|
||||
pub undo_stack: Vec<Vec<ConfigItem>>,
|
||||
}
|
||||
|
||||
impl App {
|
||||
@@ -47,6 +49,7 @@ impl App {
|
||||
status_message: None,
|
||||
input: Input::new(initial_input),
|
||||
search_query: String::new(),
|
||||
undo_stack: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,8 +162,8 @@ impl App {
|
||||
pub fn enter_insert(&mut self, variant: InsertVariant) {
|
||||
if let Some(var) = self.vars.get(self.selected) {
|
||||
if !var.is_group {
|
||||
self.save_undo_state();
|
||||
self.mode = Mode::Insert;
|
||||
self.status_message = None;
|
||||
match variant {
|
||||
InsertVariant::Start => {
|
||||
use tui_input::InputRequest;
|
||||
@@ -190,6 +193,7 @@ impl App {
|
||||
return;
|
||||
}
|
||||
|
||||
self.save_undo_state();
|
||||
let selected_path = self.vars[self.selected].path.clone();
|
||||
let is_group = self.vars[self.selected].is_group;
|
||||
|
||||
@@ -252,6 +256,7 @@ impl App {
|
||||
return;
|
||||
}
|
||||
|
||||
self.save_undo_state();
|
||||
let (base, idx, depth) = {
|
||||
let selected_item = &self.vars[self.selected];
|
||||
if selected_item.is_group {
|
||||
@@ -322,6 +327,28 @@ impl App {
|
||||
.map(|v| v.status == crate::format::ItemStatus::MissingFromActive)
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
/// Saves the current state of variables to the undo stack.
|
||||
pub fn save_undo_state(&mut self) {
|
||||
self.undo_stack.push(self.vars.clone());
|
||||
if self.undo_stack.len() > 50 {
|
||||
self.undo_stack.remove(0);
|
||||
}
|
||||
}
|
||||
|
||||
/// Reverts to the last saved state of variables.
|
||||
pub fn undo(&mut self) {
|
||||
if let Some(previous_vars) = self.undo_stack.pop() {
|
||||
self.vars = previous_vars;
|
||||
if self.selected >= self.vars.len() && !self.vars.is_empty() {
|
||||
self.selected = self.vars.len() - 1;
|
||||
}
|
||||
self.sync_input_with_selected();
|
||||
self.status_message = Some("Undo applied".to_string());
|
||||
} else {
|
||||
self.status_message = Some("Nothing to undo".to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_index(path: &str) -> Option<(&str, usize)> {
|
||||
|
||||
@@ -119,6 +119,7 @@ pub struct KeybindsConfig {
|
||||
pub append_item: String,
|
||||
pub prepend_item: String,
|
||||
pub delete_item: String,
|
||||
pub undo: String,
|
||||
}
|
||||
|
||||
impl Default for KeybindsConfig {
|
||||
@@ -140,6 +141,7 @@ impl Default for KeybindsConfig {
|
||||
append_item: "o".to_string(),
|
||||
prepend_item: "O".to_string(),
|
||||
delete_item: "dd".to_string(),
|
||||
undo: "u".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,6 +127,7 @@ where
|
||||
(&self.config.keybinds.append_item, "append_item"),
|
||||
(&self.config.keybinds.prepend_item, "prepend_item"),
|
||||
(&self.config.keybinds.delete_item, "delete_item"),
|
||||
(&self.config.keybinds.undo, "undo"),
|
||||
(&"a".to_string(), "add_missing"),
|
||||
(&":".to_string(), "command"),
|
||||
(&"q".to_string(), "quit"),
|
||||
@@ -164,7 +165,11 @@ where
|
||||
"append_item" => self.app.add_array_item(true),
|
||||
"prepend_item" => self.app.add_array_item(false),
|
||||
"delete_item" => self.app.delete_selected(),
|
||||
"add_missing" => self.add_missing_item(),
|
||||
"undo" => self.app.undo(),
|
||||
"add_missing" => {
|
||||
self.app.save_undo_state();
|
||||
self.add_missing_item();
|
||||
}
|
||||
"command" => {
|
||||
self.command_buffer.push(':');
|
||||
self.sync_command_status();
|
||||
|
||||
20
src/ui.rs
20
src/ui.rs
@@ -272,21 +272,27 @@ pub fn draw(f: &mut Frame, app: &mut App, config: &Config) {
|
||||
let status_msg = if let Some(msg) = &app.status_message {
|
||||
msg.clone()
|
||||
} else {
|
||||
let kb = &config.keybinds;
|
||||
match app.mode {
|
||||
Mode::Normal => {
|
||||
let mut parts = vec!["j/k move", "gg/G jump", "/ search"];
|
||||
let mut parts = vec![
|
||||
format!("{}/{} move", kb.down, kb.up),
|
||||
format!("{}/{} jump", kb.jump_top, kb.jump_bottom),
|
||||
format!("{} search", kb.search),
|
||||
];
|
||||
if !app.selected_is_group() {
|
||||
parts.push("i/A/S edit");
|
||||
parts.push(format!("{}/{}/{} edit", kb.edit, kb.edit_append, kb.edit_substitute));
|
||||
}
|
||||
if app.selected_is_missing() {
|
||||
parts.push("a add");
|
||||
parts.push(format!("{} add", "a")); // 'a' is currently hardcoded in runner
|
||||
}
|
||||
if app.selected_is_array() {
|
||||
parts.push("o/O array");
|
||||
parts.push(format!("{}/{} array", kb.append_item, kb.prepend_item));
|
||||
}
|
||||
parts.push("dd del");
|
||||
parts.push(":w save");
|
||||
parts.push(":q quit");
|
||||
parts.push(format!("{} del", kb.delete_item));
|
||||
parts.push(format!("{} undo", kb.undo));
|
||||
parts.push(format!("{} save", kb.save));
|
||||
parts.push(format!("{} quit", kb.quit));
|
||||
parts.join(" · ")
|
||||
}
|
||||
Mode::Insert => "Esc normal · Enter commit".to_string(),
|
||||
|
||||
Reference in New Issue
Block a user