fixing issues in the edit/normal mode
This commit is contained in:
@@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
#[cfg(feature = "cursor-style")]
|
#[cfg(feature = "cursor-style")]
|
||||||
use crate::canvas::CursorManager;
|
use crate::canvas::CursorManager;
|
||||||
|
#[cfg(feature = "cursor-style")]
|
||||||
|
use crossterm;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use crate::canvas::state::EditorState;
|
use crate::canvas::state::EditorState;
|
||||||
@@ -162,6 +164,18 @@ impl<D: DataProvider> FormEditor<D> {
|
|||||||
#[cfg(feature = "cursor-style")]
|
#[cfg(feature = "cursor-style")]
|
||||||
if old_mode != mode {
|
if old_mode != mode {
|
||||||
let _ = crate::canvas::CursorManager::update_for_mode(mode);
|
let _ = crate::canvas::CursorManager::update_for_mode(mode);
|
||||||
|
|
||||||
|
// IMMEDIATELY update terminal cursor position for the new mode
|
||||||
|
// This prevents flicker by ensuring position and style change atomically
|
||||||
|
if let Ok((x, y)) = crossterm::cursor::position() {
|
||||||
|
let display_pos = self.display_cursor_position();
|
||||||
|
let current_text = self.current_text();
|
||||||
|
let adjusted_x = x.saturating_sub(current_text.len() as u16) + display_pos as u16;
|
||||||
|
let _ = crossterm::execute!(
|
||||||
|
std::io::stdout(),
|
||||||
|
crossterm::cursor::MoveTo(adjusted_x, y)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -459,7 +473,19 @@ impl<D: DataProvider> FormEditor<D> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Exit edit mode to read-only mode (vim Escape)
|
/// Exit edit mode to read-only mode (vim Escape)
|
||||||
|
// TODO this is still flickering, I have no clue how to fix it
|
||||||
pub fn exit_edit_mode(&mut self) {
|
pub fn exit_edit_mode(&mut self) {
|
||||||
|
// Adjust cursor position when transitioning from edit to normal mode
|
||||||
|
let current_text = self.current_text();
|
||||||
|
if !current_text.is_empty() {
|
||||||
|
// In normal mode, cursor must be ON a character, not after the last one
|
||||||
|
let max_normal_pos = current_text.len().saturating_sub(1);
|
||||||
|
if self.ui_state.cursor_pos > max_normal_pos {
|
||||||
|
self.ui_state.cursor_pos = max_normal_pos;
|
||||||
|
self.ui_state.ideal_cursor_column = self.ui_state.cursor_pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self.set_mode(AppMode::ReadOnly);
|
self.set_mode(AppMode::ReadOnly);
|
||||||
// Deactivate autocomplete when exiting edit mode
|
// Deactivate autocomplete when exiting edit mode
|
||||||
self.ui_state.deactivate_autocomplete();
|
self.ui_state.deactivate_autocomplete();
|
||||||
@@ -540,6 +566,26 @@ impl<D: DataProvider> FormEditor<D> {
|
|||||||
self.ui_state.ideal_cursor_column = clamped_pos;
|
self.ui_state.ideal_cursor_column = clamped_pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get cursor position for display (respects mode-specific positioning rules)
|
||||||
|
pub fn display_cursor_position(&self) -> usize {
|
||||||
|
let current_text = self.current_text();
|
||||||
|
|
||||||
|
match self.ui_state.current_mode {
|
||||||
|
AppMode::Edit => {
|
||||||
|
// Edit mode: cursor can be past end of text
|
||||||
|
self.ui_state.cursor_pos.min(current_text.len())
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
// Normal/other modes: cursor must be on a character
|
||||||
|
if current_text.is_empty() {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
self.ui_state.cursor_pos.min(current_text.len().saturating_sub(1))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Cleanup cursor style (call this when shutting down)
|
/// Cleanup cursor style (call this when shutting down)
|
||||||
pub fn cleanup_cursor(&self) -> std::io::Result<()> {
|
pub fn cleanup_cursor(&self) -> std::io::Result<()> {
|
||||||
#[cfg(feature = "cursor-style")]
|
#[cfg(feature = "cursor-style")]
|
||||||
|
|||||||
Reference in New Issue
Block a user