A simple CPU rendered GUI IDE experience.
Diffstat (limited to 'src/menu.rs')
-rw-r--r--src/menu.rs90
1 files changed, 90 insertions, 0 deletions
diff --git a/src/menu.rs b/src/menu.rs
new file mode 100644
index 0000000..5c2d092
--- /dev/null
+++ b/src/menu.rs
@@ -0,0 +1,90 @@
+use std::borrow::Cow;
+use std::cmp::Reverse;
+use std::sync::LazyLock;
+
+use itertools::Itertools;
+
+#[lower::apply(saturating)]
+pub fn next<const N: usize>(n: usize, sel: &mut usize, vo: &mut usize) {
+ *sel += 1;
+ if *sel == n {
+ *vo = 0;
+ *sel = 0;
+ }
+ if *sel >= *vo + N {
+ *vo += 1;
+ }
+}
+#[lower::apply(saturating)]
+pub fn back<const N: usize>(n: usize, sel: &mut usize, vo: &mut usize) {
+ if *sel == 0 {
+ *vo = n - N;
+ *sel = n - 1;
+ } else {
+ *sel -= 1;
+ if *sel < *vo {
+ *vo -= 1;
+ }
+ }
+}
+
+pub fn score<'a, T: Key<'a>>(
+ x: impl Iterator<Item = T>,
+ filter: &'_ str,
+) -> Vec<(u32, T, Vec<u32>)> {
+ #[thread_local]
+ static mut MATCHER: LazyLock<nucleo::Matcher> =
+ LazyLock::new(|| nucleo::Matcher::new(nucleo::Config::DEFAULT));
+
+ let p = nucleo::pattern::Pattern::parse(
+ filter,
+ nucleo::pattern::CaseMatching::Smart,
+ nucleo::pattern::Normalization::Smart,
+ );
+ let mut v = x
+ .map(move |y| {
+ let mut utf32 = vec![];
+ // std::env::args().nth(1).unwrap().as_bytes().fi .fold(0, |acc, x| acc * 10 + x - b'0');
+ let hay = y.k();
+ let mut indices = vec![];
+ let score = p
+ .indices(
+ nucleo::Utf32Str::new(&hay, &mut utf32),
+ unsafe { &mut *MATCHER },
+ &mut indices,
+ )
+ .unwrap_or(0);
+ indices.sort_unstable();
+ indices.dedup();
+
+ (score, y, indices)
+ })
+ .collect::<Vec<_>>();
+ // std::fs::write(
+ // "com",
+ // v.iter().map(|x| x.1.label.clone() + "\n").collect::<String>(),
+ // );
+ v.sort_by_key(|x| Reverse(x.0));
+ v
+}
+
+pub fn filter<'a, T: Key<'a>>(
+ i: impl Iterator<Item = T>,
+ filter: &'_ str,
+) -> impl Iterator<Item = T> {
+ i.filter(move |y| {
+ filter.is_empty()
+ || y.k().chars().any(|x| filter.chars().contains(&x))
+ // .collect::<HashSet<_>>()
+ // .intersection(&filter.chars().collect())
+ // .count()
+ // > 0
+ })
+}
+
+pub trait Key<'a> {
+ fn key(&self) -> impl Into<Cow<'a, str>>;
+ fn k(&self) -> Cow<'a, str> {
+ self.key().into()
+ }
+}