A simple CPU rendered GUI IDE experience.
Diffstat (limited to 'src/act.rs')
-rw-r--r--src/act.rs201
1 files changed, 172 insertions, 29 deletions
diff --git a/src/act.rs b/src/act.rs
index f28ca29..fc4a221 100644
--- a/src/act.rs
+++ b/src/act.rs
@@ -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);