use std::iter::{chain, empty, repeat}; use Default::default; use Into::into; use dsb::Cell; use dsb::cell::Style; use itertools::Itertools; use kitty_rc::LaunchCommand; use lsp_types::LocationLink; use rust_analyzer::lsp::ext::{Runnable, RunnableArgs, RunnableKind}; use crate::menu::generic::{GenericMenu, MenuData}; use crate::menu::{Key, charc}; use crate::text::{col, color_, set_a}; use crate::trm; pub enum Runb {} impl MenuData for Runb { type Data = Vec; type Element<'a> = &'a Runnable; fn gn<'a>( x: &'a Self::Data, ) -> impl Iterator> { x.iter() } fn r( _: &'_ Self::Data, x: Self::Element<'_>, workspace: &std::path::Path, columns: usize, selected: bool, indices: &[u32], to: &mut Vec, ) { let bg = if selected { col!("#262d3b") } else { col!("#1c212b") }; let ds: Style = Style::new(crate::FG, bg); let d: Cell = Cell { letter: None, style: ds }; let mut b = vec![d; columns]; const MAP: [([u8; 3], [u8; 3], &str); 70] = { car::map!( amap::amap! { const { RunnableKind::Cargo as usize } => ("#9a9b9a", "󱣘 "), const { RunnableKind::Shell as usize } => ("#FFAD66", "$ "), _ => ("#9a9b9a", " "), }, |(x, y)| (set_a(color_(x), 0.5), color_(x), y) ) }; let (bgt, col, ty) = MAP[x.kind.clone() 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 qualifier = x // .location // .as_ref() // .into_iter() // .flat_map(|x| &x.detail) // .flat_map(_.chars()); let qualifier = empty(); let left = i.len() as i32 - (charc(&x.label) as i32 + qualifier.clone().count() as i32) - 3; let loc = match &x.location { Some(LocationLink { target_uri, .. }) => Some(target_uri.to_file_path().unwrap()), _ => None, // GoTo::R(_) => None, }; let locs = { loc.as_ref() .and_then(|x| { x.strip_prefix(workspace).unwrap_or(&x).to_str() }) .unwrap_or("") }; let loc = locs.chars().rev().collect::>().into_iter(); let q = if left < charc(&locs) as i32 { locs.chars() .take(left as _) .chain(['…']) .collect::>() .into_iter() .rev() .collect::>() .into_iter() } else { loc }; i.iter_mut() .rev() .zip(q.map(|x| { Style { bg, fg: color_("#979794"), ..default() }.basic(x) })) .for_each(|(a, b)| *a = b); // i.iter_mut() // .rev() // .zip(loc.map(|x| { // Style { bg, fg: color_("#979794"), ..default() } // .basic(x) // })) // .for_each(|(a, b)| *a = b); i.iter_mut() .zip( x.label .chars() .chain([' ']) .map(|x| ds.basic(x)) .zip(0..) .chain( qualifier .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 type Runnables = GenericMenu; impl<'a> Key<'a> for &'a Runnable { fn key(&self) -> impl Into> { &self.label } } pub fn run( run: Runnable, ws: &std::path::Path, ) -> impl Future> { match run.args { RunnableArgs::Cargo(x) => { // let mut a = x.cargo_args; let a = if !x.executable_args.is_empty() { [x.cargo_args, vec!["--".into()], x.executable_args] .concat() } else { x.cargo_args }; let x = LaunchCommand::new() .args([ "bash", "-c", &format!( "{}; exec xonsh", chain( [x.override_cargo.unwrap_or("cargo".into())], a ) .join(" ") ), ]) .window_type("tab") .tab_title(run.label) // .keep_focus(true) .cwd( x.workspace_root .as_ref() .map(|x| x.as_str()) .unwrap_or("."), ) .env(serde_json::Map::from_iter( x.environment .into_iter() .chain([["RUST_BACKTRACE", "short"] .map(into) .into()]) .map(|(x, y)| (x, serde_json::Value::from(y))), )); trm::launch(x, ws) } RunnableArgs::Shell(x) => { todo!("{x:?}") } } }