A simple CPU rendered GUI IDE experience.
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs119
1 files changed, 99 insertions, 20 deletions
diff --git a/src/main.rs b/src/main.rs
index 7fa9356..349dd30 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,6 +1,7 @@
// this looks pretty good though
#![feature(tuple_trait, unboxed_closures, fn_traits)]
#![feature(
+ mpmc_channel,
const_cmp,
const_default,
import_trait_associated_functions,
@@ -13,8 +14,10 @@
)]
#![allow(incomplete_features, redundant_semicolons)]
use std::convert::identity;
+use std::io::BufReader;
use std::num::NonZeroU32;
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
+use std::process::{Command, Stdio};
use std::sync::LazyLock;
use std::time::Instant;
@@ -24,10 +27,16 @@ use diff_match_patch_rs::PatchInput;
use dsb::cell::Style;
use dsb::{Cell, F};
use fimg::Image;
+use lsp_types::{
+ SemanticTokensOptions, SemanticTokensServerCapabilities,
+ ServerCapabilities, TextDocumentIdentifier,
+ TextDocumentPositionParams, WorkspaceFolder,
+};
use regex::Regex;
use ropey::Rope;
use rust_fsm::StateMachineImpl;
use swash::{FontRef, Instance};
+use url::Url;
use winit::event::{
ElementState, Event, MouseButton, MouseScrollDelta, WindowEvent,
};
@@ -37,10 +46,12 @@ use winit::keyboard::{Key, ModifiersState, NamedKey, SmolStr};
use crate::bar::Bar;
use crate::text::{Diff, TextArea};
mod bar;
+mod lsp;
mod text;
mod winit_app;
fn main() {
- // text::man();
+ env_logger::init();
+ // lsp::x();
entry(EventLoop::new().unwrap())
}
#[derive(Debug)]
@@ -108,10 +119,13 @@ impl Hist {
self.push_if_changed(x);
}
}
- pub fn record(&mut self, _: &TextArea) {
+ pub fn record(&mut self, new: &TextArea) -> bool {
// self.test_push(x);
- self.last_edit = Instant::now();
- self.changed = true;
+ if new.rope != self.last.rope {
+ self.last_edit = Instant::now();
+ self.changed = true;
+ }
+ new.rope != self.last.rope
}
}
@@ -126,8 +140,10 @@ pub(crate) fn entry(event_loop: EventLoop<()>) {
let ls = 20.0;
let mut text = TextArea::default();
- let mut origin =
- std::env::args().nth(1).and_then(|x| PathBuf::try_from(x).ok());
+ let mut origin = std::env::args()
+ .nth(1)
+ .and_then(|x| PathBuf::try_from(x).ok())
+ .and_then(|x| x.canonicalize().ok());
let mut fonts = dsb::Fonts::new(
F::FontRef(*FONT, &[(2003265652, 550.0)]),
F::instance(*FONT, *BFONT),
@@ -145,6 +161,48 @@ pub(crate) fn entry(event_loop: EventLoop<()>) {
text.insert(&std::fs::read_to_string(x).unwrap());
text.cursor = 0;
});
+ fn rooter(x: &Path) -> Option<PathBuf> {
+ for f in std::fs::read_dir(&x).unwrap().filter_map(Result::ok) {
+ if f.file_name() == "Cargo.toml" {
+ return Some(f.path().with_file_name("").to_path_buf());
+ }
+ }
+ x.parent().and_then(rooter)
+ }
+ let workspace = origin
+ .as_ref()
+ .and_then(|x| rooter(&x.parent().unwrap()))
+ .and_then(|x| x.canonicalize().ok());
+ let c = workspace.zip(origin.clone()).map(|(workspace, origin)| {
+ let mut c = Command::new("rust-analyzer")
+ .stdin(Stdio::piped())
+ .stdout(Stdio::piped())
+ .stderr(Stdio::inherit())
+ .spawn()
+ .unwrap();
+
+ let (c, t, t2) = lsp::run(
+ lsp_server::stdio::stdio_transport(
+ BufReader::new(c.stdout.take().unwrap()),
+ c.stdin.take().unwrap(),
+ ),
+ WorkspaceFolder {
+ uri: Url::from_file_path(&workspace).unwrap(),
+ name: workspace
+ .file_name()
+ .unwrap()
+ .to_string_lossy()
+ .into_owned(),
+ },
+ );
+ c.open(&origin, std::fs::read_to_string(&origin).unwrap())
+ .unwrap();
+ ((c, origin), (t, t2))
+ });
+ let (lsp, t) = c.unzip();
+
+ // let mut hl_result = None;
+
let mut hist = Hist {
history: vec![],
redo_history: vec![],
@@ -159,6 +217,19 @@ pub(crate) fn entry(event_loop: EventLoop<()>) {
.map(|x| x.metadata().unwrap().modified().unwrap())
};
}
+ macro_rules! change {
+ () => {
+ lsp.as_ref()
+ .map(|(x, origin)| {
+ x.edit(&origin, text.rope.to_string()).unwrap();
+ x.rq_semantic_tokens(origin).unwrap();
+ })
+ .unwrap();
+ };
+ }
+ lsp.as_ref()
+ .map(|(x, origin)| x.rq_semantic_tokens(origin).unwrap())
+ .unwrap();
let mut mtime = modify!();
macro_rules! save {
() => {{
@@ -301,6 +372,16 @@ pub(crate) fn entry(event_loop: EventLoop<()>) {
}
},
origin.as_deref(),
+ lsp.as_ref().and_then(|(x, _)| { match &x.initialized {
+ Some(lsp_types::InitializeResult {
+ capabilities: ServerCapabilities {
+ semantic_tokens_provider:
+ Some(SemanticTokensServerCapabilities::SemanticTokensOptions(SemanticTokensOptions{
+ legend,..
+ })),..
+ },..
+ }) => Some(legend), _ => None, }}.map(|leg|(x.semantic_tokens.0.load(), leg))
+ ),
);
bar.write_to(
@@ -314,6 +395,7 @@ pub(crate) fn entry(event_loop: EventLoop<()>) {
.unwrap_or("new buffer"),
&state,
&text,
+ lsp.as_ref().map(|x| &x.0)
);
println!("cell=");
@@ -376,16 +458,7 @@ pub(crate) fn entry(event_loop: EventLoop<()>) {
)
.as_chunks_unchecked_mut::<4>()
};
- fimg::overlay::copy_rgb_bgr_(
- i.flatten(),
- unsafe {
- std::slice::from_raw_parts_mut(
- buffer.as_ptr() as *mut u8,
- buffer.len() * 4,
- )
- .as_chunks_unchecked_mut::<4>()
- },
- );
+ fimg::overlay::copy_rgb_bgr_(i.flatten(), x);
// dbg!(now.elapsed());
buffer.present().unwrap();
}
@@ -438,7 +511,7 @@ pub(crate) fn entry(event_loop: EventLoop<()>) {
if button == MouseButton::Left {
unsafe { CLICKING = true };
}
- match state.consume(Action::M(button)).unwrap() {
+ match dbg!(state.consume(Action::M(button)).unwrap() ){
Some(Do::MoveCursor) => {
text.cursor = text.index_at(cursor_position);
text.setc();
@@ -460,6 +533,7 @@ pub(crate) fn entry(event_loop: EventLoop<()>) {
None => {}
_ => unreachable!(),
}
+ window.request_redraw();
}
Event::WindowEvent {
event:
@@ -486,6 +560,7 @@ 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::ModifiersChanged(modifiers),
@@ -542,17 +617,21 @@ pub(crate) fn entry(event_loop: EventLoop<()>) {
hist.test_push(&text);
handle2(event.logical_key, &mut text);
text.scroll_to_cursor();
- hist.record(&text);
+ if hist.record(&text) {
+ change!();
+ }
}
Some(Do::Undo) => {
hist.test_push(&text);
hist.undo(&mut text);
bar.last_action = "undid".to_string();
+ change!();
}
Some(Do::Redo) => {
hist.test_push(&text);
hist.redo(&mut text);
bar.last_action = "redid".to_string();
+ change!();
}
Some(Do::Quit) => elwt.exit(),
Some(Do::StartSelection) => {
@@ -604,7 +683,7 @@ pub(crate) fn entry(event_loop: EventLoop<()>) {
hist.push_if_changed(&text);
}
Some(Do::OpenFile(x)) => {
- origin = Some(PathBuf::try_from(&x).unwrap());
+ origin = Some(PathBuf::from(&x));
text = TextArea::default();
text.insert(
&std::fs::read_to_string(x).unwrap(),