use std::marker::PhantomData;
use std::sync::LazyLock;
use warpui::{keymap::Keystroke, AppContext};
use crate::editor::{SELECT_DOWN_ACTION_NAME, SELECT_UP_ACTION_NAME};
use crate::terminal::input::inline_menu::{
InlineMenuAction, InlineMenuMessageArgs, InlineMenuRowAction,
};
use crate::terminal::input::message_bar::{Message, MessageItem, MessageProvider};
use crate::util::bindings::keybinding_name_to_keystroke;
/// Generic message provider for inline menus.
///
/// The message line is what contains the up/down navigation hints and optionally,
/// contextual CTAs based on the currently selected item.
pub struct InlineMenuMessageProvider(PhantomData);
impl Default for InlineMenuMessageProvider {
fn default() -> Self {
Self(PhantomData)
}
}
impl MessageProvider> for InlineMenuMessageProvider
where
A: InlineMenuAction,
{
fn produce_message(&self, args: InlineMenuMessageArgs<'_, A, T>) -> Option {
A::produce_inline_menu_message(args)
}
}
/// Returns the default set of navigation/dismiss message items that should be rendered in all
/// inline menus.
pub fn default_navigation_message_items(
args: &InlineMenuMessageArgs<'_, A, T>,
) -> Vec {
let navigation_keystrokes = navigation_keystrokes(args.app);
let mut items = vec![
MessageItem::keystroke(navigation_keystrokes.0),
MessageItem::keystroke(navigation_keystrokes.1),
MessageItem::text(" to navigate"),
];
if args.inline_menu_model.tab_configs().len() > 1 {
items.push(MessageItem::keystroke(Keystroke {
key: "tab".to_owned(),
shift: true,
..Default::default()
}));
items.push(MessageItem::text(" to cycle tabs"));
}
items.push(MessageItem::clickable(
vec![
MessageItem::keystroke(Keystroke {
key: "escape".to_owned(),
..Default::default()
}),
MessageItem::text(" to dismiss"),
],
|ctx| {
ctx.dispatch_typed_action(InlineMenuRowAction::::Dismiss);
},
args.inline_menu_model.mouse_states().dismiss.clone(),
));
items
}
fn navigation_keystrokes(app: &AppContext) -> (Keystroke, Keystroke) {
static DEFAULT_SELECT_UP_BINDING: LazyLock