A simple CPU rendered GUI IDE experience.
-rw-r--r--src/lsp.rs9
-rw-r--r--src/main.rs15
-rw-r--r--src/text.rs58
3 files changed, 59 insertions, 23 deletions
diff --git a/src/lsp.rs b/src/lsp.rs
index 92d5266..cbfae52 100644
--- a/src/lsp.rs
+++ b/src/lsp.rs
@@ -355,6 +355,14 @@ impl Client {
}
}
}
+ pub fn document_highlights(&'static self, f: &Path, cursor: Position) {
+ self.request::<lsp_request!("textDocument/documentHighlight")>(&DocumentHighlightParams {
+ text_document_position_params: TextDocumentPositionParams { text_document: f.tid(), position: cursor },
+
+ work_done_progress_params: default(),
+ partial_result_params: default(),
+ }).unwrap();
+ }
pub fn symbols(
&'static self,
f: String,
@@ -545,6 +553,7 @@ pub fn run(
..default()
}),
text_document: Some(TextDocumentClientCapabilities {
+ document_highlight: Some(default()),
formatting: Some(DynamicRegistrationClientCapabilities { dynamic_registration: Some(false) }),
inlay_hint: Some(InlayHintClientCapabilities { dynamic_registration: None, resolve_support: Some(InlayHintResolveClientCapabilities {
properties: vec!["textEdits".into(), "tooltip".into(), "label.tooltip".into(), "label.command".into()], })
diff --git a/src/main.rs b/src/main.rs
index c3e262e..64f8eed 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(
+ anonymous_lifetime_in_impl_trait,
try_blocks_heterogeneous,
current_thread_id,
vec_try_remove,
@@ -757,8 +758,10 @@ pub(crate) fn entry(event_loop: EventLoop<()>) {
let (w, h) = dsb::size(&fonts.regular, ppem, ls, (columns, r));
// std::fs::write("cells", Cell::store(c));
- if w >= window.inner_size().width as usize
- // || position.1 + h >= window.inner_size().height as usize
+ if w >= size.width as usize
+ || (position.1 + h >= size.height as usize && !position.1.checked_sub(h).is_some())
+ || position.1 >= size.height as usize
+ || position.0 >= size.width as usize
{
unsafe { dsb::render_owned(c, (columns, c.len() / columns), ppem, fonts, ls, true).save("fail.png") };
return Err(());
@@ -1038,8 +1041,8 @@ pub(crate) fn entry(event_loop: EventLoop<()>) {
break 'out;
};
let (x, y) = text.xy(abspos).unwrap();
- let Some(begin) = text.reverse_source_map(y) else { break 'out };
- let start = begin[x - 1] + 1;
+ let Some(mut begin) = text.reverse_source_map(y) else { break 'out };
+ let start = begin.nth(x - 1).unwrap() + 1;
let left = mark.l[..relpos].iter().rev().take_while(_.1.as_ref() == Some(loc)).count();
let start = start + relpos - left;
let length = mark.l[relpos..].iter().take_while(_.1.as_ref() == Some(loc)).count() + left;
@@ -1100,8 +1103,8 @@ let handle: tokio::task::JoinHandle<Result<Option<Hovr>, anyhow::Error>> = cl.ru
let span = rang.or_else(|| x.range.and_then(|range| try {
let (startx, starty) = text.l_pos_to_char(range.start)?;
let (endx, endy) = text.l_pos_to_char(range.end)?;
- let x1 = text.reverse_source_map(starty)?[startx];
- let x2 = text.reverse_source_map(endy)?[endx];
+ let x1 = text.reverse_source_map(starty)?.nth(startx)?;
+ let x2 = text.reverse_source_map(endy)?.nth(endx)?;
[(x1, range.start.line as _), (x2, range.start.line as _)]
}));
anyhow::Ok(Some( hov::Hovr { span, item: text::CellBuffer { c: w, vo: 0, cells: cells.into() }}.into()))
diff --git a/src/text.rs b/src/text.rs
index a2547b9..91c9a61 100644
--- a/src/text.rs
+++ b/src/text.rs
@@ -350,7 +350,7 @@ impl TextArea {
pub fn map_to_visual(&self, (x, y): (usize, usize)) -> (usize, usize) {
(
self.reverse_source_map(y)
- .and_then(|v| v.get(x).copied())
+ .and_then(|mut v| v.nth(x))
.unwrap_or(x),
y,
)
@@ -379,16 +379,25 @@ impl TextArea {
}
})
}
- pub fn reverse_source_map(&'_ self, l: usize) -> Option<Vec<usize>> {
- let mut to = vec![];
- let mut off = 0;
- for elem in self.source_map(l)? {
- match elem {
- Mapping::Fake(..) => off += 1,
- Mapping::Char(_, i, _) => to.push(i + off),
+ pub fn reverse_source_map_w(
+ &'_ self,
+ w: impl Iterator<Item = Mapping<'_>>,
+ ) -> Option<impl Iterator<Item = usize>> {
+ w.scan(0, |off, x| match x {
+ Mapping::Fake(..) => {
+ *off += 1;
+ Some(None)
}
- }
- Some(to)
+ Mapping::Char(_, i, _) => Some(Some(i + *off)),
+ })
+ .flatten()
+ .into()
+ }
+ pub fn reverse_source_map(
+ &'_ self,
+ l: usize,
+ ) -> Option<impl Iterator<Item = usize>> {
+ self.reverse_source_map_w(self.source_map(l)?)
}
pub fn visual_eol(&self, li: usize) -> Option<usize> {
@@ -539,8 +548,8 @@ impl TextArea {
}
pub fn cursor_visual(&self) -> (usize, usize) {
let (x, y) = self.cursor();
- let z = self.reverse_source_map(y).unwrap();
- (z.get(x).copied().unwrap_or(x), y)
+ let mut z = self.reverse_source_map(y).unwrap();
+ (z.nth(x).unwrap_or(x), y)
}
pub fn visible_(&self) -> Range<usize> {
self.rope.line_to_char(self.vo)
@@ -1037,12 +1046,27 @@ impl TextArea {
{
let mut ln = 0;
let mut ch = 0;
+ let mut src_map =
+ self.source_map(ln as _).coerce().collect::<Vec<_>>();
+ let mut mapping = self
+ .reverse_source_map(ln as _)
+ .coerce()
+ .collect::<Vec<_>>();
+
for t in t {
+ let pl = ln;
ln += t.delta_line;
- let src_map =
- self.source_map(ln as _).coerce().collect::<Vec<_>>();
- let mapping =
- self.reverse_source_map(ln as _).unwrap_or_default();
+ if pl != ln {
+ src_map = self
+ .source_map(ln as _)
+ .coerce()
+ .collect::<Vec<_>>();
+ mapping = self
+ .reverse_source_map_w(src_map.iter().cloned())
+ .coerce()
+ .collect::<Vec<_>>();
+ }
+
// dbg!(
// &mapping,
// self.source_map(ln as _).coerce().collect::<Vec<_>>(),
@@ -1790,7 +1814,7 @@ impl<I: IntoIterator<Item = T>, T> CoerceOption<T> for Option<I> {
}
// #[test]
pub(crate) use col;
-#[derive(Debug, PartialEq)]
+#[derive(Debug, PartialEq, Clone)]
pub enum Mapping<'a> {
Fake(
&'a Mark,