From 7a3546fff78ae41d494b4972f9bfdd6def786585 Mon Sep 17 00:00:00 2001 From: Alexandre Pasmantier Date: Wed, 19 Mar 2025 22:18:47 +0100 Subject: [PATCH] feat(shell): add support for integration with NuShell --- cable/unix-channels.toml | 4 ++++ television/cli/args.rs | 1 + television/utils/shell.rs | 15 ++++++++++++++ television/utils/shell/completion.nu | 29 ++++++++++++++++++++++++++++ 4 files changed, 49 insertions(+) create mode 100644 television/utils/shell/completion.nu diff --git a/cable/unix-channels.toml b/cable/unix-channels.toml index fdc25a1..9a65977 100644 --- a/cable/unix-channels.toml +++ b/cable/unix-channels.toml @@ -86,3 +86,7 @@ source_command = "sed '1!G;h;$!d' ${HISTFILE:-${HOME}/.bash_history}" [[cable_channel]] name = "fish-history" source_command = "fish -c 'history'" + +[[cable_channel]] +name = "nu-history" +source_command = "nu -c 'history'" diff --git a/television/cli/args.rs b/television/cli/args.rs index a319b4a..ed20f0e 100644 --- a/television/cli/args.rs +++ b/television/cli/args.rs @@ -158,6 +158,7 @@ pub enum Shell { Fish, PowerShell, Cmd, + Nu, } #[allow(clippy::unnecessary_wraps)] diff --git a/television/utils/shell.rs b/television/utils/shell.rs index aa351fa..6dbdd33 100644 --- a/television/utils/shell.rs +++ b/television/utils/shell.rs @@ -11,6 +11,7 @@ pub enum Shell { Fish, PowerShell, Cmd, + Nu, } impl Default for Shell { @@ -77,6 +78,7 @@ impl From for Shell { CliShell::Fish => Shell::Fish, CliShell::PowerShell => Shell::PowerShell, CliShell::Cmd => Shell::Cmd, + CliShell::Nu => Shell::Nu, } } } @@ -89,6 +91,7 @@ impl From<&CliShell> for Shell { CliShell::Fish => Shell::Fish, CliShell::PowerShell => Shell::PowerShell, CliShell::Cmd => Shell::Cmd, + CliShell::Nu => Shell::Nu, } } } @@ -96,6 +99,7 @@ impl From<&CliShell> for Shell { const COMPLETION_ZSH: &str = include_str!("shell/completion.zsh"); const COMPLETION_BASH: &str = include_str!("shell/completion.bash"); const COMPLETION_FISH: &str = include_str!("shell/completion.fish"); +const COMPLETION_NU: &str = include_str!("shell/completion.nu"); // create the appropriate key binding for each supported shell pub fn ctrl_keybinding(shell: Shell, character: char) -> Result { @@ -103,6 +107,7 @@ pub fn ctrl_keybinding(shell: Shell, character: char) -> Result { Shell::Bash => Ok(format!(r"\C-{character}")), Shell::Zsh => Ok(format!(r"^{character}")), Shell::Fish => Ok(format!(r"\c{character}")), + Shell::Nu => Ok(format!(r"Ctrl-{character}")), _ => anyhow::bail!("This shell is not yet supported: {:?}", shell), } } @@ -112,6 +117,7 @@ pub fn completion_script(shell: Shell) -> Result<&'static str> { Shell::Bash => Ok(COMPLETION_BASH), Shell::Zsh => Ok(COMPLETION_ZSH), Shell::Fish => Ok(COMPLETION_FISH), + Shell::Nu => Ok(COMPLETION_NU), _ => anyhow::bail!("This shell is not yet supported: {:?}", shell), } } @@ -177,4 +183,13 @@ mod tests { let result = ctrl_keybinding(shell, character); assert!(result.is_err()); } + + #[test] + fn test_nushell_ctrl_keybinding() { + let character = 's'; + let shell = Shell::Nu; + let result = ctrl_keybinding(shell, character); + assert!(result.is_ok()); + assert_eq!(result.unwrap(), "Ctrl-s"); + } } diff --git a/television/utils/shell/completion.nu b/television/utils/shell/completion.nu new file mode 100644 index 0000000..9024095 --- /dev/null +++ b/television/utils/shell/completion.nu @@ -0,0 +1,29 @@ +def tv_smart_autocomplete [] { + let current_prompt = $env.PROMPT # Fetch the current prompt input + + let output = (tv --autocomplete-prompt $current_prompt | str trim) + + if ($output | str length) > 0 { + let needs_space = not ($current_prompt | str ends-with " ") + let new_prompt = if $needs_space { $"($current_prompt) " + $output } else { $current_prompt + $output } + + # Update the line editor with the new prompt + $env.PROMPT = $new_prompt + } +} + +def tv_shell_history [] { + let current_prompt = $env.PROMPT + + let output = (tv nu-history --input $current_prompt | str trim) + + if ($output | str length) > 0 { + $env.PROMPT = $output + } +} + +# Bind custom keybindings +$env.config = ($env.config | upsert keybindings [ + { name: "tv_completion", modifier: none, keycode: "{tv_smart_autocomplete_keybinding}", mode: "vi_normal", action: { send: "tv_smart_autocomplete" } } + { name: "tv_history", modifier: none, keycode: "{tv_shell_history_keybinding}", mode: "vi_normal", action: { send: "tv_shell_history" } } +])