working perfectly well, except for the letter e

This commit is contained in:
filipriec
2025-02-25 13:19:33 +01:00
parent 820e457525
commit 584ee2f651
3 changed files with 208 additions and 5 deletions

View File

@@ -13,6 +13,12 @@ move_left = ["h"]
move_right = ["l"]
move_up = ["k", "Up"]
move_down = ["j", "Down"]
move_word_next = ["w"] # Move to beginning of next word
move_word_end = ["e"] # Move to end of current/next word
move_word_prev = ["b"] # Move to beginning of previous word
move_word_end_prev = ["ge"] # Move to end of previous word
move_line_start = ["0"] # Move to beginning of line
move_line_end = ["$"] # Move to end of line
[colors]
theme = "dark"

View File

@@ -107,4 +107,15 @@ impl Config {
false
}
}
pub fn has_key_for_action(&self, action: &str, key_char: char) -> bool {
if let Some(bindings) = self.keybindings.get(action) {
for binding in bindings {
if binding == &key_char.to_string() {
return true;
}
}
}
false
}
}

View File

@@ -16,6 +16,13 @@ pub struct EventHandler {
pub ideal_cursor_column: usize,
}
#[derive(PartialEq)]
enum CharType {
Whitespace,
Alphanumeric,
Punctuation,
}
impl EventHandler {
pub fn new() -> Self {
EventHandler {
@@ -95,11 +102,6 @@ impl EventHandler {
];
let current_input = form_state.get_current_input();
let max_cursor_pos = if !self.is_edit_mode && !current_input.is_empty() {
current_input.len() - 1
} else {
current_input.len()
};
let max_cursor_pos = if !self.is_edit_mode && !current_input.is_empty() {
current_input.len() - 1 // In readonly mode, limit to last character
} else {
@@ -213,6 +215,55 @@ impl EventHandler {
form_state.current_cursor_pos = self.ideal_cursor_column.min(max_cursor_pos);
return Ok((false, "".to_string()));
}
"move_word_next" => {
let current_input = form_state.get_current_input();
if !current_input.is_empty() {
let new_pos = self.find_next_word_start(current_input, form_state.current_cursor_pos);
form_state.current_cursor_pos = new_pos.min(current_input.len().saturating_sub(1));
self.ideal_cursor_column = form_state.current_cursor_pos;
}
return Ok((false, "".to_string()));
}
"move_word_end" => {
let current_input = form_state.get_current_input();
if !current_input.is_empty() {
let new_pos = self.find_word_end(current_input, form_state.current_cursor_pos);
form_state.current_cursor_pos = new_pos.min(current_input.len().saturating_sub(1));
self.ideal_cursor_column = form_state.current_cursor_pos;
}
return Ok((false, "".to_string()));
}
"move_word_prev" => {
let current_input = form_state.get_current_input();
if !current_input.is_empty() {
let new_pos = self.find_prev_word_start(current_input, form_state.current_cursor_pos);
form_state.current_cursor_pos = new_pos;
self.ideal_cursor_column = form_state.current_cursor_pos;
}
return Ok((false, "".to_string()));
}
"move_word_end_prev" => {
let current_input = form_state.get_current_input();
if !current_input.is_empty() {
let new_pos = self.find_prev_word_end(current_input, form_state.current_cursor_pos);
form_state.current_cursor_pos = new_pos;
self.ideal_cursor_column = form_state.current_cursor_pos;
}
return Ok((false, "".to_string()));
}
"move_line_start" => {
form_state.current_cursor_pos = 0;
self.ideal_cursor_column = form_state.current_cursor_pos;
return Ok((false, "".to_string()));
}
"move_line_end" => {
let current_input = form_state.get_current_input();
if !current_input.is_empty() {
form_state.current_cursor_pos = current_input.len() - 1;
self.ideal_cursor_column = form_state.current_cursor_pos;
}
return Ok((false, "".to_string()));
}
_ => {}
}
}
@@ -485,4 +536,139 @@ impl EventHandler {
self.edit_mode_cooldown = false;
Ok((false, self.command_message.clone()))
}
// Helper function to determine character type
fn get_char_type(c: char) -> CharType {
if c.is_whitespace() {
CharType::Whitespace
} else if c.is_alphanumeric() {
CharType::Alphanumeric
} else {
CharType::Punctuation
}
}
// Find the beginning of the next word from current position
fn find_next_word_start(&self, text: &str, current_pos: usize) -> usize {
let chars: Vec<char> = text.chars().collect();
if chars.is_empty() || current_pos >= chars.len() {
return current_pos;
}
let mut pos = current_pos;
// Step 1: Skip current word/set of similar characters
let initial_type = Self::get_char_type(chars[pos]);
while pos < chars.len() && Self::get_char_type(chars[pos]) == initial_type {
pos += 1;
}
// Step 2: Skip any whitespace
while pos < chars.len() && Self::get_char_type(chars[pos]) == CharType::Whitespace {
pos += 1;
}
pos
}
// Find the end of the current/next word
fn find_word_end(&self, text: &str, current_pos: usize) -> usize {
let chars: Vec<char> = text.chars().collect();
if chars.is_empty() || current_pos >= chars.len() - 1 {
return if chars.is_empty() { 0 } else { chars.len() - 1 };
}
let mut pos = current_pos;
// Skip whitespace to find the next word
while pos < chars.len() && Self::get_char_type(chars[pos]) == CharType::Whitespace {
pos += 1;
}
if pos == chars.len() {
return pos.saturating_sub(1);
}
let word_type = Self::get_char_type(chars[pos]);
// Move to the end of this word
while pos < chars.len() - 1 && Self::get_char_type(chars[pos + 1]) == word_type {
pos += 1;
}
pos
}
// Find the beginning of the previous word
fn find_prev_word_start(&self, text: &str, current_pos: usize) -> usize {
let chars: Vec<char> = text.chars().collect();
if chars.is_empty() || current_pos == 0 {
return 0;
}
let mut pos = current_pos.saturating_sub(1);
// Step 1: Skip any whitespace backward
while pos > 0 && Self::get_char_type(chars[pos]) == CharType::Whitespace {
pos -= 1;
}
if Self::get_char_type(chars[pos]) != CharType::Whitespace {
// Step 2: Find the beginning of this word
let word_type = Self::get_char_type(chars[pos]);
while pos > 0 && Self::get_char_type(chars[pos - 1]) == word_type {
pos -= 1;
}
}
pos
}
// Find the end of the previous word
fn find_prev_word_end(&self, text: &str, current_pos: usize) -> usize {
let chars: Vec<char> = text.chars().collect();
if chars.is_empty() || current_pos <= 1 {
return 0;
}
let mut pos = current_pos.saturating_sub(1);
// Step 1: Skip any whitespace backward
while pos > 0 && Self::get_char_type(chars[pos]) == CharType::Whitespace {
pos -= 1;
}
// If we hit a non-whitespace character, find the beginning of this word
if pos > 0 && Self::get_char_type(chars[pos]) != CharType::Whitespace {
let word_type = Self::get_char_type(chars[pos]);
// Step 2: Skip backward past this word
while pos > 0 && Self::get_char_type(chars[pos - 1]) == word_type {
pos -= 1;
}
// Step 3: Skip whitespace before this word
while pos > 0 && Self::get_char_type(chars[pos - 1]) == CharType::Whitespace {
pos -= 1;
}
// Step 4: Find end of previous word
if pos > 0 {
pos -= 1;
let prev_word_type = Self::get_char_type(chars[pos]);
while pos > 0 && Self::get_char_type(chars[pos - 1]) == prev_word_type {
pos -= 1;
}
// Find the end of this word
while pos < chars.len() - 1 &&
Self::get_char_type(chars[pos + 1]) == prev_word_type {
pos += 1;
}
}
}
pos
}
}