working perfectly well, except for the letter e
This commit is contained in:
@@ -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"
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user