Compare commits

1 Commits

Author SHA1 Message Date
fc89826794 ctrl a & word movement 2025-11-22 15:01:22 -05:00

View File

@@ -169,12 +169,20 @@ impl<'a> TextEditCtx<'a> {
.cursor_motion(self.font_system, cursor, None, motion) .cursor_motion(self.font_system, cursor, None, motion)
{ {
self.text.selection = TextSelection::Pos(cursor); self.text.selection = TextSelection::Pos(cursor);
} else if let TextSelection::Span { start, end } = self.text.selection {
let (start, end) = sort_cursors(start, end);
let sel = &mut self.text.selection;
match motion {
Motion::Left | Motion::LeftWord => *sel = TextSelection::Pos(start),
Motion::Right | Motion::RightWord => *sel = TextSelection::Pos(end),
_ => (),
}
} }
} }
pub fn replace(&mut self, len: usize, text: &str) { pub fn replace(&mut self, len: usize, text: &str) {
for _ in 0..len { for _ in 0..len {
self.delete(); self.delete(false);
} }
self.insert_inner(text, false); self.insert_inner(text, false);
} }
@@ -193,6 +201,16 @@ impl<'a> TextEditCtx<'a> {
pub fn clear_span(&mut self) -> bool { pub fn clear_span(&mut self) -> bool {
if let TextSelection::Span { start, end } = self.text.selection { if let TextSelection::Span { start, end } = self.text.selection {
self.delete_between(start, end);
let (start, _) = sort_cursors(start, end);
self.text.selection = TextSelection::Pos(start);
true
} else {
false
}
}
pub fn delete_between(&mut self, start: Cursor, end: Cursor) {
let lines = &mut self.text.view.buf.lines; let lines = &mut self.text.view.buf.lines;
let (start, end) = sort_cursors(start, end); let (start, end) = sort_cursors(start, end);
if start.line == end.line { if start.line == end.line {
@@ -212,11 +230,6 @@ impl<'a> TextEditCtx<'a> {
if !range.is_empty() { if !range.is_empty() {
lines.splice(range, None); lines.splice(range, None);
} }
self.text.selection = TextSelection::Pos(start);
true
} else {
false
}
} }
fn insert_inner(&mut self, text: &str, mov: bool) { fn insert_inner(&mut self, text: &str, mov: bool) {
@@ -246,20 +259,30 @@ impl<'a> TextEditCtx<'a> {
} }
} }
pub fn backspace(&mut self) { pub fn backspace(&mut self, word: bool) {
if !self.clear_span() if !self.clear_span()
&& let TextSelection::Pos(cursor) = &mut self.text.selection && let TextSelection::Pos(cursor) = &mut self.text.selection
&& (cursor.index != 0 || cursor.line != 0) && (cursor.index != 0 || cursor.line != 0)
{ {
self.motion(Motion::Left); self.motion(if word { Motion::LeftWord } else { Motion::Left });
self.delete(); self.delete(word);
} }
} }
pub fn delete(&mut self) { pub fn delete(&mut self, word: bool) {
if !self.clear_span() if !self.clear_span()
&& let TextSelection::Pos(cursor) = &mut self.text.selection && let TextSelection::Pos(cursor) = &mut self.text.selection
{ {
if word {
let start = *cursor;
if let Some((end, _)) =
self.text
.buf
.cursor_motion(self.font_system, start, None, Motion::RightWord)
{
self.delete_between(start, end);
}
} else {
let lines = &mut self.text.view.buf.lines; let lines = &mut self.text.view.buf.lines;
let line = &mut lines[cursor.line]; let line = &mut lines[cursor.line];
if cursor.index == line.text().len() { if cursor.index == line.text().len() {
@@ -278,6 +301,7 @@ impl<'a> TextEditCtx<'a> {
} }
} }
} }
}
pub fn select(&mut self, pos: Vec2, size: Vec2, drag: bool) { pub fn select(&mut self, pos: Vec2, size: Vec2, drag: bool) {
let pos = pos - self.text.region().top_left().to_abs(size); let pos = pos - self.text.region().top_left().to_abs(size);
@@ -316,8 +340,8 @@ impl<'a> TextEditCtx<'a> {
pub fn apply_event(&mut self, event: &KeyEvent, modifiers: &Modifiers) -> TextInputResult { pub fn apply_event(&mut self, event: &KeyEvent, modifiers: &Modifiers) -> TextInputResult {
match &event.logical_key { match &event.logical_key {
Key::Named(named) => match named { Key::Named(named) => match named {
NamedKey::Backspace => self.backspace(), NamedKey::Backspace => self.backspace(modifiers.control),
NamedKey::Delete => self.delete(), NamedKey::Delete => self.delete(modifiers.control),
NamedKey::Space => self.insert(" "), NamedKey::Space => self.insert(" "),
NamedKey::Enter => { NamedKey::Enter => {
if modifiers.shift { if modifiers.shift {
@@ -326,8 +350,20 @@ impl<'a> TextEditCtx<'a> {
return TextInputResult::Submit; return TextInputResult::Submit;
} }
} }
NamedKey::ArrowRight => self.motion(Motion::Right), NamedKey::ArrowRight => {
NamedKey::ArrowLeft => self.motion(Motion::Left), if modifiers.control {
self.motion(Motion::RightWord)
} else {
self.motion(Motion::Right)
}
}
NamedKey::ArrowLeft => {
if modifiers.control {
self.motion(Motion::LeftWord)
} else {
self.motion(Motion::Left)
}
}
NamedKey::ArrowUp => self.motion(Motion::Up), NamedKey::ArrowUp => self.motion(Motion::Up),
NamedKey::ArrowDown => self.motion(Motion::Down), NamedKey::ArrowDown => self.motion(Motion::Down),
NamedKey::Escape => { NamedKey::Escape => {
@@ -345,12 +381,25 @@ impl<'a> TextEditCtx<'a> {
let content = self.text.select_content(start, end); let content = self.text.select_content(start, end);
return TextInputResult::Copy(content); return TextInputResult::Copy(content);
} }
return TextInputResult::Used;
} }
_ => (), "a" => {
if !self.text.buf.lines[0].text().is_empty()
|| self.text.buf.lines.len() > 1
{
let lines = &self.text.buf.lines;
let last_line = lines.len() - 1;
let last_idx = lines[last_line].text().len();
self.text.selection = TextSelection::Span {
start: Cursor::new(0, 0),
end: Cursor::new(last_line, last_idx),
};
} }
} }
self.insert(text) _ => self.insert(text),
}
} else {
self.insert(text);
}
} }
_ => return TextInputResult::Unused, _ => return TextInputResult::Unused,
} }
@@ -380,7 +429,7 @@ pub enum TextInputResult {
Paste, Paste,
} }
#[derive(Default)] #[derive(Debug, Default)]
pub enum TextSelection { pub enum TextSelection {
#[default] #[default]
None, None,