Compare commits

...

2 Commits

Author SHA1 Message Date
Joe Bellus 3b6f7cdbf4 Implemented Change Word
continuous-integration/drone/push Build is passing Details
Change word forward and backward were implemented in the editor_data
and bound in the editor to "cw" and "cb" respectively.

Scan word forward and scan word backward now utilize a shared function
that gets the scan position. This is now also used for delete word
forward/backward, so they can share logic

Updated keybinds in README
2022-10-17 02:00:25 -04:00
Joe Bellus e239573903 Shift Arrow Selection
Fixed issues where shift + arrow keys would not select text. This
creates an issue with cursor movements after using shift + arrow
keys. Further cursor movements retain the selection mode and allow
selecting. Cursor movements should clear the active
selection. However, this would invalidate the ability for selecting
via marking selection (v).

Selection marking will be refactored, which will fix this inconsistency.
2022-10-17 01:27:22 -04:00
3 changed files with 76 additions and 43 deletions

View File

@ -32,6 +32,9 @@ In normal mode the cursor is a block and functional keybinds can be used for mov
| w | Scan forward a word |
| v | Mark selection |
| x | Delete current character or selection |
| dd | Delete the current line |
| cw | Change word forward |
| cb | Change word backward |
** Insert mode
In insert mode the cursor is a line and text can be edited. To return to normal mode use the ESC key.

View File

@ -104,37 +104,63 @@ impl EditorData {
self.deselect();
}
pub fn word_scan_forward(&mut self) {
while self.cursor_pos < self.content.len_chars() {
self.cursor_pos += 1;
if !self
.current_char()
.map(|c| c.is_alphanumeric())
.unwrap_or(false)
pub fn get_word_scan_forward_position(&mut self, skip_first: bool) -> usize {
if self.cursor_pos < self.content.len_chars() {
for (idx, ch) in self
.content
.chars_at(self.cursor_pos)
.skip(if skip_first { 1 } else { 0 })
.enumerate()
{
break;
if !ch.is_alphanumeric() {
return (idx + self.cursor_pos + 2).min(self.content.len_chars());
}
}
self.deselect();
self.content.len_chars()
} else {
self.content.len_chars()
}
}
pub fn word_scan_backward(&mut self) {
if self.cursor_pos > 0 {
self.cursor_pos -= 1;
pub fn get_word_scan_backward_position(&mut self, skip_first: bool) -> usize {
let mut pos = self.cursor_pos;
if pos > 0 && skip_first {
pos -= 1;
}
while self.cursor_pos > 0 {
while pos > 0 {
if !self
.content
.get_char(self.cursor_pos - 1)
.get_char(pos - 1)
.map(|c| c.is_alphanumeric())
.unwrap_or(false)
{
break;
} else {
self.cursor_pos -= 1;
pos -= 1;
}
self.deselect();
}
pos
}
pub fn delete_word_forward(&mut self) {
let end = self.get_word_scan_forward_position(false);
self.content.remove(self.cursor_pos..end);
}
pub fn delete_word_backward(&mut self) {
let start = self.get_word_scan_backward_position(true);
self.content.remove(start..self.cursor_pos);
self.cursor_pos = start;
}
pub fn word_scan_forward(&mut self) {
self.cursor_pos = self.get_word_scan_forward_position(true);
self.deselect();
}
pub fn word_scan_backward(&mut self) {
self.cursor_pos = self.get_word_scan_backward_position(true);
self.deselect();
}
pub fn delete_char_forward(&mut self) {
@ -201,15 +227,8 @@ impl EditorData {
}
pub fn select_up(&mut self) {
let line_idx = self.content.char_to_line(self.cursor_pos);
if line_idx > 0 {
let start_of_current_line = self.content.line_to_char(line_idx);
let line_pos = self.cursor_pos - start_of_current_line;
let up_line_start = self.content.line_to_char(line_idx - 1);
let up_line = self.content.line(line_idx - 1);
self.cursor_pos = up_line_start + line_pos.min(up_line.len_chars() - 1);
}
self.start_selection();
self.cursor_up();
}
pub fn cursor_down(&mut self) {
@ -225,17 +244,8 @@ impl EditorData {
}
pub fn select_down(&mut self) {
//12 -> 11
let line_idx = self.content.char_to_line(self.cursor_pos);
if line_idx < self.content.len_lines() - 1 {
let start_of_current_line = self.content.line_to_char(line_idx);
let line_pos = self.cursor_pos - start_of_current_line;
let start_of_next_line = self.content.line_to_char(line_idx + 1) + 1;
let next_line_len = self.content.line(line_idx + 1).len_chars();
self.cursor_pos =
(start_of_next_line + line_pos.min(next_line_len)).min(start_of_next_line);
}
self.start_selection();
self.cursor_down();
}
pub fn cursor_right(&mut self) {
@ -281,21 +291,24 @@ impl EditorData {
self.deselect();
}
pub fn insert_mode(&mut self) {
self.mode = EditMode::Insert;
self.deselect();
}
pub fn select_all(&mut self) {
self.selection_pos = Some(0);
self.cursor_pos = self.content.len_chars();
}
pub fn select_left(&mut self) {
if self.cursor_pos > 0 {
self.cursor_pos -= 1
}
self.start_selection();
self.cursor_left();
}
pub fn select_right(&mut self) {
if self.cursor_pos < self.content.len_chars() {
self.cursor_pos += 1;
}
self.start_selection();
self.cursor_right();
}
pub fn current_line(&self) -> ropey::RopeSlice {
@ -310,6 +323,12 @@ impl EditorData {
.unwrap()
}
pub fn start_selection(&mut self) {
if self.selection_pos.is_none() {
self.selection_pos = Some(self.cursor_pos);
}
}
pub fn current_line_index(&self) -> usize {
self.content.char_to_line(self.cursor_pos)
}

View File

@ -36,6 +36,8 @@ mod keymap {
pub const WORD_FORWARD: &str = "w";
pub const WORD_BACK: &str = "b";
pub const SELECT_MODE: &str = "v";
pub const CHANGE_WORD_FORWARD: &str = "cw";
pub const CHANGE_WORD_BACKWARD: &str = "cb";
#[derive(Debug, Default)]
pub struct KeyList {
@ -63,6 +65,8 @@ mod keymap {
WORD_FORWARD,
WORD_BACK,
SELECT_MODE,
CHANGE_WORD_FORWARD,
CHANGE_WORD_BACKWARD,
],
}
}
@ -360,6 +364,14 @@ impl Widget<EditorData> for AbacusEditor {
Some(keymap::SELECT_MODE) => {
data.selection_pos = Some(data.cursor_pos);
}
Some(keymap::CHANGE_WORD_FORWARD) => {
data.delete_word_forward();
data.insert_mode();
}
Some(keymap::CHANGE_WORD_BACKWARD) => {
data.delete_word_backward();
data.insert_mode();
}
_ => {}
}
}
@ -414,7 +426,6 @@ impl Widget<EditorData> for AbacusEditor {
druid::keyboard_types::Key::ArrowUp if e.mods.shift() => {
data.select_up();
data.deselect();
}
druid::keyboard_types::Key::ArrowDown if e.mods.shift() => {
data.select_down();