@@ -44,7 +44,7 @@ use movement::Movement;
4444use crate::{
4545 args,
4646 compositor::{self, Component, Compositor},
47− ui::{self, overlay::overlayed, FilePicker, Popup, Prompt, PromptEvent},
47+ ui::{self, overlay::overlayed, FilePicker, Picker, Popup, Prompt, PromptEvent},
4848};
4949
5050use crate::job::{self, Job, Jobs};
@@ -430,6 +430,7 @@ impl MappableCommand {
430430 decrement, "Decrement",
431431 record_macro, "Record macro",
432432 replay_macro, "Replay macro",
433+ command_palette, "Open command pallete",
433434 );
434435}
435436
@@ -3692,6 +3693,69 @@ pub fn code_action(cx: &mut Context) {
36923693 )
36933694}
36943695
3696+pub fn command_palette(cx: &mut Context) {
3697+ cx.callback = Some(Box::new(
3698+ move |compositor: &mut Compositor, cx: &mut compositor::Context| {
3699+ let doc = doc_mut!(cx.editor);
3700+ let keymap =
3701+ compositor.find::<ui::EditorView>().unwrap().keymaps[&doc.mode].reverse_map();
3702+
3703+ let mut commands: Vec<MappableCommand> = MappableCommand::STATIC_COMMAND_LIST.into();
3704+ commands.extend(
3705+ cmd::TYPABLE_COMMAND_LIST
3706+ .iter()
3707+ .map(|cmd| MappableCommand::Typable {
3708+ name: cmd.name.to_owned(),
3709+ doc: cmd.doc.to_owned(),
3710+ args: Vec::new(),
3711+ }),
3712+ );
3713+
3714+ // formats key bindings, multiple bindings are comma separated,
3715+ // individual key presses are joined with `+`
3716+ let fmt_binding = |bindings: &Vec<Vec<KeyEvent>>| -> String {
3717+ bindings
3718+ .iter()
3719+ .map(|bind| {
3720+ bind.iter()
3721+ .map(|key| key.to_string())
3722+ .collect::<Vec<String>>()
3723+ .join("+")
3724+ })
3725+ .collect::<Vec<String>>()
3726+ .join(", ")
3727+ };
3728+
3729+ let picker = Picker::new(
3730+ commands,
3731+ move |command| match command {
3732+ MappableCommand::Typable { doc, name, .. } => match keymap.get(name as &String)
3733+ {
3734+ Some(bindings) => format!("{} ({})", doc, fmt_binding(bindings)).into(),
3735+ None => doc.into(),
3736+ },
3737+ MappableCommand::Static { doc, name, .. } => match keymap.get(*name) {
3738+ Some(bindings) => format!("{} ({})", doc, fmt_binding(bindings)).into(),
3739+ None => (*doc).into(),
3740+ },
3741+ },
3742+ move |cx, command, _action| {
3743+ let mut ctx = Context {
3744+ register: None,
3745+ count: std::num::NonZeroUsize::new(1),
3746+ editor: cx.editor,
3747+ callback: None,
3748+ on_next_key_callback: None,
3749+ jobs: cx.jobs,
3750+ };
3751+ command.execute(&mut ctx);
3752+ },
3753+ );
3754+ compositor.push(Box::new(picker));
3755+ },
3756+ ));
3757+}
3758+
36953759pub fn execute_lsp_command(editor: &mut Editor, cmd: lsp::Command) {
36963760 let doc = doc!(editor);
36973761 let language_server = match doc.language_server() {