fish使用.md
色彩
命令为红色为无效命令,命令为蓝色为有效命令
有效路径有下划线,无效路径没有下划线
命令提示
按->
或Ctrl + F
可以采纳全部建议
按ALT + ->
可以采纳部分建议
fish配置文件
fish的一个配置文件~/.config/fish/config.fish
,fish启动时会自动加载这个文件,类似于bash中的.bashrc文件。
fish语法及使用
四种变量
https://fishshell.com/docs/current/language.html#variables-universal
https://fishshell.com/docs/current/language.html#variables-scope
There are four kinds of variables in fish: universal, global, function and local variables.
Universal variables are shared between all fish sessions a user is running on one computer. They are stored on disk and persist even after reboot.
Global variables are specific to the current fish session. They can be erased by explicitly requesting
set -e
.1
2
3
4
5
6
7❯ set -gx py python
❯ echo $py
python
# 关闭终端后重启
❯ echo $py
# 无输出Function variables are specific to the currently executing function. They are erased (“go out of scope”) when the current function ends. Outside of a function, they don’t go out of scope.
Local variables are specific to the current block of commands, and automatically erased when a specific block goes out of scope. A block of commands is a series of commands that begins with one of the commands
for
,while
,if
,function
,begin
orswitch
, and ends with the commandend
. Outside of a block, this is the same as the function scope.
Variables can be explicitly set to be universal with the -U
or --universal
switch, global with -g
or --global
, function-scoped with -f
or --function
and local to the current block with -l
or --local
. The scoping rules when creating or updating a variable are:
- When a scope is explicitly given, it will be used. If a variable of the same name exists in a different scope, that variable will not be changed.(当明确指定范围时,将使用它。如果不同范围内存在同名变量,则不会更改其他范围的同名变量)
- When no scope is given, but a variable of that name exists, the variable of the smallest scope will be modified. The scope will not be changed.(未指定范围但存在同名变量时,将修改最小范围的变量。范围不会更改)
- When no scope is given and no variable of that name exists, the variable is created in function scope if inside a function, or global scope if no function is executing.(未指定范围且不存在同名变量时,如果变量位于函数内,则在函数范围内创建该变量;如果未执行任何函数,则在全局范围内创建该变量。)
There can be many variables with the same name, but different scopes. When you use a variable, the smallest scoped variable of that name will be used. If a local variable exists, it will be used instead of the global or universal variable of the same name.
可以有多个同名但作用域不同的变量。当你 使用变量 时,将使用该名称的最小作用域变量。如果存在局部变量,则将使用该局部变量,而不是同名的全局或通用变量。
应用场景:
Typically inside functions you should use local scope:
1 | function something |
If you want to set something in config.fish, or set something in a function and have it available for the rest of the session, global scope is a good choice:
只在当前shell session生效,关闭当前shell session后失效
1 | # Don't shorten the working directory in the prompt |
If you want to set some personal customization, universal variables are nice:(永久保存,关机后也存在)
1 | # Typically you'd run this interactively, fish takes care of keeping it. |
关于universal variables,fish文档有点冲突
https://fishshell.com/docs/current/language.html#variables-scope中描述Universal variables are shared between all fish sessions a user is running on one computer,是a user,即仅对一个用户有效
https://fishshell.com/docs/current/language.html#variables-universal中描述Universal variables are variables that are shared between all the user’s fish sessions on the computer,是all user,对所有用户有效
测试了一下:
1 | ❯ set -U fish_color_autosuggestion 555 |
应该是one user
【注意】
- 不要将universal variables 附加到 config.fish 文件中,因为这些变量会随着每个新 shell 实例而变长。相反,只需在命令行运行一次 set -Ux 即可。从 Fish 3.0 开始,通用变量将存储在文件 ~/.config/fish/fish_variables 中。在之前的版本中,它是 ~/.config/fish/fishd.MACHINE_ID,其中 MACHINE_ID 通常是 MAC 地址。参考https://stackoverflow.com/questions/25632846/how-to-set-environment-variables-in-fish-shell
- 不要将global variables附加到 config.fish 中,因为global variables的本意是当前shell session有效的变量,如果将其添加到config.fish中,那么所有shell session中都会加载config.fish中的global variables
添加路径到PATH变量
fish_add_path命令
https://fishshell.com/docs/current/cmds/fish_add_path.html
fish_add_path is a simple way to add more components to fish’s PATH
. It does this by adding the components either to $fish_user_paths or directly to PATH
(if the --path
switch is given).
Components are added in the order they are given, and they are prepended(前置) to the path unless --append
is given (if PATH
, so they still stay ahead of the system paths).
-a or –append
Add components to the end of the variable.
-m or –move
Move already-existing components to the place they would be added - by default they would be left in place and not added again.(如果组件已经存在,则不会再次添加,除非给出 –move 开关,否则组件将保留在同一位置。)
-U or –universal
Use a universal fish_user_paths
- this is the default if it doesn’t already exist.(如不不存在参数,则默认为-U)
-P or –path
Manipulate PATH
directly.(直接加入
例子
1 | # I just installed mycoolthing and need to add it to the path to use it. |
设置环境变量(set命令)
set
manipulates shell variables.
If both NAME and VALUE are provided, set
assigns any values to variable NAME. Variables in fish are lists, multiple values are allowed. One or more variable INDEX can be specified including ranges (not for all options.)
(可以设置多个值,如set -gx py py1 py2 py3)
1 | ❯ set -gx py python1 python2 |
If no VALUE is given, the variable will be set to the empty list.
If set
is ran without arguments, it prints the names and values of all shell variables in sorted order. Passing scope or export flags allows filtering this to only matching variables, so set --local
would only show local variables.
With --show
, set
will describe the given variable names, explaining how they have been defined - in which scope with which values and options.
1 | ❯ set --show py (base) |
With --erase
and optionally a scope flag set
will erase the matching variable (or the variable of that name in the smallest possible scope).
1 | ❯ set --erase py # 删除 |
四种范围选项:
The following options control variable scope:
-U or –universal
Sets a universal variable. The variable will be immediately available to all the user’s
fish
instances on the machine, and will be persisted across restarts of the shell.-f or –function
Sets a variable scoped to the executing function. It is erased when the function ends.
-l or –local
Sets a locally-scoped variable in this block. It is erased when the block ends. Outside of a block, this is the same as –function.
-g or –global
Sets a globally-scoped variable. Global variables are available to all functions running in the same shell. They can be modified or erased.
–export or -x
Causes the specified shell variable to be exported to child processes (making it an “environment variable”).
–unexport or -u
Causes the specified shell variable to NOT be exported to child processes.
使用了-x,变量会被导入子进程
测试
创建test.fish,在shell中执行fish脚本,会开启一个子进程执行fish脚本
1 |
|
不使用-x
1 | ❯ set -g py python |
使用-x
1 | ❯ set -gx py python |
-e or –erase *NAME*[INDEX]删除环境变量
Causes the specified shell variables to be erased. Supports erasing from multiple scopes at once. Individual items in a variable at INDEX in brackets can be specified.
-S or –show查看环境变量
Shows information about the given variables. If no variable names are given then all variables are shown in sorted order. It shows the scopes the given variables are set in, along with the values in each and whether or not it is exported. No other flags can be used with this option.
用的最多的
1 | set -Ux key value #全局生效 |
fish取别名(alias/function)
https://fishshell.com/docs/current/language.html#functions
alias
is a simple wrapper for the function
builtin, which creates a function wrapping a command. It has similar syntax to POSIX shell alias
. For other uses, it is recommended to define a function.
alias会创建一个function,因此学习fish functions
Functions are programs written in the fish syntax. They group together various commands and their arguments using a single name.
For example, here’s a simple function to list directories:
1 | function ll |
The first line tells fish to define a function by the name of ll
, so it can be used by simply writing ll
on the commandline.
The second line tells fish that the command ls -l $argv
should be called when ll
is invoked.
$argv is a list variable, which always contains all arguments sent to the function.
In the example above, these are simply passed on to the ls
command. The end
on the third line ends the definition.
Calling this as ll /tmp/
will end up running ls -l /tmp/
, which will list the contents of /tmp.
Fish’s prompt is also defined in a function, called fish_prompt.
Defining aliases
One of the most common uses for functions is to slightly alter the behavior of an already existing command(修改存在的命令行的表现). For example, one might want to redefine the ls
command to display colors. The switch for turning on colors on GNU systems is --color=auto
. An alias around ls
might look like this:
1 | function ls |
There are a few important things that need to be noted about aliases:
- Always take care to add the $argv variable to the list of parameters to the wrapped command. This makes sure that if the user specifies any additional parameters to the function, they are passed on to the underlying command.
- If the alias has the same name as the aliased command, you need to prefix the call to the program with
command
to tell fish that the function should not call itself, but rather a command with the same name. If you forget to do so, the function would call itself until the end of time. Usually fish is smart enough to figure this out and will refrain from doing so (which is hopefully in your interest).
Autoloading functions(自动加载函数)
Functions can be defined on the commandline or in a configuration file, but they can also be automatically loaded. This has some advantages:
- An autoloaded function becomes available automatically to all running shells.
- If the function definition is changed, all running shells will automatically reload the altered version, after a while.
- Startup time and memory usage is improved, etc.
简单的说,Autoloading functions就是会自动加载,因此在命令行可以直接使用这个函数的函数名
因此,如果有为命令定义别名,或创建新命令,可以使用Autoloading functions,而不是直接在config.fish中添加,由于shell启动会执行config.fish,因此在config.fish中添加会导致fish启动速度减慢。
When fish needs to load a function, it searches through any directories in the list variable $fish_function_path
for a file with a name consisting of the name of the function plus the suffix .fish
and loads the first it finds.
For example if you try to execute something called banana
, fish will go through all directories in $fish_function_path looking for a file called banana.fish
and load the first one it finds.
当fish想要加载一个函数xxx时,会查找$fish_function_path(是一个list变量)中所有路径下是否有相应的xxx.fish文件
By default $fish_function_path
contains the following:
- A directory for users to keep their own functions, usually
~/.config/fish/functions
(controlled by theXDG_CONFIG_HOME
environment variable). - A directory for functions for all users on the system, usually
/etc/fish/functions
(really$__fish_sysconfdir/functions
). - Directories for other software to put their own functions. These are in the directories under
$__fish_user_data_dir
(usually~/.local/share/fish
, controlled by theXDG_DATA_HOME
environment variable) and in theXDG_DATA_DIRS
environment variable, in a subdirectory calledfish/vendor_functions.d
. The default value forXDG_DATA_DIRS
is usually/usr/share/fish/vendor_functions.d
and/usr/local/share/fish/vendor_functions.d
. - The functions shipped with fish, usually installed in
/usr/share/fish/functions
(really$__fish_data_dir/functions
).
If you are unsure, your functions probably belong in ~/.config/fish/functions
.
As we’ve explained, autoload files are loaded by name, so, while you can put multiple functions into one file, the file will only be loaded automatically once you try to execute the one that shares the name.
正如我们所解释的,自动加载文件是按名称加载的,因此,虽然您可以将多个函数放入一个文件中,但只有在您尝试执行同名的函数时才会自动加载该文件。
If a file of the right name doesn’t define the function, fish will not read other autoload files, instead it will go on to try builtins and finally commands. This allows masking a function defined later in $fish_function_path, e.g. if your administrator has put something into /etc/fish/functions that you want to skip.
这种设计允许在$fish_function_path路径中存在多个autoload文件,但只会加载与命令名匹配的第一个autoload文件,避免了重复加载相同的函数定义。同时,如果在系统管理员预设的目录(比如/etc/fish/functions)中存在某个函数定义,但用户不想使用它,可以通过在用户自定义的autoload文件中定义同名函数来覆盖系统管理员预设的函数。
alias
alias
is a simple wrapper for the function
builtin, which creates a function wrapping a command. It has similar syntax to POSIX shell alias
. For other uses, it is recommended to define a function.
alias会创建函数
If you want to ease your interactive use, to save typing, consider using an abbreviation instead.
fish
marks functions that have been created by alias
by including the command used to create them in the function description. You can list alias
-created functions by running alias
without arguments. They must be erased using functions -e
.
NAME
is the name of the aliasDEFINITION
is the actual command to execute.alias
automatically appends$argv
, so that all parameters used with the alias are passed to the actual command.
You cannot create an alias to a function with the same name. Note that spaces need to be escaped in the call to alias
just like at the command line, even inside quoted parts.
-s or –save(保存为自动加载文件)
Saves the function created by the alias into your fish configuration directory using funcsave.
funcsave
saves a function to a file in the fish configuration directory. This function will be automatically loaded by current and future fish sessions. This can be useful to commit functions created interactively(交互式) for permanent use.
问题解决
ubuntu系统语言为中文,此时Git相关命令的输出也为中文,想要使Git输出为英文,可以用function或alias解决。
创建function解决:
在~/.config/fish/functions目录下,新建git.fish文件(文件名必须为git,参考Autoloading functions中的要求)
文件内容为:
1 | function git |
注意:
- LANG=en_US设置语言
- command不能省略,否则会提示递归调用git函数,用command表示函数中的git不是一个函数,而是一个命令git
使用alias命令解决
1 | ❯ alias --save git="LANG=en_US command git" |