From 8182df2c5058963ed0732c25ba5b83b21cce1425 Mon Sep 17 00:00:00 2001 From: RGBCube Date: Sat, 12 Jul 2025 14:35:32 +0300 Subject: [PATCH 01/12] darwin: stop printing "last login" message --- modules/darwin/stop-login-print-in-shell.nix | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 modules/darwin/stop-login-print-in-shell.nix diff --git a/modules/darwin/stop-login-print-in-shell.nix b/modules/darwin/stop-login-print-in-shell.nix new file mode 100644 index 0000000..cf6ee02 --- /dev/null +++ b/modules/darwin/stop-login-print-in-shell.nix @@ -0,0 +1,5 @@ +{ + home-manager.sharedModules = [{ + home.file.".hushlogin".text = ""; + }]; +} From cf23682ea098f32b53731dc57d6b71660bb55e59 Mon Sep 17 00:00:00 2001 From: RGBCube Date: Sat, 12 Jul 2025 14:40:35 +0300 Subject: [PATCH 02/12] nushell: update configs --- modules/common/nushell/config.nu | 704 +++++++++++--------------- modules/common/nushell/default.nix | 14 - modules/common/nushell/environment.nu | 155 +----- 3 files changed, 300 insertions(+), 573 deletions(-) diff --git a/modules/common/nushell/config.nu b/modules/common/nushell/config.nu index ccd7a1c..fb27269 100644 --- a/modules/common/nushell/config.nu +++ b/modules/common/nushell/config.nu @@ -1,424 +1,318 @@ -$env.config = { - bracketed_paste: true - buffer_editor: "" - datetime_format: {} - edit_mode: vi - error_style: fancy - float_precision: 2 - footer_mode: 25 - render_right_prompt_on_last_line: false - show_banner: false - use_ansi_coloring: true - use_kitty_protocol: true +use std-rfc/clip - shell_integration: { - osc2: false - osc7: true - osc8: true - osc9_9: false - osc133: true - osc633: true - reset_application_mode: true - } -} - -$env.config.color_config = { - binary: white - block: white - bool: {|| if $in { "light_green" } else { "light_red" } } - cell-path: white - date: purple - duration: white - empty: blue - filesize: cyan - float: white - header: green_bold - hints: dark_gray - int: white - list: white - nothing: white - range: white - record: white - row_index: green_bold - search_result: { bg: red fg: white } - separator: white - string: {|| if $in =~ "^(#|0x)[a-fA-F0-9]+$" { ($in | str replace "0x" "#") } else { "white" } } - leading_trailing_space_bg: { attr: n } - - 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_filepath: cyan - shape_flag: blue_bold - shape_float: purple_bold - shape_garbage: { fg: white bg: red attr: b} - shape_globpattern: cyan_bold - shape_int: purple_bold - shape_internalcall: cyan_bold - shape_list: cyan_bold - shape_literal: blue - shape_match_pattern: green - 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_table: blue_bold - shape_vardecl: purple - shape_variable: purple - shape_matching_brackets: { attr: u } - shape_string_interpolation: cyan_bold -} - -$env.config.ls = { - clickable_links: true - use_ls_colors: true -} - -$env.config.rm.always_trash = false - -$env.config.table = { - header_on_separator: false - index_mode: always - mode: rounded - padding: { left: 1 right: 1 } - show_empty: true - trim: { - methodology: wrapping - wrapping_try_keep_words: true - truncating_suffix: "..." - } -} - -$env.config.explore = { - command_bar_text: { fg: "#C4C9C6" } - highlight: { fg: black bg: yellow } - status: { - error: { fg: white bg: red } - warn: {} - info: {} - } - status_bar_background: { fg: "#1D1F21" bg: "#C4C9C6" } - table: { - split_line: { fg: "#404040" } - selected_cell: { bg: light_blue } - selected_row: {} - selected_column: {} - } -} - -$env.config.history = { - file_format: sqlite - isolation: false - max_size: 100_000 - sync_on_enter: true -} - -$env.config.completions = { - algorithm: prefix - case_sensitive: false - partial: true - quick: true - external: { - enable: true - max_results: 100 - completer: {|tokens: list| - let expanded = scope aliases | where name == $tokens.0 | get --ignore-errors expansion.0 - - mut expanded_tokens = if $expanded != null and $tokens.0 != "cd" { - $expanded | split row " " | append ($tokens | skip 1) - } else { - $tokens - } - - $expanded_tokens.0 = ($expanded_tokens.0 | str trim --left --char "^") - - fish --command $"complete '--do-complete=($expanded_tokens | str join ' ')'" - | $"value(char tab)description(char newline)" + $in - | from tsv --flexible --no-infer - } - } -} - -$env.config.cursor_shape = { - vi_insert: line - vi_normal: block -} - -$env.config.hooks = { - command_not_found: {||} - - display_output: { - tee { table --expand | print } - | $env.last = $in - } - - env_change: {} - - pre_execution: [ - { - let prompt = commandline | str trim - - if ($prompt | is-empty) { - return - } - - print $"(ansi title)($prompt) — nu(char bel)" - } - ] - - pre_prompt: [] -} +source ~/.config/nushell/zoxide.nu +source ~/.config/nushell/starship.nu # Retrieve the output of the last command. def _ []: nothing -> any { - $env.last + $env.last? } -$env.config.menus = [ - { - marker: "| " - name: completion_menu - only_buffer_difference: false - style: { - description_text: yellow - selected_text: green_reverse - text: green - } - type: { - col_padding: 2 - col_width: 20 - columns: 4 - layout: columnar - } +# Create a directory and cd into it. +def --env mc [path: path]: nothing -> nothing { + mkdir $path + cd $path +} + +# Create a directory, cd into it and initialize version control. +def --env mcg [path: path]: nothing -> nothing { + mkdir $path + cd $path + jj git init --colocate +} + +# `nu-highlight` with default colors +# +# Custom themes can produce a lot more ansi color codes and make the output +# exceed discord's character limits +def nu-highlight-default [] { + let input = $in + $env.config.color_config = {} + $input | nu-highlight +} + +$env.config.history.file_format = "sqlite" +$env.config.history.isolation = false +$env.config.history.max_size = 10_000_000 +$env.config.history.sync_on_enter = true + +$env.config.show_banner = false + +$env.config.rm.always_trash = true + +$env.config.recursion_limit = 100 + +$env.config.edit_mode = "vi" +$env.config.buffer_editor = "editor" + +$env.config.cursor_shape.emacs = "line" +$env.config.cursor_shape.vi_insert = "line" +$env.config.cursor_shape.vi_normal = "block" + +$env.config.completions.algorithm = "substring" +$env.config.completions.sort = "smart" +$env.config.completions.case_sensitive = false +$env.config.completions.quick = true +$env.config.completions.partial = true +$env.config.completions.use_ls_colors = true +$env.config.completions.external.enable = true +$env.config.completions.external.max_results = 100 +$env.config.completions.external.completer = {|tokens: list| + let expanded = scope aliases + | where name == $tokens.0 + | get --ignore-errors 0.expansion + + mut tokens = if $expanded != null and $tokens.0 != "cd" { + $expanded | split row " " | append ($tokens | skip 1) + } else { + $tokens } - { - marker: "? " - name: history_menu - only_buffer_difference: true - style: { - description_text: yellow - selected_text: green_reverse - text: green - } - type: { - layout: list - page_size: 10 - } + + $tokens.0 = $tokens.0 | str trim --left --char "^" + + let command = $tokens + | str join " " + | str replace --all (char single_quote) $"\\(char single_quote)" + + fish --command $"complete '--do-complete=($command)'" + | $"value(char tab)description(char newline)" + $in + | from tsv --flexible --no-infer +} + +$env.config.use_kitty_protocol = true + +$env.config.shell_integration.osc2 = true +$env.config.shell_integration.osc7 = true +$env.config.shell_integration.osc8 = true +$env.config.shell_integration.osc9_9 = true +$env.config.shell_integration.osc133 = true +$env.config.shell_integration.osc633 = true +$env.config.shell_integration.reset_application_mode = true + +$env.config.bracketed_paste = true + +$env.config.use_ansi_coloring = "auto" + +$env.config.error_style = "fancy" + +$env.config.highlight_resolved_externals = true + +$env.config.display_errors.exit_code = false +$env.config.display_errors.termination_signal = true + +$env.config.footer_mode = 25 + +$env.config.table.mode = "single" +$env.config.table.index_mode = "always" +$env.config.table.show_empty = true +$env.config.table.padding.left = 1 +$env.config.table.padding.right = 1 +$env.config.table.trim.methodology = "wrapping" +$env.config.table.trim.wrapping_try_keep_words = true +$env.config.table.trim.truncating_suffix = "..." +$env.config.table.header_on_separator = true +$env.config.table.abbreviated_row_count = null +$env.config.table.footer_inheritance = true +$env.config.table.missing_value_symbol = $"(ansi magenta_bold)nope(ansi reset)" + +$env.config.datetime_format.table = null +$env.config.datetime_format.normal = $"(ansi blue_bold)%Y(ansi reset)(ansi yellow)-(ansi blue_bold)%m(ansi reset)(ansi yellow)-(ansi blue_bold)%d(ansi reset)(ansi black)T(ansi magenta_bold)%H(ansi reset)(ansi yellow):(ansi magenta_bold)%M(ansi reset)(ansi yellow):(ansi magenta_bold)%S(ansi reset)" + +$env.config.filesize.unit = "metric" +$env.config.filesize.show_unit = true +$env.config.filesize.precision = 1 + +$env.config.render_right_prompt_on_last_line = false + +$env.config.float_precision = 2 + +$env.LS_COLORS = (open ~/.config/nushell/ls_colors.txt) +$env.config.ls.use_ls_colors = true + +$env.config.hooks.pre_prompt = [] + +$env.config.hooks.pre_execution = [ + {|| + commandline + | str trim + | if ($in | is-not-empty) { print $"(ansi title)($in) — nu(char bel)" } } +] + +$env.config.hooks.env_change.PWD = [ + {|_before, after| + ls $after + | if ($in | length) < 20 { print } + } +] + +$env.config.hooks.display_output = {|| + tee { table --expand | print } + | if $in != null { $env.last = $in } +} + +$env.config.hooks.command_not_found = [] + +# Copy the current commandline, add syntax highlighting, wrap it in a +# markdown code block, copy that to the system clipboard. +# +# Perfect for sharing code snippets on discord +def "nu-keybind commandline-copy" []: nothing -> nothing { + commandline + | nu-highlight-default + | [ + "```ansi" + $in + "```" + ] + | str join (char nl) + | clip copy --ansi +} + +$env.config.keybindings ++= [ { - marker: "? " - name: help_menu - only_buffer_difference: true - style: { - description_text: yellow - selected_text: green_reverse - text: green - } - type: { - col_padding: 2 - col_width: 20 - columns: 4 - description_rows: 10 - layout: description - selection_rows: 4 + name: copy_color_commandline + modifier: control_alt + keycode: char_c + mode: [ emacs vi_insert vi_normal ] + event: { + send: executehostcommand + cmd: 'nu-keybind commandline-copy' } } ] -$env.config.keybindings = [ - { - name: copy_commandline - modifier: alt - keycode: char_c - mode: [ vi_normal vi_insert ] - event: { - send: executehostcommand - cmd: 'commandline | nu-highlight | $"```ansi\n($in)\n```" | copy' +$env.config.color_config.bool = {|| + if $in { + "light_green_bold" + } else { + "light_red_bold" + } +} + +$env.config.color_config.string = {|| + if $in =~ "^(#|0x)[a-fA-F0-9]+$" { + $in | str replace "0x" "#" + } else { + "white" + } +} + +module dump { + def site-path []: nothing -> path { + $env.HOME | path join "Projects" "site" + } + + def dump-path []: nothing -> path { + site-path | path join "site" "dump" + } + + # Convert a thought dump namespace to the filesystem path. + export def to-path []: string -> path { + let namespace = $in + + dump-path + | path join ...($namespace | split row ".") + | $in + ".md" + } + + # Convert a filesystem path to a thought dump namespace. + export def to-dump []: path -> string { + let path = $in + + $path + | path relative-to (dump-path) + | path split + | str join "." + | str substring 0..<-3 + } + + # List all thought dumps that start with the given namespace. + export def list [ + namespace: string = "" + ]: nothing -> table { + let dump_prefix = dump-path | path join ...($namespace | split row ".") + + let dump_parent_contents = glob ($dump_prefix | path parse | get parent | path join "**" "*.md") + let dump_matches = $dump_parent_contents | where { str starts-with $dump_prefix } + + ls ...$dump_matches | each { + merge { path: $in.name } + | select path size modified + | merge { namespace: ($in.path | to-dump) } } } - { - name: completion_menu - modifier: none - keycode: tab - mode: [ vi_normal vi_insert ] - event: { - until: [ - { send: menu name: completion_menu } - { send: menunext } - { edit: complete } - ] + + # Deploy the thought dumps and thus the website. + export def deploy []: nothing -> nothing { + print $"(ansi green)deploying...(ansi reset)" + + cd (site-path) + ./apply.nu + } + + # Edit a thought dump. + export def edit [ + namespace: string # The thought dump to edit. Namespaced using '.', does not include file extension. + ]: nothing -> nothing { + let dump_path = $namespace | to-path + + let old_dump_size = try { ls $dump_path } + + mkdir ($dump_path | path parse | get parent) + touch $dump_path + + let old_dump_hash = open $dump_path | hash sha256 + + ^$env.EDITOR $dump_path + + let dump_size = ls $dump_path | get 0.size + if $dump_size == 0b { + print $"(ansi red)thought dump was emptied(ansi reset)" + delete $namespace --existed-before ($old_dump_size != null) + } else if $old_dump_hash == (open $dump_path | hash sha256) { + print $"(ansi yellow)thought dump was not modifier, doing nothing(ansi reset)" + } else { + print $"(ansi magenta)thought dump was edited(ansi reset)" + + let jj_arguments = [ "--repository", (site-path) ] + + jj ...$jj_arguments commit --message $"dump\(($namespace)\): update" + jj ...$jj_arguments bookmark set master --revision @- + + [ + { jj ...$jj_arguments git push --remote origin } + { jj ...$jj_arguments git push --remote rad } + { deploy } + ] | par-each { do $in } | last } } - { - name: history_menu - modifier: control - keycode: char_h - mode: [ vi_insert vi_normal ] - event: { send: menu name: history_menu } - } - { - name: escape - modifier: none - keycode: escape - mode: [ vi_normal vi_insert ] - event: { send: esc } - } - { - name: cancel_command - modifier: control - keycode: char_c - mode: [ vi_normal vi_insert ] - event: { send: ctrlc } - } - { - name: quit_shell - modifier: control - keycode: char_d - mode: [ vi_normal vi_insert ] - event: { send: ctrld } - } - { - name: clear_screen - modifier: control - keycode: char_l - mode: [ vi_normal vi_insert ] - event: { send: clearscreen } - } - { - name: open_command_editor - modifier: control - keycode: char_o - mode: [ vi_normal vi_insert ] - event: { send: openeditor } - } - { - name: abbr - modifier: control - keycode: space - mode: [ vi_normal vi_insert ] - event: [ - { send: menu name: abbr_menu } - { edit: insertchar, value: " " } - ] - } - { - name: move_up - modifier: none - keycode: up - mode: [ vi_normal vi_insert ] - event: { - until: [ - { send: menuup } - { send: up } - ] + + # Delete a thought dump. + export def delete [ + namespace: string # The thought dump to edit. Namespaced using '.', does not include file extension. + --existed-before = true + ]: nothing -> nothing { + let dump_path = $namespace | to-path + let parent_path = $dump_path | path parse | get parent + + print $"(ansi red)deleting thought dump...(ansi reset)" + print --no-newline (ansi red) + rm --verbose $dump_path + print --no-newline (ansi reset) + + if (ls $parent_path | length) == 0 { + print $"(ansi red)parent folder is empty, deleting that too...(ansi reset)" + print $"(ansi yellow)other parents will not be deleted, if you want to delete those do it manually(ansi reset)" + rm $parent_path + } + + if $existed_before { + deploy + } else { + print $"(ansi green)the thought dump didn't exist before, so skipping deployment(ansi reset)" } } - { - name: move_down - modifier: none - keycode: down - mode: [ vi_normal vi_insert ] - event: { - until: [ - { send: menudown } - { send: down } - ] - } - } - { - name: move_left - modifier: none - keycode: left - mode: [ vi_normal vi_insert ] - event: { - until: [ - { send: menuleft } - { send: left } - ] - } - } - { - name: move_right_or_take_history_hint - modifier: none - keycode: right - mode: [ vi_normal vi_insert ] - event: { - until: [ - { send: historyhintcomplete } - { send: menuright } - { send: right } - ] - } - } - { - name: move_one_word_left - modifier: control - keycode: left - mode: [ vi_normal vi_insert ] - event: { edit: movewordleft } - } - { - name: move_one_word_right_or_take_history_hint - modifier: control - keycode: right - mode: [ vi_normal vi_insert ] - event: { - until: [ - { send: historyhintwordcomplete } - { edit: movewordright } - ] - } - } - { - name: move_to_line_start - modifier: control - keycode: char_a - mode: [ vi_normal vi_insert ] - event: { edit: movetolinestart } - } - { - name: move_to_line_end_or_take_history_hint - modifier: control - keycode: char_e - mode: [ vi_normal vi_insert ] - event: { - until: [ - { send: historyhintcomplete } - { edit: movetolineend } - ] - } - } - { - name: delete_one_character_backward - modifier: none - keycode: backspace - mode: vi_insert - event: { edit: backspace } - } - { - name: delete_one_word_backward - modifier: control - keycode: backspace - mode: vi_insert - event: { edit: backspaceword } - } - { - name: newline_or_run_command - modifier: none - keycode: enter - mode: vi_insert - event: { send: enter } - } -] +} + +use dump diff --git a/modules/common/nushell/default.nix b/modules/common/nushell/default.nix index 9a4506f..d4a9419 100644 --- a/modules/common/nushell/default.nix +++ b/modules/common/nushell/default.nix @@ -31,20 +31,6 @@ in { }; nixpkgs.overlays = [(self: super: { - zoxide = super.zoxide.overrideAttrs (old: { - src = self.fetchFromGitHub { - owner = "Bahex"; - repo = "zoxide"; - rev = "0450775af9b1430460967ba8fb5aa434f95c4bc4"; - hash = "sha256-WhACxJMuhI9HGohcwg+ztZpQCVUZ4uibIQqGfJEEp/Y="; - }; - - cargoDeps = self.rustPlatform.fetchCargoVendor { - inherit (self.zoxide) src; - hash = "sha256-v3tcQaEXfGyt1j2fShvxxrA9Xc90AWxEzEUT09cQ+is="; - }; - }); - starship = super.starship.overrideAttrs (old: { src = self.fetchFromGitHub { owner = "poliorcetics"; diff --git a/modules/common/nushell/environment.nu b/modules/common/nushell/environment.nu index 6c63dd8..bf1124b 100644 --- a/modules/common/nushell/environment.nu +++ b/modules/common/nushell/environment.nu @@ -1,154 +1 @@ -$env.ENV_CONVERSIONS.PATH = { - from_string: {|string| - $string | split row (char esep) | path expand --no-symlink - } - to_string: {|value| - $value | path expand --no-symlink | str join (char esep) - } -} - -$env.LS_COLORS = (open ~/.config/nushell/ls_colors.txt) - -source ~/.config/nushell/zoxide.nu - -source ~/.config/nushell/starship.nu - -def copy []: string -> nothing { - print --no-newline $"(ansi osc)52;c;($in | encode base64)(ansi st)" -} - -def today []: nothing -> string { - date now | format date "%Y-%m-%d" -} - -# Create a directory and cd into it. -def --env mc [path: path]: nothing -> nothing { - mkdir $path - cd $path -} - -# Create a directory, cd into it and initialize version control. -def --env mcg [path: path]: nothing -> nothing { - mkdir $path - cd $path - jj git init --colocate -} - -module dump { - def site-path []: nothing -> path { - $env.HOME | path join "Projects" "site" - } - - def dump-path []: nothing -> path { - site-path | path join "site" "dump" - } - - # Convert a thought dump namespace to the filesystem path. - export def to-path []: string -> path { - let namespace = $in - - dump-path - | path join ...($namespace | split row ".") - | $in + ".md" - } - - # Convert a filesystem path to a thought dump namespace. - export def to-dump []: path -> string { - let path = $in - - $path - | path relative-to (dump-path) - | path split - | str join "." - | str substring 0..<-3 - } - - # List all thought dumps that start with the given namespace. - export def list [ - namespace: string = "" - ]: nothing -> table { - let dump_prefix = dump-path | path join ...($namespace | split row ".") - - let dump_parent_contents = glob ($dump_prefix | path parse | get parent | path join "**" "*.md") - let dump_matches = $dump_parent_contents | where { str starts-with $dump_prefix } - - ls ...$dump_matches | each { - merge { path: $in.name } - | select path size modified - | merge { namespace: ($in.path | to-dump) } - } - } - - # Deploy the thought dumps and thus the website. - export def deploy []: nothing -> nothing { - print $"(ansi green)deploying...(ansi reset)" - - cd (site-path) - ./apply.nu - } - - # Edit a thought dump. - export def edit [ - namespace: string # The thought dump to edit. Namespaced using '.', does not include file extension. - ]: nothing -> nothing { - let dump_path = $namespace | to-path - - let old_dump_size = try { ls $dump_path } - - mkdir ($dump_path | path parse | get parent) - touch $dump_path - - let old_dump_hash = open $dump_path | hash sha256 - - ^$env.EDITOR $dump_path - - let dump_size = ls $dump_path | get 0.size - if $dump_size == 0b { - print $"(ansi red)thought dump was emptied(ansi reset)" - delete $namespace --existed-before ($old_dump_size != null) - } else if $old_dump_hash == (open $dump_path | hash sha256) { - print $"(ansi yellow)thought dump was not modifier, doing nothing(ansi reset)" - } else { - print $"(ansi magenta)thought dump was edited(ansi reset)" - - let jj_arguments = [ "--repository", (site-path) ] - - jj ...$jj_arguments commit --message $"dump\(($namespace)\): update" - jj ...$jj_arguments bookmark set master --revision @- - - [ - { jj ...$jj_arguments git push --remote origin } - { jj ...$jj_arguments git push --remote rad } - { deploy } - ] | par-each { do $in } | last - } - } - - # Delete a thought dump. - export def delete [ - namespace: string # The thought dump to edit. Namespaced using '.', does not include file extension. - --existed-before = true - ]: nothing -> nothing { - let dump_path = $namespace | to-path - let parent_path = $dump_path | path parse | get parent - - print $"(ansi red)deleting thought dump...(ansi reset)" - print --no-newline (ansi red) - rm --verbose $dump_path - print --no-newline (ansi reset) - - if (ls $parent_path | length) == 0 { - print $"(ansi red)parent folder is empty, deleting that too...(ansi reset)" - print $"(ansi yellow)other parents will not be deleted, if you want to delete those do it manually(ansi reset)" - rm $parent_path - } - - if $existed_before { - deploy - } else { - print $"(ansi green)the thought dump didn't exist before, so skipping deployment(ansi reset)" - } - } -} - -use dump +# Crickets... From 1cdd201b04b8a0fcc2691dfbd27d2ce2630473e5 Mon Sep 17 00:00:00 2001 From: RGBCube Date: Sat, 12 Jul 2025 14:45:12 +0300 Subject: [PATCH 03/12] rebuild: make nu commandline a single line --- rebuild.nu | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/rebuild.nu b/rebuild.nu index b41b88c..a8599e1 100755 --- a/rebuild.nu +++ b/rebuild.nu @@ -123,22 +123,16 @@ def darwin-shadow-xcode-popup [] { def darwin-set-zshrc [] { print "setting zshrc..." - let nu_command = $" - let usr_bin_index = $env.PATH - | enumerate - | where item == /usr/bin - | get 0.index + let nu_command = $"let usr_bin_index = $env.PATH +| enumerate +| where item == /usr/bin +| get 0.index; - $env.PATH = $env.PATH | insert $usr_bin_index ($shadow_path | path expand) +$env.PATH = $env.PATH | insert $usr_bin_index ($shadow_path | path expand); - $env.SHELL = which nu | get 0.path - " +$env.SHELL = which nu | get 0.path" | str replace --all "\n" "" - let zshrc = $" - exec nu --execute ' - ($nu_command) - ' - " + let zshrc = $"exec nu --execute '($nu_command)'" $zshrc | save --force ~/.zshrc } From 78546a6fb3ee5b438a871340b385975ad0fa0674 Mon Sep 17 00:00:00 2001 From: RGBCube Date: Sat, 12 Jul 2025 14:52:35 +0300 Subject: [PATCH 04/12] nushell: don't trash --- modules/common/nushell/config.nu | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/common/nushell/config.nu b/modules/common/nushell/config.nu index fb27269..fe419e5 100644 --- a/modules/common/nushell/config.nu +++ b/modules/common/nushell/config.nu @@ -38,7 +38,7 @@ $env.config.history.sync_on_enter = true $env.config.show_banner = false -$env.config.rm.always_trash = true +$env.config.rm.always_trash = false $env.config.recursion_limit = 100 From cbd9d5c906cf3bd3873989661b67301523f9c1af Mon Sep 17 00:00:00 2001 From: RGBCube Date: Sat, 12 Jul 2025 14:53:31 +0300 Subject: [PATCH 05/12] nushell: unset buffer_editor to use $env.EDITOR --- modules/common/nushell/config.nu | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/common/nushell/config.nu b/modules/common/nushell/config.nu index fe419e5..13f2e6c 100644 --- a/modules/common/nushell/config.nu +++ b/modules/common/nushell/config.nu @@ -43,7 +43,6 @@ $env.config.rm.always_trash = false $env.config.recursion_limit = 100 $env.config.edit_mode = "vi" -$env.config.buffer_editor = "editor" $env.config.cursor_shape.emacs = "line" $env.config.cursor_shape.vi_insert = "line" From 6f97a03ae729cd4a17743de90062628003e1b22d Mon Sep 17 00:00:00 2001 From: RGBCube Date: Sat, 12 Jul 2025 16:28:42 +0300 Subject: [PATCH 06/12] nushell: remove starship --- modules/common/nushell/config.nu | 82 +++++++++++++++++++++++++++++- modules/common/nushell/default.nix | 50 +----------------- 2 files changed, 82 insertions(+), 50 deletions(-) diff --git a/modules/common/nushell/config.nu b/modules/common/nushell/config.nu index 13f2e6c..ef02e6e 100644 --- a/modules/common/nushell/config.nu +++ b/modules/common/nushell/config.nu @@ -1,7 +1,7 @@ use std-rfc/clip +use std null_device source ~/.config/nushell/zoxide.nu -source ~/.config/nushell/starship.nu # Retrieve the output of the last command. def _ []: nothing -> any { @@ -128,6 +128,86 @@ $env.config.float_precision = 2 $env.LS_COLORS = (open ~/.config/nushell/ls_colors.txt) $env.config.ls.use_ls_colors = true +do --env { + def prompt-header [ + --left-char: string + ]: nothing -> string { + let jj_workspace_root = try { + jj workspace root err> $null_device + } catch { + "" + } + + let body = if ($jj_workspace_root | is-not-empty) { + let subpath = pwd | path relative-to $jj_workspace_root + let subpath = if ($subpath | is-not-empty) { + $"(ansi magenta_bold) → (ansi reset)(ansi blue)($subpath)" + } + + $"(ansi light_yellow_bold)($jj_workspace_root | path basename)($subpath)(ansi reset)" + } else { + let pwd = if (pwd | str starts-with $env.HOME) { + "~" | path join (pwd | path relative-to $env.HOME) + } else { + pwd + } + + $"(ansi cyan)($pwd)(ansi reset)" + } + + $"(ansi light_yellow_bold)($left_char)━━━(ansi reset) ($body)(char newline)" + } + + $env.PROMPT_INDICATOR = $"(ansi light_yellow_bold)┃(ansi reset) " + $env.PROMPT_INDICATOR_VI_NORMAL = $env.PROMPT_INDICATOR + $env.PROMPT_INDICATOR_VI_INSERT = $env.PROMPT_INDICATOR + $env.PROMPT_MULTILINE_INDICATOR = $env.PROMPT_INDICATOR + $env.PROMPT_COMMAND = {|| + prompt-header --left-char "┏" + } + $env.PROMPT_COMMAND_RIGHT = {|| + let jj_status = try { + jj --quiet --color always --ignore-working-copy log --no-graph --revisions @ --template ' + separate( + " ", + if(empty, label("empty", "(empty)")), + coalesce( + surround( + "\"", + "\"", + if( + description.first_line().substr(0, 24).starts_with(description.first_line()), + description.first_line().substr(0, 24), + description.first_line().substr(0, 23) ++ "…" + ) + ), + label(if(empty, "empty"), description_placeholder) + ), + bookmarks.join(", "), + change_id.shortest(), + commit_id.shortest(), + if(conflict, label("conflict", "(conflict)")), + if(divergent, label("divergent prefix", "(divergent)")), + if(hidden, label("hidden prefix", "(hidden)")), + ) + ' err> $null_device + } catch { + "" + } + + $jj_status + } + + $env.TRANSIENT_PROMPT_INDICATOR = " " + $env.TRANSIENT_PROMPT_INDICATOR_VI_INSERT = $env.TRANSIENT_PROMPT_INDICATOR + $env.TRANSIENT_PROMPT_INDICATOR_VI_NORMAL = $env.TRANSIENT_PROMPT_INDICATOR + $env.TRANSIENT_PROMPT_MULTILINE_INDICATOR = $env.TRANSIENT_PROMPT_INDICATOR + $env.TRANSIENT_PROMPT_COMMAND = {|| + prompt-header --left-char "━" + } + $env.TRANSIENT_PROMPT_COMMAND_RIGHT = $env.PROMPT_COMMAND_RIGHT +} + $env.config.hooks.pre_prompt = [] $env.config.hooks.pre_execution = [ diff --git a/modules/common/nushell/default.nix b/modules/common/nushell/default.nix index d4a9419..a010db5 100644 --- a/modules/common/nushell/default.nix +++ b/modules/common/nushell/default.nix @@ -1,5 +1,5 @@ { config, lib, pkgs, ... }: let - inherit (lib) attrValues const enabled getExe mapAttrs mkIf optionalAttrs readFile removeAttrs replaceString; + inherit (lib) attrValues const disabled enabled getExe mapAttrs mkIf optionalAttrs readFile removeAttrs replaceString; in { environment = optionalAttrs config.isLinux { sessionVariables.SHELLS = getExe pkgs.nushell; @@ -26,31 +26,8 @@ in { zoxide # For completions and better cd. ; }; - - variables.STARSHIP_LOG = "error"; }; - nixpkgs.overlays = [(self: super: { - starship = super.starship.overrideAttrs (old: { - src = self.fetchFromGitHub { - owner = "poliorcetics"; - repo = "starship"; - rev = "92aba18381994599850053ba667c25017566b8ee"; - hash = "sha256-FKDvkDcxUPDLcjFQzvqsGXeJUm0Dq8TcA4edf5OkdWo="; - }; - - cargoDeps = self.rustPlatform.fetchCargoVendor { - inherit (self.starship) src; - hash = "sha256-nH1iYjKw/GbYKadoymH3onWBbMzuMUaRCSTNWVE+A9E="; - }; - - nativeBuildInputs = old.nativeBuildInputs ++ [ - pkgs.cmake - pkgs.zlib-ng - ]; - }); - })]; - home-manager.sharedModules = [(homeArgs: let homeConfig = homeArgs.config; in { @@ -62,31 +39,6 @@ in { "nushell/ls_colors.txt".source = pkgs.runCommand "ls_colors.txt" {} '' ${getExe pkgs.vivid} generate gruvbox-dark-hard > $out ''; - - "nushell/starship.nu".source = pkgs.runCommand "starship.nu" {} '' - ${getExe pkgs.starship} init nu > $out - ''; - }; - - programs.starship = enabled { - # No because we are doing it at build time instead of the way - # this retarded module does it. Why the hell do you generate - # the config every time the shell is launched? - enableNushellIntegration = false; - - settings = { - vcs.disabled = false; - - command_timeout = 100; - scan_timeout = 20; - - cmd_duration.show_notifications = config.isDesktop; - - package.disabled = config.isServer; - - character.error_symbol = ""; - character.success_symbol = ""; - }; }; programs.direnv = enabled { From b759c1ba26fd5669d6a05307c1992916d2e56603 Mon Sep 17 00:00:00 2001 From: RGBCube Date: Sat, 12 Jul 2025 16:47:27 +0300 Subject: [PATCH 07/12] nushell: set table header color to yellow --- modules/common/nushell/config.nu | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/common/nushell/config.nu b/modules/common/nushell/config.nu index ef02e6e..0342ccc 100644 --- a/modules/common/nushell/config.nu +++ b/modules/common/nushell/config.nu @@ -277,6 +277,9 @@ $env.config.color_config.string = {|| } } +$env.config.color_config.row_index = "light_yellow_bold" +$env.config.color_config.header = "light_yellow_bold" + module dump { def site-path []: nothing -> path { $env.HOME | path join "Projects" "site" From da47978c4b8fb73eaf194d71bbbd297a0a25a6c7 Mon Sep 17 00:00:00 2001 From: RGBCube Date: Sat, 12 Jul 2025 17:21:23 +0300 Subject: [PATCH 08/12] nushell: ide-style completions --- modules/common/nushell/config.nu | 162 ++++++++++++++++++------------- 1 file changed, 93 insertions(+), 69 deletions(-) diff --git a/modules/common/nushell/config.nu b/modules/common/nushell/config.nu index 0342ccc..46bb334 100644 --- a/modules/common/nushell/config.nu +++ b/modules/common/nushell/config.nu @@ -128,6 +128,80 @@ $env.config.float_precision = 2 $env.LS_COLORS = (open ~/.config/nushell/ls_colors.txt) $env.config.ls.use_ls_colors = true +$env.config.hooks.pre_prompt = [] + +$env.config.hooks.pre_execution = [ + {|| + commandline + | str trim + | if ($in | is-not-empty) { print $"(ansi title)($in) — nu(char bel)" } + } +] + +$env.config.hooks.env_change.PWD = [ + {|_before, after| + ls $after + | if ($in | length) < 20 { print } + } +] + +$env.config.hooks.display_output = {|| + tee { table --expand | print } + | if $in != null { $env.last = $in } +} + +$env.config.hooks.command_not_found = [] + +# Copy the current commandline, add syntax highlighting, wrap it in a +# markdown code block, copy that to the system clipboard. +# +# Perfect for sharing code snippets on discord +def "nu-keybind commandline-copy" []: nothing -> nothing { + commandline + | nu-highlight-default + | [ + "```ansi" + $in + "```" + ] + | str join (char nl) + | clip copy --ansi +} + +$env.config.keybindings ++= [ + { + name: copy_color_commandline + modifier: control_alt + keycode: char_c + mode: [ emacs vi_insert vi_normal ] + event: { + send: executehostcommand + cmd: 'nu-keybind commandline-copy' + } + } +] + +$env.config.color_config.bool = {|| + if $in { + "light_green_bold" + } else { + "light_red_bold" + } +} + +$env.config.color_config.string = {|| + if $in =~ "^(#|0x)[a-fA-F0-9]+$" { + $in | str replace "0x" "#" + } else { + "white" + } +} + +$env.config.color_config.row_index = "light_yellow_bold" +$env.config.color_config.header = "light_yellow_bold" + +$env.config.color_config.shape_externalarg = "white" + do --env { def prompt-header [ --left-char: string @@ -206,80 +280,30 @@ do --env { prompt-header --left-char "━" } $env.TRANSIENT_PROMPT_COMMAND_RIGHT = $env.PROMPT_COMMAND_RIGHT -} -$env.config.hooks.pre_prompt = [] - -$env.config.hooks.pre_execution = [ - {|| - commandline - | str trim - | if ($in | is-not-empty) { print $"(ansi title)($in) — nu(char bel)" } - } -] - -$env.config.hooks.env_change.PWD = [ - {|_before, after| - ls $after - | if ($in | length) < 20 { print } - } -] - -$env.config.hooks.display_output = {|| - tee { table --expand | print } - | if $in != null { $env.last = $in } -} - -$env.config.hooks.command_not_found = [] - -# Copy the current commandline, add syntax highlighting, wrap it in a -# markdown code block, copy that to the system clipboard. -# -# Perfect for sharing code snippets on discord -def "nu-keybind commandline-copy" []: nothing -> nothing { - commandline - | nu-highlight-default - | [ - "```ansi" - $in - "```" - ] - | str join (char nl) - | clip copy --ansi -} - -$env.config.keybindings ++= [ - { - name: copy_color_commandline - modifier: control_alt - keycode: char_c - mode: [ emacs vi_insert vi_normal ] - event: { - send: executehostcommand - cmd: 'nu-keybind commandline-copy' + let menus = [{ + name: completion_menu + only_buffer_difference: false + marker: $env.PROMPT_INDICATOR + type: { + layout: ide + border: false + correct_cursor_pos: true } - } -] + style: { + text: white + selected_text: white_reverse + description_text: yellow + match_text: { attr: u } + selected_match_text: { attr: ur } + } + }] -$env.config.color_config.bool = {|| - if $in { - "light_green_bold" - } else { - "light_red_bold" - } + $env.config.menus = $env.config.menus + | where name not-in ($menus | get name) + | append $menus } -$env.config.color_config.string = {|| - if $in =~ "^(#|0x)[a-fA-F0-9]+$" { - $in | str replace "0x" "#" - } else { - "white" - } -} - -$env.config.color_config.row_index = "light_yellow_bold" -$env.config.color_config.header = "light_yellow_bold" - module dump { def site-path []: nothing -> path { $env.HOME | path join "Projects" "site" From 16b4f9f3a4e2cab39b2c0e22923b51aedfc277c1 Mon Sep 17 00:00:00 2001 From: RGBCube Date: Sat, 12 Jul 2025 17:47:50 +0300 Subject: [PATCH 09/12] nushell: set history menu prompt character --- modules/common/nushell/config.nu | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/modules/common/nushell/config.nu b/modules/common/nushell/config.nu index 46bb334..4169326 100644 --- a/modules/common/nushell/config.nu +++ b/modules/common/nushell/config.nu @@ -280,8 +280,10 @@ do --env { prompt-header --left-char "━" } $env.TRANSIENT_PROMPT_COMMAND_RIGHT = $env.PROMPT_COMMAND_RIGHT +} - let menus = [{ +let menus = [ + { name: completion_menu only_buffer_difference: false marker: $env.PROMPT_INDICATOR @@ -297,12 +299,25 @@ do --env { match_text: { attr: u } selected_match_text: { attr: ur } } - }] + } + { + name: history_menu + only_buffer_difference: true + marker: $env.PROMPT_INDICATOR + type: { + layout: list + page_size: 10 + } + style: { + text: white + selected_text: white_reverse + } + } +] - $env.config.menus = $env.config.menus - | where name not-in ($menus | get name) - | append $menus -} +$env.config.menus = $env.config.menus +| where name not-in ($menus | get name) +| append $menus module dump { def site-path []: nothing -> path { From 6a5ea3ef02f7b018d6a8a95f61b496034f89197d Mon Sep 17 00:00:00 2001 From: RGBCube Date: Sat, 12 Jul 2025 17:48:45 +0300 Subject: [PATCH 10/12] nushell: revert setting external argument colors to white --- modules/common/nushell/config.nu | 2 -- 1 file changed, 2 deletions(-) diff --git a/modules/common/nushell/config.nu b/modules/common/nushell/config.nu index 4169326..e11c3c7 100644 --- a/modules/common/nushell/config.nu +++ b/modules/common/nushell/config.nu @@ -200,8 +200,6 @@ $env.config.color_config.string = {|| $env.config.color_config.row_index = "light_yellow_bold" $env.config.color_config.header = "light_yellow_bold" -$env.config.color_config.shape_externalarg = "white" - do --env { def prompt-header [ --left-char: string From 43e0439341ff413adbbde5f1cc408666caec198d Mon Sep 17 00:00:00 2001 From: RGBCube Date: Sat, 12 Jul 2025 17:50:15 +0300 Subject: [PATCH 11/12] nushell: don't print ls on new cd --- modules/common/nushell/config.nu | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/modules/common/nushell/config.nu b/modules/common/nushell/config.nu index e11c3c7..75f25e3 100644 --- a/modules/common/nushell/config.nu +++ b/modules/common/nushell/config.nu @@ -138,12 +138,7 @@ $env.config.hooks.pre_execution = [ } ] -$env.config.hooks.env_change.PWD = [ - {|_before, after| - ls $after - | if ($in | length) < 20 { print } - } -] +$env.config.hooks.env_change = {} $env.config.hooks.display_output = {|| tee { table --expand | print } From 0eb9a36ce6a37653b1a58ebcb592da8e549bfd2b Mon Sep 17 00:00:00 2001 From: RGBCube Date: Sat, 12 Jul 2025 18:44:20 +0300 Subject: [PATCH 12/12] nushell: show exit code in prompt --- modules/common/nushell/config.nu | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/modules/common/nushell/config.nu b/modules/common/nushell/config.nu index 75f25e3..241cc66 100644 --- a/modules/common/nushell/config.nu +++ b/modules/common/nushell/config.nu @@ -222,7 +222,13 @@ do --env { $"(ansi cyan)($pwd)(ansi reset)" } - $"(ansi light_yellow_bold)($left_char)━━━(ansi reset) ($body)(char newline)" + let middle = if $env.LAST_EXIT_CODE == 0 { + "━" + } else { + $"┫(ansi light_red_bold)($env.LAST_EXIT_CODE)(ansi light_yellow_bold)┣" + } + + $"(ansi light_yellow_bold)($left_char)($middle)━(ansi reset) ($body)(char newline)" } $env.PROMPT_INDICATOR = $"(ansi light_yellow_bold)┃(ansi reset) "