A simple CPU rendered GUI IDE experience.
Diffstat (limited to 'src/act.rs')
| -rw-r--r-- | src/act.rs | 201 |
1 files changed, 172 insertions, 29 deletions
@@ -1,58 +1,185 @@ use dsb::Cell; use dsb::cell::Style; -use lsp_types::CodeAction; +use itertools::Itertools; +use lsp_types::{CodeAction, CodeActionKind}; + +#[derive(Debug, Clone)] +enum N<T> { + One(T), + Many(Vec<T>, Entry, Vec<String>), +} +#[derive(Debug, Clone, Copy)] +enum Entry { + Inside(usize), + Outside(usize), +} #[derive(Debug, Clone)] pub struct CodeActions { - pub inner: Vec<CodeAction>, + pub inner: N<Vec<CodeAction>>, pub selection: usize, pub vo: usize, } use crate::FG; -use crate::text::col; +use crate::text::{col, set_a}; const N: usize = 13; impl CodeActions { - pub fn next(&mut self) { - let n = self.inner.len(); - self.selection += 1; - if self.selection == n { - self.vo = 0; - self.selection = 0; + /// there is a clear most intuitive way to do this, but. it is hard. + pub fn new(x: Vec<CodeAction>) -> Self { + let has_groups = x.iter().any(|x| x.group.is_some()); + let inner = if has_groups { + let lem: Vec<Vec<CodeAction>> = x + .into_iter() + .chunk_by(|x| x.group.clone().unwrap_or("0".into())) + .into_iter() + .map(|x| x.1.collect::<Vec<_>>()) + .collect(); + let g = lem + .iter() + .map(|x| x[0].group.clone().unwrap_or("misc".into())) + .collect::<Vec<_>>(); + N::Many(lem, Entry::Outside(0), g) + } else { + N::One(x) + }; + Self { inner, selection: 0, vo: 0 } + } + + pub fn down(&mut self) { + let mut adj = |y: &mut usize, max| { + *y += 1; + if *y == max { + self.vo = 0; + *y = 0; + } + if *y >= self.vo + 13 { + self.vo += 1; + } + }; + match &mut self.inner { + N::Many(x, Entry::Outside(y), so) => { + let n = x.len(); + adj(y, n); + } + N::Many(x, Entry::Inside(g_sel), _) => { + let z = &x[*g_sel]; + let n = z.len(); + + // TODO: think about this + adj(&mut self.selection, n); + } + N::One(x) => { + let n = x.len(); + adj(&mut self.selection, n); + } + }; + } + pub fn innr(&self) -> Option<&[CodeAction]> { + match &self.inner { + N::One(x) => Some(x), + N::Many(x, Entry::Inside(y), _) => Some(&x[*y]), + N::Many(_, Entry::Outside(_), _) => None, } - if self.selection >= self.vo + 13 { - self.vo += 1; + } + pub fn left(&mut self) { + match &mut self.inner { + N::Many(items, x @ Entry::Inside(_), items1) => { + let Entry::Inside(y) = x else { unreachable!() }; + *x = Entry::Outside(*y); + } + _ => {} } } - - pub fn sel(&self) -> &CodeAction { - &self.inner[self.selection] + pub fn right(&mut self) -> Option<&CodeAction> { + match &mut self.inner { + N::One(x) => Some(&x[self.selection]), + N::Many(y, Entry::Inside(x), _) => + Some(&y[*x][self.selection]), + N::Many(_, y, _) => { + let x = + if let Entry::Outside(x) = y { *x } else { panic!() }; + *y = Entry::Inside(x); + None + } + } } #[lower::apply(saturating)] - pub fn back(&mut self) { - let n = self.inner.len(); - if self.selection == 0 { - self.vo = n - N; - self.selection = n - 1; + pub fn up(&mut self) { + if let Some(x) = self.innr() { + let n = x.len(); + if self.selection == 0 { + self.vo = n - N; + self.selection = n - 1; + } else { + self.selection -= 1; + if self.selection < self.vo { + self.vo -= 1; + } + } } else { - self.selection -= 1; - if self.selection < self.vo { - self.vo -= 1; + match &mut self.inner { + N::Many(_, Entry::Outside(y), z) => { + let n = z.len(); + if *y == 0 { + self.vo = n - N; + *y = n - 1; + } else { + *y = *y - 1; + if *y < self.vo { + self.vo -= 1; + } + } + } + _ => unreachable!(), } } } pub fn maxc(&self) -> usize { - self.inner - .iter() - .map(|x| x.title.chars().count()) - .max() - .unwrap_or(0) + match &self.inner { + N::One(x) => x + .iter() + .map(|x| x.title.chars().count() + 2) + .max() + .unwrap_or(0), + N::Many(x, _, g) => x + .iter() + .flatten() + .map(|x| &x.title) + .chain(g) + .map(|x| x.chars().count() + 2) + .max() + .unwrap_or(0), + } } pub fn write(&self, c: usize) -> Vec<Cell> { let mut into = vec![]; - for (el, i) in self.inner.iter().zip(0..) { - write(el, c, self.selection == i, &mut into); + if let Some(x) = self.innr() { + for (el, i) in x.iter().zip(0..).skip(self.vo).take(13) { + write(el, c, self.selection == i, &mut into); + } + } else if let N::Many(_, Entry::Outside(n), z) = &self.inner { + for (el, i) in z.iter().skip(self.vo).zip(0..).take(13) { + let bg = if *n == i { + col!("#262d3b") + } else { + col!("#1c212b") + }; + + let mut to = vec![ + Cell { + style: Style { bg, color: FG, flags: 0 }, + ..Default::default() + }; + c + ]; + to.iter_mut() + .zip(el.chars()) + .for_each(|(a, b)| a.letter = Some(b)); + into.extend(to); + // write(el, c, self.selection == i, &mut into); + } } into } @@ -66,7 +193,23 @@ fn write(x: &CodeAction, c: usize, selected: bool, to: &mut Vec<Cell>) { }; c ]; + + let t = match &x.kind { + Some(x) if x == &CodeActionKind::QUICKFIX => '', + Some(x) + if x == &CodeActionKind::REFACTOR + || x == &CodeActionKind::REFACTOR_EXTRACT + || x == &CodeActionKind::REFACTOR_INLINE + || x == &CodeActionKind::REFACTOR_REWRITE => + '', + 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].letter = Some(t); into.iter_mut() + .skip(1) .zip(x.title.chars()) .for_each(|(a, b)| a.letter = Some(b)); to.extend(into); |