A simple CPU rendered GUI IDE experience.
bendn 9 days ago
parent 1857bd4 · commit 90986bf
-rw-r--r--Cargo.toml14
-rw-r--r--src/edi.rs31
-rw-r--r--src/edi/input_handlers/keyboard.rs11
-rw-r--r--src/edi/lsp_impl.rs4
-rw-r--r--src/edi/lsp_mn.rs12
-rw-r--r--src/edi/st.rs18
-rw-r--r--src/hov.rs9
-rw-r--r--src/lsp.rs2
-rw-r--r--src/main.rs9
-rw-r--r--src/menu/generic.rs4
-rw-r--r--src/rnd.rs9
-rw-r--r--src/runnables.rs4
-rw-r--r--src/text.rs4
-rw-r--r--src/text/hist.rs11
14 files changed, 106 insertions, 36 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 3d9f0e7..45bc3fd 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -9,9 +9,9 @@ fimg = { git = "https://git.bendn.org/fimg" }
pattypan = { git = "https://git.bendn.org/pattypan" }
implicit-fn = "0.1.0"
ropey = "1.6.1"
-softbuffer = "0.4.8"
+softbuffer = { version = "0.4.8", default-features = false, features = ["wayland", "x11"] }
swash = "0.2.9"
-winit = "0.31.0-beta.2"
+winit = { version = "0.31.0-beta.2", default-features = false, features = ["wayland", "x11"] }
tree-sitter = "0.25.10"
memchr = "2.8.2"
@@ -58,7 +58,6 @@ arc-swap = "1.9.1"
atools = "0.1.12"
swizzle = "0.1.0"
walkdir = "2.5.0"
-niri = { package = "niri-ipc", version = "25.11.0" }
libc = "0.2.186"
rustc-hash = "=2.1.1"
git2 = "0.20.4"
@@ -66,7 +65,7 @@ imara-diff = "0.2.0"
vecto = "0.1.1"
rangemap = { version = "1.7.1", features = ["const_fn", "nightly", "serde1"] }
itern = "0.1.1"
-kitty-rc = { version = "0.4.2", git = "https://github.com/bend-n/kitty-rc-rs" }
+
smol_str = "0.3.6"
futures = "0.3.32"
rootcause = { version = "0.12.1", features = ["compat-anyhow1"] }
@@ -78,12 +77,19 @@ annotate-snippets = "0.12.16"
toml = "1.1.2"
bendncode = { git = "https://git.bendn.org/bendncode" }
rfd = "0.17.2"
+
+[target.'cfg(unix)'.dependencies]
+kitty-rc = { version = "0.4.2", git = "https://github.com/bend-n/kitty-rc-rs" }
+niri = { package = "niri-ipc", version = "25.11.0" }
+
[profile.dev.package]
rust-analyzer.opt-level = 3
fimg.opt-level = 3
nucleo.opt-level = 3
tree-house.debug-assertions = false
+
+
[profile.release.package.tree-house]
debug-assertions = false
diff --git a/src/edi.rs b/src/edi.rs
index 804406d..9a591e9 100644
--- a/src/edi.rs
+++ b/src/edi.rs
@@ -9,7 +9,6 @@ use std::time::SystemTime;
use Default::default;
use ftools::Bind;
-use helix_core::syntax::config::FileType;
use lsp_types::*;
use regex::Regex;
use rootcause::report;
@@ -34,7 +33,7 @@ use st::*;
use crate::bar::Bar;
use crate::commands::Cmds;
-use crate::edi::lsp_mn::{LSPM, LoadedLSP};
+use crate::edi::lsp_mn::LSPM;
use crate::error::WDebug;
use crate::gotolist::{At, GoTo};
use crate::hov::{self, HOV_HEIGHT, Hovr, Hovring, Rendered};
@@ -50,7 +49,7 @@ use crate::text::hist::{ClickHistory, Hist};
use crate::text::{LOADER, Mapping, RopeExt, SortTedits, TextArea};
use crate::{
BoolRequest, CDo, CompletionAction, CompletionState, Freq, KillRing,
- alt, ctrl, filter, hash, shift, sym, trm,
+ alt, ctrl, filter, hash, shift, sym,
};
impl Debug for Editor {
@@ -223,7 +222,9 @@ impl Editor {
.pick_folder()
});
if let Some(x) = &o {
- match std::fs::read_to_string(x) {
+ match std::fs::read_to_string(x)
+ .map(|x| x.replace("\r\n", "\n"))
+ {
Ok(_) => {}
Err(e)
if e.kind() == ErrorKind::IsADirectory
@@ -306,7 +307,9 @@ impl Editor {
) -> rootcause::Result<(Self, Freq, KillRing)> {
let mut me = Self::default();
if let Some(o) = o.as_deref()
- && let o = std::fs::read_to_string(o).unwrap()
+ && let o = std::fs::read_to_string(o)
+ .map(|x| x.replace("\r\n", "\n"))
+ .unwrap()
{
me.text.insert(&o);
me.text.cursor = default();
@@ -397,7 +400,8 @@ impl Editor {
if let Some((c, origin)) = lsp!(me + p) {
c.open(
&origin,
- std::fs::read_to_string(&origin)?,
+ std::fs::read_to_string(&origin)
+ .map(|x| x.replace("\r\n", "\n"))?,
me.language.unwrap(),
)?;
c.rq_semantic_tokens(
@@ -408,7 +412,7 @@ impl Editor {
}
me.git_dir = g;
me.mtime = Self::modify(me.origin.as_deref());
-
+ me.tree();
// me.hist.last = me.text.clone();
// me.lsp.as_ref().zip(me.origin.as_deref()).map(
// |((x, ..), origin)| {
@@ -628,6 +632,7 @@ impl Editor {
.as_ref()
.ok_or(report!("origin missing"))?,
)
+ .map(|x| x.replace("\r\n", "\n"))
.unwrap(),
);
@@ -670,7 +675,8 @@ impl Editor {
// self.workspace = ws;
self.origin = Some(x.to_path_buf());
- let new = std::fs::read_to_string(&x)?;
+ let new = std::fs::read_to_string(&x)
+ .map(|x| x.replace("\r\n", "\n"))?;
take(&mut self.text);
self.text.insert(&new);
take(&mut self.text.changes);
@@ -691,6 +697,11 @@ impl Editor {
}
}
+ self.tree();
+ self.set_title(w);
+ Ok(())
+ }
+ pub fn tree(&mut self) {
fn is_hidden(entry: &walkdir::DirEntry) -> bool {
entry
.file_name()
@@ -698,7 +709,6 @@ impl Editor {
.map(|s| s.starts_with("."))
.unwrap_or(false)
}
-
self.tree = self.git_dir.as_ref().map(|x| {
walkdir::WalkDir::new(x)
.into_iter()
@@ -708,8 +718,6 @@ impl Editor {
.map(|x| x.path().to_owned())
.collect::<Vec<_>>()
});
- self.set_title(w);
- Ok(())
}
pub fn set_title(&self, w: Option<Arc<dyn Window>>) {
if let Some(x) = w
@@ -807,6 +815,7 @@ fn cfgdir() -> PathBuf {
std::env::var("HOME")
.map(PathBuf::from)
.map(|x| x.join(".config"))
+ .or(std::env::var("AppData").map(PathBuf::from))
})
.unwrap_or("/tmp/".into())
.join("gracilaria")
diff --git a/src/edi/input_handlers/keyboard.rs b/src/edi/input_handlers/keyboard.rs
index d91e562..7dadc9b 100644
--- a/src/edi/input_handlers/keyboard.rs
+++ b/src/edi/input_handlers/keyboard.rs
@@ -67,8 +67,9 @@ impl Editor {
self.text.cursor.clear_selections();
change!(self, window.clone());
}
+ #[cfg(target_family = "unix")]
Do::SpawnTerminal => {
- if let Err(e) = trm::toggle(
+ if let Err(e) = crate::trm::toggle(
&lsp!(self)
.as_deref()
.map_or(Path::new("/home/os/").into(), |x| {
@@ -78,6 +79,10 @@ impl Editor {
log::error!("opening terminal failed {e}");
}
}
+ #[cfg(not(target_family = "unix"))]
+ Do::SpawnTerminal => {
+ unimplemented!()
+ }
Do::MatchingBrace =>
if let Some((l, f)) = lsp!(self + p) {
l.matching_brace(f, &mut self.text)
@@ -562,6 +567,7 @@ impl Editor {
self.text.cursor.add(x, &self.text.rope);
});
}
+ #[cfg(target_family = "unix")]
Do::Run(x) =>
if let Some((l, ws)) =
lsp!(self).zip(self.git_dir.as_deref())
@@ -570,6 +576,8 @@ impl Editor {
.block_on(crate::runnables::run(x, ws))
.unwrap();
},
+ #[cfg(not(target_family = "unix"))]
+ Do::Run(_) => {}
Do::GoToImplementations => {
let State::GoToL(x) = &mut self.state else {
unreachable!()
@@ -891,6 +899,7 @@ impl Editor {
self.hist.push_if_changed(&mut self.text);
self.text.rope = Rope::from_str(
&std::fs::read_to_string(self.origin.as_ref().unwrap())
+ .map(|x| x.replace("\r\n", "\n"))
.unwrap(),
);
diff --git a/src/edi/lsp_impl.rs b/src/edi/lsp_impl.rs
index 105595f..269ddb0 100644
--- a/src/edi/lsp_impl.rs
+++ b/src/edi/lsp_impl.rs
@@ -12,7 +12,6 @@ use crate::edi::lsp;
use crate::edi::st::*;
use crate::hov::{Hoverable, Hovring};
use crate::lsp::{RequestError, Rq};
-use crate::runnables::Runnables;
use crate::sym::GoTo;
use crate::{CompletionState, act, sig, sym};
@@ -172,9 +171,10 @@ impl crate::edi::Editor {
self.state = State::Default;
}
}
+ #[cfg(target_family = "unix")]
State::Runnables(x) => {
x.poll(|x, ((), old)| {
- Some(Runnables {
+ Some(crate::runnables::Runnables {
data: x.ok()?,
..old.unwrap_or_default()
})
diff --git a/src/edi/lsp_mn.rs b/src/edi/lsp_mn.rs
index 0bc7dce..a505e5c 100644
--- a/src/edi/lsp_mn.rs
+++ b/src/edi/lsp_mn.rs
@@ -29,6 +29,10 @@ impl LSPM {
vsc: Option<serde_json::Value>,
) -> Option<(Arc<Client>, Option<Sender<Arc<dyn Window + 'static>>>)>
{
+ let ra_conn_used = self
+ .four
+ .values()
+ .any(|x| x.c.lsp_data.1.name == "rust-analyzer");
let e = match self.four.entry((l, workspace.to_owned())) {
std::collections::hash_map::Entry::Occupied(x) => {
let x = x.get();
@@ -36,7 +40,7 @@ impl LSPM {
}
std::collections::hash_map::Entry::Vacant(e) => e,
};
- let (l, w) = load(workspace, l, vsc)?;
+ let (l, w) = load(workspace, l, vsc, ra_conn_used)?;
let v = e.insert(l);
Some((v.c.clone(), Some(w)))
}
@@ -46,11 +50,11 @@ pub fn load(
workspace: &PathBuf,
l: Language,
vsc: Option<serde_json::Value>,
+ ra_conn_used: bool,
) -> Option<(LoadedLSP, Sender<Arc<dyn Window>>)> {
let l = super::LOADER.language(l).config();
- let (Connection { sender, receiver }, conf, iot) = if l.language_id
- == "rust"
- {
+ let use_builtin_ra = l.language_id == "rust" && !ra_conn_used;
+ let (Connection { sender, receiver }, conf, iot) = if use_builtin_ra {
let (_jh, a) = super::ra::ra(workspace.clone());
(
a,
diff --git a/src/edi/st.rs b/src/edi/st.rs
index db98b9a..efc2081 100644
--- a/src/edi/st.rs
+++ b/src/edi/st.rs
@@ -35,6 +35,11 @@ pub enum LR {
Left,
Right,
}
+
+#[cfg(target_family = "unix")]
+type Run = crate::runnables::Runnables;
+#[cfg(not(target_family = "unix"))]
+type Run = ();
rust_fsm::state_machine! {
#[derive(Debug)]
pub(crate) State => #[derive(Debug)] pub(crate) Action => #[derive(Debug)] pub(crate) Do
@@ -114,21 +119,32 @@ Command(mut t) => K(k) => Command({ if let Some(_) = handle2(&k, &mut t.tedit, N
}; t }) [CmdTyped],
Command(t) => C(_) => _,
Command(t) => K(_) => _,
+#[cfg(target_family = "unix")]
Runnables(_x) => {
+ #[cfg(target_family = "unix")]
K(Key::Named(Escape)) => Default,
},
-Runnables(RqS::<crate::runnables::Runnables, rust_analyzer::lsp::ext::Runnables> => Rq { result: Some(mut x), request }) => {
+#[cfg(target_family = "unix")]
+Runnables(RqS::<Run, rust_analyzer::lsp::ext::Runnables> => Rq { result: Some(mut x), request }) => {
+ #[cfg(target_family = "unix")]
K(Key::Named(Tab) if shift()) => Runnables({ x.next(); Rq { result: Some(x), request }}),
+ #[cfg(target_family = "unix")]
K(Key::Named(ArrowDown)) => Runnables({ x.next(); Rq { result: Some(x), request }}),
+ #[cfg(target_family = "unix")]
K(Key::Named(ArrowUp | Tab)) => Runnables({ x.back(); Rq { result: Some(x), request }}),
+ #[cfg(target_family = "unix")]
K(Key::Named(Enter) if let Some(Ok(x_)) = x.clone().sel(None)) => Default [Run(Runnable => x_.clone())],
+ #[cfg(target_family = "unix")]
K(k) => Runnables({
if let Some(_) = handle2(&k, &mut x.tedit, None) {
x.selection = 0; x.vo = 0;
}; Rq { result: Some(x), request } }),
},
+#[cfg(target_family = "unix")]
Runnables(_x) => {
+ #[cfg(target_family = "unix")]
C(_) => _,
+ #[cfg(target_family = "unix")]
M(_) => _,
},
diff --git a/src/hov.rs b/src/hov.rs
index 47192e7..2c3f4b8 100644
--- a/src/hov.rs
+++ b/src/hov.rs
@@ -1,6 +1,5 @@
use std::fmt::Debug;
use std::iter::{empty, once, repeat_n};
-use std::os::fd::AsFd;
use std::pin::pin;
use std::str::FromStr;
use std::sync::Arc;
@@ -399,7 +398,13 @@ impl DiagnosticHovr {
simplify_path(&dawg.replace('\n', "\r\n").replace("⸬", ":"))
.bytes()
{
- t.rx(b, std::fs::File::open("/dev/null").unwrap().as_fd());
+ t.rx(
+ b,
+ #[cfg(target_family = "unix")]
+ std::os::fd::AsFd::as_fd(
+ &std::fs::File::open("/dev/null").unwrap(),
+ ),
+ );
}
let y_lim = t
.cells
diff --git a/src/lsp.rs b/src/lsp.rs
index b684d85..8df05fc 100644
--- a/src/lsp.rs
+++ b/src/lsp.rs
@@ -49,7 +49,7 @@ pub fn run(
progress: Box::leak(Box::new(papaya::HashMap::new())),
runtime: tokio::runtime::Builder::new_multi_thread()
.enable_time()
- .enable_io()
+ // .enable_io()
.worker_threads(3)
.thread_name("lsp runtime")
.build()?,
diff --git a/src/main.rs b/src/main.rs
index 7e81e5e..8c617ba 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -48,8 +48,10 @@ mod gotolist;
mod killring;
mod meta;
mod rnd;
+#[cfg(target_family = "unix")]
mod runnables;
mod sym;
+#[cfg(target_family = "unix")]
mod trm;
use std::fmt::{Debug, Display};
@@ -182,9 +184,11 @@ pub(crate) fn entry(event_loop: EventLoop) {
let app = winit_app::WinitAppBuilder::with_init(
move |elwt| {
let window = winit_app::make_window(elwt, |x| {
+ #[cfg(target_family = "unix")]
+ let x = x.with_platform_attributes(
+ Box::new(winit::platform::wayland::WindowAttributesWayland::default().with_name("com.bendn.gracilaria", "com.bendn.gracilaria"))
+ ).with_decorations(false);
x.with_title("gracilaria")
- .with_platform_attributes(Box::new(winit::platform::wayland::WindowAttributesWayland::default().with_name("com.bendn.gracilaria", "com.bendn.gracilaria")))
- .with_decorations(false)
// .with_name("com.bendn.gracilaria", "")
// .with_resize_increments(PhysicalSize::new(fw, fh))
.with_window_icon(Some(
@@ -196,6 +200,7 @@ pub(crate) fn entry(event_loop: EventLoop) {
.unwrap().into()
))
});
+
if let Some(x) = w.take() {
x.send(window.clone()).unwrap();
}
diff --git a/src/menu/generic.rs b/src/menu/generic.rs
index 2584f9e..da465c5 100644
--- a/src/menu/generic.rs
+++ b/src/menu/generic.rs
@@ -62,9 +62,7 @@ impl ID for crate::commands::Cmds {
impl ID for crate::gotolist::GTL {
const ID: u8 = 1;
}
-impl ID for crate::runnables::Runb {
- const ID: u8 = 2;
-}
+// RunB = 2
impl ID for crate::sym::Symb {
const ID: u8 = 3;
}
diff --git a/src/rnd.rs b/src/rnd.rs
index 927418e..a401009 100644
--- a/src/rnd.rs
+++ b/src/rnd.rs
@@ -856,6 +856,7 @@ pub fn render(
let c = x.cells(50, ws, Some(freq));
drawb(&c, 50);
}
+ #[cfg(target_family = "unix")]
State::Runnables(Rq { result: Some(x), .. }) => {
let ws = ed.git_dir.as_deref().unwrap();
let c = x.cells(50, ws, None);
@@ -1093,7 +1094,13 @@ pub fn simplify_path(x: &str) -> String {
static RUST_SRC: LazyLock<Regex> = LazyLock::new(|| {
Regex::new(r".rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library").unwrap()
});
- let x = x.replace(env!("HOME"), " ");
+ let x = x.replace(
+ #[cfg(target_family = "unix")]
+ env!("HOME"),
+ #[cfg(target_family = "windows")]
+ env!("HOMEPATH"),
+ " ",
+ );
[(&*RUST_SRC, " "), (&*DEP, " /$name"), (&*DEP2, " /$name")]
.into_iter()
.fold(x, |acc, (r, repl)| r.replace(&acc, repl).into_owned())
diff --git a/src/runnables.rs b/src/runnables.rs
index 287868c..e70aab9 100644
--- a/src/runnables.rs
+++ b/src/runnables.rs
@@ -191,3 +191,7 @@ pub fn run(
}
}
}
+
+impl crate::menu::generic::ID for crate::runnables::Runb {
+ const ID: u8 = 2;
+}
diff --git a/src/text.rs b/src/text.rs
index dac9e52..f3677b0 100644
--- a/src/text.rs
+++ b/src/text.rs
@@ -804,9 +804,9 @@ impl TextArea {
.take(c)
.zip(0..)
{
- if e.c() != '\n' {
+ if e.c() != '\n' && e.c() != '\r' {
cells.get((x + self.ho, y)).unwrap().letter =
- Some(e.c());
+ Some(if e.c() == '\t' { ' ' } else { e.c() });
let s =
&mut cells.get((x + self.ho, y)).unwrap().style;
diff --git a/src/text/hist.rs b/src/text/hist.rs
index 6edb771..df678d2 100644
--- a/src/text/hist.rs
+++ b/src/text/hist.rs
@@ -211,14 +211,21 @@ impl Hist {
}
pub fn undo(&mut self, t: &mut TextArea) -> ropey::Result<Option<()>> {
self.push_if_changed(t);
- self.undo_()
+ let r = self
+ .undo_()
.map(|x| {
let r = x.apply(t, false);
self.lc = t.cursor.clone();
self.last = t.changes.clone();
r
})
- .transpose()
+ .transpose();
+ let l = t.len_chars();
+ t.cursor
+ .inner
+ .iter_mut()
+ .for_each(|x| x.position = x.position.max(l));
+ r
}
pub fn redo(&mut self, t: &mut TextArea) -> ropey::Result<Option<()>> {
self.redo_()