A simple CPU rendered GUI IDE experience.
| -rw-r--r-- | src/act.rs | 15 | ||||
| -rw-r--r-- | src/bar.rs | 4 | ||||
| -rw-r--r-- | src/com.rs | 9 | ||||
| -rw-r--r-- | src/edi.rs | 65 | ||||
| -rw-r--r-- | src/hov.rs | 11 | ||||
| -rw-r--r-- | src/lsp.rs | 12 | ||||
| -rw-r--r-- | src/main.rs | 55 | ||||
| -rw-r--r-- | src/sig.rs | 2 | ||||
| -rw-r--r-- | src/sym.rs | 10 | ||||
| -rw-r--r-- | src/text.rs | 24 |
10 files changed, 149 insertions, 58 deletions
@@ -154,7 +154,7 @@ impl CodeActions { let mut to = vec![ Cell { - style: Style { bg, color: FG, flags: 0 }, + style: Style::new(FG, bg), ..Default::default() }; c @@ -171,13 +171,8 @@ impl CodeActions { } fn write(x: &CodeAction, c: usize, selected: bool, to: &mut Vec<Cell>) { let bg = if selected { col!("#262d3b") } else { col!("#1c212b") }; - let mut into = vec![ - Cell { - style: Style { bg, color: FG, flags: 0 }, - ..Default::default() - }; - c - ]; + let mut into = + vec![Cell { style: Style::new(FG, bg), ..Default::default() }; c]; let t = match &x.kind { Some(x) if x == &CodeActionKind::QUICKFIX => '', @@ -190,8 +185,8 @@ fn write(x: &CodeAction, c: usize, selected: bool, to: &mut Vec<Cell>) { Some(x) if x == &CodeActionKind::SOURCE => '', _ => '', /* ☭ */ }; - into[0].style.color = col!("#E5C07B"); - into[0].style.bg = set_a(into[0].style.color, 0.5); + into[0].style.fg = col!("#E5C07B"); + into[0].style.bg = set_a(into[0].style.fg, 0.5); into[0].letter = Some(t); into.iter_mut() .skip(1) @@ -7,7 +7,7 @@ use lsp_types::WorkDoneProgress; use crate::lsp::{Client, Rq}; use crate::sym::Symbols; use crate::text::TextArea; - +#[derive(Default)] pub struct Bar { pub last_action: String, } @@ -26,7 +26,7 @@ impl Bar { ) { let row = &mut into[oy * w..oy * w + w]; row.fill(Cell { - style: Style { color, bg, flags: Style::ITALIC }, + style: Style::new(color, bg) | Style::ITALIC, letter: None, }); fn s(s: &str) -> impl Iterator<Item = (char, u8)> { @@ -205,7 +205,7 @@ fn r( ) { let bg = if selected { col!("#262d3b") } else { col!("#1c212b") }; - let ds: Style = Style { bg: bg, color: FG, flags: 0 }; + let ds = Style::new(FG, bg); let d: Cell = Cell { letter: None, style: ds }; let mut b = vec![d; c]; const MAP: [([u8; 3], [u8; 3], &str); 26] = { @@ -237,7 +237,7 @@ fn r( let (bgt, col, ty) = MAP[x.kind.unwrap_or(CompletionItemKind(50)).0 as usize]; b.iter_mut().zip(ty.chars()).for_each(|(x, c)| { - *x = Style { bg: bgt, color: col, flags: Style::BOLD }.basic(c) + *x = (Style::new(col, bgt) | Style::BOLD).basic(c) }); let i = &mut b[2..]; @@ -267,8 +267,7 @@ fn r( i.iter_mut() .rev() .zip(details.map(|x| { - Style { bg, color: color_("#979794"), ..default() } - .basic(x) + Style { bg, fg: color_("#979794"), ..default() }.basic(x) })) .for_each(|(a, b)| *a = b); } @@ -277,7 +276,7 @@ fn r( x.label.chars().map(|x| ds.basic(x)).zip(0..).chain( label_details .map(|x| { - Style { bg, color: color_("#858685"), ..default() } + Style { bg, fg: color_("#858685"), ..default() } .basic(x) }) .zip(repeat(u32::MAX)), diff --git a/src/edi.rs b/src/edi.rs new file mode 100644 index 0000000..d825409 --- /dev/null +++ b/src/edi.rs @@ -0,0 +1,65 @@ +use std::path::PathBuf; +use std::sync::Arc; +use std::thread::JoinHandle; + +use lsp_types::request::*; +use lsp_types::*; +use tokio::sync::oneshot::Sender; + +use crate::bar::Bar; +use crate::hov::Hovr; +use crate::lsp::{Client, RequestError, Rq, RqS}; +use crate::text::TextArea; +use crate::{ClickHistory, CompletionState, Hist, State}; +#[derive(Default)] +pub struct Editor { + text: TextArea, + origin: Option<PathBuf>, + state: State, + bar: Bar, + workspace: Option<PathBuf>, + lsp: Option<( + &'static Client, + JoinHandle<()>, + Sender<Arc<winit::window::Window>>, + )>, + tree: Option<Vec<PathBuf>>, + hovering: Rq<Hovr, Option<Hovr>, (usize, usize), anyhow::Error>, + document_highlights: Rq< + Vec<DocumentHighlight>, + Vec<DocumentHighlight>, + (), + RequestError<DocumentHighlightRequest>, + >, + complete: CompletionState, + sig_help: Rq< + (SignatureHelp, usize, Option<usize>), + Option<SignatureHelp>, + (), + RequestError<SignatureHelpRequest>, + >, // vo, lines + semantic_tokens: Rq< + Box<[SemanticToken]>, + Box<[SemanticToken]>, + (), + RequestError<SemanticTokensFullRequest>, + >, + diag: Rq<String, Option<String>, (), anyhow::Error>, + inlay: Rq< + Vec<InlayHint>, + Vec<InlayHint>, + (), + RequestError<lsp_request!("textDocument/inlayHint")>, + >, + def: Rq< + LocationLink, + Option<GotoDefinitionResponse>, + (usize, usize), + RequestError<lsp_request!("textDocument/definition")>, + >, + chist: ClickHistory, + hist: Hist, + mtime: Option<std::time::SystemTime>, +} + +impl Editor {} @@ -8,8 +8,7 @@ use dsb::cell::Style; use itertools::Itertools; use markdown::mdast::{self, Node}; use ropey::Rope; -const D: Cell = - Cell { letter: None, style: Style { bg: BG, color: FG, flags: 0 } }; +const D: Cell = Cell { letter: None, style: Style::new(FG, BG) }; use crate::{FG, text}; struct Builder { @@ -117,17 +116,17 @@ impl Builder { } Node::Link(_) => { inherit.flags |= Style::UNDERLINE; - inherit.color = [244, 196, 98]; + inherit.fg = [244, 196, 98]; self.extend(node, inherit) } Node::LinkReference(_) => { inherit.flags |= Style::UNDERLINE; - inherit.color = [244, 196, 98]; + inherit.fg = [244, 196, 98]; self.extend(node, inherit) } Node::Heading(_) => { inherit.flags |= Style::BOLD; - inherit.color = [255, 255, 255]; + inherit.fg = [255, 255, 255]; self.extend_(node, [Action::Finish], inherit) } @@ -229,7 +228,7 @@ pub fn l(node: &Node) -> Vec<usize> { pub fn markdown2(c: usize, x: &Node) -> Vec<Cell> { let mut r = Builder { c, to: vec![], scratch: vec![] }; for (is_put, act) in r - .run(&x, Style { bg: BG, color: FG, flags: 0 }) + .run(&x, Style::new(FG, BG)) .into_iter() .chunk_by(|x| matches!(x, Action::Put(_))) .into_iter() @@ -355,13 +355,15 @@ impl Client { } } } - pub fn document_highlights(&'static self, f: &Path, cursor: Position) { - self.request::<lsp_request!("textDocument/documentHighlight")>(&DocumentHighlightParams { + pub fn document_highlights<'me>(&'me self, f: &Path, cursor: Position) -> impl Future<Output = Result<Vec<DocumentHighlight>, RequestError<DocumentHighlightRequest>>> + use<'me> { + let p = DocumentHighlightParams { text_document_position_params: TextDocumentPositionParams { text_document: f.tid(), position: cursor }, - work_done_progress_params: default(), partial_result_params: default(), - }).unwrap(); + }; + self.request::<lsp_request!("textDocument/documentHighlight")>(&p).unwrap().0.map(|x| { + x.map(|x| x.unwrap_or_default()) + }) } pub fn symbols( &'static self, @@ -955,7 +957,7 @@ fn x33() { let y = serde_json::from_str::<SemanticTokensParams>(&y).unwrap(); } #[pin_project::pin_project] -struct Map<T, U, F: FnMut(T) -> U, Fu: Future<Output = T>>(#[pin] Fu, F); +pub struct Map<T, U, F: FnMut(T) -> U, Fu: Future<Output = T>>(#[pin] Fu, F); impl<T, F: FnMut(T) -> U, U, Fu: Future<Output = T>> Future for Map<T, U, F, Fu> { diff --git a/src/main.rs b/src/main.rs index 64f8eed..8acf0bd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -39,6 +39,7 @@ use std::iter::once; mod act; mod sym; mod trm; +mod edi; use std::num::NonZeroU32; use std::os::fd::AsFd; use std::path::{Path, PathBuf}; @@ -105,6 +106,15 @@ struct Hist { pub last: TextArea, pub last_edit: std::time::Instant, pub changed: bool, +}impl Default for Hist{ + fn default() -> Self { + Self{ + history: vec![], + redo_history: vec![], + last: TextArea::default(), + last_edit: Instant::now(), + changed: false, + } } } #[derive(Debug, Default)] struct ClickHistory { @@ -199,7 +209,7 @@ impl Hist { static mut MODIFIERS: ModifiersState = ModifiersState::empty(); static mut CLICKING: bool = false; -const BG: [u8; 3] = [31, 36, 48]; +const BG: [u8; 3] = col!("#1f2430"); const FG: [u8; 3] = [204, 202, 194]; const BORDER: [u8; 3] = col!("#ffffff"); #[implicit_fn::implicit_fn] @@ -310,6 +320,7 @@ pub(crate) fn entry(event_loop: EventLoop<()>) { } let mut hovering = Rq::<Hovr, Option<Hovr>, (usize, usize), anyhow::Error>::default(); + let mut document_highlights: Rq<Vec<DocumentHighlight>, _, _, _> = Rq::default(); let mut complete = CompletionState::None; let mut sig_help = // vo, lines RqS::<(SignatureHelp, usize, Option<usize>), SignatureHelpRequest, ()>::default(); @@ -449,15 +460,19 @@ pub(crate) fn entry(event_loop: EventLoop<()>) { rq => log::debug!("discarding request {rq:?}"), } - } + } + let r = &l.runtime; inlay.poll(|x, p| x.ok().or(p.1).inspect(|x| { text.set_inlay(x); - }), &l.runtime); - diag.poll(|x, _|x.ok().flatten(), &l.runtime); + }), r); + document_highlights.poll(|x, _| { + x.ok() + }, r); + diag.poll(|x, _|x.ok().flatten(), r); if let CompletionState::Complete(rq)= &mut complete { rq.poll(|f, (c,_)| { f.ok().flatten().map(|x| {Complete {r:x,start:c,selection:0,vo:0,}}) - }, &l.runtime); + }, r); }; if let State::Symbols(x) = &mut state { @@ -529,7 +544,8 @@ pub(crate) fn entry(event_loop: EventLoop<()>) { cells = vec![ Cell { style: Style { - color: BG, + fg: BG, + secondary_color: BG, bg: BG, flags: 0 }, @@ -572,7 +588,7 @@ pub(crate) fn entry(event_loop: EventLoop<()>) { return; } cells.fill(Cell { - style: Style { color: BG, bg: BG, flags: 0 }, + style: Style { fg: BG, secondary_color: BG, bg: BG, flags: 0 }, letter: None, }); let x = match &state { @@ -609,6 +625,20 @@ pub(crate) fn entry(event_loop: EventLoop<()>) { (t_ox, 0), x, |(_c, _r), text, mut x| { + if let Some(hl) = &document_highlights.result { + for DocumentHighlight { range: r, .. } in hl { + // let s = match kind { + // Some(DocumentHighlightKind::READ) => Style::UNDERLINE, + // Some(DocumentHighlightKind::WRITE) => Style::UNDERLINE, + // _ => Style::UNDERCURL, + // }; + let (x1, y1) = text.map_to_visual((r.start.character as _, r.start.line as _)); + let (x2, y2) = text.map_to_visual((r.end.character as _, r.end.line as _)); + x.get_simple((x1, y1), (x2, y2)).coerce().for_each(|x| { + x.style.bg = col!("#3a4358"); + }); + } + } if let Some(LocationLink { origin_selection_range: Some(r), .. }) = def.result { _ = try { @@ -616,7 +646,7 @@ pub(crate) fn entry(event_loop: EventLoop<()>) { let (x2, y2) = text.map_to_visual((r.end.character as _, r.end.line as _)); x.get_simple((x1, y1), (x2, y2))?.iter_mut().for_each(|x| { x.style.flags |= Style::UNDERLINE; - x.style.color = col!("#FFD173"); + x.style.fg = col!("#FFD173"); }); } } if let Some((lsp, p)) = lsp!() && let uri = Url::from_file_path(p).unwrap() && let Some(diag) = lsp.diagnostics.get(&uri, &lsp.diagnostics.guard()) { @@ -677,7 +707,7 @@ pub(crate) fn entry(event_loop: EventLoop<()>) { _ => return }; x.style.bg.blend(bg); - x.style.color = fg; + x.style.fg = fg; x.letter = Some(ch); }) }); @@ -1139,6 +1169,7 @@ hovering.request = (DropH::new(handle), cursor_position).into(); text.cursor = text.mapped_index_at(cursor_position); if let Some((lsp, path)) = lsp!() { sig_help.request(lsp.runtime.spawn(window.redraw_after(lsp.request_sig_help(path, text.cursor())))); + document_highlights.request(lsp.runtime.spawn(window.redraw_after(lsp.document_highlights(path, text.to_l_position(text.cursor).unwrap())))); } hist.last.cursor = text.cursor; chist.push(text.cursor()); @@ -1735,7 +1766,11 @@ impl State { } use std::ops::Range; - +impl Default for State { + fn default() -> Self { + Self::Default + } +} rust_fsm::state_machine! { #[derive(Debug)] pub(crate) State => Action => Do @@ -26,7 +26,7 @@ pub fn sig( c: usize, ) -> Vec<Cell> { let bg = color_("#1c212b"); - let ds: Style = Style { bg: bg, color: FG, flags: 0 }; + let ds = Style::new(FG, bg); let d: Cell = Cell { letter: None, style: ds }; let sig = y.label.chars().zip(0..).map(|(x, i)| { let mut a = ds.basic(x); @@ -124,7 +124,7 @@ fn r( ) { let bg = if selected { col!("#262d3b") } else { col!("#1c212b") }; - let ds: Style = Style { bg: bg, color: FG, flags: 0 }; + let ds: Style = Style::new(FG, bg); let d: Cell = Cell { letter: None, style: ds }; let mut b = vec![d; c]; const MAP: [([u8; 3], [u8; 3], &str); 70] = { @@ -158,7 +158,7 @@ fn r( }; let (bgt, col, ty) = MAP[x.kind.0 as usize]; b.iter_mut().zip(ty.chars()).for_each(|(x, c)| { - *x = Style { bg: bgt, color: col, flags: Style::BOLD }.basic(c) + *x = (Style::new(col, bgt) | Style::BOLD).basic(c) }); let i = &mut b[2..]; let qualifier = x @@ -189,14 +189,14 @@ fn r( i.iter_mut() .rev() .zip(q.map(|x| { - Style { bg, color: color_("#979794"), ..default() }.basic(x) + Style { bg, fg: color_("#979794"), ..default() }.basic(x) })) .for_each(|(a, b)| *a = b); // i.iter_mut() // .rev() // .zip(loc.map(|x| { - // Style { bg, color: color_("#979794"), ..default() } + // Style { bg, fg: color_("#979794"), ..default() } // .basic(x) // })) // .for_each(|(a, b)| *a = b); @@ -212,7 +212,7 @@ fn r( .map(|x| { Style { bg, - color: color_("#858685"), + fg: color_("#858685"), ..default() } .basic(x) diff --git a/src/text.rs b/src/text.rs index 91c9a61..c5e7b5b 100644 --- a/src/text.rs +++ b/src/text.rs @@ -1012,17 +1012,13 @@ impl TextArea { cells.get((x + self.ho, y)).unwrap().letter = Some(e.c()); cells.get((x + self.ho, y)).unwrap().style = match e { - Mapping::Char(..) => Style { - color: crate::FG, - bg: crate::BG, - flags: 0, - }, + Mapping::Char(..) => + Style::new(crate::FG, crate::BG), Mapping::Fake(Mark { ty: INLAY, .. }, ..) => - Style { - color: const { color_("#536172") }, - bg: crate::BG, - flags: 0, - }, + Style::new( + const { color_("#536172") }, + crate::BG, + ), _ => unreachable!(), }; } @@ -1118,7 +1114,7 @@ impl TextArea { ) }) .for_each(|(x, _)| { - x.style.color = semantic::COLORS[f]; + x.style.fg = semantic::COLORS[f]; x.style.flags |= semantic::STYLES[f]; }); } @@ -1153,7 +1149,7 @@ impl TextArea { ) }) .for_each(|(x, _)| { - x.style.color = MCOLORS[i]; + x.style.fg = MCOLORS[i]; x.style.flags |= MSTYLE[i]; }); }); @@ -1194,7 +1190,7 @@ impl TextArea { .for_each(|(x, _)| { if x.letter == Some(' ') { x.letter = Some('·'); // tabs? what are those - x.style.color = [0x4e, 0x62, 0x79]; + x.style.fg = [0x4e, 0x62, 0x79]; } x.style.bg = [0x27, 0x43, 0x64]; // 0x23, 0x34, 0x4B @@ -1249,7 +1245,7 @@ impl TextArea { .zip(into[(y + oy) * w..].iter_mut().skip(ox)) .for_each(|(a, b)| { *b = Cell { - style: Style { color, bg, flags: 0 }, + style: Style::new(color, bg), letter: Some(a), } }); |