use color_eyre::eyre::{Result, ensure};
use crossterm::event::KeyEvent;
use crate::keybinding::{
bash_zsh::keyevent_to_shell_seq, fish::fish_keyevent_to_shell_seq,
nushell::nushell_keyevent_to_fields,
};
pub enum Shell {
Bash,
Fish,
Nushell,
Zsh,
}
pub fn keyevents_to_shell_binding(
events: &[KeyEvent],
function_name: &str,
shell: Shell,
) -> Result<String> {
ensure!(
!events.is_empty(),
"Invalid leadr keymap: No key events provided."
);
match shell {
Shell::Bash => {
let key_code_string = events
.iter()
.map(|ev| keyevent_to_shell_seq(*ev))
.collect::<String>();
Ok(format!(
"\nbind -m emacs -x '\"{key_code_string}\":{function_name}'\n\
bind -m vi-insert -x '\"{key_code_string}\":{function_name}'\n\
# In vi-command mode, switch to insert mode, invoke leadr using the binding defined above, then return to command mode\n\
bind -m vi-command '\"{key_code_string}\":i{function_name}\\e'\n",
))
}
Shell::Fish => {
let key_code_string = events
.iter()
.map(|ev| fish_keyevent_to_shell_seq(*ev))
.collect::<Vec<_>>()
.join(",");
Ok(format!("\nbind {key_code_string} {function_name}\n"))
}
Shell::Nushell => {
ensure!(
events.len() == 1,
"Invalid keymap: Nushell only supports single-chord keybindings (e.g. `<C-g>` or <S-M-a>).\n \
Multi-chord sequences like `<C-x><C-f>` are not supported.\n \
Please adjust the leadr keymap in your configuration accordingly."
);
let event = events[0];
let fields = nushell_keyevent_to_fields(event)?;
Ok(format!(
"\n$env.config.keybindings ++= [{{\n \
name: leadr\n \
modifier: {}\n \
keycode: {}\n \
mode: [emacs vi_insert vi_normal]\n \
event: {{\n \
send: executehostcommand\n \
cmd: \"{}\"\n \
}}\n\
}}]",
fields.modifier, fields.keycode, function_name
))
}
Shell::Zsh => {
let key_code_string = events
.iter()
.map(|ev| keyevent_to_shell_seq(*ev))
.collect::<String>();
Ok(format!(
"zle -N {function_name}\n\
bindkey '{key_code_string}' {function_name}"
))
}
}
}