fish functions and user key bindings

This commit is contained in:
Noah Masur 2025-02-02 21:45:34 -05:00
parent 1226eafef2
commit 6f2b2a7694
No known key found for this signature in database
24 changed files with 274 additions and 335 deletions

View File

@ -1,22 +0,0 @@
bind -M insert \co edit
bind -M default \co edit
bind -M insert \cs search-and-edit
bind -M default \cs search-and-edit
bind -M insert \ca 'cd ~; and edit; and commandline -a "; cd -"; commandline -f execute'
bind -M default \ca 'cd ~; and edit; and commandline -a "; cd -"; commandline -f execute'
bind -M insert \ce recent
bind -M default \ce recent
bind -M default \cg commandline-git-commits
bind -M insert \cg 'commandline -i (git rev-parse --show-toplevel 2>/dev/null || echo ".")'
bind -M insert \cf fcd
bind -M default \cf fcd
bind -M insert \cp projects
bind -M default \cp projects
bind -M insert \x1F accept-autosuggestion
bind -M default \x1F accept-autosuggestion
bind -M insert \cn 'commandline -r "nix shell nixpkgs#"'
bind -M default \cn 'commandline -r "nix shell nixpkgs#"'
bind -M insert \x11F nix-fzf
bind -M default \x11F nix-fzf
bind -M insert \ch '_atuin_search --filter-mode global'
bind -M default \ch '_atuin_search --filter-mode global'

View File

@ -1,122 +0,0 @@
#!/usr/local/bin/fish
function fish_vi_cursor -d 'Set cursor shape for different vi modes'
# If we're not interactive, there is effectively no bind mode.
if not status is-interactive
return
end
# This is hard to test in expect, since the exact sequences depend on the environment.
# Instead disable it.
if set -q FISH_UNIT_TESTS_RUNNING
return
end
# If this variable is set, skip all checks
if not set -q fish_vi_force_cursor
# Emacs Makes All Cursors Suck
if set -q INSIDE_EMACS
return
end
# vte-based terms set $TERM = xterm*, but only gained support in 2015.
# From https://bugzilla.gnome.org/show_bug.cgi?id=720821, it appears it was version 0.40.0
if set -q VTE_VERSION
and test "$VTE_VERSION" -lt 4000 2>/dev/null
return
end
# Similarly, genuine XTerm can do it since v280.
if set -q XTERM_VERSION
and not test (string replace -r "XTerm\((\d+)\)" '$1' -- "$XTERM_VERSION") -ge 280 2>/dev/null
return
end
# We need one of these terms.
# It would be lovely if we could rely on terminfo, but:
# - The "Ss" entry isn't a thing in macOS' old and crusty terminfo
# - It is set for xterm, and everyone and their dog claims to be xterm
#
# So we just don't care about $TERM, unless it is one of the few terminals that actually have their own entry.
#
# Note: Previous versions also checked $TMUX, and made sure that then $TERM was screen* or tmux*.
# We don't care, since we *cannot* handle term-in-a-terms 100% correctly.
if not set -q KONSOLE_PROFILE_NAME
and not test -n "$KONSOLE_VERSION" -a "$KONSOLE_VERSION" -ge 200400 # konsole, but new.
and not set -q ITERM_PROFILE
and not set -q VTE_VERSION # which version is already checked above
and not set -q WT_PROFILE_ID
and not set -q XTERM_VERSION
and not string match -rq '^st(-.*)$' -- $TERM
and not string match -q 'xterm-kitty*' -- $TERM
and not string match -q 'rxvt*' -- $TERM
and not string match -q 'alacritty*' -- $TERM
return
end
# HACK: Explicitly disable on ITERM because of #3696, which is weirdness with multi-line prompts.
# --force-iterm is now deprecated; set $fish_vi_force_cursor instead
if contains -- $argv[1] --force-iterm
set -e argv[1]
else if set -q ITERM_PROFILE
return
end
end
set -l terminal $argv[1]
set -q terminal[1]
or set terminal auto
set -l function
switch "$terminal"
case auto
# Nowadays, konsole does not set $KONSOLE_PROFILE_NAME anymore,
# and it uses the xterm sequences.
if set -q KONSOLE_PROFILE_NAME
set function __fish_cursor_konsole
else if set -q ITERM_PROFILE
set function __fish_cursor_1337
else
set function __fish_cursor_xterm
end
case konsole
set function __fish_cursor_konsole
case xterm
set function __fish_cursor_xterm
end
set -l tmux_prefix
set -l tmux_postfix
if set -q TMUX
set tmux_prefix echo -ne "'\ePtmux;\e'"
set tmux_postfix echo -ne "'\e\\\\'"
end
set -q fish_cursor_unknown
or set -g fish_cursor_unknown block blink
echo "
function fish_vi_cursor_handle --on-variable fish_bind_mode --on-event fish_postexec --on-event fish_focus_in
set -l varname fish_cursor_\$fish_bind_mode
if not set -q \$varname
set varname fish_cursor_unknown
end
$tmux_prefix
$function \$\$varname
$tmux_postfix
end
" | source
echo "
function fish_vi_cursor_handle_preexec --on-event fish_preexec
set -l varname fish_cursor_default
if not set -q \$varname
set varname fish_cursor_unknown
end
$tmux_prefix
$function \$\$varname
$tmux_postfix
end
" | source
end

View File

@ -36,5 +36,12 @@ in
};
};
config.nmasur.presets.programs.fish.fish_user_key_bindings = # fish
''
# Ctrl-h
bind -M insert \ch '_atuin_search --filter-mode global'
bind -M default \ch '_atuin_search --filter-mode global'
'';
};
}

View File

@ -13,6 +13,7 @@ in
options.nmasur.presets.programs.bash.enable = lib.mkEnableOption "Bash shell";
config = lib.mkIf cfg.enable {
programs.bash = {
enable = true;
shellAliases = config.programs.fish.shellAliases;
@ -20,9 +21,5 @@ in
profileExtra = "";
};
programs.starship.enableBashIntegration = false;
programs.zoxide.enableBashIntegration = true;
programs.fzf.enableBashIntegration = true;
};
}

View File

@ -10,34 +10,35 @@ in
{
options.nmasur.presets.programs.fish.enable = lib.mkEnableOption "Fish shell";
options.nmasur.presets.programs.fish = {
enable = lib.mkEnableOption "Fish shell";
fish_user_key_bindings = lib.mkOption {
type = lib.types.lines;
description = "Text of fish_user_key_bindings function";
default = "";
};
};
config = lib.mkIf cfg.enable {
cfg.fish_user_key_bindings = # fish
''
# Shift-Enter (defined by terminal)
bind -M insert \x1F accept-autosuggestion
bind -M default \x1F accept-autosuggestion
'';
programs.fish = {
enable = true;
functions = {
commandline-git-commits = {
description = "Insert commit into commandline";
body = builtins.readFile ./functions/commandline-git-commits.fish;
};
copy = {
description = "Copy file contents into clipboard";
body = "cat $argv | pbcopy"; # Need to fix for non-macOS
};
edit = {
description = "Open a file in Vim";
body = builtins.readFile ./functions/edit.fish;
};
envs = {
description = "Evaluate a bash-like environment variables file";
body = ''set -gx (cat $argv | tr "=" " " | string split ' ')'';
};
fcd = {
description = "Jump to directory";
argumentNames = "directory";
body = builtins.readFile ./functions/fcd.fish;
};
fish_user_key_bindings = {
body = builtins.readFile ./functions/fish_user_key_bindings.fish;
};
@ -48,14 +49,6 @@ in
description = "Tidy up JSON using jq";
body = "pbpaste | jq '.' | pbcopy"; # Need to fix for non-macOS
};
recent = {
description = "Open a recent file in Vim";
body = builtins.readFile ./functions/recent.fish;
};
search-and-edit = {
description = "Search and open the relevant file in Vim";
body = builtins.readFile ./functions/search-and-edit.fish;
};
_which = {
description = "Identify the path to a program in the shell";
body = "command --search (string sub --start=2 $argv)";
@ -123,9 +116,5 @@ in
home.sessionVariables.fish_greeting = "";
programs.starship.enableFishIntegration = true;
programs.zoxide.enableFishIntegration = true;
programs.fzf.enableFishIntegration = true;
};
}

View File

@ -1,67 +0,0 @@
{
config,
pkgs,
lib,
...
}:
let
cfg = config.nmasur.presets.programs.fzf;
in
{
options.nmasur.presets.programs.fzf.enable = lib.mkEnableOption "Fzf fuzzy finder";
config = lib.mkIf cfg.enable {
programs.fzf.enable = true;
programs.fish = {
functions = {
projects = {
description = "Jump to a project";
body = ''
set projdir ( \
fd \
--search-path $HOME/dev \
--type directory \
--exact-depth 2 \
| ${pkgs.proximity-sort}/bin/proximity-sort $PWD \
| sed 's/\\/$//' \
| fzf --tiebreak=index \
)
and cd $projdir
and commandline -f execute
'';
};
};
shellAbbrs = {
lsf = "ls -lh | fzf";
};
};
# Global fzf configuration
home.sessionVariables =
let
fzfCommand = "fd --type file";
in
{
FZF_DEFAULT_COMMAND = fzfCommand;
FZF_CTRL_T_COMMAND = fzfCommand;
FZF_DEFAULT_OPTS = "-m --height 50% --border";
};
home.packages = [
(pkgs.writeShellApplication {
name = "jqr";
runtimeInputs = [
pkgs.jq
pkgs.fzf
];
text = builtins.readFile ./bash/scripts/jqr.sh;
})
];
};
}

View File

@ -0,0 +1,100 @@
{
config,
pkgs,
lib,
...
}:
let
cfg = config.nmasur.presets.programs.fzf;
in
{
options.nmasur.presets.programs.fzf.enable = lib.mkEnableOption "Fzf fuzzy finder";
config = lib.mkIf cfg.enable {
programs.fzf = {
enable = true;
enableFishIntegration = true;
enableBashIntegration = true;
};
programs.fish = {
functions = {
edit = {
description = "Open a file in Vim";
body = builtins.readFile ./fish/edit.fish;
};
fcd = {
description = "Jump to directory";
argumentNames = "directory";
body = builtins.readFile ./fish/fcd.fish;
};
projects = {
description = "Jump to a project";
body = # fish
''
set projdir ( \
fd \
--search-path $HOME/dev \
--type directory \
--exact-depth 2 \
| ${lib.getExe pkgs.proximity-sort} $PWD \
| sed 's/\\/$//' \
| fzf --tiebreak=index \
)
and cd $projdir
and commandline -f execute
'';
};
recent = {
description = "Open a recent file in Vim";
body = builtins.readFile ./edit/recent.fish;
};
search-and-edit = {
description = "Search and open the relevant file in Vim";
body = builtins.readFile ./edit/search-and-edit.fish;
};
};
shellAbbrs = {
lsf = "ls -lh | fzf";
};
};
config.nmasur.presets.programs.fish.fish_user_key_bindings = # fish
''
# Ctrl-o
bind -M insert \co edit
bind -M default \co edit
# Ctrl-s
bind -M insert \cs search-and-edit
bind -M default \cs search-and-edit
# Ctrl-a
bind -M insert \ca 'cd ~; and edit; and commandline -a "; cd -"; commandline -f execute'
bind -M default \ca 'cd ~; and edit; and commandline -a "; cd -"; commandline -f execute'
# Ctrl-e
bind -M insert \ce recent
bind -M default \ce recent
# Ctrl-f
bind -M insert \cf fcd
bind -M default \cf fcd
# Ctrl-p
bind -M insert \cp projects
bind -M default \cp projects
'';
# Global fzf configuration
home.sessionVariables =
let
fzfCommand = "${lib.getExe pkgs.fd} --type file";
in
{
FZF_DEFAULT_COMMAND = fzfCommand;
FZF_CTRL_T_COMMAND = fzfCommand;
FZF_DEFAULT_OPTS = "-m --height 50% --border";
};
};
}

View File

@ -108,14 +108,14 @@ in
programs.fish.functions = {
git = {
body = builtins.readFile ./fish/functions/git.fish;
body = builtins.readFile ./fish/git.fish;
};
git-add-fuzzy = {
body = builtins.readFile ./fish/functions/git-add-fuzzy.fish;
body = builtins.readFile ./fish/git-add-fuzzy.fish;
};
git-fuzzy-branch = {
argumentNames = "header";
body = builtins.readFile ./fish/functions/git-fuzzy-branch.fish;
body = builtins.readFile ./fish/git-fuzzy-branch.fish;
};
git-checkout-fuzzy = {
body = ''
@ -149,18 +149,30 @@ in
'';
};
git-show-fuzzy = {
body = builtins.readFile ./fish/functions/git-show-fuzzy.fish;
body = builtins.readFile ./fish/git-show-fuzzy.fish;
};
git-commits = {
body = builtins.readFile ./fish/functions/git-commits.fish;
body = builtins.readFile ./fish/git-commits.fish;
};
commandline-git-commits = {
description = "Insert commit into commandline";
body = builtins.readFile ./fish/commandline-git-commits.fish;
};
git-history = {
body = builtins.readFile ./fish/functions/git-history.fish;
body = builtins.readFile ./fish/git-history.fish;
};
uncommitted = {
description = "Find uncommitted git repos";
body = builtins.readFile ./fish/functions/uncommitted.fish;
body = builtins.readFile ./fish/uncommitted.fish;
};
};
config.nmasur.presets.programs.fish.fish_user_key_bindings = # fish
''
# Ctrl-g
bind -M default \cg commandline-git-commits
bind -M insert \cg 'commandline -i (git rev-parse --show-toplevel 2>/dev/null || echo ".")'
'';
};
}

View File

@ -36,45 +36,60 @@ in
};
functions = {
nix-shell-run = {
body = ''
set program $argv[1]
if test (count $argv) -ge 2
commandline -r "nix run nixpkgs#$program -- $argv[2..-1]"
else
commandline -r "nix run nixpkgs#$program"
end
commandline -f execute
'';
body = # fish
''
set program $argv[1]
if test (count $argv) -ge 2
commandline -r "nix run nixpkgs#$program -- $argv[2..-1]"
else
commandline -r "nix run nixpkgs#$program"
end
commandline -f execute
'';
};
nix-fzf = {
body = ''
commandline -i (nix-instantiate --eval --json \
-E 'builtins.attrNames (import <nixpkgs> {})' \
| jq '.[]' -r | fzf)
commandline -f repaint
'';
body = # fish
''
commandline -i (nix-instantiate --eval --json \
-E 'builtins.attrNames (import <nixpkgs> {})' \
| ${lib.getExe pkgs.jq} '.[]' -r | ${lib.getExe pkgs.fzf})
commandline -f repaint
'';
};
rebuild-nixos = {
body = ''
git -C ${config.dotfilesPath} add --intent-to-add --all
echo "doas nixos-rebuild switch --flake ${config.dotfilesPath}#${config.networking.hostName}"
'';
body = # fish
''
git -C ${config.dotfilesPath} add --intent-to-add --all
echo "doas nixos-rebuild switch --flake ${config.dotfilesPath}#${config.networking.hostName}"
'';
};
rebuild-nixos-offline = {
body = ''
git -C ${config.dotfilesPath} add --intent-to-add --all
echo "doas nixos-rebuild switch --option substitute false --flake ${config.dotfilesPath}#${config.networking.hostName}"
'';
body = # fish
''
git -C ${config.dotfilesPath} add --intent-to-add --all
echo "doas nixos-rebuild switch --option substitute false --flake ${config.dotfilesPath}#${config.networking.hostName}"
'';
};
rebuild-home = {
body = ''
git -C ${config.dotfilesPath} add --intent-to-add --all
echo "${pkgs.home-manager}/bin/home-manager switch --flake ${config.dotfilesPath}#${config.networking.hostName}";
'';
body = # fish
''
git -C ${config.dotfilesPath} add --intent-to-add --all
echo "${lib.getExe pkgs.home-manager} switch --flake ${config.dotfilesPath}#${config.networking.hostName}";
'';
};
};
};
config.nmasur.presets.programs.fish.fish_user_key_bindings = # fish
''
# Ctrl-n
bind -M insert \cn 'commandline -r "nix shell nixpkgs#"'
bind -M default \cn 'commandline -r "nix shell nixpkgs#"'
# Ctrl-Shift-n (defined by terminal)
bind -M insert \x11F nix-fzf
bind -M default \x11F nix-fzf
'';
# Provides "command-not-found" options
programs.nix-index = {
enable = true;

View File

@ -14,65 +14,70 @@ in
options.nmasur.presets.programs.starship.enable = lib.mkEnableOption "Starship shell prompt";
config = lib.mkIf cfg.enable {
enable = true;
settings = {
add_newline = false; # Don't print new line at the start of the prompt
format = lib.concatStrings [
"$directory"
"$git_branch"
"$git_commit"
"$git_status"
"$hostname"
"$cmd_duration"
"$character"
];
right_format = "$nix_shell";
character = {
success_symbol = "[](bold green)";
error_symbol = "[](bold red)";
vicmd_symbol = "[](bold green)";
};
cmd_duration = {
min_time = 5000;
show_notifications = if pkgs.stdenv.isLinux then false else true;
min_time_to_notify = 30000;
format = "[$duration]($style) ";
};
directory = {
truncate_to_repo = true;
truncation_length = 100;
};
git_branch = {
format = "[$symbol$branch]($style)";
};
git_commit = {
format = "( @ [$hash]($style) )";
only_detached = false;
};
git_status = {
format = "([$all_status$ahead_behind]($style) )";
conflicted = "=";
ahead = "";
behind = "";
diverged = "";
untracked = "";
stashed = "";
modified = "";
staged = "+";
renamed = "»";
deleted = "";
style = "red";
};
hostname = {
ssh_only = true;
format = "on [$hostname](bold red) ";
};
nix_shell = {
format = "[$symbol $name]($style)";
symbol = "";
};
python = {
format = "[\${version}\\(\${virtualenv}\\)]($style)";
programs.starship = {
enable = true;
enableFishIntegration = true;
enableBashIntegration = true;
settings = {
add_newline = false; # Don't print new line at the start of the prompt
format = lib.concatStrings [
"$directory"
"$git_branch"
"$git_commit"
"$git_status"
"$hostname"
"$cmd_duration"
"$character"
];
right_format = "$nix_shell";
character = {
success_symbol = "[](bold green)";
error_symbol = "[](bold red)";
vicmd_symbol = "[](bold green)";
};
cmd_duration = {
min_time = 5000;
show_notifications = if pkgs.stdenv.isLinux then false else true;
min_time_to_notify = 30000;
format = "[$duration]($style) ";
};
directory = {
truncate_to_repo = true;
truncation_length = 100;
};
git_branch = {
format = "[$symbol$branch]($style)";
};
git_commit = {
format = "( @ [$hash]($style) )";
only_detached = false;
};
git_status = {
format = "([$all_status$ahead_behind]($style) )";
conflicted = "=";
ahead = "";
behind = "";
diverged = "";
untracked = "";
stashed = "";
modified = "";
staged = "+";
renamed = "»";
deleted = "";
style = "red";
};
hostname = {
ssh_only = true;
format = "on [$hostname](bold red) ";
};
nix_shell = {
format = "[$symbol $name]($style)";
symbol = "";
};
python = {
format = "[\${version}\\(\${virtualenv}\\)]($style)";
};
};
};

View File

@ -0,0 +1,25 @@
{
config,
pkgs,
lib,
...
}:
let
cfg = config.nmasur.presets.programs.zoxide;
in
{
options.nmasur.presets.programs.zoxide.enable = lib.mkEnableOption "zoxide smart cd replacement";
config = lib.mkIf cfg.enable {
programs.zoxide = {
enable = true;
enableFishIntegration = true;
enableBashIntegration = true;
};
};
}

View File

@ -33,7 +33,6 @@ in
pkgs.mpd # TUI slideshows
];
programs.zoxide.enable = lib.mkDefault true; # Shortcut jump command
programs.fish.shellAliases = {
"cd" = lib.mkDefault lib.getExe pkgs.zoxide;
"du" = lib.mkDefault lib.getExe pkgs.dua;
@ -53,6 +52,7 @@ in
ripgrep.enable = lib.mkDefault true;
prettyping.enable = lib.mkDefault true;
weather.enable = lib.mkDefault true;
zoxide.enable = lib.mkDefault true;
};
};