A simple CPU rendered GUI IDE experience.
fix some problems
bendn 5 months ago
parent a18b827 · commit b73f13f
-rw-r--r--src/main.rs63
-rw-r--r--src/text.rs28
2 files changed, 66 insertions, 25 deletions
diff --git a/src/main.rs b/src/main.rs
index 021cfdc..5940be9 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -2,7 +2,6 @@
#![feature(tuple_trait, unboxed_closures, fn_traits)]
#![feature(
import_trait_associated_functions,
- guard_patterns,
if_let_guard,
deref_patterns,
generic_const_exprs,
@@ -283,18 +282,21 @@ pub(crate) fn entry(event_loop: EventLoop<()>) {
} if bt.is_pressed() => {
match state.consume(Action::M(button)).unwrap() {
Some(Do::MoveCursor) => {
- let l_i = text.vo + cursor_position.1;
- _ = text.rope.try_line_to_char(l_i).map(|l| {
- text.cursor = l
- + (text.rope.line(l_i).len_chars()
- - 1)
- .min(
- cursor_position.0.saturating_sub(
- text.line_number_offset() + 1,
- ),
- );
- text.setc();
- });
+ text.cursor = text.index_at(cursor_position);
+ text.setc();
+ }
+ Some(Do::ExtendSelectionToMouse) => {
+ *state.sel() = text.extend_selection_to(
+ text.index_at(cursor_position),
+ state.sel().clone(),
+ );
+ }
+ Some(Do::StartSelection) => {
+ let x = text.index_at(cursor_position);
+ *state.sel() = text.extend_selection_to(
+ x,
+ text.cursor..text.cursor,
+ );
}
None => {}
_ => unreachable!(),
@@ -364,29 +366,26 @@ pub(crate) fn entry(event_loop: EventLoop<()>) {
}
Some(Do::Quit) => elwt.exit(),
Some(Do::StartSelection) => {
- let State::Selection(x) = &mut state else {
- panic!()
- };
let Key::Named(y) = event.logical_key else {
panic!()
};
- *x = text.extend_selection(
+ *state.sel() = text.extend_selection(
y,
text.cursor..text.cursor,
);
}
Some(Do::UpdateSelection) => {
- let State::Selection(x) = &mut state else {
- panic!()
- };
let Key::Named(y) = event.logical_key else {
panic!()
};
- *x = text.extend_selection(y, x.clone());
+ *state.sel() = text
+ .extend_selection(y, state.sel().clone());
text.scroll_to_cursor();
}
Some(Do::Insert((x, c))) => {
- text.rope.remove(x);
+ text.rope.remove(x.clone());
+ text.cursor = x.start;
+ text.setc();
text.insert_(c);
}
Some(Do::Delete(x)) => {
@@ -404,7 +403,9 @@ pub(crate) fn entry(event_loop: EventLoop<()>) {
Some(Do::Paste) => {
text.insert(&clipp::paste());
}
- Some(Do::MoveCursor) => {
+ Some(
+ Do::MoveCursor | Do::ExtendSelectionToMouse,
+ ) => {
unreachable!()
}
None => {}
@@ -474,12 +475,19 @@ pub static BIFONT: LazyLock<Instance<'static>> = LazyLock::new(|| {
pub static BFONT: LazyLock<Instance<'static>> =
LazyLock::new(|| FONT.instances().find_by_name("Bold").unwrap());
fn shift() -> bool {
- unsafe { MODIFIERS }.shift_key()
+ dbg!(unsafe { MODIFIERS }.shift_key())
}
fn ctrl() -> bool {
unsafe { MODIFIERS }.control_key()
}
+impl State {
+ fn sel(&mut self) -> &mut Range<usize> {
+ let State::Selection(x) = self else { panic!() };
+ x
+ }
+}
+
// use NamedKey::Arrow
use std::ops::Range;
rust_fsm::state_machine! {
@@ -492,12 +500,17 @@ Default => {
K(Key::Character(x) if x == "q" && ctrl()) => Dead [Quit],
K(Key::Character(x) if x == "v" && ctrl()) => Default [Paste],
K(Key::Named(NamedKey::ArrowUp | NamedKey::ArrowLeft | NamedKey::ArrowDown | NamedKey::ArrowRight | NamedKey::Home | NamedKey::End) if shift()) => Selection(Range<usize> => 0..0) [StartSelection],
+ M(MouseButton => MouseButton::Left if shift()) => Selection(Range<usize> => 0..0) [StartSelection],
M(MouseButton => MouseButton::Left) => Default [MoveCursor],
K(_) => Default [Edit],
M(_) => Default,
},
+Selection(x if shift()) => {
+ K(Key::Named(NamedKey::ArrowUp | NamedKey::ArrowLeft | NamedKey::ArrowDown | NamedKey::ArrowRight | NamedKey::Home | NamedKey::End)) => Selection(x) [UpdateSelection],
+ M(MouseButton => MouseButton::Left) => Selection(x) [ExtendSelectionToMouse],
+},
Selection(x) => {
- K(Key::Named(NamedKey::ArrowUp | NamedKey::ArrowLeft | NamedKey::ArrowDown | NamedKey::ArrowRight | NamedKey::Home | NamedKey::End) if shift()) => Selection(x) [UpdateSelection],
+ M(MouseButton => MouseButton::Left) => Default [MoveCursor],
K(Key::Named(NamedKey::Backspace)) => Default [Delete(Range<usize> => x)],
K(Key::Character(y) if y == "x" && ctrl()) => Default [Cut(Range<usize> => x)],
K(Key::Character(y) if y == "c" && ctrl()) => Default [Copy(Range<usize> => x)],
diff --git a/src/text.rs b/src/text.rs
index 75b9b73..f8b9ee4 100644
--- a/src/text.rs
+++ b/src/text.rs
@@ -99,6 +99,17 @@ impl TextArea {
self.rope.len_lines()
}
+ pub fn index_at(&self, (x, y): (usize, usize)) -> usize {
+ let l_i = self.vo + y;
+ self.rope
+ .try_line_to_char(l_i)
+ .map(|l| {
+ l + (self.rope.line(l_i).len_chars() - 1)
+ .min(x.saturating_sub(self.line_number_offset() + 1))
+ })
+ .unwrap_or(self.rope.len_chars())
+ }
+
pub fn insert_(&mut self, c: SmolStr) {
self.rope.insert(self.cursor, &c);
self.cursor += c.chars().count();
@@ -468,4 +479,21 @@ impl TextArea {
_ => unreachable!(),
}
}
+
+ pub fn extend_selection_to(
+ &mut self,
+ to: usize,
+ r: std::ops::Range<usize>,
+ ) -> std::ops::Range<usize> {
+ let r = if self.cursor == r.start {
+ if to < r.start { to..r.end } else { r.end..to } // to > r.end
+ } else if self.cursor == r.end {
+ if to > r.end { r.start..to } else { to..r.start } // to < r.start
+ } else {
+ panic!()
+ };
+ self.cursor = to;
+ self.setc();
+ r
+ }
}