A simple CPU rendered GUI IDE experience.
Diffstat (limited to 'src/main.rs')
| -rw-r--r-- | src/main.rs | 186 |
1 files changed, 111 insertions, 75 deletions
diff --git a/src/main.rs b/src/main.rs index 5935a9f..6899a92 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,8 @@ +// this looks pretty good though #![feature(tuple_trait, unboxed_closures, fn_traits)] #![feature( + import_trait_associated_functions, + guard_patterns, if_let_guard, deref_patterns, generic_const_exprs, @@ -17,6 +20,7 @@ use std::simd::prelude::*; use std::sync::LazyLock; use std::time::Instant; +use Default::default; use array_chunks::*; use atools::prelude::*; use dsb::cell::Style; @@ -26,10 +30,9 @@ use rust_fsm::StateMachineImpl; use swash::{FontRef, Instance}; use winit::event::{ElementState, Event, MouseScrollDelta, WindowEvent}; use winit::event_loop::{ControlFlow, EventLoop}; -use winit::keyboard::{Key, NamedKey}; +use winit::keyboard::{Key, ModifiersState, NamedKey}; use crate::bar::Bar; -use crate::bar::state::{Input, State}; use crate::text::TextArea; mod bar; mod text; @@ -38,6 +41,8 @@ fn main() { entry(EventLoop::new().unwrap()) } +static mut MODIFIERS: ModifiersState = ModifiersState::empty(); + const BG: [u8; 3] = [31, 36, 48]; const FG: [u8; 3] = [204, 202, 194]; #[implicit_fn::implicit_fn] @@ -48,16 +53,14 @@ pub(crate) fn entry(event_loop: EventLoop<()>) { let mut text = TextArea::default(); let mut origin = std::env::args().nth(1); let mut fonts = dsb::Fonts::new( - *FONT, F::instance(*FONT, *BFONT), + *FONT, *IFONT, F::instance(*IFONT, *BIFONT), ); - let mut bar = Bar { - text: TextArea::default(), - state: bar::state::StateMachine::new(), - last_action: String::default(), - }; + let mut state = State::Default; + let mut bar = + Bar { text: TextArea::default(), last_action: String::default() }; let mut i = Image::build(1, 1).fill(BG); let mut cells = vec![]; std::env::args().nth(1).map(|x| { @@ -101,7 +104,6 @@ pub(crate) fn entry(event_loop: EventLoop<()>) { window.inner_size().height as _, ), ); - dbg!(&bar.state); match event { Event::WindowEvent { window_id, @@ -167,12 +169,15 @@ pub(crate) fn entry(event_loop: EventLoop<()>) { (&mut cells, (c, r)), (t_ox, 0), ); + text.c = c - t_ox; + text.r = r - 1; bar.write_to( BG, FG, (&mut cells, (c, r)), r - 1, &origin.as_deref().unwrap_or("new buffer"), + &state, ); println!("cell="); @@ -264,89 +269,56 @@ pub(crate) fn entry(event_loop: EventLoop<()>) { } } Event::WindowEvent { - event: WindowEvent::KeyboardInput { event, .. }, + event: WindowEvent::ModifiersChanged(modifiers), .. - } if event.state == ElementState::Released - && *bar.state.state() == State::Control - && event.logical_key == NamedKey::Control => - { - bar.state.consume(&Input::Released).unwrap(); + } => { + unsafe { MODIFIERS = modifiers.state() }; window.request_redraw(); } Event::WindowEvent { event: WindowEvent::KeyboardInput { event, .. }, .. - } if *bar.state.state() == State::Control - && event.state == ElementState::Pressed => - { - use Key::*; - match event.logical_key { - Character(x) if x == "s" => match &origin { + } if event.state == ElementState::Pressed => { + let o = state + .consume(Action::K(event.logical_key.clone())) + .unwrap(); + match o { + Some(Do::Save) => match &origin { Some(_) => { - bar.state.consume(&Input::Saved).unwrap(); + state.consume(Action::Saved).unwrap(); save!(); } None => { - bar.state - .consume(&Input::WaitingForFname) + state + .consume(Action::RequireFilename) .unwrap(); } }, - // Character(x) - // if x == "s" - // && => - // { - // bar.state.consume(State::Save); - // text.rope - // .write_to(File::open(origin).unwrap()) - // .unwrap(); - // } - // Character(x) if x == "s" => {} - _ => panic!(), - } - window.request_redraw(); - } - - Event::WindowEvent { - event: WindowEvent::KeyboardInput { event, .. }, - .. - } if event.state == ElementState::Pressed => { - use Key::*; - use NamedKey::*; - let text = if bar.state.state() == &State::InputFname { - &mut bar.text - } else { - &mut text - }; - match event.logical_key { - Named(Space) => text.insert(" "), - Named(Backspace) => text.backspace(), - Named(ArrowLeft) => text.left(), - Named(Home) => text.home(), - Named(End) => text.end(), - Named(ArrowRight) => text.right(), - Named(ArrowUp) => text.up(), - Named(ArrowDown) => text.down(r), - Named(Enter) - if bar.state.state() == &State::InputFname => - { - bar.state.consume(&Input::Enter).unwrap(); - origin = Some( - std::mem::take(&mut bar.text) - .rope - .to_string(), - ); + Some(Do::SaveTo(x)) => { + origin = Some(x); save!(); } - Named(Enter) => text.enter(), - Named(Control) => { - bar.state.consume(&Input::Control).unwrap(); + Some(Do::Edit) => { + handle2(event.logical_key, &mut text); } - Character(x) => { - text.insert(&*x); + Some(Do::Quit) => elwt.exit(), + Some(Do::StartSelection) => { + let State::Selection(x) = &mut state else { + panic!() + }; + *x = 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()); + } + None => {} + } window.request_redraw(); } _ => {} @@ -356,6 +328,31 @@ pub(crate) fn entry(event_loop: EventLoop<()>) { winit_app::run_app(event_loop, app); } + +fn handle2(key: Key, text: &mut TextArea) { + use Key::*; + use NamedKey::*; + + match key { + Named(Space) => text.insert(" "), + Named(Backspace) => text.backspace(), + Named(ArrowLeft) => text.left(), + Named(Home) => text.home(), + Named(End) => text.end(), + Named(ArrowRight) => text.right(), + Named(ArrowUp) => text.up(), + Named(ArrowDown) => text.down(), + Named(Enter) => text.enter(), + Character(x) => { + text.insert(&*x); + } + _ => {} + }; +} +fn handle(key: Key, mut text: TextArea) -> TextArea { + handle2(key, &mut text); + text +} pub static FONT: LazyLock<FontRef<'static>> = LazyLock::new(|| { FontRef::from_index( &include_bytes!("/home/os/CascadiaCodeNF.ttf")[..], @@ -377,3 +374,42 @@ 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() +} +fn ctrl() -> bool { + unsafe { MODIFIERS }.control_key() +} +fn arrow(k: &Key) -> bool { + matches!( + k, + Key::Named( + NamedKey::ArrowLeft + | NamedKey::ArrowRight + | NamedKey::ArrowDown + | NamedKey::ArrowUp + ) + ) +} + +// use NamedKey::Arrow +use std::ops::Range; +rust_fsm::state_machine! { + #[derive(Clone, Debug)] + pub(crate) State => Action => Do + + Dead => K(Key => _) => Dead, + Default => { + K(Key => Key::Character(x) if x == "s" && ctrl()) => Save [Save], + K(Key => Key::Character(x) if x == "q" && ctrl()) => Dead [Quit], + K(Key => x if shift() && arrow(&x)) => Selection(Range<usize> => 0..0) [StartSelection], + K(Key => _) => Default [Edit], + }, + Selection(Range<usize> => x) => K(Key => y if arrow(&y) && shift()) => Selection(Range<usize> => x) [UpdateSelection], + Save => { + RequireFilename => InputFname(TextArea => default()), + Saved => Default, + }, + InputFname(TextArea => t) => K(Key => Key::Named(NamedKey::Enter)) => Default [SaveTo(String => t.rope.to_string())], + InputFname(TextArea => t) => K(Key => k) => InputFname(TextArea => handle(k, t)), +} |