A simple CPU rendered GUI IDE experience.
Diffstat (limited to 'src/com.rs')
| -rw-r--r-- | src/com.rs | 244 |
1 files changed, 244 insertions, 0 deletions
diff --git a/src/com.rs b/src/com.rs new file mode 100644 index 0000000..f2c47ca --- /dev/null +++ b/src/com.rs @@ -0,0 +1,244 @@ +use std::mem::MaybeUninit; +use std::sync::LazyLock; + +use Default::default; +use dsb::cell::Style; +use dsb::{Cell, F}; +use fimg::Image; +use itertools::Itertools; +use lsp_types::*; + +use crate::{Complete, FG}; +const BG: [u8; 3] = crate::text::color(*b"1c212b"); +const T_BG: [u8; 3] = crate::text::color(*b"11141a"); + +pub fn s(x: &Complete, c: usize, filter: &str) -> Vec<Cell> { + let mut out = vec![]; + let x = &x.r; + let y = match x { + CompletionResponse::Array(x) => x, + CompletionResponse::List(x) => &x.items, + }; + static mut MATCHER: LazyLock<nucleo::Matcher> = + LazyLock::new(|| nucleo::Matcher::new(nucleo::Config::DEFAULT)); + let p = nucleo::pattern::Pattern::parse( + filter, + nucleo::pattern::CaseMatching::Ignore, + nucleo::pattern::Normalization::Smart, + ); + + let mut i = y + .iter() + .filter(|y| { + y.filter_text + .as_deref() + .unwrap_or(&y.label) + .starts_with(filter) + }) + .map(|y| { + let mut to = vec![]; + let score = p + .score( + nucleo::Utf32Str::new( + y.filter_text.as_deref().unwrap_or(&y.label), + &mut to, + ), + unsafe { &mut *MATCHER }, + ) + .unwrap_or(0); + (score, y) + }) + .sorted_by_key(|x| x.0) + .take(13); + + // 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)| r(x, c, &mut out)); + out +} +fn charc(c: &str) -> usize { + c.chars().count() +} +#[implicit_fn::implicit_fn] +fn r(x: &CompletionItem, c: usize, to: &mut Vec<Cell>) { + let mut b = vec![D; c]; + let ty = match x.kind { + Some(CompletionItemKind::TEXT) => " ", + Some( + CompletionItemKind::METHOD | CompletionItemKind::FUNCTION, + ) => "λ ", + Some(CompletionItemKind::CONSTRUCTOR) => "->", + Some(CompletionItemKind::FIELD) => "x.", + Some(CompletionItemKind::VARIABLE) => "x", + Some(CompletionItemKind::MODULE) => "::", + Some(CompletionItemKind::PROPERTY) => "x.", + Some(CompletionItemKind::VALUE) => "4 ", + Some(CompletionItemKind::ENUM) => "u", + Some(CompletionItemKind::SNIPPET) => "! ", + Some(CompletionItemKind::INTERFACE) => "t ", + Some(CompletionItemKind::REFERENCE) => "& ", + Some(CompletionItemKind::CONSTANT) => "N ", + Some(CompletionItemKind::STRUCT) => "X{", + Some(CompletionItemKind::OPERATOR) => "+ ", + Some(CompletionItemKind::TYPE_PARAMETER) => "T ", + Some(CompletionItemKind::KEYWORD) => " ", + + _ => " ", + }; + b.iter_mut().zip(ty.chars()).for_each(|(x, c)| { + *x = Style { bg: T_BG, color: [154, 155, 154], ..default() } + .basic(c) + }); + let i = &mut b[2..]; + + let left = i.len() as i32 - charc(&x.label) 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: BG, color: [154, 155, 154], ..default() } + .basic(x) + })) + .for_each(|(a, b)| *a = b); + } + i.iter_mut() + .zip(x.label.chars().map(|x| DS.basic(x))) + .for_each(|(a, b)| *a = b); + to.extend(b); +} +const DS: Style = Style { bg: BG, color: FG, flags: 0 }; +const D: Cell = Cell { letter: None, style: DS }; +#[test] +fn t() { + 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, start: 0, selection: 0, scroll: 0 }, c, ""); + dbg!(c, r); + dbg!(w, h); + + let mut fonts = dsb::Fonts::new( + F::FontRef(*crate::FONT, &[(2003265652, 550.0)]), + F::instance(*crate::FONT, *crate::BFONT), + F::FontRef(*crate::IFONT, &[(2003265652, 550.0)]), + F::instance(*crate::IFONT, *crate::BIFONT), + ); + + 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"); +} + +pub struct Dq<T, const N: usize> { + arr: [MaybeUninit<T>; N], + front: u8, + len: u8, +} + +impl<T: Copy, const N: usize> Dq<T, N> { + pub fn new(first: T) -> Self { + let mut dq = Dq { + arr: [const { MaybeUninit::uninit() }; N], + front: 0, + len: 1, + }; + dq.arr[0].write(first); + dq + } + + pub fn first(&mut self) -> T { + unsafe { + self.arr.get_unchecked(self.front as usize).assume_init() + } + } + + pub fn push_front(&mut self, elem: T) { + // sub 1 + match self.front { + 0 => self.front = N as u8 - 1, + n => self.front = n - 1, + } + self.len += 1; + unsafe { + self.arr.get_unchecked_mut(self.front as usize).write(elem) + }; + } + + pub fn iter(&self) -> impl Iterator<Item = T> + '_ { + self.arr + .iter() + .cycle() + .skip(self.front as _) + .take((self.len as usize).min(N)) + .map(|x| unsafe { x.assume_init() }) + } +} |