A simple CPU rendered GUI IDE experience.
Diffstat (limited to 'src/com.rs')
-rw-r--r--src/com.rs262
1 files changed, 262 insertions, 0 deletions
diff --git a/src/com.rs b/src/com.rs
new file mode 100644
index 0000000..e157787
--- /dev/null
+++ b/src/com.rs
@@ -0,0 +1,262 @@
+use std::borrow::Cow;
+use std::iter::repeat;
+
+use Default::default;
+use dsb::Cell;
+use dsb::cell::Style;
+use lsp_types::*;
+use serde::{Deserialize, Serialize};
+
+use crate::FG;
+use crate::menu::{Key, back, filter, next, score};
+use crate::text::{col, color_, set_a};
+
+#[derive(Serialize, Deserialize)]
+pub struct Complete {
+ pub r: CompletionResponse,
+ pub start: usize,
+ pub selection: usize,
+ pub vo: usize,
+}
+impl std::fmt::Debug for Complete {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ f.debug_struct("Complete")
+ .field("start", &self.start)
+ .field("selection", &self.selection)
+ .field("vo", &self.vo)
+ .finish()
+ }
+}
+impl Complete {
+ pub fn next(&mut self, f: &str) {
+ let n = filter_c(self, f).count();
+ next::<N>(n, &mut self.selection, &mut self.vo);
+ }
+
+ pub fn sel(&self, f: &str) -> &CompletionItem {
+ score_c(filter_c(self, f), f)[self.selection].1
+ }
+
+ pub fn back(&mut self, f: &str) {
+ let n = filter_c(self, f).count();
+ back::<N>(n, &mut self.selection, &mut self.vo);
+ }
+}
+impl<'a> Key<'a> for &'a CompletionItem {
+ fn key(&self) -> impl Into<Cow<'a, str>> {
+ self.filter_text.as_deref().unwrap_or(&self.label)
+ }
+}
+
+fn score_c<'a>(
+ x: impl Iterator<Item = &'a CompletionItem>,
+ filter: &'_ str,
+) -> Vec<(u32, &'a CompletionItem, Vec<u32>)> {
+ score(x, filter)
+}
+
+fn filter_c<'a>(
+ completion: &'a Complete,
+ f: &'_ str,
+) -> impl Iterator<Item = &'a CompletionItem> {
+ let x = &completion.r;
+ let y = match x {
+ CompletionResponse::Array(x) => x,
+ CompletionResponse::List(x) => &x.items,
+ };
+ filter(y.iter(), f)
+}
+
+pub fn s(completion: &Complete, c: usize, f: &str) -> Vec<Cell> {
+ let mut out = vec![];
+ let i = score_c(filter_c(completion, f), f)
+ .into_iter()
+ .zip(0..)
+ .skip(completion.vo)
+ .take(N);
+
+ // let Some((s, x)) = i.next() else {
+ // return vec![];
+ // };
+
+ // let mut q = Dq::<_, 13>::new((s, x));
+ // for (s, x) in i {
+ // if q.first().0 <= s {
+ // q.push_front((s, x));
+ // }
+ // }
+
+ // fuzzy_aho_corasick::FuzzyAhoCorasickBuilder::new()
+ // .fuzzy(
+ // FuzzyLimits::new()
+ // .insertions(20)
+ // .deletions(2)
+ // .edits(4)
+ // .substitutions(5)
+ // .swaps(3),
+ // .penalties(FuzzyPenalties {
+ // )
+ // insertion: 0.0,
+ // deletion: 1.0,
+ // substitution: 0.5,
+ // swap: 0.5,
+ // })
+ // .build(
+ // y.iter().map(|x| x.filter_text.as_deref().unwrap_or(&x.label)),
+ // )
+ // .search(filter, 0.25)
+ // .into_iter()
+ // .map(|x| &y[x.pattern_index])
+ // // .take(13);
+ // // for x in y
+ // // .iter()
+ // // .filter(|x| {
+ // // x.filter_text
+ // // .as_deref()
+ // // .unwrap_or(&x.label)
+ // // .starts_with(filter)
+ // // })
+ // .take(13)
+ i.for_each(|((_, x, indices), i)| {
+ r(x, c, i == completion.selection, &indices, &mut out)
+ });
+
+ out
+}
+fn charc(c: &str) -> usize {
+ c.chars().count()
+}
+#[implicit_fn::implicit_fn]
+fn r(
+ x: &CompletionItem,
+ c: usize,
+ selected: bool,
+ indices: &[u32],
+ to: &mut Vec<Cell>,
+) {
+ let bg = if selected { col!("#262d3b") } else { col!("#1c212b") };
+
+ 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] = {
+ car::map!(
+ amap::amap! {
+ const { CompletionItemKind::TEXT.0 as usize } => ("#9a9b9a", " "),
+ const { CompletionItemKind::METHOD.0 as usize } | const { CompletionItemKind::FUNCTION.0 as usize } => ("#FFD173", "λ "),
+ const { CompletionItemKind::CONSTRUCTOR.0 as usize } => ("#FFAD66", "->"),
+ const { CompletionItemKind::FIELD.0 as usize } => ("#E06C75", "x."),
+ const { CompletionItemKind::VARIABLE.0 as usize } => ("#E06C75", "x "),
+ const { CompletionItemKind::MODULE.0 as usize } => ("#D5FF80", "::"),
+ const { CompletionItemKind::PROPERTY.0 as usize } => ("#e6e1cf", "x."),
+ const { CompletionItemKind::VALUE.0 as usize } => ("#DFBFFF", "4 "),
+ const { CompletionItemKind::ENUM.0 as usize } => ("#73b9ff", "󰓹u"),
+ const { CompletionItemKind::ENUM_MEMBER.0 as usize } => ("#73b9ff", "󰓹:"),
+ const { CompletionItemKind::SNIPPET.0 as usize } => ("#9a9b9a", "! "),
+ const { CompletionItemKind::INTERFACE.0 as usize } => ("#E5C07B", "t "),
+ const { CompletionItemKind::REFERENCE.0 as usize } => ("#9a9b9a", "& "),
+ const { CompletionItemKind::CONSTANT.0 as usize } => ("#DFBFFF", "N "),
+ const { CompletionItemKind::STRUCT.0 as usize } => ("#73D0FF", "X{"),
+ const { CompletionItemKind::OPERATOR.0 as usize } => ("#F29E74", "+ "),
+ const { CompletionItemKind::TYPE_PARAMETER.0 as usize } => ("#9a9b9a", "T "),
+ const { CompletionItemKind::KEYWORD.0 as usize } => ("#FFAD66", "as"),
+ _ => ("#9a9b9a", " ")
+ },
+ |(x, y)| (set_a(color_(x), 0.5), color_(x), y)
+ )
+ };
+ 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::new(col, bgt) | Style::BOLD).basic(c)
+ });
+ let i = &mut b[2..];
+
+ let label_details = x
+ .label_details
+ .as_ref()
+ .into_iter()
+ .flat_map(|x| &x.detail)
+ .flat_map(_.chars());
+ let left = i.len() as i32
+ - (charc(&x.label) as i32 + label_details.clone().count() as i32)
+ - 2;
+ if let Some(details) = &x.detail {
+ let details = if left < charc(details) as i32 {
+ details
+ .chars()
+ .take(left as _)
+ .chain(['…'])
+ .collect::<Vec<_>>()
+ .into_iter()
+ .rev()
+ .collect::<Vec<_>>()
+ .into_iter()
+ } else {
+ details.chars().rev().collect::<Vec<_>>().into_iter()
+ };
+ i.iter_mut()
+ .rev()
+ .zip(details.map(|x| {
+ Style { bg, fg: color_("#979794"), ..default() }.basic(x)
+ }))
+ .for_each(|(a, b)| *a = b);
+ }
+ i.iter_mut()
+ .zip(
+ x.label.chars().map(|x| ds.basic(x)).zip(0..).chain(
+ label_details
+ .map(|x| {
+ Style { bg, fg: color_("#858685"), ..default() }
+ .basic(x)
+ })
+ .zip(repeat(u32::MAX)),
+ ),
+ )
+ .for_each(|(a, (b, i))| {
+ *a = b;
+ if indices.contains(&i) {
+ a.style |= (Style::BOLD, color_("#ffcc66"));
+ }
+ });
+ to.extend(b);
+}
+pub const N: usize = 13;
+#[test]
+fn t() {
+ use dsb::F;
+ use fimg::Image;
+ let ppem = 20.0;
+ let lh = 10.0;
+ let (w, h) = (611, 8000);
+ let (c, r) = dsb::fit(&crate::FONT, ppem, lh, (w, h));
+ dbg!(dsb::size(&crate::FONT, ppem, lh, (c, r)));
+ let y = serde_json::from_str(include_str!("../complete_")).unwrap();
+ let cells =
+ s(&Complete { r: y, selection: 0, vo: 0, start: 0 }, c, "");
+ dbg!(w, h);
+ dbg!(c, r);
+
+ let mut fonts = dsb::Fonts::new(
+ F::FontRef(*crate::FONT, &[(2003265652, 550.0)]),
+ F::FontRef(*crate::BFONT, &[]),
+ F::FontRef(*crate::IFONT, &[(2003265652, 550.0)]),
+ F::FontRef(*crate::IFONT, &[]),
+ );
+
+ let mut x = Image::build(w as u32, h as u32).fill(crate::hov::BG);
+ unsafe {
+ dsb::render(
+ &cells,
+ (c, r),
+ ppem,
+ &mut fonts,
+ lh,
+ true,
+ x.as_mut(),
+ (0, 0),
+ )
+ };
+ // println!("{:?}", now.elapsed());
+ x.as_ref().save("x");
+}