diff --git a/config/config.nu b/config/config.nu new file mode 100644 index 0000000..8f3c831 --- /dev/null +++ b/config/config.nu @@ -0,0 +1,764 @@ +# Nushell Config File +# +# version = "0.88.1" + +# For more information on defining custom themes, see +# https://www.nushell.sh/book/coloring_and_theming.html +# And here is the theme collection +# https://github.com/nushell/nu_scripts/tree/main/themes +let dark_theme = { + # color for nushell primitives + separator: white + leading_trailing_space_bg: { attr: n } # no fg, no bg, attr none effectively turns this off + header: green_bold + empty: blue + # Closures can be used to choose colors for specific values. + # The value (in this case, a bool) is piped into the closure. + # eg) {|| if $in { 'light_cyan' } else { 'light_gray' } } + bool: light_cyan + int: white + filesize: cyan + duration: white + date: purple + range: white + float: white + string: white + nothing: white + binary: white + cell-path: white + row_index: green_bold + record: white + list: white + block: white + hints: dark_gray + search_result: {bg: red fg: white} + shape_and: purple_bold + shape_binary: purple_bold + shape_block: blue_bold + shape_bool: light_cyan + shape_closure: green_bold + shape_custom: green + shape_datetime: cyan_bold + shape_directory: cyan + shape_external: cyan + shape_externalarg: green_bold + shape_external_resolved: light_yellow_bold + shape_filepath: cyan + shape_flag: blue_bold + shape_float: purple_bold + # shapes are used to change the cli syntax highlighting + shape_garbage: { fg: white bg: red attr: b} + shape_globpattern: cyan_bold + shape_int: purple_bold + shape_internalcall: cyan_bold + shape_keyword: cyan_bold + shape_list: cyan_bold + shape_literal: blue + shape_match_pattern: green + shape_matching_brackets: { attr: u } + shape_nothing: light_cyan + shape_operator: yellow + shape_or: purple_bold + shape_pipe: purple_bold + shape_range: yellow_bold + shape_record: cyan_bold + shape_redirection: purple_bold + shape_signature: green_bold + shape_string: green + shape_string_interpolation: cyan_bold + shape_table: blue_bold + shape_variable: purple + shape_vardecl: purple +} + +let light_theme = { + # color for nushell primitives + separator: dark_gray + leading_trailing_space_bg: { attr: n } # no fg, no bg, attr none effectively turns this off + header: green_bold + empty: blue + # Closures can be used to choose colors for specific values. + # The value (in this case, a bool) is piped into the closure. + # eg) {|| if $in { 'dark_cyan' } else { 'dark_gray' } } + bool: dark_cyan + int: dark_gray + filesize: cyan_bold + duration: dark_gray + date: purple + range: dark_gray + float: dark_gray + string: dark_gray + nothing: dark_gray + binary: dark_gray + cell-path: dark_gray + row_index: green_bold + record: dark_gray + list: dark_gray + block: dark_gray + hints: dark_gray + search_result: {fg: white bg: red} + shape_and: purple_bold + shape_binary: purple_bold + shape_block: blue_bold + shape_bool: light_cyan + shape_closure: green_bold + shape_custom: green + shape_datetime: cyan_bold + shape_directory: cyan + shape_external: cyan + shape_externalarg: green_bold + shape_external_resolved: light_purple_bold + shape_filepath: cyan + shape_flag: blue_bold + shape_float: purple_bold + # shapes are used to change the cli syntax highlighting + shape_garbage: { fg: white bg: red attr: b} + shape_globpattern: cyan_bold + shape_int: purple_bold + shape_internalcall: cyan_bold + shape_keyword: cyan_bold + shape_list: cyan_bold + shape_literal: blue + shape_match_pattern: green + shape_matching_brackets: { attr: u } + shape_nothing: light_cyan + shape_operator: yellow + shape_or: purple_bold + shape_pipe: purple_bold + shape_range: yellow_bold + shape_record: cyan_bold + shape_redirection: purple_bold + shape_signature: green_bold + shape_string: green + shape_string_interpolation: cyan_bold + shape_table: blue_bold + shape_variable: purple + shape_vardecl: purple +} + +# External completer example +# let carapace_completer = {|spans| +# carapace $spans.0 nushell $spans | from json +# } + +# The default config record. This is where much of your global configuration is setup. +$env.config = { + show_banner: true # true or false to enable or disable the welcome banner at startup + + ls: { + use_ls_colors: true # use the LS_COLORS environment variable to colorize output + clickable_links: true # enable or disable clickable links. Your terminal has to support links. + } + + rm: { + always_trash: false # always act as if -t was given. Can be overridden with -p + } + + table: { + mode: rounded # basic, compact, compact_double, light, thin, with_love, rounded, reinforced, heavy, none, other + index_mode: always # "always" show indexes, "never" show indexes, "auto" = show indexes when a table has "index" column + show_empty: true # show 'empty list' and 'empty record' placeholders for command output + padding: { left: 1, right: 1 } # a left right padding of each column in a table + trim: { + methodology: wrapping # wrapping or truncating + wrapping_try_keep_words: true # A strategy used by the 'wrapping' methodology + truncating_suffix: "..." # A suffix used by the 'truncating' methodology + } + header_on_separator: false # show header text on separator/border line + # abbreviated_row_count: 10 # limit data rows from top and bottom after reaching a set point + } + + error_style: "fancy" # "fancy" or "plain" for screen reader-friendly error messages + + # datetime_format determines what a datetime rendered in the shell would look like. + # Behavior without this configuration point will be to "humanize" the datetime display, + # showing something like "a day ago." + datetime_format: { + # normal: '%a, %d %b %Y %H:%M:%S %z' # shows up in displays of variables or other datetime's outside of tables + # table: '%m/%d/%y %I:%M:%S%p' # generally shows up in tabular outputs such as ls. commenting this out will change it to the default human readable datetime format + } + + explore: { + status_bar_background: {fg: "#1D1F21", bg: "#C4C9C6"}, + command_bar_text: {fg: "#C4C9C6"}, + highlight: {fg: "black", bg: "yellow"}, + status: { + error: {fg: "white", bg: "red"}, + warn: {} + info: {} + }, + table: { + split_line: {fg: "#404040"}, + selected_cell: {bg: light_blue}, + selected_row: {}, + selected_column: {}, + }, + } + + history: { + max_size: 100_000 # Session has to be reloaded for this to take effect + sync_on_enter: true # Enable to share history between multiple sessions, else you have to close the session to write history to file + file_format: "plaintext" # "sqlite" or "plaintext" + isolation: false # only available with sqlite file_format. true enables history isolation, false disables it. true will allow the history to be isolated to the current session using up/down arrows. false will allow the history to be shared across all sessions. + } + + completions: { + case_sensitive: false # set to true to enable case-sensitive completions + quick: true # set this to false to prevent auto-selecting completions when only one remains + partial: true # set this to false to prevent partial filling of the prompt + algorithm: "prefix" # prefix or fuzzy + external: { + enable: true # set to false to prevent nushell looking into $env.PATH to find more suggestions, `false` recommended for WSL users as this look up may be very slow + max_results: 100 # setting it lower can improve completion performance at the cost of omitting some options + completer: null # check 'carapace_completer' above as an example + } + } + + filesize: { + metric: false # true => KB, MB, GB (ISO standard), false => KiB, MiB, GiB (Windows standard) + format: "auto" # b, kb, kib, mb, mib, gb, gib, tb, tib, pb, pib, eb, eib, auto + } + + cursor_shape: { + emacs: line # block, underscore, line, blink_block, blink_underscore, blink_line, inherit to skip setting cursor shape (line is the default) + vi_insert: block # block, underscore, line, blink_block, blink_underscore, blink_line, inherit to skip setting cursor shape (block is the default) + vi_normal: underscore # block, underscore, line, blink_block, blink_underscore, blink_line, inherit to skip setting cursor shape (underscore is the default) + } + + color_config: $dark_theme # if you want a more interesting theme, you can replace the empty record with `$dark_theme`, `$light_theme` or another custom record + use_grid_icons: true + footer_mode: "25" # always, never, number_of_rows, auto + float_precision: 2 # the precision for displaying floats in tables + buffer_editor: "" # command that will be used to edit the current line buffer with ctrl+o, if unset fallback to $env.EDITOR and $env.VISUAL + use_ansi_coloring: true + bracketed_paste: true # enable bracketed paste, currently useless on windows + edit_mode: emacs # emacs, vi + shell_integration: false # enables terminal shell integration. Off by default, as some terminals have issues with this. + render_right_prompt_on_last_line: false # true or false to enable or disable right prompt to be rendered on last line of the prompt. + # use_kitty_protocol: false # enables keyboard enhancement protocol implemented by kitty console, only if your terminal support this. + # highlight_resolved_externals: false # true enables highlighting of external commands in the repl resolved by which. + + hooks: { + pre_prompt: [{ null }] # run before the prompt is shown + pre_execution: [{ null }] # run before the repl input is run + env_change: { + PWD: [{|before, after| null }] # run if the PWD environment is different since the last repl input + } + display_output: "if (term size).columns >= 100 { table -e } else { table }" # run to display the output of a pipeline + command_not_found: { null } # return an error message when a command is not found + } + + menus: [ + # Configuration for default nushell menus + # Note the lack of source parameter + { + name: completion_menu + only_buffer_difference: false + marker: "| " + type: { + layout: columnar + columns: 4 + col_width: 20 # Optional value. If missing all the screen width is used to calculate column width + col_padding: 2 + } + style: { + text: green + selected_text: green_reverse + description_text: yellow + } + } + { + name: history_menu + only_buffer_difference: true + marker: "? " + type: { + layout: list + page_size: 10 + } + style: { + text: green + selected_text: green_reverse + description_text: yellow + } + } + { + name: help_menu + only_buffer_difference: true + marker: "? " + type: { + layout: description + columns: 4 + col_width: 20 # Optional value. If missing all the screen width is used to calculate column width + col_padding: 2 + selection_rows: 4 + description_rows: 10 + } + style: { + text: green + selected_text: green_reverse + description_text: yellow + } + } + ] + + keybindings: [ + { + name: completion_menu + modifier: none + keycode: tab + mode: [emacs vi_normal vi_insert] + event: { + until: [ + { send: menu name: completion_menu } + { send: menunext } + { edit: complete } + ] + } + } + { + name: history_menu + modifier: control + keycode: char_r + mode: [emacs, vi_insert, vi_normal] + event: { send: menu name: history_menu } + } + { + name: help_menu + modifier: none + keycode: f1 + mode: [emacs, vi_insert, vi_normal] + event: { send: menu name: help_menu } + } + { + name: completion_previous_menu + modifier: shift + keycode: backtab + mode: [emacs, vi_normal, vi_insert] + event: { send: menuprevious } + } + { + name: next_page_menu + modifier: control + keycode: char_x + mode: emacs + event: { send: menupagenext } + } + { + name: undo_or_previous_page_menu + modifier: control + keycode: char_z + mode: emacs + event: { + until: [ + { send: menupageprevious } + { edit: undo } + ] + } + } + { + name: escape + modifier: none + keycode: escape + mode: [emacs, vi_normal, vi_insert] + event: { send: esc } # NOTE: does not appear to work + } + { + name: cancel_command + modifier: control + keycode: char_c + mode: [emacs, vi_normal, vi_insert] + event: { send: ctrlc } + } + { + name: quit_shell + modifier: control + keycode: char_d + mode: [emacs, vi_normal, vi_insert] + event: { send: ctrld } + } + { + name: clear_screen + modifier: control + keycode: char_l + mode: [emacs, vi_normal, vi_insert] + event: { send: clearscreen } + } + { + name: search_history + modifier: control + keycode: char_q + mode: [emacs, vi_normal, vi_insert] + event: { send: searchhistory } + } + { + name: open_command_editor + modifier: control + keycode: char_o + mode: [emacs, vi_normal, vi_insert] + event: { send: openeditor } + } + { + name: move_up + modifier: none + keycode: up + mode: [emacs, vi_normal, vi_insert] + event: { + until: [ + {send: menuup} + {send: up} + ] + } + } + { + name: move_down + modifier: none + keycode: down + mode: [emacs, vi_normal, vi_insert] + event: { + until: [ + {send: menudown} + {send: down} + ] + } + } + { + name: move_left + modifier: none + keycode: left + mode: [emacs, vi_normal, vi_insert] + event: { + until: [ + {send: menuleft} + {send: left} + ] + } + } + { + name: move_right_or_take_history_hint + modifier: none + keycode: right + mode: [emacs, vi_normal, vi_insert] + event: { + until: [ + {send: historyhintcomplete} + {send: menuright} + {send: right} + ] + } + } + { + name: move_one_word_left + modifier: control + keycode: left + mode: [emacs, vi_normal, vi_insert] + event: {edit: movewordleft} + } + { + name: move_one_word_right_or_take_history_hint + modifier: control + keycode: right + mode: [emacs, vi_normal, vi_insert] + event: { + until: [ + {send: historyhintwordcomplete} + {edit: movewordright} + ] + } + } + { + name: move_to_line_start + modifier: none + keycode: home + mode: [emacs, vi_normal, vi_insert] + event: {edit: movetolinestart} + } + { + name: move_to_line_start + modifier: control + keycode: char_a + mode: [emacs, vi_normal, vi_insert] + event: {edit: movetolinestart} + } + { + name: move_to_line_end_or_take_history_hint + modifier: none + keycode: end + mode: [emacs, vi_normal, vi_insert] + event: { + until: [ + {send: historyhintcomplete} + {edit: movetolineend} + ] + } + } + { + name: move_to_line_end_or_take_history_hint + modifier: control + keycode: char_e + mode: [emacs, vi_normal, vi_insert] + event: { + until: [ + {send: historyhintcomplete} + {edit: movetolineend} + ] + } + } + { + name: move_to_line_start + modifier: control + keycode: home + mode: [emacs, vi_normal, vi_insert] + event: {edit: movetolinestart} + } + { + name: move_to_line_end + modifier: control + keycode: end + mode: [emacs, vi_normal, vi_insert] + event: {edit: movetolineend} + } + { + name: move_up + modifier: control + keycode: char_p + mode: [emacs, vi_normal, vi_insert] + event: { + until: [ + {send: menuup} + {send: up} + ] + } + } + { + name: move_down + modifier: control + keycode: char_t + mode: [emacs, vi_normal, vi_insert] + event: { + until: [ + {send: menudown} + {send: down} + ] + } + } + { + name: delete_one_character_backward + modifier: none + keycode: backspace + mode: [emacs, vi_insert] + event: {edit: backspace} + } + { + name: delete_one_word_backward + modifier: control + keycode: backspace + mode: [emacs, vi_insert] + event: {edit: backspaceword} + } + { + name: delete_one_character_forward + modifier: none + keycode: delete + mode: [emacs, vi_insert] + event: {edit: delete} + } + { + name: delete_one_character_forward + modifier: control + keycode: delete + mode: [emacs, vi_insert] + event: {edit: delete} + } + { + name: delete_one_character_forward + modifier: control + keycode: char_h + mode: [emacs, vi_insert] + event: {edit: backspace} + } + { + name: delete_one_word_backward + modifier: control + keycode: char_w + mode: [emacs, vi_insert] + event: {edit: backspaceword} + } + { + name: move_left + modifier: none + keycode: backspace + mode: vi_normal + event: {edit: moveleft} + } + { + name: newline_or_run_command + modifier: none + keycode: enter + mode: emacs + event: {send: enter} + } + { + name: move_left + modifier: control + keycode: char_b + mode: emacs + event: { + until: [ + {send: menuleft} + {send: left} + ] + } + } + { + name: move_right_or_take_history_hint + modifier: control + keycode: char_f + mode: emacs + event: { + until: [ + {send: historyhintcomplete} + {send: menuright} + {send: right} + ] + } + } + { + name: redo_change + modifier: control + keycode: char_g + mode: emacs + event: {edit: redo} + } + { + name: undo_change + modifier: control + keycode: char_z + mode: emacs + event: {edit: undo} + } + { + name: paste_before + modifier: control + keycode: char_y + mode: emacs + event: {edit: pastecutbufferbefore} + } + { + name: cut_word_left + modifier: control + keycode: char_w + mode: emacs + event: {edit: cutwordleft} + } + { + name: cut_line_to_end + modifier: control + keycode: char_k + mode: emacs + event: {edit: cuttoend} + } + { + name: cut_line_from_start + modifier: control + keycode: char_u + mode: emacs + event: {edit: cutfromstart} + } + { + name: swap_graphemes + modifier: control + keycode: char_t + mode: emacs + event: {edit: swapgraphemes} + } + { + name: move_one_word_left + modifier: alt + keycode: left + mode: emacs + event: {edit: movewordleft} + } + { + name: move_one_word_right_or_take_history_hint + modifier: alt + keycode: right + mode: emacs + event: { + until: [ + {send: historyhintwordcomplete} + {edit: movewordright} + ] + } + } + { + name: move_one_word_left + modifier: alt + keycode: char_b + mode: emacs + event: {edit: movewordleft} + } + { + name: move_one_word_right_or_take_history_hint + modifier: alt + keycode: char_f + mode: emacs + event: { + until: [ + {send: historyhintwordcomplete} + {edit: movewordright} + ] + } + } + { + name: delete_one_word_forward + modifier: alt + keycode: delete + mode: emacs + event: {edit: deleteword} + } + { + name: delete_one_word_backward + modifier: alt + keycode: backspace + mode: emacs + event: {edit: backspaceword} + } + { + name: delete_one_word_backward + modifier: alt + keycode: char_m + mode: emacs + event: {edit: backspaceword} + } + { + name: cut_word_to_right + modifier: alt + keycode: char_d + mode: emacs + event: {edit: cutwordright} + } + { + name: upper_case_word + modifier: alt + keycode: char_u + mode: emacs + event: {edit: uppercaseword} + } + { + name: lower_case_word + modifier: alt + keycode: char_l + mode: emacs + event: {edit: lowercaseword} + } + { + name: capitalize_char + modifier: alt + keycode: char_c + mode: emacs + event: {edit: capitalizechar} + } + ] +} + + diff --git a/config/env.nu b/config/env.nu new file mode 100644 index 0000000..177d6ee --- /dev/null +++ b/config/env.nu @@ -0,0 +1,139 @@ +# Nushell Environment Config File +# +# version = "0.88.1" + +def create_left_prompt [] { + let home = $nu.home-path + + # Perform tilde substitution on dir + # To determine if the prefix of the path matches the home dir, we split the current path into + # segments, and compare those with the segments of the home dir. In cases where the current dir + # is a parent of the home dir (e.g. `/home`, homedir is `/home/user`), this comparison will + # also evaluate to true. Inside the condition, we attempt to str replace `$home` with `~`. + # Inside the condition, either: + # 1. The home prefix will be replaced + # 2. The current dir is a parent of the home dir, so it will be uneffected by the str replace + let dir = ( + if ($env.PWD | path split | zip ($home | path split) | all { $in.0 == $in.1 }) { + ($env.PWD | str replace $home "~") + } else { + $env.PWD + } + ) + + let path_color = (if (is-admin) { ansi red_bold } else { ansi green_bold }) + let separator_color = (if (is-admin) { ansi light_red_bold } else { ansi light_green_bold }) + let path_segment = $"($path_color)($dir)" + + $path_segment | str replace --all (char path_sep) $"($separator_color)(char path_sep)($path_color)" +} + +def create_right_prompt [] { + # create a right prompt in magenta with green separators and am/pm underlined + let time_segment = ([ + (ansi reset) + (ansi magenta) + (date now | format date '%x %X %p') # try to respect user's locale + ] | str join | str replace --regex --all "([/:])" $"(ansi green)${1}(ansi magenta)" | + str replace --regex --all "([AP]M)" $"(ansi magenta_underline)${1}") + + let last_exit_code = if ($env.LAST_EXIT_CODE != 0) {([ + (ansi rb) + ($env.LAST_EXIT_CODE) + ] | str join) + } else { "" } + + ([$last_exit_code, (char space), $time_segment] | str join) +} + +# Use nushell functions to define your right and left prompt +$env.PROMPT_COMMAND = {|| create_left_prompt } +# FIXME: This default is not implemented in rust code as of 2023-09-08. +$env.PROMPT_COMMAND_RIGHT = {|| create_right_prompt } + +# The prompt indicators are environmental variables that represent +# the state of the prompt +$env.PROMPT_INDICATOR = {|| "> " } +$env.PROMPT_INDICATOR_VI_INSERT = {|| ": " } +$env.PROMPT_INDICATOR_VI_NORMAL = {|| "> " } +$env.PROMPT_MULTILINE_INDICATOR = {|| "::: " } + +# If you want previously entered commands to have a different prompt from the usual one, +# you can uncomment one or more of the following lines. +# This can be useful if you have a 2-line prompt and it's taking up a lot of space +# because every command entered takes up 2 lines instead of 1. You can then uncomment +# the line below so that previously entered commands show with a single `🚀`. +# $env.TRANSIENT_PROMPT_COMMAND = {|| "🚀 " } +# $env.TRANSIENT_PROMPT_INDICATOR = {|| "" } +# $env.TRANSIENT_PROMPT_INDICATOR_VI_INSERT = {|| "" } +# $env.TRANSIENT_PROMPT_INDICATOR_VI_NORMAL = {|| "" } +# $env.TRANSIENT_PROMPT_MULTILINE_INDICATOR = {|| "" } +# $env.TRANSIENT_PROMPT_COMMAND_RIGHT = {|| "" } + +# Specifies how environment variables are: +# - converted from a string to a value on Nushell startup (from_string) +# - converted from a value back to a string when running external commands (to_string) +# Note: The conversions happen *after* config.nu is loaded +$env.ENV_CONVERSIONS = { + "PATH": { + from_string: { |s| $s | split row (char esep) | path expand --no-symlink } + to_string: { |v| $v | path expand --no-symlink | str join (char esep) } + } + "Path": { + from_string: { |s| $s | split row (char esep) | path expand --no-symlink } + to_string: { |v| $v | path expand --no-symlink | str join (char esep) } + } +} + +# Directories to search for scripts when calling source or use +# The default for this is $nu.default-config-dir/scripts +$env.NU_LIB_DIRS = [ + ($nu.default-config-dir | path join 'scripts') # add /scripts +] + +# Directories to search for plugin binaries when calling register +# The default for this is $nu.default-config-dir/plugins +$env.NU_PLUGIN_DIRS = [ + ($nu.default-config-dir | path join 'plugins') # add /plugins +] + +def paths_sandbox [] { + let envpath = $env.PATH + | where ($it | str contains -n '.apple.security') + | where ($it | str contains -n 'Cryptexes') + | where ($it | str contains -n 'dotnet') + | where ($it | str contains -n -i 'gpg') + | where ($it | str contains -n -i 'nix') + | where ($it | str contains -n -i 'reflex') + | append ($env.HOME | path join .cargo/bin) + | append ($env.HOME | path join hero/bin) + | uniq + | sort + return $envpath +} + +def paths_nix [] { + let $mybase = $"($env.BASE)/bin" + # print $env.PATH + # print "====" + let envpath = $env.PATH + | where ($it | str contains 'nix/store') + | prepend ($"($mybase)") + | append "/usr/bin" + | append "/usr/sbin" + | append "/bin" + | append "/sbin" + # print $envpath + return $envpath +} + + +# path_add | $env.PATH + + +# load-env {PATH:( path_add | str join ":")} + + + + + diff --git a/examples/ifconfig_tun_find.nu b/examples/ifconfig_tun_find.nu new file mode 100644 index 0000000..2ffb82a --- /dev/null +++ b/examples/ifconfig_tun_find.nu @@ -0,0 +1,3 @@ +ifconfig | lines -s | each { |row| (find "tun") } | each { |row| (find "prefixlen") } + | split column --collapse-empty --regex "[% ]" "interface" "mac" "dev" "pl" + | select "dev" "mac" \ No newline at end of file diff --git a/examples/menu.nu b/examples/menu.nu new file mode 100644 index 0000000..210d1fc --- /dev/null +++ b/examples/menu.nu @@ -0,0 +1,32 @@ +let new_menu = { + name: new_menu + only_buffer_difference: true + marker: "# " + type: { + layout: list + page_size: 10 + } + style: { + text: green + selected_text: green_reverse + description_text: yellow + } + source: { |buffer, position| + $nu.scope.vars + | where name =~ $buffer + | sort-by name + | each { |it| {value: $it.name description: $it.type} } + } +} + +$env.config.menus = ($env.config.menus | append $new_menu) + +# let $nu.scope.vars = [{ +# value: # The value that will be inserted in the buffer +# description: # Optional. Description that will be display with the selected value +# span: { # Optional. Span indicating what section of the string will be replaced by the value +# start: +# end: +# } +# extra: [string] # Optional. A list of strings that will be displayed with the selected value. Only works with a description menu +# }] \ No newline at end of file diff --git a/examples/paths.nu b/examples/paths.nu new file mode 100644 index 0000000..25bcd9f --- /dev/null +++ b/examples/paths.nu @@ -0,0 +1,17 @@ + + +let envpath = $env.PATH + | where ($it | str contains -n '.apple.security') + | where ($it | str contains -n 'Cryptexes') + | where ($it | str contains -n 'dotnet') + | where ($it | str contains -n -i 'gpg') + | append ($env.HOME | path join .cargo/bin) + | append ($env.HOME | path join hero/bin) + | uniq + | sort + +load-env {PATH:$envpath} + +# -i means case insensitive +# -n means not + diff --git a/examples/restcall_xml.nu b/examples/restcall_xml.nu new file mode 100644 index 0000000..cce1479 --- /dev/null +++ b/examples/restcall_xml.nu @@ -0,0 +1,26 @@ +let l = http get https://blog.rust-lang.org/feed.xml +let data = $l.content | into value | where tag == 'author' + +echo $data | to json + +# now we get one list of the content +$data | get content | each { get content | each { get content } } | flatten | flatten | to json | save /tmp/test.json + +let input = "182.178.55.3:4333" +$input | parse --regex '(?P\d{1,3}(\.\d{1,3}){3})(:(?P\d+))?' | default port 2222 | select addr port + +let input = "182.178.55.3" +$input | parse --regex '(?P\d{1,3}(\.\d{1,3}){3})(:(?P\d+))?' | default port 2222 | select addr port + + +let input = "182.178.55.3:4333" +$input | parse --regex '(?P\d{1,3}(\.\d{1,3}){3})(:(?P\d+))?' | + each { |row| if $row.port == $"" { $row | upsert port 2222 } else { $row } } | select addr port + +let ipaddr_ = $input | parse --regex '(?P\d{1,3}(\.\d{1,3}){3})(:(?P\d+))?' | select addr port +let ipaddr = $ipaddr_.port ??? + +$input | parse '{addr}:{port}' + +let data = open data.json | from json +let x = "sss" diff --git a/examples/schiit.nu b/examples/schiit.nu new file mode 100644 index 0000000..46ff295 --- /dev/null +++ b/examples/schiit.nu @@ -0,0 +1,23 @@ +#!/usr/bin/env nu +let baseurl = 'https://www.schiit.co.uk/' +let pages = ['headphone-amps' 'dacs'] + +# Simple script to check stock of https://schiit.co.uk store +def schiit [] { + $pages | par-each { |page| + http get ($baseurl + $page) + |query web -q '.price, .stock, .product-item h5' + |str trim + |group 3 + |each { + |x| { + name: $x.0, + avail: $x.1, + price: $x.2 + } + } + } + |sort-by avail +} + +schiit \ No newline at end of file diff --git a/examples/string_format.nu b/examples/string_format.nu new file mode 100644 index 0000000..b9c957f --- /dev/null +++ b/examples/string_format.nu @@ -0,0 +1,7 @@ +# string interpolation + +let name = "this is a string" +$"s ($name)" + +https://www.nushell.sh/book/working_with_strings.html#string-comparison + diff --git a/examples/text_write.nu b/examples/text_write.nu new file mode 100644 index 0000000..9e85687 --- /dev/null +++ b/examples/text_write.nu @@ -0,0 +1,20 @@ +" +Band,Album,Year + +Fugazi,In On The Kill Taker,1993 +Fugazi,The Argument,2001{$x} + +Fugazi,7 Songs,1988 +Fugazi,Repeater,1990 +Fugazi,Steady Diet of Nothing,1991 + +" | save -f /tmp/test.txt + + +#-s is skip empty lines +let data = open /tmp/test.txt | lines -s | split column "," Band Album Year | skip 1 | sort-by Year + +$data | each { |row| $row.Band + ":" + $row.Album + ":" + $row.Year } +$data |to csv + + diff --git a/load.nu b/load.nu new file mode 100644 index 0000000..6a514ca --- /dev/null +++ b/load.nu @@ -0,0 +1,6 @@ + +use tools/download.nu +use tools/runonce.nu +use tools/git.nu +use tools/herotools.nu + diff --git a/plugins/clipboard.nu b/plugins/clipboard.nu new file mode 100644 index 0000000..f8f3320 --- /dev/null +++ b/plugins/clipboard.nu @@ -0,0 +1,4 @@ +cargo install nu_plugin_clipboard +register ~/.cargo/bin/nu_plugin_clipboard + +# DOESNT WORK \ No newline at end of file diff --git a/plugins/dns.nu b/plugins/dns.nu new file mode 100644 index 0000000..6a32323 --- /dev/null +++ b/plugins/dns.nu @@ -0,0 +1,10 @@ + + +# https://github.com/dead10ck/nu_plugin_dns + +use ../tools/runonce.nu + +runonce run 'nu_plugin_dns' { + ^cargo install nu_plugin_dns + register ~/.cargo/bin/nu_plugin_dns +} diff --git a/plugins/highlights.nu b/plugins/highlights.nu new file mode 100644 index 0000000..504e8b2 --- /dev/null +++ b/plugins/highlights.nu @@ -0,0 +1,8 @@ + + +# https://github.com/FMotalleb/nu_plugin_port_list + +run_once 'nu_plugin_highlight' { + cargo install nu_plugin_highlight + register ~/.cargo/bin/nu_plugin_highlight +} diff --git a/plugins/net.nu b/plugins/net.nu new file mode 100644 index 0000000..21d4708 --- /dev/null +++ b/plugins/net.nu @@ -0,0 +1,11 @@ + +use ../tools/runonce.nu + +runonce run 'nu_plugin_net' { + cargo install nu_plugin_net + register ~/.cargo/bin/nu_plugin_net +} + + + +# https://docs.rs/crate/nu_plugin_net/1.3.0 \ No newline at end of file diff --git a/plugins/plugin_desktop_notification.nu b/plugins/plugin_desktop_notification.nu new file mode 100644 index 0000000..b6f450c --- /dev/null +++ b/plugins/plugin_desktop_notification.nu @@ -0,0 +1,32 @@ +# https://github.com/FMotalleb/nu_plugin_desktop_notifications + +cargo install nu_plugin_desktop_notifications +register ~/.cargo/bin/nu_plugin_desktop_notifications +notify -t "test notification body" --summary "test title" + + +# OTHER IMPLEMENTATION + +def "notify_on_done" [ + task: closure +] { + let start = date now + let result = do $task + let end = date now + let total = $end - $start | format duration sec + let body = $"given task finished in ($total)" + notify "task is done" $body + return $result +} + + +def notify [title message] { + # ^osascript -e 'display notification "' + $message + '" with title "' + $title + '"' + let msg = 'display notification "' + $message + '" with title "' + $title + '"' + $msg + ^osascript -e $msg +} + +notify_on_done { port scan 8.8.8.8 53 } + + diff --git a/plugins/plugin_dialog.nu b/plugins/plugin_dialog.nu new file mode 100644 index 0000000..a137b90 --- /dev/null +++ b/plugins/plugin_dialog.nu @@ -0,0 +1,2 @@ + +# https://github.com/Trivernis/nu-plugin-dialog diff --git a/plugins/port_list.nu b/plugins/port_list.nu new file mode 100644 index 0000000..5f593cc --- /dev/null +++ b/plugins/port_list.nu @@ -0,0 +1,10 @@ + + +# https://github.com/FMotalleb/nu_plugin_port_list + +run_once 'nu_plugin_port_list' { + cargo install nu_plugin_port_list + register ~/.cargo/bin/nu_plugin_port_list +} + +port list -4 -t | where state == LISTEN | select [pid,local_port ] | sort-by local_port diff --git a/plugins/port_scan.nu b/plugins/port_scan.nu new file mode 100644 index 0000000..62457e0 --- /dev/null +++ b/plugins/port_scan.nu @@ -0,0 +1,8 @@ +# https://github.com/FMotalleb/nu_plugin_port_scan + + + +cargo install nu_plugin_port_scan +register ~/.cargo/bin/nu_plugin_port_scan + +50..60 | par-each { |it| port scan 8.8.8.8 $it -t 100ms } | where is_open | collect { $in } diff --git a/plugins/web_query.nu b/plugins/web_query.nu new file mode 100644 index 0000000..9ddb79f --- /dev/null +++ b/plugins/web_query.nu @@ -0,0 +1,11 @@ + +use ../tools/runonce.nu + +runonce run 'nu_plugin_query' { + cargo install nu_plugin_query + register ~/.cargo/bin/nu_plugin_query +} + + + +# https://www.nushell.sh/commands/docs/query_web.html \ No newline at end of file diff --git a/push_code.sh b/push_code.sh new file mode 100755 index 0000000..541bf4c --- /dev/null +++ b/push_code.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +set -e + +MYDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +cd "$MYDIR" + +echo "Enter the commit message:" +read commit_message + +git add . -A ; git commit -m "$commit_message"; git push \ No newline at end of file diff --git a/tools/dns.nu b/tools/dns.nu new file mode 100644 index 0000000..4ef9f18 --- /dev/null +++ b/tools/dns.nu @@ -0,0 +1,11 @@ +use runonce.nu + +export def init [] { + runonce run 'nu_plugin_dns' { + cargo install nu_plugin_dns + register ~/.cargo/bin/nu_plugin_port_list + } +} + + +# runonce once 'lls' { ls / } --reset true \ No newline at end of file diff --git a/tools/download.nu b/tools/download.nu new file mode 100644 index 0000000..148c155 --- /dev/null +++ b/tools/download.nu @@ -0,0 +1,86 @@ + +# Function to extract archives with different extensions. +export def extract [path:string] { + let $destdir = $path | path dirname + let $name = $path | split row '/' | last + + if not ($path | path exists) { + print $"could not find ($path) to expand" + exit 1 + } + + let handlers = [ [extension command]; + ['tar\.bz2|tbz|tbz2' 'tar xvjf'] + ['tar\.gz|tgz' 'tar xvzf'] + ['tar\.xz|txz' 'tar xvf'] + ['tar\.Z' 'tar xvZf'] + ['bz2' 'bunzip2'] + ['deb' 'ar x'] + ['gz' 'gunzip'] + ['pkg' 'pkgutil --expand'] + ['rar' 'unrar x'] + ['tar' 'tar xvf'] + ['xz' 'xz --decompress'] + ['zip|war|jar|nupkg' 'unzip'] + ['Z' 'uncompress'] + ['7z' '7za x'] + ] + let maybe_handler = ($handlers | where $name =~ $'\.(($it.extension))$') + if ($maybe_handler | is-empty) { + error make { msg: "unsupported file extension" } + } else { + let handler = ($maybe_handler | first) + cd $destdir + nu -c ($handler.command + ' ' + $name) + } +} + + +export def "download_do" [ dest: string url: string , --minsize=1] { + + let $destdir = $dest | path dirname + mkdir $destdir + print $"download url:($url) to dest:($dest)" + # Download the file + http get $url | save -f $dest + + let minsize = $minsize * 1000000 + + if ($minsize > 0) { + let p = ls $dest + + if (($p.size | into int).0 < $minsize) { + print $"The download was too small for ($dest)" + exit 1 + } else { + print $"Download ok for ($dest)" + } + } + + # echo $"File size: $file_size bytes" + +} + +export def "download_expand" [ dest: string url: string , --minsize=1] { + mkdir $dest + print $"download expand url:($url) to dest:($dest)" + let $file_name = $url | split row '/' | last + let $ext = $file_name | split row '.' | skip 1 | | str join "." | str downcase + let $dest2 = $"($dest)/downloadedfile.($ext)" + print $dest2 + download_do $dest2 $url --minsize=$minsize + let $e = extract $dest2 +} + + +# export def init_plugins [] { +# runonce run init_plugins { +# register bin/nu_plugin_dns +# register bin/nu_plugin_desktop_notifications +# register bin/nu_plugin_net +# register bin/nu_plugin_port_list +# register bin/nu_plugin_port_scan +# register bin/nu_plugin_query +# } --reset true +# } + diff --git a/tools/git.nu b/tools/git.nu new file mode 100644 index 0000000..142dc89 --- /dev/null +++ b/tools/git.nu @@ -0,0 +1,56 @@ + +def gitcheck [] { + let $email = ^git config user.email + # Check if Git email is set + if ( $email | str stats | get words) < 2 { + print "Git email is not set!" + let $email = input "Enter your Git email: " + # Set the Git email + ^git config --global user.email "$git_email" + echo "Git email set to '$git_email'." + } +} + +export def git_configure [] { + gitcheck + mkdir ~/.ssh + let $nr_known_hosts = ^grep github.com ~/.ssh/known_hosts | str stats| get lines + # Check if Git email is set + if $nr_known_hosts < 1 {n + ssh-keyscan github.com >> ~/.ssh/known_hosts + git config --global pull.rebase false + } +} + + + +export def git_clone [ name: string url: string , --reset=false , --pull=false ] string { + print $"git clone '($url)'" + + git_configure + + let $dest = $"($env.BASE)/code/($name)" + if $reset { + print $"remove git dir: ($dest)" + rm -f $dest + } + if ($dest | path exists) and ( ( ls $dest | length ) > 0 ) { + mkdir $dest + cd $dest + if $pull == true { + print $"git pull for ($url)" + git pull + } + } else { + print $"git clone execute" + cd $"($env.BASE)/code" + git clone --depth 1 --no-single-branch $url + } + # git checkout $CLBRANCH + return $dest +} + +def sshagent_loaded [ ] bool { + return ( (ssh-add -l | lines -s | length) > 0 ) +} + diff --git a/tools/herotools.nu b/tools/herotools.nu new file mode 100644 index 0000000..0d28409 --- /dev/null +++ b/tools/herotools.nu @@ -0,0 +1,111 @@ +use git.nu +use download.nu + +def sshagent_loaded [ ] bool { + return ( (ssh-add -l | lines -s | length) > 0 ) +} + + +def url_crystal [] { + let $ssha = sshagent_loaded + if $ssha { + return "git@github.com:freeflowuniverse/crystallib.git" + } else { + return "https://github.com/freeflowuniverse/crystallib" + } +} + +export def clone_crystal [ --reset=false , --pull=false ] string { + let $url = url_crystal + let $r = git git_clone crystallib $url + return $r +} + +export def clone_nuscripts [ --reset=false , --pull=false ] string { + let $ssha = sshagent_loaded + let $dest = $"($env.BASE)/nuscripts" + let $dest_org = $"($env.BASE)/nushell" + if $ssha { + let $r = git git_clone nuscripts "git@git.ourworld.tf:despiegk/nuscripts.git" + rm -f $dest + ln -s $r $dest + sync_nuscripts + return $r + } else { + error make { msg: "load ssh-agent" } + } +} + +export def sync_nuscripts [ --reset=false , --pull=false ] string { + let $code_dir = $"($env.BASE)code/nuscripts/" + let $dest_org = $"($env.BASE)/nushell/" + if not ($code_dir | path exists) { + print $"could not find ($code_dir) to sync to nushell dir" + exit 1 + } + rsync -rav --exclude .git $code_dir $dest_org +} + + + +def url_mycelium [] string { + let $os = $nu.os-info.name + let $arch = $nu.os-info.arch + if $os == "macos" { + if $arch == "aarch64" { + return "https://github.com/threefoldtech/mycelium/releases/download/v0.2.3/mycelium-aarch64-apple-darwin.tar.gz" + } else if $arch == "x86_64" { + return "https://github.com/threefoldtech/mycelium/releases/download/v0.2.3/mycelium-x86_64-apple-darwin.tar.gz" + } + } else if $os == "linux" { + if $arch == "aarch64" { + return "https://github.com/threefoldtech/mycelium/releases/download/v0.2.3/mycelium-aarch64-unknown-linux-musl.tar.gz" + } else if $arch == "x86_64" { + return "https://github.com/threefoldtech/mycelium/releases/download/v0.2.3/mycelium-x86_64-unknown-linux-musl.tar.gz" + } + } else { + error make { msg: "only support darwin & linux" } + } +} + +export def install_mycelium [] { + let $name = "mycelium" + let tmppath = $"/tmp/($name)" + let $bin_dir = $"($env.BASE)/bin" + mkdir $bin_dir + let $url = url_mycelium + print $url + download download_expand $tmppath $"($url)" --minsize 2 + mv -f $"($tmppath)/($name)" $"($bin_dir)/($name)" + chmod +x $"($bin_dir)/($name)" +} + + +def url_hero [] string { + let $os = $nu.os-info.name + let $arch = $nu.os-info.arch + if $os == "macos" { + if $arch == "aarch64" { + return "https://f003.backblazeb2.com/file/threefold/macos-arm64/hero" + } else if $arch == "x86_64" { + return "https://f003.backblazeb2.com/file/threefold/macos-i64/hero" + } + } else if $os == "linux" { + if $arch == "aarch64" { + error make { msg: "find url for hero on linux arm" } + } else if $arch == "x86_64" { + return "https://f003.backblazeb2.com/file/threefold/linux-i64/hero" + } + } else { + error make { msg: "only support darwin & linux" } + } +} + +export def install_hero [] { + let $name = "hero" + let $destpath = $"($env.BASE)/bin/hero" + let $url = url_hero + print $url + download download_do $destpath $"($url)" --minsize 4 + chmod +x $destpath +} \ No newline at end of file diff --git a/tools/nixinstall.nu b/tools/nixinstall.nu new file mode 100644 index 0000000..ed1f9c6 --- /dev/null +++ b/tools/nixinstall.nu @@ -0,0 +1,53 @@ + + +# do "/bin/bash <(curl -L https://nixos.org/nix/install) --daemon" + + +def nixos_remove [] { + if ( "/etc/bashrc.backup-before-nix" | path exists) { + sudo mv -f "/etc/bashrc.backup-before-nix" /etc/bashrc + sudo rm -f "/etc/bash.bashrc.backup-before-nix" + } +} + +def "nix_update" [] { + nix-channel --add https://nixos.org/channels/nixos-23.11 nixpkgs + /nix/var/nix/profiles/default/bin/nix-env -u updates +} + +def "nix_install" [ ...names ] { + $env.NIXPKGS_ALLOW_UNFREE = 1 + $names | each { + |name| /nix/var/nix/profiles/default/bin/nix-env -i $name + } +} + + + +def nixos_install [] { + http get https://nixos.org/nix/install | save -f /tmp/install.sh + chmod +x /tmp/install.sh + ^/tmp/install.sh + + nix_update + + nix-env -u updates + nix_install mc + nix_install nushell + nix_install mdbook mdbook-toc mdbook-pdf mdbook-man-unstable mdbook-mermaid mdbook-footnote mdbook-linkcheck mdbook-kroki-preprocessor + nix_install zola + nix_install vscode-with-extensions + nix_install rustup tailwindcss + nix_install vlang + nix_install go + + # nix_install vscode-with-extensions vscode-extensions.zxh404.vscode-proto3 + # nix_install vscode-extensions.yzhang.markdown-all-in-one + +} + +# for i in 'seq -w 1 n'; do userdel guixbuilder$i; done + + +# nixos_remove +# nixos_install \ No newline at end of file diff --git a/tools/runonce.nu b/tools/runonce.nu new file mode 100644 index 0000000..6926538 --- /dev/null +++ b/tools/runonce.nu @@ -0,0 +1,60 @@ + +#run a command only once +export def "run" [ + name: string + task: closure + #is the code which will be executed + --reset: bool = false + #means we redo the command +] { + mkdir $"($env.HOME)/hero/done/)" + let state_file = [ $env.HOME 'hero' done ('nu_done_' + $name) ] | path join + if ($reset or (not ($state_file | path exists ) ) ) { + let start = date now + # let result = do $task + do $task + let end = date now + let total = $end - $start | format duration sec + let body = $"given task finished in ($total)" + "" | save $state_file -f + # return $result + # } else { + # "Command " + $name + " has already been run." + } + +} + +#reset all the done states +export def "reset" [ + prefix: string +] { + ls $"($env.HOME)/hero/done/nu_done*" | each { |it| rm $it.name} +} + + + +# runonce once 'lls' { ls / } --reset true + + +# def "runonce" [ +# name: string +# task: closure +# #is the code which will be executed +# --reset: bool = false +# #means we redo the command +# ] { +# let state_file = [ $env.HOME 'hero' ('nu_done_' + $name) ] | path join +# if ($reset or (not ($state_file | path exists ) ) ) { +# let start = date now +# # let result = do $task +# do $task +# let end = date now +# let total = $end - $start | format duration sec +# let body = $"given task finished in ($total)" +# "" | save $state_file -f +# # return $result +# # } else { +# # "Command " + $name + " has already been run." +# } + +# } diff --git a/tools/uninstall.nu b/tools/uninstall.nu new file mode 100644 index 0000000..908f678 --- /dev/null +++ b/tools/uninstall.nu @@ -0,0 +1,23 @@ + +# Attempt to remove Homebrew directories and files +echo "Removing Homebrew directories and files..." +let homebrew_dirs = ["/usr/local/Cellar" "/usr/local/Homebrew" + "~/.cache/Homebrew" "~/Library/Caches/Homebrew" "~/Library/Logs/Homebrew" + "/usr/local/Caskroom" "/opt/homebrew" ] +for dir in $homebrew_dirs { + if ($dir | path exists) { + # rm -rfv $dir + let to_remove = $dir | str replace '~' $env.HOME + echo $to_remove + ^sudo rm -r $to_remove + # if ($? == 0) { + # echo "File successfully removed" + # } else { + # echo "Failed to remove file" + # } + echo $"Removed: ($dir)" + + } +} + +echo "Homebrew cleanup process is complete." diff --git a/tools/varia.nu b/tools/varia.nu new file mode 100644 index 0000000..742d01e --- /dev/null +++ b/tools/varia.nu @@ -0,0 +1,64 @@ +# use runonce.nu + + +export def "cargo search" [ query: string, --limit=10] { + ^cargo search $query --limit $limit + | lines + | each { + |line| if ($line | str contains "#") { + $line | parse --regex '(?P.+) = "(?P.+)" +# (?P.+)' + } else { + $line | parse --regex '(?P.+) = "(?P.+)"' + } + } + | flatten +} + +export def "download" [ dest: string url: string , --minsize=1] { + + let $destdir = $dest | path dirname + mkdir $destdir + print $"download url:($url) to dest:($dest)" + # Download the file + http get $url | save -f $dest + + let minsize = $minsize * 1000000 + + if ($minsize > 0) { + let p = ls $dest + + if (($p.size | into int).0 < $minsize) { + print $"The download was too small for ($dest)" + exit 1 + } else { + print $"Download ok for ($dest)" + } + } + + # echo $"File size: $file_size bytes" + +} + +export def "download_expand" [ dest: string url: string , --minsize=1] { + mkdir $dest + print $"download expand url:($url) to dest:($dest)" + let $file_name = $url | split row '/' | last + let $ext = $file_name | split row '.' | skip 1 | | str join "." | str downcase + let $dest2 = $"($dest)/downloadedfile.($ext)" + print $dest2 + download $dest2 $url --minsize=$minsize + let $e = extract $dest2 +} + + +# export def init_plugins [] { +# runonce run init_plugins { +# register bin/nu_plugin_dns +# register bin/nu_plugin_desktop_notifications +# register bin/nu_plugin_net +# register bin/nu_plugin_port_list +# register bin/nu_plugin_port_scan +# register bin/nu_plugin_query +# } --reset true +# } +