# Module: User Interface Utilities # Purpose: Provides terminal UI utilities: output formatting, prompts, spinners, and status displays. # Dependencies: error for error handling, logging for debug utilities use ../config/accessor.nu * use logging.nu [is-debug-enabled] # Check if no-terminal mode is enabled export def get-provisioning-no-terminal [] { # Check environment variable first (use -o for optional in Nushell 0.106+) let env_no_terminal = ($env | get -o PROVISIONING_NO_TERMINAL | default "false") if ($env_no_terminal == "true") or ($env_no_terminal == "1") { return true } # Check config setting config-get "debug.no_terminal" false } # Get output format (json, yaml, table, etc.) export def get-provisioning-out [] { # Check environment variable first let env_out = ($env | get -o PROVISIONING_OUT | default "") if ($env_out | is-not-empty) { return $env_out } # Check config setting config-get "output.format" "" } # Set no-terminal mode export def set-provisioning-no-terminal [value: bool] { $env.PROVISIONING_NO_TERMINAL = $value } # Set output format export def set-provisioning-out [value: string] { $env.PROVISIONING_OUT = $value } # Get notification icon path export def get-notify-icon [] : nothing -> string { $env.PROVISIONING_NOTIFY_ICON? | default "" } export def _ansi [ arg?: string --escape: record ] { if (get-provisioning-no-terminal) { "" } else if (is-terminal --stdout) { if $escape != null { (ansi --escape $escape) } else if ($arg != null) and ($arg != "") { (ansi $arg) } else { "" } } else { "" } } export def format_out [ data: string src?: string mode?: string ] { let msg = match $src { "json" => ($data | from json), _ => $data, } match $mode { "table" => { ($msg | table -i false) }, _ => { $msg } } } export def _print [ data: string src?: string context?: string mode?: string -n # no newline ] { let output = (get-provisioning-out) if $n { if ($output | is-empty) { print -n $data } return } if ($output | is-empty) { print (format_out $data $src $mode) } else { match $output { "json" => { if $context != "result" { return } if $src == "json" { print ($data) } else { print ($data | to json) } }, "yaml" | "yml" => { if $context != "result" { return } if $src == "json" { print ($data | from json | to yaml) } else { print ($data | to yaml) } }, "toml" | "tml" => { if $context != "result" { return } if $src == "json" { print ($data | from json | to toml) } else { print ($data) } }, "text" | "txt" => { if $context != "result" { return } print (format_out $data $src $mode) }, _ => { if ($output | str ends-with ".json" ) { if $context != "result" { return } (if $src == "json" { ($data) } else { ($data | to json) } | save --force $output) } else if ($output | str ends-with ".yaml" ) { if $context != "result" { return } (if $src == "json" { ($data | from json | to yaml) } else { ($data | to yaml) } | save --force $output) } else if ($output | str ends-with ".toml" ) { if $context != "result" { return } (if $src == "json" { ($data | from json | to toml) } else { ($data) } | save --force $output) } else if ($output | str ends-with ".text" ) or ($output | str ends-with ".txt" ) { if $context != "result" { return } format_out $data $src $mode | save --force $output } else { format_out $data $src $mode | save --append $output } } } } } export def end_run [ context: string ] { if ($env.PROVISIONING_OUT? | default "" | is-not-empty) { return } if ($env.PROVISIONING_NO_TITLES? | default false) { return } if (detect_claude_code) { return } if (is-debug-enabled) { _print $"\n(_ansi blue)----🌥 ----🌥 ----🌥 ---- oOo ----🌥 ----🌥 ----🌥 ---- (_ansi reset)" } else { let the_context = if $context != "" { $" to ($context)" } else { "" } if (is-terminal --stdout) { _print $"\n(_ansi cyan)Thanks for using (_ansi blue_bold)((get-provisioning-url) | ansi link --text 'Provisioning')(_ansi reset)" if $the_context != "" { _print $"(_ansi yellow_dimmed)($the_context)(_ansi reset)" } _print ((get-provisioning-url) | ansi link --text $"(_ansi default_dimmed)Click here for more info or visit \n((get-provisioning-url))(_ansi reset)") } else { _print $"\n(_ansi cyan)Thanks for using (_ansi blue_bold) Provisioning [((get-provisioning-url))](_ansi reset)($the_context)" _print $"(_ansi default_dimmed)For more info or visit ((get-provisioning-url))(_ansi reset)" } } } export def show_clip_to [ msg: string show: bool ] { if $show { _print $msg } if (is-terminal --stdout) { if ((version).installed_plugins | str contains "clipboard") { $msg | clipboard copy print $"(ansi default_dimmed)copied into clipboard now (ansi reset)" } } } export def log_debug [ msg: string ] { use std std log debug $msg # std assert (1 == 1) } #// Examples: #// desktop_run_notify "Port scan" "Done" { port scan 8.8.8.8 53 } #// desktop_run_notify "Task try" "Done" --timeout 5sec export def desktop_run_notify [ title: string body: string task?: closure --timeout: duration --icon: string ] { let icon_path = if $icon == null { (get-notify-icon) } else { $icon } let time_out = if $timeout == null { 8sec } else { $timeout } if $task != null { let start = date now let result = do $task let end = date now let total = $end - $start | format duration sec let result_typ = ($result | describe) let msg = if $result_typ == "bool" { (if $result { "✅ done " } else { $"🛑 fail "}) } else if ($result_typ | str starts-with "record") { (if $result.status { "✅ done " } else { $"🛑 fail ($result.error)" }) } else { "" } let time_body = $"($body) ($msg) finished in ($total) " if ((version).installed_plugins | str contains "desktop_notifications") { notify -s $title -t $time_body --timeout $time_out -i $icon_path } else { _print $"(_ansi blue)($title)(_ansi reset)\n(_ansi blue_bold)($time_body)(_ansi reset)" } return $result } else { if ((version).installed_plugins | str contains "desktop_notifications") { notify -s $title -t $body --timeout $time_out -i $icon_path } else { _print $"(_ansi blue)($title)(_ansi reset)\n(_ansi blue_bold)($body)(_ansi reset)" } true } } export def detect_claude_code [] { let claudecode = ($env.CLAUDECODE? | default "" | str contains "1") let entrypoint = ($env.CLAUDE_CODE_ENTRYPOINT? | default "" | str contains "cli") $claudecode or $entrypoint }