Functions for the Fish Shell, making common tasks more convenient.
Backup any existing ~/.config/fish, then:
git clone https://git.sr.ht/~razzi/fish-functions ~/.config/fishIn previous versions, other fish config including abbrs were included as well. That changed much more frequently than the functions, so I split them out.
Now they are at https://git.sr.ht/~razzi/.dotfiles (see that repository's README for installation instructions).
fishInteractive Utilities- File Manipulation
- Zipfile Utilities
- Text Utilities
fishScripting Utilities- Environment Utilities
- Symlink Utilities
gitUtilitieslimaUtilitiesvimUtilities- Postgres Utilities
- Date Utilities
- MacOS Utilities
Fish functions designed to be typed and run in the shell.
abbr-add <name> <expansion> [<args>] (source)
Adds an abbr and syncs your abbrs to ~/.config/fish/conf.d/abbrs.fish.
This way the abbr will be loaded the next time you open your shell.
Without abbr-add, you can use abbr -a to make your own abbrs,
and add abbr -a calls to your fish config manually,
but I recommend using abbr-add and tracking
~/.config/fish/conf.d/abbrs.fish in version control.
All abbr options work with this command, so for example you can run:
$ abbr-add --position anywhere isntall installRecommended abbreviation: abbr-add ab abbr-add
abbr-erase <name> (source)
Erases an abbr and removes it from ~/.config/fish/conf.d/abbrs.fish.
Recommended abbreviation: abbr-add ae abbr-erase
Completion: completes abbr names.
clip [args] (source)
Copies the arguments that follow clip to the clipboard.
$ clip cat ~/.ssh/id_ed25519.pub
# now "cat ~/.ssh/id_ed25519.pub" is on the clipboard
$ echo (fish_clipboard_paste)
cat ~/.ssh/id_ed25519.pubThis is useful when you want to copy a command to your clipboard (possibly to paste the command into documentation).
You can press the up arrow or control+p to get to the previous command,
then hit control-a to move your cursor to the start, prepend clip ,
and you can quickly copy a command.
If you want to copy the output of a command, pipe it to fish_clipboard_copy:
$ echo 1 | fish_clipboard_copy
$ echo (fish_clipboard_paste)
1funcsave-last (source)
Save the last-edited fish function.
$ function hi
echo hi
end
$ funcsave-last
funcsave: wrote /Users/razzi/.config/fish/functions/hi.fishRecommended abbreviation: abbr-add fs funcsave-last
mkdir-cd <directory> (source)
Make a directory and cd into it.
$ mkdir-cd folder
folder $Recommended abbreviation: abbr-add mc mkdir-cd
backup <file> (source)
Creates a copy of file as file.bak.
$ ls
README.md
$ backup README.md
$ ls
README.md README.md.bakcopy <source> ... [<destination>] (source)
cp with some extra behaviors.
Automatic recursive copy for directories. Rather than only copying the files from a directory, copies the directory itself.
Also uses -i flag by default, which will warn you if a copy would overwrite a destination file.
Example:
$ mkdir testdir
$ touch testdir/file.txt
$ mkdir destdir
# Standard cp needs -r flag
$ cp testdir/ destdir/
cp: testdir/ is a directory (not copied).
# And does not preserve the source folder
$ cp -r testdir/ destdir/
$ ls destdir/
file.txt
# Cleaning up...
$ rm destdir/file.txt
# In contrast, using `copy` function:
$ copy testdir/ destdir/
$ ls destdir/
testdirRecommended abbreviation: abbr-add cp copy
If you do this abbreviation, use command cp for the low-level cp.
create-file <target> (source)
Creates a file, including parent directories as necessary.
$ create-file a/b/c
$ tree
.
└── a
└── b
└── ceat <target> (source)
Moves a directory's contents to the current directory and removes the empty directory.
$ tree
.
└── a
└── b
└── c
$ eat a
$ tree
.
└── b
└── cIf a file in the current directory would be overwritten by eat, it will error with exit status 1.
An illustration of this:
$ tree
.
├── dir-a
│ └── dir-b
│ └── some_file
└── dir-b
└── would_be_overwritten
3 directories, 3 files
$ eat dir-a
eat: file would be overwritten: ./dir-bmove <source> ... <destination> (source)
Like mv but uses -i flag by default,
which will warn you if mv would overwrite a destination file.
Also warns you if you are trying to move a directory symlink which is ending in slash:
$ mkdir mydir
$ ln -s mydir mylink
$ mv mylink/ renamed
mv: cannot move 'mylink/' to 'renamed': Not a directorymove gives a more descriptive error:
$ move mylink/ renamed
move: `from` argument "mylink/" is a symlink with a trailing slash.
move: to rename a symlink, remove the trailing slash from the argument.This arises because tab completion adds the slash. Completion for move could avoid the slash, but then again you might want to move a file within the symlinked directory.
move-last-download [<dest>] (source)
Move the latest download to destination directory, which is the current directory if none is specified.
Recommended abbreviation: abbr-add mvl move-last-download
remove <target> (source)
rm with an extra behavior.
If removing a directory with write-protected .git, confirm once to ensure the git directory is desired to be removed.
$ ls -a dodo
. .. .git x
$ remove dodo
Remove .git directory dodo/.git?> yUsing plain rm:
$ rm -r dodo
override r--r--r-- razzi/staff for dodo/.git/objects/58/05b676e247eb9a8046ad0c4d249cd2fb2513df? y
override r--r--r-- razzi/staff for dodo/.git/objects/f3/7f81fa1f16e78ac451e2d9ce42eab8933bd99f? y
override r--r--r-- razzi/staff for dodo/.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391? ^C
$ rm -rf dodoRecommended abbreviation: abbr-add rm remove
If you do this abbreviation, use command rm for the low-level rm.
restore <backup> (source)
Rename a backup such as file.bak to remove the .bak extension.
$ ls
README.md README.md.bak
$ restore README.md.bak
$ ls
README.mdclean-unzip <zipfile> (source)
Unzips a .zip archive without polluting the current directory, by creating a
directory even if the zipfile does not have a folder level.
unzip-cd <zipfile> (source)
Unzip a zip directory and cd into it. Uses clean-unzip to create a folder if
the zipfile doesn't have one.
$ unzip-cd files.zip
Archive: files.zip
extracting: out/a.txt
extracting: out/b.txt
files $ ls
a.txt b.txtcoln <number> (source)
Splits input on whitespace and prints the column indicated.
$ echo 1 2 | coln 2
2row <number> (source)
Prints the row of input indicated.
$ seq 3 | row 2
2skip-lines <number> (source)
Skips the first n lines of stdin.
$ seq 5 | skip-lines 2
3
4
5take <n> (source)
Take the first n lines of standard input.
$ seq 5 | take 3
1
2
3word-count (source)
Count the words from standard input. Like wc -w but does not put spaces around the number.
$ echo a b | word-count
2
# Compare to:
$ echo a b | wc -w
2line-count (source)
Count the lines from standard input. Like wc -l but does not put spaces around the number.
$ seq 3 | line-count
3
# Compare to:
$ seq 3 | wc -l
3char-count (source)
Count the characters from standard input. Like wc -c but does not put spaces around the number.
$ echo -n a b | char-count
3
# Compare to:
$ echo -n a b | wc -c
3string-empty <value> (source)
Test if the value is the empty string.
$ string-empty ''
$ echo $status
0Can be used to test for arguments:
$ function something
if string-empty $argv
echo No arguments passed
else
echo Arguments were passed
end
end
$ something
No arguments passed
$ something 1
Arguments were passedIf you use this on a variable, be sure to get the variable's value using $:
$ if string-empty $VIRTUAL_ENV
echo in venv
endsince string-empty VIRTUAL_ENV will always return false.
file-exists <file> (source)
Test if $file exists.
is-dir <path> (source)
Check if $path is a directory.
is-symlink <path> (source)
Check if $path is a symlink.
confirm (source)
Prompts the user for confirmation. Exit with status according to whether they answered y, Y, yes, or YES.
curdir (source)
Just the current directory name, please.
mydir $ curdir
mydirYou probably won't need this interactively since the current directory is usually part of your fish_prompt,
but this is useful for scripting.
echo-variable <variable> (source)
Like echo, but without the $ or capitalization.
$ echo-variable user
razzi
$ echo $USER
razziRecommended abbreviation: abbr-add ev echo-variable
Completion: completes environment variable names.
readpass <name> (source)
Prompt for a password. Does not echo entered characters.
$ readpass email
●●●●●●●●●●●●●●●●●
$ echo $email
[email protected]symlink <from> <to> (source)
Create a symbolic link, using absolute paths.
~/dotfiles $ symlink .prettierrc ~
~/dotfiles $ cat ~/.prettierrc
singleQuote: true
semi: falseWithout using absolute paths:
~/dotfiles $ ln -s .prettierrc ~
~/dotfiles $ cat ~/.prettierrc
cat: /Users/razzi/.prettierrc: Too many levels of symbolic linksunsymlink <file> (source)
Remove a symlink. Errors if the file is not a symlink.
Recommended abbreviation: abbr-add us unsymlink
symlinks [<dir>] (source)
List symlinks in the given directory, or the current directory if none is passed.
link-rc [<file>] (source)
Create a symlink from $file to the home directory (~).
Sample usage:
.dotfiles $ link-rc .tmux.conf
.dotfiles $ head -1 ~/.tmux.conf
set -g prefix ^SpaceRecommended abbreviation: abbr-add lrc link-rc
clone-cd url [destination] (source)
Clone a git repository into the current directory (or the optional $destination), and cd into it.
If a folder by that name already exists, great, you probably already cloned it, just cd into the directory and pull.
If it's trying to clone into a non-empty directory, make a new folder in that directory with the repository name and clone into that, instead of erroring.
Recommended abbreviation: abbr-add cc clone-cd
clone-shallow-cd url [destination] (source)
Like clone-cd but clones with --depth=1 for speed.
wip [message] (source)
Adds untracked changes and commits them with a WIP message. Additional arguments are added to the WIP message.
I use this instead of git stash so that changes are associated with the branch they're on, and the commit is tracked in the reflog.
$ git stat
## master
M tests.py
$ git switch -c testing
$ wip failing tests
[testing 0078f7f] WIP failing tests
$ git switch -git-add [paths] (source)
Like git add, but defaults to . if no arguments given, rather than erroring.
Also understand ... to mean ../... If you need more levels of ../.. I guess they could be added.
Did I mention I have a function called ... that cds up 2 levels?
Recommended abbreviation: abbr-add ga git-add
git-commit [message] (source)
Like git commit -m without the need to quote the commit message.
If no commit message is given and there's only 1 file changed, commit "(Add / Update / Delete) (that file)".
$ git-commit
[master c77868d] Update README.md
1 file changed, 57 insertions(+), 18 deletions(-)
$ git reset @^
Unstaged changes after reset:
M README.md
$ git-add
$ git-commit Fix typo in README.md
[master 0078f7f] Fix typo in README.md
1 file changed, 57 insertions(+), 18 deletions(-)Recommended abbreviation: abbr-add gc git-commit
gitignore <pattern> (source)
Add a pattern to the .gitignore.
Recommended abbreviation: abbr-add giti gitignore
lima Utilities
lima-ssh [name] (source)
Connect to a lima virtual machine. Defaults the machine named default.
Creates and starts the machine as necessary, so it works in 1 command.
lima-vnc (source)
Connect to a Lima virtual machine over VNC.
Creates and starts the machine as necessary, like lima-ssh.
vim-plugin <url> (source)
Install a vim plugin using the builtin vim plugin mechanism.
ensuredb <name> (source)
Ensure that a fresh database by the name given is created. Drops a database by that name if it exists, clearing database connections as necessary.
renamedb <from> <to> (source)
Renames a database.
isodate (source)
Prints the date in ISO format.
$ isodate
2020-01-28isodatetime (source)
Prints the date and time in ISO format.
$ isodatetime
2025-03-07T23:11:53wifi-network-name (source)
Prints the current wifi network name.
wifi-password (source)
Prints the current wifi network password.
wifi-reset (source)
Turns the wifi off and on again.