A simple CPU rendered GUI IDE experience.
implement save
bendn 5 months ago
parent 9da1151 · commit 84364be
-rw-r--r--Cargo.toml1
-rw-r--r--src/bar.rs55
-rw-r--r--src/main.rs99
-rw-r--r--src/text.rs10
4 files changed, 133 insertions, 32 deletions
diff --git a/Cargo.toml b/Cargo.toml
index d5ea8b0..76ee558 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -22,6 +22,7 @@ lower = "0.2.0"
amap = "0.1.2"
run_times = "0.1.0"
array_chunks = "1.0.0"
+rust-fsm = { version = "0.8.0", features = ["diagram"] }
[build-dependencies]
cc = "*"
diff --git a/src/bar.rs b/src/bar.rs
index 3aea79e..39167b5 100644
--- a/src/bar.rs
+++ b/src/bar.rs
@@ -2,11 +2,28 @@ use std::iter::{once, repeat};
use dsb::Cell;
use dsb::cell::Style;
-use winit::keyboard::{Key, NamedKey};
pub struct Bar {
- pub holding: Option<Key>,
- pub fname: String,
+ pub state: state::StateMachine,
+ pub text: crate::text::TextArea,
+ pub last_action: String,
+}
+
+rust_fsm::state_machine! {
+ #[derive(Debug, PartialEq, Eq, Copy, Clone)]
+ pub(crate) state(Inactive)
+
+ Inactive => {
+ Control => Control,
+ },
+ Control => {
+ Saved => Inactive,
+ WaitingForFname => InputFname,
+ Released => Inactive,
+ },
+ InputFname => {
+ Enter => Inactive,
+ }
}
impl Bar {
@@ -16,6 +33,7 @@ impl Bar {
bg: [u8; 3],
(into, (w, _)): (&mut [Cell], (usize, usize)),
oy: usize,
+ fname: &str,
) {
let row = &mut into[oy * w..oy * w + w];
row.fill(Cell {
@@ -25,19 +43,23 @@ impl Bar {
fn s(s: &str) -> impl Iterator<Item = (char, u8)> {
s.chars().zip(repeat(0))
}
- match self.holding {
- None => {
+ match self.state.state() {
+ state::State::Inactive => {
row[1.."gracilaria".len() + 1]
.iter_mut()
.zip("gracilaria".chars())
.for_each(|(x, y)| x.letter = Some(y));
- row[w / 2 - self.fname.len() / 2
- ..w / 2 - self.fname.len() / 2 + self.fname.len()]
+ row[w / 2 - fname.len() / 2
+ ..w / 2 - fname.len() / 2 + fname.len()]
.iter_mut()
- .zip(self.fname.chars())
+ .zip(fname.chars())
+ .for_each(|(x, y)| x.letter = Some(y));
+ row.iter_mut()
+ .rev()
+ .zip(self.last_action.chars().rev())
.for_each(|(x, y)| x.letter = Some(y));
}
- Some(Key::Named(NamedKey::Control)) => {
+ state::State::Control => {
let x = s("C + { ")
.chain(once(('S', Style::BOLD)))
.chain(s("ave, "))
@@ -52,7 +74,20 @@ impl Bar {
}
});
}
- Some(_) => panic!(),
+ state::State::InputFname => {
+ "write to file: "
+ .chars()
+ .zip(repeat(Style::BOLD | Style::ITALIC))
+ .chain(s(&self.text.rope.to_string()))
+ .zip(row)
+ .for_each(|((x, z), y)| {
+ *y = Cell {
+ letter: Some(x),
+ style: Style { flags: z, ..y.style },
+ ..*y
+ }
+ });
+ }
}
}
}
diff --git a/src/main.rs b/src/main.rs
index 354a2a2..5935a9f 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,3 +1,4 @@
+#![feature(tuple_trait, unboxed_closures, fn_traits)]
#![feature(
if_let_guard,
deref_patterns,
@@ -8,6 +9,7 @@
)]
#![allow(incomplete_features, redundant_semicolons)]
use std::convert::identity;
+use std::fs::File;
use std::hint::assert_unchecked;
use std::iter::zip;
use std::num::NonZeroU32;
@@ -20,12 +22,14 @@ use atools::prelude::*;
use dsb::cell::Style;
use dsb::{Cell, F};
use fimg::Image;
+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 crate::bar::Bar;
+use crate::bar::state::{Input, State};
use crate::text::TextArea;
mod bar;
mod text;
@@ -42,20 +46,34 @@ pub(crate) fn entry(event_loop: EventLoop<()>) {
let ls = 20.0;
let mut text = TextArea::default();
- let fname = std::env::args().nth(1).unwrap_or("new buffer".into());
+ let mut origin = std::env::args().nth(1);
let mut fonts = dsb::Fonts::new(
*FONT,
F::instance(*FONT, *BFONT),
*IFONT,
F::instance(*IFONT, *BIFONT),
);
- let mut bar = Bar { holding: None, fname };
+ let mut bar = Bar {
+ text: TextArea::default(),
+ state: bar::state::StateMachine::new(),
+ last_action: String::default(),
+ };
let mut i = Image::build(1, 1).fill(BG);
let mut cells = vec![];
std::env::args().nth(1).map(|x| {
text.insert(&std::fs::read_to_string(x).unwrap());
text.cursor = 0;
});
+ macro_rules! save {
+ () => {{
+ std::fs::write(
+ origin.as_ref().unwrap(),
+ &text.rope.to_string(),
+ )
+ .unwrap();
+ bar.last_action = "saved".into();
+ }};
+ }
let app = winit_app::WinitAppBuilder::with_init(
|elwt| {
let window = winit_app::make_window(elwt, identity);
@@ -83,6 +101,7 @@ pub(crate) fn entry(event_loop: EventLoop<()>) {
window.inner_size().height as _,
),
);
+ dbg!(&bar.state);
match event {
Event::WindowEvent {
window_id,
@@ -140,15 +159,21 @@ pub(crate) fn entry(event_loop: EventLoop<()>) {
BG,
(&mut cells, (c, r)),
(1, 0),
- );
+ ) + 1;
text.write_to(
(c - t_ox, r - 1),
FG,
BG,
(&mut cells, (c, r)),
- (1 + t_ox, 0),
+ (t_ox, 0),
+ );
+ bar.write_to(
+ BG,
+ FG,
+ (&mut cells, (c, r)),
+ r - 1,
+ &origin.as_deref().unwrap_or("new buffer"),
);
- bar.write_to(BG, FG, (&mut cells, (c, r)), r - 1);
println!("cell=");
dbg!(now.elapsed());
@@ -179,7 +204,8 @@ pub(crate) fn entry(event_loop: EventLoop<()>) {
.fill([0xFF, 0xCC, 0x66, 255]);
unsafe {
let (x, y) = text.cursor();
- let y = y;
+ let x = x + t_ox;
+
if (text.vo..text.vo + r).contains(&y) {
i.as_mut().overlay_at(
&cursor,
@@ -236,32 +262,49 @@ pub(crate) fn entry(event_loop: EventLoop<()>) {
let rows = rows.floor() as usize;
text.vo = text.vo.saturating_sub(rows);
}
- window.request_redraw();
}
Event::WindowEvent {
event: WindowEvent::KeyboardInput { event, .. },
..
} if event.state == ElementState::Released
- && bar
- .holding
- .as_ref()
- .is_some_and(|x| x == &event.logical_key) =>
+ && *bar.state.state() == State::Control
+ && event.logical_key == NamedKey::Control =>
{
- bar.holding = None;
+ bar.state.consume(&Input::Released).unwrap();
window.request_redraw();
}
Event::WindowEvent {
event: WindowEvent::KeyboardInput { event, .. },
..
- } if let Some(Key::Named(NamedKey::Control)) =
- bar.holding
+ } if *bar.state.state() == State::Control
&& event.state == ElementState::Pressed =>
{
use Key::*;
match event.logical_key {
- Character(x) if x == "s" => {}
+ Character(x) if x == "s" => match &origin {
+ Some(_) => {
+ bar.state.consume(&Input::Saved).unwrap();
+ save!();
+ }
+ None => {
+ bar.state
+ .consume(&Input::WaitingForFname)
+ .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 {
@@ -270,6 +313,11 @@ pub(crate) fn entry(event_loop: EventLoop<()>) {
} 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(),
@@ -279,19 +327,30 @@ pub(crate) fn entry(event_loop: EventLoop<()>) {
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(),
+ );
+ save!();
+ }
Named(Enter) => text.enter(),
- Named(Control) =>
- bar.holding = Some(event.logical_key),
+ Named(Control) => {
+ bar.state.consume(&Input::Control).unwrap();
+ }
Character(x) => {
text.insert(&*x);
}
_ => {}
- }
-
+ };
window.request_redraw();
}
_ => {}
- }
+ };
},
);
diff --git a/src/text.rs b/src/text.rs
index cb6518a..1f92481 100644
--- a/src/text.rs
+++ b/src/text.rs
@@ -7,6 +7,7 @@ use ropey::Rope;
use tree_sitter_highlight::{
HighlightConfiguration, HighlightEvent, Highlighter,
};
+use winit::keyboard::SmolStr;
#[rustfmt::skip]
const NAMES: [&str; 13] = ["attribute", "comment", "constant", "function", "keyword", "number", "operator", "punctuation",
"string", "tag", "type", "variable", "variable.parameter"];
@@ -34,7 +35,7 @@ const fn color(x: &[u8; 6]) -> [u8; 3] {
#[derive(Default)]
pub struct TextArea {
- rope: Rope,
+ pub rope: Rope,
pub cursor: usize,
highlighter: Highlighter,
column: usize,
@@ -46,8 +47,13 @@ impl TextArea {
self.rope.len_lines()
}
+ pub fn insert_(&mut self, c: SmolStr) {
+ self.rope.insert(self.cursor, &c);
+ self.cursor += c.chars().count();
+ self.setc();
+ }
pub fn insert(&mut self, c: &str) {
- self.rope.insert(self.cursor, c);
+ self.rope.insert(self.cursor, &c);
self.cursor += c.chars().count();
self.setc();
}