refactor: use mark_dirty() helper di input.rs, DRY 22 lokasi
This commit is contained in:
@@ -11,6 +11,12 @@ use crate::app::state::rest::AppStateRest;
|
|||||||
use crate::app::state::types::Overlay;
|
use crate::app::state::types::Overlay;
|
||||||
use crate::controller::command::parse_command;
|
use crate::controller::command::parse_command;
|
||||||
|
|
||||||
|
/// Mark state dirty and return an empty action list.
|
||||||
|
fn mark(state: &mut AppStateRest) -> Vec<Action> {
|
||||||
|
state.mark_dirty();
|
||||||
|
Vec::new()
|
||||||
|
}
|
||||||
|
|
||||||
/// Translate a terminal `KeyEvent` into zero or more `Action` values
|
/// Translate a terminal `KeyEvent` into zero or more `Action` values
|
||||||
/// based on the current application state.
|
/// based on the current application state.
|
||||||
///
|
///
|
||||||
@@ -36,7 +42,7 @@ pub fn handle_key(key: KeyEvent, state: &mut AppStateRest) -> Vec<Action> {
|
|||||||
} else {
|
} else {
|
||||||
state.toast_success(format!("Saved {}", ed.path));
|
state.toast_success(format!("Saved {}", ed.path));
|
||||||
}
|
}
|
||||||
state.dirty = true;
|
state.mark_dirty();
|
||||||
}
|
}
|
||||||
return vec![];
|
return vec![];
|
||||||
}
|
}
|
||||||
@@ -47,7 +53,7 @@ pub fn handle_key(key: KeyEvent, state: &mut AppStateRest) -> Vec<Action> {
|
|||||||
KeyCode::Backspace => {
|
KeyCode::Backspace => {
|
||||||
if let Some(ref mut ed) = state.misc.editor {
|
if let Some(ref mut ed) = state.misc.editor {
|
||||||
ed.delete_left();
|
ed.delete_left();
|
||||||
state.dirty = true;
|
state.mark_dirty();
|
||||||
}
|
}
|
||||||
return vec![];
|
return vec![];
|
||||||
}
|
}
|
||||||
@@ -75,15 +81,13 @@ pub fn handle_key(key: KeyEvent, state: &mut AppStateRest) -> Vec<Action> {
|
|||||||
let items = crate::app::mode::learning::get_learning_items(state);
|
let items = crate::app::mode::learning::get_learning_items(state);
|
||||||
let n = items.len();
|
let n = items.len();
|
||||||
state.misc.selected_index = crate::app::mode::cycle_selected_index(state.misc.selected_index, n, false);
|
state.misc.selected_index = crate::app::mode::cycle_selected_index(state.misc.selected_index, n, false);
|
||||||
state.dirty = true;
|
return mark(state);
|
||||||
return vec![];
|
|
||||||
}
|
}
|
||||||
KeyCode::Down => {
|
KeyCode::Down => {
|
||||||
let items = crate::app::mode::learning::get_learning_items(state);
|
let items = crate::app::mode::learning::get_learning_items(state);
|
||||||
let n = items.len();
|
let n = items.len();
|
||||||
state.misc.selected_index = crate::app::mode::cycle_selected_index(state.misc.selected_index, n, true);
|
state.misc.selected_index = crate::app::mode::cycle_selected_index(state.misc.selected_index, n, true);
|
||||||
state.dirty = true;
|
return mark(state);
|
||||||
return vec![];
|
|
||||||
}
|
}
|
||||||
KeyCode::Enter | KeyCode::Char('a') => {
|
KeyCode::Enter | KeyCode::Char('a') => {
|
||||||
let items = crate::app::mode::learning::get_learning_items(state);
|
let items = crate::app::mode::learning::get_learning_items(state);
|
||||||
@@ -148,8 +152,7 @@ pub fn handle_key(key: KeyEvent, state: &mut AppStateRest) -> Vec<Action> {
|
|||||||
KeyCode::Enter => {
|
KeyCode::Enter => {
|
||||||
if state.input.autocomplete_visible {
|
if state.input.autocomplete_visible {
|
||||||
state.input.select_autocomplete();
|
state.input.select_autocomplete();
|
||||||
state.dirty = true;
|
return mark(state);
|
||||||
return Vec::new();
|
|
||||||
}
|
}
|
||||||
if state.misc.overlay.is_active() {
|
if state.misc.overlay.is_active() {
|
||||||
return handle_overlay_enter(state);
|
return handle_overlay_enter(state);
|
||||||
@@ -163,16 +166,14 @@ pub fn handle_key(key: KeyEvent, state: &mut AppStateRest) -> Vec<Action> {
|
|||||||
KeyCode::Backspace => {
|
KeyCode::Backspace => {
|
||||||
if state.input.autocomplete_visible {
|
if state.input.autocomplete_visible {
|
||||||
state.input.close_autocomplete();
|
state.input.close_autocomplete();
|
||||||
state.dirty = true;
|
return mark(state);
|
||||||
return Vec::new();
|
|
||||||
}
|
}
|
||||||
vec![Action::DeleteChar]
|
vec![Action::DeleteChar]
|
||||||
}
|
}
|
||||||
KeyCode::Delete => {
|
KeyCode::Delete => {
|
||||||
if state.input.autocomplete_visible {
|
if state.input.autocomplete_visible {
|
||||||
state.input.close_autocomplete();
|
state.input.close_autocomplete();
|
||||||
state.dirty = true;
|
return mark(state);
|
||||||
return Vec::new();
|
|
||||||
}
|
}
|
||||||
vec![Action::DeleteCharRight]
|
vec![Action::DeleteCharRight]
|
||||||
}
|
}
|
||||||
@@ -185,7 +186,7 @@ pub fn handle_key(key: KeyEvent, state: &mut AppStateRest) -> Vec<Action> {
|
|||||||
KeyCode::Up => {
|
KeyCode::Up => {
|
||||||
if state.input.autocomplete_visible {
|
if state.input.autocomplete_visible {
|
||||||
state.input.cycle_autocomplete(false);
|
state.input.cycle_autocomplete(false);
|
||||||
state.dirty = true;
|
state.mark_dirty();
|
||||||
Vec::new()
|
Vec::new()
|
||||||
} else if state.misc.overlay == Overlay::Effort {
|
} else if state.misc.overlay == Overlay::Effort {
|
||||||
mode::effort::cycle_effort(state);
|
mode::effort::cycle_effort(state);
|
||||||
@@ -193,12 +194,12 @@ pub fn handle_key(key: KeyEvent, state: &mut AppStateRest) -> Vec<Action> {
|
|||||||
} else if state.misc.overlay == Overlay::Rewind {
|
} else if state.misc.overlay == Overlay::Rewind {
|
||||||
let n = mode::rewind::rewind_count(state);
|
let n = mode::rewind::rewind_count(state);
|
||||||
state.misc.selected_index = mode::cycle_selected_index(state.misc.selected_index, n, false);
|
state.misc.selected_index = mode::cycle_selected_index(state.misc.selected_index, n, false);
|
||||||
state.dirty = true;
|
state.mark_dirty();
|
||||||
Vec::new()
|
Vec::new()
|
||||||
} else if state.misc.overlay == Overlay::ModelSelector {
|
} else if state.misc.overlay == Overlay::ModelSelector {
|
||||||
let n = state.app_config.providers.len();
|
let n = state.app_config.providers.len();
|
||||||
state.misc.selected_index = mode::cycle_selected_index(state.misc.selected_index, n, false);
|
state.misc.selected_index = mode::cycle_selected_index(state.misc.selected_index, n, false);
|
||||||
state.dirty = true;
|
state.mark_dirty();
|
||||||
Vec::new()
|
Vec::new()
|
||||||
} else if key.modifiers.contains(KeyModifiers::CONTROL) {
|
} else if key.modifiers.contains(KeyModifiers::CONTROL) {
|
||||||
vec![Action::ScrollUp]
|
vec![Action::ScrollUp]
|
||||||
@@ -209,7 +210,7 @@ pub fn handle_key(key: KeyEvent, state: &mut AppStateRest) -> Vec<Action> {
|
|||||||
KeyCode::Down => {
|
KeyCode::Down => {
|
||||||
if state.input.autocomplete_visible {
|
if state.input.autocomplete_visible {
|
||||||
state.input.cycle_autocomplete(true);
|
state.input.cycle_autocomplete(true);
|
||||||
state.dirty = true;
|
state.mark_dirty();
|
||||||
Vec::new()
|
Vec::new()
|
||||||
} else if state.misc.overlay == Overlay::Effort {
|
} else if state.misc.overlay == Overlay::Effort {
|
||||||
mode::effort::cycle_effort(state);
|
mode::effort::cycle_effort(state);
|
||||||
@@ -217,12 +218,12 @@ pub fn handle_key(key: KeyEvent, state: &mut AppStateRest) -> Vec<Action> {
|
|||||||
} else if state.misc.overlay == Overlay::Rewind {
|
} else if state.misc.overlay == Overlay::Rewind {
|
||||||
let n = mode::rewind::rewind_count(state);
|
let n = mode::rewind::rewind_count(state);
|
||||||
state.misc.selected_index = mode::cycle_selected_index(state.misc.selected_index, n, true);
|
state.misc.selected_index = mode::cycle_selected_index(state.misc.selected_index, n, true);
|
||||||
state.dirty = true;
|
state.mark_dirty();
|
||||||
Vec::new()
|
Vec::new()
|
||||||
} else if state.misc.overlay == Overlay::ModelSelector {
|
} else if state.misc.overlay == Overlay::ModelSelector {
|
||||||
let n = state.app_config.providers.len();
|
let n = state.app_config.providers.len();
|
||||||
state.misc.selected_index = mode::cycle_selected_index(state.misc.selected_index, n, true);
|
state.misc.selected_index = mode::cycle_selected_index(state.misc.selected_index, n, true);
|
||||||
state.dirty = true;
|
state.mark_dirty();
|
||||||
Vec::new()
|
Vec::new()
|
||||||
} else if key.modifiers.contains(KeyModifiers::CONTROL) {
|
} else if key.modifiers.contains(KeyModifiers::CONTROL) {
|
||||||
vec![Action::ScrollDown]
|
vec![Action::ScrollDown]
|
||||||
@@ -241,7 +242,7 @@ pub fn handle_key(key: KeyEvent, state: &mut AppStateRest) -> Vec<Action> {
|
|||||||
vec![Action::AbortTurn]
|
vec![Action::AbortTurn]
|
||||||
} else if state.input.autocomplete_visible {
|
} else if state.input.autocomplete_visible {
|
||||||
state.input.close_autocomplete();
|
state.input.close_autocomplete();
|
||||||
state.dirty = true;
|
state.mark_dirty();
|
||||||
Vec::new()
|
Vec::new()
|
||||||
} else if state.misc.overlay.is_active() {
|
} else if state.misc.overlay.is_active() {
|
||||||
vec![Action::CloseOverlay]
|
vec![Action::CloseOverlay]
|
||||||
@@ -256,24 +257,24 @@ pub fn handle_key(key: KeyEvent, state: &mut AppStateRest) -> Vec<Action> {
|
|||||||
} else {
|
} else {
|
||||||
state.input.tab_complete();
|
state.input.tab_complete();
|
||||||
}
|
}
|
||||||
state.dirty = true;
|
state.mark_dirty();
|
||||||
} else if state.input.autocomplete_kind == AutocompleteKind::FileMention
|
} else if state.input.autocomplete_kind == AutocompleteKind::FileMention
|
||||||
&& state.input.autocomplete_visible
|
&& state.input.autocomplete_visible
|
||||||
{
|
{
|
||||||
state.input.cycle_autocomplete(true);
|
state.input.cycle_autocomplete(true);
|
||||||
state.dirty = true;
|
state.mark_dirty();
|
||||||
}
|
}
|
||||||
Vec::new()
|
Vec::new()
|
||||||
}
|
}
|
||||||
KeyCode::Char(c) => {
|
KeyCode::Char(c) => {
|
||||||
if state.input.autocomplete_visible {
|
if state.input.autocomplete_visible {
|
||||||
state.input.close_autocomplete();
|
state.input.close_autocomplete();
|
||||||
state.dirty = true;
|
state.mark_dirty();
|
||||||
}
|
}
|
||||||
// Insert the character inline so we can immediately check the
|
// Insert the character inline so we can immediately check the
|
||||||
// new buffer state for autocomplete triggers.
|
// new buffer state for autocomplete triggers.
|
||||||
state.input.insert(c);
|
state.input.insert(c);
|
||||||
state.dirty = true;
|
state.mark_dirty();
|
||||||
// Show autocomplete immediately when the buffer starts with `/`,
|
// Show autocomplete immediately when the buffer starts with `/`,
|
||||||
// without requiring an extra Tab press.
|
// without requiring an extra Tab press.
|
||||||
if state.input.buffer.starts_with('/') {
|
if state.input.buffer.starts_with('/') {
|
||||||
@@ -304,7 +305,7 @@ fn handle_overlay_enter(state: &mut AppStateRest) -> Vec<Action> {
|
|||||||
}
|
}
|
||||||
Overlay::Settings => {
|
Overlay::Settings => {
|
||||||
mode::settings::cycle_internet_mode(&mut state.settings);
|
mode::settings::cycle_internet_mode(&mut state.settings);
|
||||||
state.dirty = true;
|
state.mark_dirty();
|
||||||
Vec::new()
|
Vec::new()
|
||||||
}
|
}
|
||||||
Overlay::Todo => {
|
Overlay::Todo => {
|
||||||
@@ -330,7 +331,7 @@ fn handle_overlay_enter(state: &mut AppStateRest) -> Vec<Action> {
|
|||||||
state.input.cursor = 0;
|
state.input.cursor = 0;
|
||||||
state.misc.overlay = Overlay::None;
|
state.misc.overlay = Overlay::None;
|
||||||
state.toast_success("API key saved".to_string());
|
state.toast_success("API key saved".to_string());
|
||||||
state.dirty = true;
|
state.mark_dirty();
|
||||||
Vec::new()
|
Vec::new()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -373,13 +374,13 @@ fn handle_overlay_enter(state: &mut AppStateRest) -> Vec<Action> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
state.misc.overlay = Overlay::None;
|
state.misc.overlay = Overlay::None;
|
||||||
state.dirty = true;
|
state.mark_dirty();
|
||||||
Vec::new()
|
Vec::new()
|
||||||
}
|
}
|
||||||
Overlay::ClearConfirm => {
|
Overlay::ClearConfirm => {
|
||||||
state.toast_info("Transcript cleared".to_string());
|
state.toast_info("Transcript cleared".to_string());
|
||||||
state.misc.overlay = Overlay::None;
|
state.misc.overlay = Overlay::None;
|
||||||
state.dirty = true;
|
state.mark_dirty();
|
||||||
Vec::new()
|
Vec::new()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user