diff --git a/modules/shell/default.nix b/modules/shell/default.nix index 7381939..90287a1 100644 --- a/modules/shell/default.nix +++ b/modules/shell/default.nix @@ -1,4 +1,5 @@ { + inputs, ... }: { @@ -7,6 +8,10 @@ { programs.fish.enable = true; users.defaultUserShell = pkgs.fish; + + home-manager.sharedModules = [ + inputs.self.modules.homeManager.shell + ]; }; flake.modules.darwin.shell = @@ -14,5 +19,250 @@ { programs.fish.enable = true; users.defaultUserShell = pkgs.fish; + + home-manager.sharedModules = [ + inputs.self.modules.homeManager.shell + ]; + }; + + flake.modules.homeManager.shell = + { pkgs, ... }: + { + programs.fish = { + enable = true; + functions = { + ff = "bash ${./ff.bash}"; + fish_greeting = "fortune -a"; + localip = "ifconfig | grep \"inet \" | grep -v 127.0.0.1 | awk '{print $2}' | head -n 1"; + publicip = "curl -4 ifconfig.me"; + enter_vps = "ssh dnsc-vps-sm -t tmux new -As main"; + rebuild_vps = "ssh -t dnsc-vps-sm 'cd ~/nix-config && git pull && sudo just deploy'"; + enter_server = "ssh dnsc-server -t tmux new -As main"; + rebuild_server = "ssh -t dnsc-server 'cd ~/nix-config && git pull && sudo just deploy'"; + kill_tunnels = /* fish */ '' + ps -o pid,command | grep "^[0-9]\{4,5\} ssh -fNL" | awk '{print $1}' | xargs kill -9 + ''; + dbui = '' + uvx --with PyMySQL --with sqlit-tui[ssh] --from sqlit-tui@1.2.11 sqlit + ''; + dev_projects = /* fish */ '' + if test "$hn" = "dnsc-work" + begin + fd . ~/dev/ride/apps/backend/edge-services -t d -d 1; + fd . ~/dev/ride/apps/backend/backend-services -t d -d 1; + fd . ~/dev/ride/apps/frontend/projects -t d -d 1; + fd . ~/dev/ride/apps/native -t d -d 1; + fd . ~/dev/ride/packages -t d -d 1; + fd . ~/dev -t d -d 1; + echo "$HOME/dev/ride/apps/frontend"; + echo "$HOME/dev/ride/apps/lib"; + echo "$HOME/dev/ride/apps/packages"; + end + else + begin + echo "$HOME/notes" + fd . ~/dev -t d -d 1 + end + end + ''; + cdd = /* fish */ '' + set folder (dev_projects | fzf) + cd $folder + ''; + cdr = /* fish */ '' + set folder (dev_projects | fzf) + cd $folder + + if test -n "$folder" + set service (basename $folder) + cd $folder + + if test -f "package.json" + set script_cmd (jq -r '.scripts | to_entries | .[] | "\(.key): \(.value)"' package.json | fzf) + + if test -n "$script_cmd" + set script_name (string split ": " $script_cmd)[1] + if test -n "$script_name" + echo "Running: npm run $script_name" + npm run $script_name + end + end + end + end + ''; + sessionizer = /* fish */ '' + set -l selected (tmuxinator ls -n | tail -n +2 | fzf --prompt " switch to >> ") + + if test -z "$selected" + return 1 + end + + tmuxinator start "$selected" + ''; + tmux_sessionizer = /* fish */ '' + tmux display-popup -h 50% -w 80% -E sessionizer + ''; + nn = /* fish */ '' + # Require a title argument + if test (count $argv) -lt 1 + echo "Usage: nn \"My Note\"" + return 1 + end + + # Join all arguments into single title (preserves spaces inside quotes) + set -l title $argv[1] + + # Timestamp up to minutes, format: YYYY-MM-DD_HH-MM + set -l ts (date "+%Y%m%d%H%M") + + # Normalize title: lowercase, replace spaces with hyphens, remove/replace + # characters unsafe for filenames (keep a-z0-9- and replace others with -) + set -l slug (string lower -- $title) + # Replace any sequence of non-alphanumeric characters with single hyphen + set -l slug (echo $slug | sed -E 's/[^a-z0-9]+/-/g' | sed -E 's/^-|-$//g') + + # Compose filename + set -l filename "$ts"_"$slug.md" + + # Directory for notes (change if you prefer another path) + set -l notes_dir ~/dev/notes + + # Ensure directory exists + test -d $notes_dir; or mkdir -p $notes_dir + + # Full path + set -l fullpath "$notes_dir/$filename" + + # If file doesn't exist, create with timestamp and title at top + if not test -f $fullpath + # Human-friendly timestamp line (no seconds) + set -l display_ts (date "+%Y-%m-%d %H:%M") + printf "---\nCREATED_AT: %s\n---\n\n# %s\n\n" "$display_ts" "$title" > $fullpath + end + + # Open file in neovim + nvim $fullpath + ''; + fish_mode_prompt = /* fish */ '' + switch $fish_bind_mode + case default + set_color --bold brcyan + echo '[N] ' + case insert + set_color --bold brgreen + echo '[I] ' + case replace_one + set_color --bold yellow + echo '[R] ' + case replace + set_color --bold bryellow + echo '[R] ' + case visual + set_color --bold brmagenta + echo '[V] ' + case '*' + set_color --bold red + echo '[?] ' + end + set_color normal + ''; + setup_winterly_theme_colors = /* fish */ '' + set --universal fish_color_autosuggestion brblack # autosuggestions + set --universal fish_color_command brwhite # commands + set --universal fish_color_comment brblack # code comments + set --universal fish_color_cwd brblack # current working directory in the default prompt + set --universal fish_color_end brblack # process separators like ';' and '&' + set --universal fish_color_error brwhite # highlight potential errors + set --universal fish_color_escape brblack # highlight character escapes like '\n' and '\x70' + set --universal fish_color_match yellow # highlight matching parenthesis + set --universal fish_color_normal brwhite # default color + set --universal fish_color_operator brblack # parameter expansion operators like '*' and '~' + set --universal fish_color_param bryellow # regular command parameters + set --universal fish_color_quote brmagenta # quoted blocks of text + set --universal fish_color_redirection brwhite # IO redirections + set --universal fish_color_search --bold --background=black --foreground=bryellow + set --universal fish_color_search_match --background black # highlight history search matches and the selected pager item (must be a background) + set --universal fish_pager_color_selected_background --background black --foreground brmagenta + set --universal fish_pager_color_progress --foreground=brwhite --background=black + set --universal fish_color_selection --background magenta # when selecting text (in vi visual mode) + set --universal fish_color_cancel brblack # the '^C' indicator on a canceled command + set --universal fish_color_host brwhite # current host system in some of fish default prompts + set --universal fish_color_host_remote yellow #ayu:syntax.constant current host system in some of fish default prompts, if fish is running remotely (via ssh or similar) + set --universal fish_color_user brwhite # current username in some of fish default prompts + ''; + setup_homebrew = /* fish */ '' + fish_add_path /opt/homebrew/bin + + if test -d (brew --prefix)"/share/fish/completions" + set -p fish_complete_path (brew --prefix)/share/fish/completions + end + + if test -d (brew --prefix)"/share/fish/vendor_completions.d" + set -p fish_complete_path (brew --prefix)/share/fish/vendor_completions.d + end + ''; + setup_path = /* fish */ '' + fish_add_path /run/wrappers/bin + fish_add_path /run/current-system/sw/bin + fish_add_path $HOME/.nix-profile/bin + + if test "$(uname)" = "Darwin" + fish_add_path /nix/var/nix/profiles/default/bin + setup_homebrew + end + ''; + setup_env = /* fish */ '' + for line in (cat $HOME/.env | grep -v '^#') + set item (string split -m 1 '=' $line) + set -gx $item[1] $item[2] + end + ''; + setup_work = /* fish */ '' + fish_add_path $ANDROID_HOME/emulator + fish_add_path $ANDROID_HOME/platform-tools + fish_add_path $HOME/.local/share/uv/tools + rbenv init - | source + fnm env --use-on-cd --shell fish | source + ''; + }; + + interactiveShellInit = /* fish */ '' + # Set some global values + set -x GPG_TTY (tty) + set hn (prompt_hostname) + + fish_vi_key_bindings insert + fish_vi_cursor xterm + + setup_winterly_theme_colors + setup_env + setup_path + + if test "$hn" = "dnsc-work" + setup_work + end + + # Custom init + direnv hook fish | source + + # Auto start tmux + if status is-interactive; and not set -q TMUX + if tmux list-sessions >/dev/null 2>&1 + # Attach to the first available session + tmux a + else + # Create a new session + tmux new-session -t main + end + end + ''; + + shellAbbrs = { + lg = "lazygit"; + gg = "lazygit"; + g = "git"; + frc = "source ~/.config/fish/**/*.fish"; + }; + }; }; }