278 lines
10 KiB
Markdown
278 lines
10 KiB
Markdown
---
|
||
obj: application
|
||
website: https://fishshell.com
|
||
repo: https://github.com/fish-shell/fish-shell
|
||
---
|
||
|
||
# fish
|
||
fish is a smart and user-friendly command line shell for Linux, macOS, and the rest of the family.
|
||
|
||
## Usage
|
||
### Abbreviations
|
||
To avoid needless typing, a frequently-run command like `git checkout` can be abbreviated to `gco` using the `abbr` command.
|
||
|
||
```
|
||
abbr -a gco git checkout
|
||
```
|
||
|
||
After entering `gco` and pressing space or enter, a `gco` in command position will turn into `git checkout` in the command line. If you want to use a literal `gco` sometimes, use `ctrl-space`.
|
||
|
||
Abbreviations are a lot more powerful than just replacing literal strings. For example you can make going up a number of directories easier with this:
|
||
|
||
```fish
|
||
function multicd
|
||
echo cd (string repeat -n (math (string length -- $argv[1]) - 1) ../)
|
||
end
|
||
abbr --add dotdot --regex '^\.\.+$' --function multicd
|
||
```
|
||
|
||
Now, `..` transforms to `cd ../`, while `...` turns into `cd ../../` and `....` expands to `cd ../../../`.
|
||
|
||
The advantage over aliases is that you can see the actual command before using it, add to it or change it, and the actual command will be stored in history.
|
||
|
||
### Custom bindings
|
||
In addition to the standard bindings listed here, you can also define your own with `bind`:
|
||
|
||
```
|
||
# Just clear the commandline on control-c
|
||
bind ctrl-c 'commandline -r ""'
|
||
```
|
||
|
||
Put `bind` statements into `config.fish` or a function called `fish_user_key_bindings`.
|
||
|
||
If you change your mind on a binding and want to go back to fish’s default, you can simply erase it again:
|
||
|
||
```
|
||
bind --erase ctrl-c
|
||
```
|
||
|
||
### History
|
||
After a command has been executed, it is remembered in the history list. Any duplicate history items are automatically removed. By pressing the up and down keys, you can search forwards and backwards in the history. If the current command line is not empty when starting a history search, only the commands containing the string entered into the command line are shown.
|
||
|
||
By pressing `alt-up` (`↑`) and `alt-down` (`↓`), a history search is also performed, but instead of searching for a complete commandline, each commandline is broken into separate elements just like it would be before execution, and the history is searched for an element matching that under the cursor.
|
||
|
||
For more complicated searches, you can press `ctrl-r` to open a pager that allows you to search the history. It shows a limited number of entries in one page, press `ctrl-r` again to move to the next page and `ctrl-s` to move to the previous page. You can change the text to refine your search.
|
||
|
||
History searches are case-insensitive unless the search string contains an uppercase character. You can stop a search to edit your search string by pressing `escape` or `pagedown`.
|
||
|
||
Prefixing the commandline with a space will prevent the entire line from being stored in the history. It will still be available for recall until the next command is executed, but will not be stored on disk. This is to allow you to fix misspellings and such.
|
||
|
||
The command history is stored in the file `~/.local/share/fish/fish_history` (or `$XDG_DATA_HOME/fish/fish_history` if that variable is set) by default. However, you can set the `fish_history` environment variable to change the name of the history session (resulting in a `<session>_history` file); both before starting the shell and while the shell is running.
|
||
|
||
See the `history` command for other manipulations.
|
||
|
||
#### Private mode
|
||
Fish has a private mode, in which command history will not be written to the history file on disk. To enable it, either set `$fish_private_mode` to a non-empty value, or launch with `fish --private` (or `fish -P` for short).
|
||
|
||
If you launch fish with `-P`, it both hides old history and prevents writing history to disk. This is useful to avoid leaking personal information (e.g. for screencasts) or when dealing with sensitive information.
|
||
|
||
You can query the variable `fish_private_mode (if test -n "$fish_private_mode" ...)` if you would like to respect the user’s wish for privacy and alter the behavior of your own fish scripts.
|
||
|
||
### Directory History
|
||
Navigating directories is usually done with the `cd` command, but fish offers some advanced features as well.
|
||
|
||
The current working directory can be displayed with the `pwd` command, or the `$PWD` special variable. Usually your prompt already does this.
|
||
|
||
Fish automatically keeps a trail of the recent visited directories with `cd` by storing this history in the `dirprev` and `dirnext` variables.
|
||
|
||
Several commands are provided to interact with this directory history:
|
||
|
||
- `dirh` prints the history
|
||
- `cdh` displays a prompt to quickly navigate the history
|
||
- `prevd` moves backward through the history. It is bound to `alt-left` (`←`)
|
||
- `nextd` moves forward through the history. It is bound to `alt-right` (`→`)
|
||
|
||
## Configuration
|
||
To store configuration write it to a file called `~/.config/fish/config.fish`.
|
||
|
||
`.fish` scripts in `~/.config/fish/conf.d/` are also automatically executed before `config.fish`.
|
||
|
||
These files are read on the startup of every shell, whether interactive and/or if they’re login shells. Use `status --is-interactive` and `status --is-login` to do things only in interactive/login shells, respectively.
|
||
|
||
## Shell Scripting
|
||
### Shebang
|
||
Because shell scripts are written in many different languages, they need to carry information about which interpreter should be used to execute them. For this, they are expected to have a first line, the shebang line, which names the interpreter executable.
|
||
|
||
A script written in **bash** would need a first line like this:
|
||
|
||
```
|
||
#!/bin/bash
|
||
```
|
||
|
||
When the shell tells the kernel to execute the file, it will use the interpreter `/bin/bash`.
|
||
|
||
For a script written in another language, just replace `/bin/bash` with the interpreter for that language. For example: `/usr/bin/python` for a python script, or `/usr/local/bin/fish` for a fish script, if that is where you have them installed.
|
||
|
||
If you want to share your script with others, you might want to use **env** to allow for the interpreter to be installed in other locations. For example:
|
||
|
||
```
|
||
#!/usr/bin/env fish
|
||
echo Hello from fish $version
|
||
```
|
||
|
||
This will call `env`, which then goes through [`PATH`](https://fishshell.com/docs/current/language.html#envvar-PATH) to find a program called “fish”. This makes it work, whether fish is installed in (for example) `/usr/local/bin/fish`, `/usr/bin/fish`, or `~/.local/bin/fish`, as long as that directory is in [`PATH`](https://fishshell.com/docs/current/language.html#envvar-PATH).
|
||
|
||
The shebang line is only used when scripts are executed without specifying the interpreter. For functions inside fish or when executing a script with `fish /path/to/script`, a shebang is not required (but it doesn’t hurt!).
|
||
|
||
When executing files without an interpreter, fish, like other shells, tries your system shell, typically `/bin/sh`. This is needed because some scripts are shipped without a shebang line.
|
||
|
||
### Variables
|
||
In Fish, variables are assigned using the `set` command:
|
||
|
||
```fish
|
||
set name "Alice"
|
||
set -g global_var "I'm global"
|
||
set -x PATH $PATH /custom/bin # export variable to child processes
|
||
```
|
||
|
||
* `-g`: Sets a global variable.
|
||
* `-x`: Exports the variable.
|
||
* Arrays are space-separated:
|
||
|
||
```fish
|
||
set colors red green blue
|
||
echo $colors[1] # Outputs: red
|
||
```
|
||
|
||
### Conditionals
|
||
|
||
Fish uses `if`, `else if`, and `else`:
|
||
|
||
```fish
|
||
set age 20
|
||
|
||
if test $age -ge 18
|
||
echo "You're an adult"
|
||
else if test $age -ge 13
|
||
echo "You're a teenager"
|
||
else
|
||
echo "You're a child"
|
||
end
|
||
```
|
||
|
||
#### Switch Statements
|
||
|
||
Use `switch` for cleaner branching with string values:
|
||
|
||
```fish
|
||
set lang "rust"
|
||
|
||
switch $lang
|
||
case rust
|
||
echo "You're using Rust!"
|
||
case python
|
||
echo "Python is cool too."
|
||
case '*'
|
||
echo "Unknown language"
|
||
end
|
||
```
|
||
|
||
### Loops
|
||
|
||
#### `for` Loop
|
||
|
||
```fish
|
||
for color in red green blue
|
||
echo $color
|
||
end
|
||
```
|
||
|
||
#### `while` Loop
|
||
|
||
```fish
|
||
set count 1
|
||
while test $count -le 3
|
||
echo "Count: $count"
|
||
set count (math $count + 1)
|
||
end
|
||
```
|
||
|
||
### Functions
|
||
|
||
Define reusable blocks of code with `function`:
|
||
|
||
```fish
|
||
function greet
|
||
echo "Hello, $argv"
|
||
end
|
||
|
||
greet "World" # Output: Hello, World
|
||
```
|
||
|
||
* `$argv` holds all passed arguments.
|
||
* `$argv[1]` is the first argument.
|
||
|
||
#### Returning Values
|
||
|
||
Functions can return more than just a status code. They can return actual output:
|
||
|
||
```fish
|
||
function get_username
|
||
echo "alice"
|
||
end
|
||
|
||
set user (get_username)
|
||
echo $user # Outputs: alice
|
||
```
|
||
|
||
For status codes, use `return`:
|
||
|
||
```fish
|
||
function is_even
|
||
if test (math "$argv[1] % 2") -eq 0
|
||
return 0
|
||
else
|
||
return 1
|
||
end
|
||
end
|
||
```
|
||
|
||
#### Events
|
||
|
||
Fish supports event-driven scripting using `functions --on-event`:
|
||
|
||
```fish
|
||
function notify_start --on-event fish_prompt
|
||
echo "Shell is ready!"
|
||
end
|
||
```
|
||
|
||
Events can be fired with the `emit` command, and do not have to be defined before. The names just need to match. For example:
|
||
|
||
```fish
|
||
function handler --on-event imdone
|
||
echo generator is done $argv
|
||
end
|
||
|
||
function generator
|
||
sleep 1
|
||
# The "imdone" is the name of the event
|
||
# the rest is the arguments to pass to the handler
|
||
emit imdone with $argv
|
||
end
|
||
```
|
||
|
||
### Tools
|
||
Builtins to do a task, like
|
||
|
||
- `cd` to change the current directory.
|
||
- `echo` or `printf` to produce output.
|
||
- `set_color` to colorize output.
|
||
- `set` to set, query or erase variables.
|
||
- `read` to read input.
|
||
- `string` for string manipulation.
|
||
- `path` for filtering paths and handling their components.
|
||
- `math` does arithmetic.
|
||
- `argparse` to make arguments easier to handle.
|
||
- `count` to count arguments.
|
||
- `type` to find out what sort of thing (command, builtin or function) fish would call, or if it exists at all.
|
||
- `test` checks conditions like if a file exists or a string is empty.
|
||
- `contains` to see if a list contains an entry.
|
||
- `eval` and `source` to run fish code from a string or file.
|
||
- `status` to get shell information, like whether it’s interactive or a login shell, or which file it is currently running.
|
||
- `abbr` manages Abbreviations.
|
||
- `bind` to change bindings.
|
||
- `complete` manages completions.
|
||
- `commandline` to get or change the commandline contents.
|
||
- `fish_config` to easily change fish’s configuration, like the prompt or colorscheme.
|
||
- `random` to generate random numbers or pick from a list.
|