Compare commits
1 Commits
140be50baa
...
fc89826794
| Author | SHA1 | Date | |
|---|---|---|---|
| fc89826794 |
@@ -169,12 +169,20 @@ impl<'a> TextEditCtx<'a> {
|
||||
.cursor_motion(self.font_system, cursor, None, motion)
|
||||
{
|
||||
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) {
|
||||
for _ in 0..len {
|
||||
self.delete();
|
||||
self.delete(false);
|
||||
}
|
||||
self.insert_inner(text, false);
|
||||
}
|
||||
@@ -193,25 +201,8 @@ impl<'a> TextEditCtx<'a> {
|
||||
|
||||
pub fn clear_span(&mut self) -> bool {
|
||||
if let TextSelection::Span { start, end } = self.text.selection {
|
||||
let lines = &mut self.text.view.buf.lines;
|
||||
let (start, end) = sort_cursors(start, end);
|
||||
if start.line == end.line {
|
||||
let line = &mut lines[start.line];
|
||||
let text = line.text();
|
||||
let text = text[..start.index].to_string() + &text[end.index..];
|
||||
edit_line(line, text);
|
||||
} else {
|
||||
// start
|
||||
let start_text = lines[start.line].text()[..start.index].to_string();
|
||||
let end_text = &lines[end.line].text()[end.index..];
|
||||
let text = start_text + end_text;
|
||||
edit_line(&mut lines[start.line], text);
|
||||
}
|
||||
// between
|
||||
let range = (start.line + 1)..=end.line;
|
||||
if !range.is_empty() {
|
||||
lines.splice(range, None);
|
||||
}
|
||||
self.delete_between(start, end);
|
||||
let (start, _) = sort_cursors(start, end);
|
||||
self.text.selection = TextSelection::Pos(start);
|
||||
true
|
||||
} else {
|
||||
@@ -219,6 +210,28 @@ impl<'a> TextEditCtx<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn delete_between(&mut self, start: Cursor, end: Cursor) {
|
||||
let lines = &mut self.text.view.buf.lines;
|
||||
let (start, end) = sort_cursors(start, end);
|
||||
if start.line == end.line {
|
||||
let line = &mut lines[start.line];
|
||||
let text = line.text();
|
||||
let text = text[..start.index].to_string() + &text[end.index..];
|
||||
edit_line(line, text);
|
||||
} else {
|
||||
// start
|
||||
let start_text = lines[start.line].text()[..start.index].to_string();
|
||||
let end_text = &lines[end.line].text()[end.index..];
|
||||
let text = start_text + end_text;
|
||||
edit_line(&mut lines[start.line], text);
|
||||
}
|
||||
// between
|
||||
let range = (start.line + 1)..=end.line;
|
||||
if !range.is_empty() {
|
||||
lines.splice(range, None);
|
||||
}
|
||||
}
|
||||
|
||||
fn insert_inner(&mut self, text: &str, mov: bool) {
|
||||
self.clear_span();
|
||||
if let TextSelection::Pos(cursor) = &mut self.text.selection {
|
||||
@@ -246,35 +259,46 @@ impl<'a> TextEditCtx<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn backspace(&mut self) {
|
||||
pub fn backspace(&mut self, word: bool) {
|
||||
if !self.clear_span()
|
||||
&& let TextSelection::Pos(cursor) = &mut self.text.selection
|
||||
&& (cursor.index != 0 || cursor.line != 0)
|
||||
{
|
||||
self.motion(Motion::Left);
|
||||
self.delete();
|
||||
self.motion(if word { Motion::LeftWord } else { Motion::Left });
|
||||
self.delete(word);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn delete(&mut self) {
|
||||
pub fn delete(&mut self, word: bool) {
|
||||
if !self.clear_span()
|
||||
&& let TextSelection::Pos(cursor) = &mut self.text.selection
|
||||
{
|
||||
let lines = &mut self.text.view.buf.lines;
|
||||
let line = &mut lines[cursor.line];
|
||||
if cursor.index == line.text().len() {
|
||||
if cursor.line == lines.len() - 1 {
|
||||
return;
|
||||
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);
|
||||
}
|
||||
let add = lines.remove(cursor.line + 1).into_text();
|
||||
let line = &mut lines[cursor.line];
|
||||
let mut cur = line.text().to_string();
|
||||
cur.push_str(&add);
|
||||
edit_line(line, cur);
|
||||
} else {
|
||||
let mut text = line.text().to_string();
|
||||
text.remove(cursor.index);
|
||||
edit_line(line, text);
|
||||
let lines = &mut self.text.view.buf.lines;
|
||||
let line = &mut lines[cursor.line];
|
||||
if cursor.index == line.text().len() {
|
||||
if cursor.line == lines.len() - 1 {
|
||||
return;
|
||||
}
|
||||
let add = lines.remove(cursor.line + 1).into_text();
|
||||
let line = &mut lines[cursor.line];
|
||||
let mut cur = line.text().to_string();
|
||||
cur.push_str(&add);
|
||||
edit_line(line, cur);
|
||||
} else {
|
||||
let mut text = line.text().to_string();
|
||||
text.remove(cursor.index);
|
||||
edit_line(line, text);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -316,8 +340,8 @@ impl<'a> TextEditCtx<'a> {
|
||||
pub fn apply_event(&mut self, event: &KeyEvent, modifiers: &Modifiers) -> TextInputResult {
|
||||
match &event.logical_key {
|
||||
Key::Named(named) => match named {
|
||||
NamedKey::Backspace => self.backspace(),
|
||||
NamedKey::Delete => self.delete(),
|
||||
NamedKey::Backspace => self.backspace(modifiers.control),
|
||||
NamedKey::Delete => self.delete(modifiers.control),
|
||||
NamedKey::Space => self.insert(" "),
|
||||
NamedKey::Enter => {
|
||||
if modifiers.shift {
|
||||
@@ -326,8 +350,20 @@ impl<'a> TextEditCtx<'a> {
|
||||
return TextInputResult::Submit;
|
||||
}
|
||||
}
|
||||
NamedKey::ArrowRight => self.motion(Motion::Right),
|
||||
NamedKey::ArrowLeft => self.motion(Motion::Left),
|
||||
NamedKey::ArrowRight => {
|
||||
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::ArrowDown => self.motion(Motion::Down),
|
||||
NamedKey::Escape => {
|
||||
@@ -345,12 +381,25 @@ impl<'a> TextEditCtx<'a> {
|
||||
let content = self.text.select_content(start, end);
|
||||
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),
|
||||
}
|
||||
} else {
|
||||
self.insert(text);
|
||||
}
|
||||
self.insert(text)
|
||||
}
|
||||
_ => return TextInputResult::Unused,
|
||||
}
|
||||
@@ -380,7 +429,7 @@ pub enum TextInputResult {
|
||||
Paste,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
#[derive(Debug, Default)]
|
||||
pub enum TextSelection {
|
||||
#[default]
|
||||
None,
|
||||
|
||||
Reference in New Issue
Block a user