ytil_noxi/
vim_ui_select.rs1use core::fmt::Debug;
4use core::fmt::Display;
5use std::rc::Rc;
6
7use nvim_oxi::mlua;
8use nvim_oxi::mlua::IntoLua;
9use nvim_oxi::mlua::ObjectLike;
10use rootcause::report;
11
12pub struct QuickfixConfig {
18 pub trigger_value: String,
20 pub all_items: Vec<(String, i64)>,
22}
23
24pub fn open<C, K, V>(
36 choices: impl IntoIterator<Item = C> + Debug,
37 opts: &(impl IntoIterator<Item = (K, V)> + Debug + Clone),
38 callback: impl Fn(usize) + 'static,
39 maybe_quickfix: Option<QuickfixConfig>,
40) -> rootcause::Result<()>
41where
42 C: Display,
43 K: IntoLua,
44 V: IntoLua,
45{
46 let lua = mlua::lua();
47
48 let vim_ui_select = lua
49 .globals()
50 .get_path::<mlua::Function>("vim.ui.select")
51 .map_err(|err| report!("cannot fetch vim.ui.select function from Lua globals").attach(err.to_string()))?;
52
53 let opts_table = lua.create_table_from(opts.clone()).map_err(|err| {
54 report!("cannot create opts table")
55 .attach(format!("opts={opts:#?}"))
56 .attach(err.to_string())
57 })?;
58
59 let quickfix = maybe_quickfix.map(Rc::new);
60
61 let vim_ui_select_callback = lua
62 .create_function(
63 move |_: &mlua::Lua, (selected_value, idx): (Option<String>, Option<usize>)| {
64 if let Some(quickfix) = &quickfix
65 && selected_value.is_some_and(|x| x == quickfix.trigger_value)
66 {
67 let _ = crate::quickfix::open(quickfix.all_items.iter().map(|(s, i)| (s.as_str(), *i)))
68 .inspect_err(|err| {
69 crate::notify::error(format!("error opening quickfix: {err:#}"));
70 });
71 return Ok(());
72 }
73 if let Some(idx) = idx {
74 callback(idx.saturating_sub(1));
75 }
76 Ok(())
77 },
78 )
79 .map_err(|err| {
80 report!("cannot create vim.ui.select callback")
81 .attach(format!("choices={choices:#?} opts={opts_table:#?}"))
82 .attach(err.to_string())
83 })?;
84
85 let vim_ui_choices = choices.into_iter().map(|c| c.to_string()).collect::<Vec<_>>();
86
87 vim_ui_select
88 .call::<()>((vim_ui_choices.clone(), opts_table.clone(), vim_ui_select_callback))
89 .map_err(|err| {
90 report!("cannot call vim.ui.select")
91 .attach(format!("choices={vim_ui_choices:#?} opts={opts_table:#?}"))
92 .attach(err.to_string())
93 })?;
94
95 Ok(())
96}