From 7a3546fff78ae41d494b4972f9bfdd6def786585 Mon Sep 17 00:00:00 2001 From: Alexandre Pasmantier Date: Wed, 19 Mar 2025 22:18:47 +0100 Subject: [PATCH 1/3] 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" } } +]) From feafd9b7aad8c9a8193aa90ee13c791b8d54ccb6 Mon Sep 17 00:00:00 2001 From: nick <64329369+nasteffe@users.noreply.github.com> Date: Tue, 29 Apr 2025 21:46:14 +0200 Subject: [PATCH 2/3] fix(shell): update nushell completion script (#488) I've updated the completion.nu script to use nushell syntax. I tested this with a custom cable channel and placed the keybinding logic directly within completion.nu. Next steps will mean figuring out how to move that logic into, I think, shell.rs. Co-authored-by: Victor --- television/utils/shell/completion.nu | 54 +++++++++++++++++++++------- 1 file changed, 42 insertions(+), 12 deletions(-) diff --git a/television/utils/shell/completion.nu b/television/utils/shell/completion.nu index 9024095..477c32d 100644 --- a/television/utils/shell/completion.nu +++ b/television/utils/shell/completion.nu @@ -1,29 +1,59 @@ def tv_smart_autocomplete [] { - let current_prompt = $env.PROMPT # Fetch the current prompt input - + let current_prompt = (commandline) + let cursor = (commandline get-cursor) + let current_prompt = ($current_prompt | str substring 0..$cursor) + 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 - # Update the line editor with the new prompt - $env.PROMPT = $new_prompt + if ($output | is-not-empty) { + commandline edit --replace $output + commandline set-cursor --end } } def tv_shell_history [] { - let current_prompt = $env.PROMPT - + let current_prompt = (commandline) + let cursor = (commandline get-cursor) + let current_prompt = ($current_prompt | str substring 0..$cursor) + let output = (tv nu-history --input $current_prompt | str trim) - if ($output | str length) > 0 { - $env.PROMPT = $output + if ($output | is-not-empty) { + commandline edit --replace $output + commandline set-cursor --end } } # 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" } } -]) + +$env.config = ( + $env.config + | upsert keybindings [ + { + name: tv_completion, + modifier: Control, + keycode: char_t, + mode: [vi_normal, vi_insert, emacs], + event: { + send: executehostcommand, + cmd: "tv_smart_autocomplete" + } + } + { + name: tv_history, + modifier: Control, + keycode: char_r, + mode: [vi_normal, vi_insert, emacs], + event: { + send: executehostcommand, + cmd: "tv_shell_history" + } + } + ] +) From 624c485d68f9bee39d8a34940e87acbae2800c11 Mon Sep 17 00:00:00 2001 From: Alexandre Pasmantier Date: Tue, 29 Apr 2025 21:48:19 +0200 Subject: [PATCH 3/3] fix(shell): add match arm for Nushell's binary name --- television/utils/shell.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/television/utils/shell.rs b/television/utils/shell.rs index 6dbdd33..b3381ac 100644 --- a/television/utils/shell.rs +++ b/television/utils/shell.rs @@ -66,6 +66,7 @@ impl Shell { Shell::Fish => "fish", Shell::PowerShell => "powershell", Shell::Cmd => "cmd", + Shell::Nu => "nu", } } }