fish shell介绍
fish shell简介
fish是一个专注于交互性和可用性的Unix shell,fish这个名称来自于它的英文释义“the friendly interactive shell”,意思是“人机交互非常友好的shell”。Fish被设计为默认为用户提供功能,而不是通过配置。Fish被认为是一个外来的shell,因为它没有严格遵守POSIX shell标准,这是由维护者决定的。
也就是说,很多常见shell命令是无法在fish上执行的,不过无所谓,如果你要执行shell脚本,你可以在里面用#!/bin/bash
来指定bash执行,或者直接显式的用bash执行bash /path/to/xxx.sh
。
fish首次发布于2005年2月13日,原作者为Axel Liljencrantz,现在在github开源,有700多个贡献者。
fish有哪些优点
- 1、样式美观且可高度定制,包含选项提示
- 2、按Tab键可列出当前文件夹下的文件(夹),继续按可在文件列表中跳转选中(也可直接用方向键选择);
- 3、快速回到上一个/下一个文件夹(其实用
cd -
更方便,zsh也支持cd -
) - 4、能以不同的颜色提示你敲的命令是否存在(不存在是红色,存在的话你可以自己调颜色)
- 5、输入命令时会显示历史执行过的命令,显示后按一下方向键右键,直接就输入了,免去重新输入的麻烦,这里以
cd
命令为例,但绝不限于cd,任何命令都可以 - 6、可以用不同符号显示git分支上发生的一些事,比如有新文件未加入暂存区、加入了暂存区但未提交、全部文件已提交、当前有冲突等等
- 7、回删更方便,按
command+w
(macOS)或ctrl+w
(Linux)可一段一段的回删(如果bash的话,是直接整段回删的,不能一节一节的删除) - 8、可定义abbr,一种比alias更好用的命令缩写方法(输入缩写后按空格或回车,它能展开成原形)
- 9、可以很方便的自定义函数(命令),就比如最常见的
cd
,ls
这些命令,你都可以轻易的重定义,当然你也可以定义你自己的函数(一个函数就是一个命令)。
fish的缺点:不兼容bash。
目前fish的一个bug:ls或cd之类的命令后面跟上带路径后,按tab,会列出该路径下的所有文件和文件夹,但是fish无法配置文件和文件夹分别显示不同颜色,而zsh默认就是分别显示不同颜色的。
fish和oh-my-fish的安装
几个相关链接:fish官网、fish官方文档、fish官方配置文档、fish github、oh-my-fish。
安装fish
在fish官网的“Go fish”部分,有各个系统的安装方法
Ubuntu点Subscribe进去,其它的由于Subscribe和Download同一个链接,就直接点进去就行,其实都是“先添加源,再用包管理工具安装”,fedora和archlinux由于它们的包都会比较新,所以无需要额外添加安装源。
debian11添加fish安装源并更新
echo 'deb http://download.opensuse.org/repositories/shells:/fish:/release:/3/Debian_11/ /' | sudo tee /etc/apt/sources.list.d/shells:fish:release:3.list
curl -fsSL https://download.opensuse.org/repositories/shells:fish:release:3/Debian_11/Release.key | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/shells_fish_release_3.gpg > /dev/null
sudo apt update
然后使用apt安装
apt install fish
安装好之后,默认配置文件在/etc/fish/
下,但我们修改配置一般不会去该文件夹下修改,而是在自己用户目录下创建配置文件夹~/.config/
(不过不需要自己创建,安装oh-my-fish会自动创建,后面会说到)。
macOS可以用brew安装
brew install fis
brew安装后也会有配置文件,不过是在/usr/local/etc/fish/
下,这是brew安装软件的惯例。
无论是macOS还是Linux,安装好之后,都要设置默认shell为fish
# 首先查看fish被安装在哪儿
which fish
# 然后用切换(记得把/path/to/fish换成which fish输出的路径)
chsh -s /path/to/fish
其实该命令就是修改/etc/passwd
中用户对应的默认shell,比如以下就是root用户在/etc/passwd
文件中的内容,它的最后一段/usr/bin/fish
就是登录该用户后默认执行的shell
root:x:0:0:root:/root:/usr/bin/fish
当然macOS用户并不存在/etc/passwd
中,而是存在以下文件夹中,一个用户一个plist文件,比如用户名为bruce,则有bruce.plist
/private/var/db/dslocal/nodes/Default/users/
我们用以下命令把bruce.plist拷贝出来,你拷贝的时候换一下自己用户名就行
# 先切换到超级用户
sudo -s
# 然后进入存储用户数据的文件夹
cd /private/var/db/dslocal/nodes/Default/users/
# 把bruce用户的plist文件拷贝到“下载”文件夹
cp bruce.plist ~/Downloads
# 进入“下载”文件夹
cd ~/Downloads
# 修改刚刚拷贝的文件所有者为当前用户(whoami可以查看当前用户名)
chown bruce:staff bruce.plist
现在我们可以查看bruce.plist了,需要用到plist查看软件,我用的是“PlistEdit Pro”,先打开“PlistEdit Pro”,然后把bruce.plist插到“PlistEdit Pro”界面上,就能打开,如下所示,shell已经切换为/usr/local/bin/fish
了
安装oh-my-fish
类似oh-my-zsh,相当于给你提供一个工具,让你能更加方便的配置fish shell。
安装oh-my-fish之前必须安装git(1.9.5以上)和curl,如果你已经安装过了,就忽略这一步
# Debian/Ubuntu
apt install git curl
# macOS
brew install git curl
安装oh-my-fish,由于源码在github,如果没有科学上网,这个很可能会安装失败,因此建议开启科学上网再安装。
curl https://raw.githubusercontent.com/oh-my-fish/oh-my-fish/master/bin/install | fish
- 1、oh-my-fish会被安装到
~/.local/share/omf/
; - 2、oh-my-fish安装过程会自动创建
~/.config/
目录(里面有fish和omf两个子目录); - 3、安装好之后,如果你用
ls -l
之类的命令列出文件,在有些系统中排列会发生错乱,此时你只需要关闭终端当前tab,新开一个tab重新登录进去就好了; - 4、安装好之后,会有一个
omf
命令可以使用(omf
直接查看帮助,不用-h
),它用于管理一些主题和插件,类似zsh的omz
命令; - 5、oh-my-fish的启动入口脚本为
~/.config/fish/conf.d/omf.fish
;
多用户安装问题
对于桌面系统来说,无论是macOS还是Linux桌面系统(Ubuntu,archLinux等等),一般桌面系统用户都是一个普通用户(比如我用鼠标新建一个文件夹,它会属于这个普通用户),但是可以su -
或sudo -s
切换到root用户。
对于fish
这个命令来说,肯定是普通用户和超级用户都可以用的,但问题是配置文件,包括oh-my-fish它本质也属于配置文件,它们应该是普通用户和超级用户各配置一份吗?
对于macOS:其实不需要配置多份,只需要普通用户安装一份即可,切换到超级用户时,使用sudo -s
来切换,这样虽然切换到root了,但配置文件都会用普通用户的配置文件,所以根本无需设置两份配置,只需要普通用户一份配置文件即可。
对于Linux桌面系统:linux用sudo -s
(或su
/su -
等)切换到root后不会使用普通用户的配置,这跟macOS不一样,我们可以把普通用户下的配置做一个符号链接到root用户下
ln -s /home/用户名/.local/share/fish /root/.local/share/fish
ln -s /home/用户名/.local/share/omf /root/.local/share/omf
ln -s /home/用户名/.config/fish /root/.config/fish
ln -s /home/用户名/.config/omf /root/.config/omf
对于Linux服务器:如果是个人使用的,可以跟桌面系统一样,做一个符号链接到/root/
下即可,但是如果是多人共用的,就看情况了,你也可以用创建符号链接的方式,把其中一个用户的配置链接到root用户,也可以重新安装配置,但我认为没有这个必要,一般来说,超级管理员把它自己的普通用户配置做个符号链接过去就可以了。当然会在服务器安装fish的,应该只有个人用户了,公司线上机器是不可能安装fish的。
fish和oh-my-fish的使用
使用omf安装主题
显示有哪些主题可以安装(这里可以预览主题样式)
omf theme
选择其中一个主题安装,安装后会存储在~/.local/share/omf/themes/
下
omf install bobthefish
可以看到我安装了agnoster和bobthefish两个主题,而default则是默认主题
> ls -l ~/.local/share/omf/themes/ Sun Feb 19 14:41:39 2023
total 12
drwxr-xr-x 4 root root 4096 Feb 18 01:23 agnoster/
drwxr-xr-x 5 root root 4096 Feb 18 01:26 bobthefish/
drwxr-xr-x 4 root root 4096 Feb 18 00:53 default/
安装符号字体
安装好bobthefish主题后,输入sudo -s
并输入密码,切换到超级用户,然后进入以下文件夹
~/.local/share/omf/themes/bobthefish/functions
然后会看到以下效果
我们用鼠标划选,让它反显,显示如下,我们可以看到很多黑色的三角形
其实在终端中其实是没有“三角形”这种形状的,你看到的“三角形”其实是“字”,还有②所示的那个“git分支”符号,也是“字”,只不过这些“字”并不是中文或英文或其它语言的字,而是一些“符号”,因为“字”本身也是一种符号,只不过我们把它叫成是“字”而已。
由于这些“字”并不是普通的字,所以系统本身是不带这些字体的,所以如果你之前没有安装过这些字体,这些符号你是看不见的,应该会显示成一个“方框”之类的,表示无法显示,我这边能显示是因为我之前用的是zsh,zsh的主题也要用到这些字体,所以我已经安装过这些字体了,所以才不会显示为“方框”。
那么要安装什么字体呢?有两种字体库:
你可以只安装其中一种,也可以两种安装,不过从github更新来看,Powerline fonts已经没怎么更新了,最新的一个更新已经是6年前(当前时间2023.02.27),而nerd-fonts最新的是2年前(文档、安装脚本之类的更新不算,我说的是真正的字体更新)。
以下是nerd-fonts的所有符号(引用自github)
nerd有技术迷,电脑迷的意思,所以nerd-fonts意思就是给开发者使用的字体(这些字体都是一些开发者群体常用的一些符号)。
修改fish/omf配置的方法
修改配置无非是两种需求:
- 1、主题(theme)的配置:包括配色、一些提示符号等等;
- 2、添加环境变量:有时候如果安装的软件不在标准可执行文件路径下,就需要手动把它们添加到环境变量中;
fish/omf的配置主要有三种修改方法:
- 1、一般情况下,配置都会放到
~/.config/fish/config.fish
文件下,其作用相当于zsh
的.zshrc
和bash
的.bashrc
,config.fish如果不存在,你就手动创建一下(是否默认存在可能跟不同版本有关); - 2、一部分配置会放到
~/.config/fish/fish_variables
文件中,但该文件不能直接编辑,而是需要通过set -U
来设置(U是Universal,表示全局); - 3、如果没有配置项,则需要直接修改源码,但是修改源码也不是直接修改,而是采用覆盖方式(把对应的functions目录中你需要修改的文件原样复制到
~/.config/fish/functions/
然后在这里修改); - 4、
~/.config/fish/conf.d/
下的omf.fish
是omf的入口文件,其内容如下,其实说白了,就是~/.config/fish/
文件夹才是fish的配置文件夹,其它文件夹中的配置都是因为从这里引入了所以才能放在其它位置# Path to Oh My Fish install. set -q XDG_DATA_HOME and set -gx OMF_PATH "$XDG_DATA_HOME/omf" or set -gx OMF_PATH "$HOME/.local/share/omf" # Load Oh My Fish configuration. source $OMF_PATH/init.fish
BashCopy
如果config.fish默认是存在的,它的默认内容应该是这样的
if status is-interactive
# Commands to run in interactive sessions can go here
end
如果把配置放到if里面,表示在交互状态下配置才会生效,平时我们操作shell,都是属于交互状态,如果写成脚本执行就不属于交互。不过脚本执行的话,也与界面显示无关,所以一般不需要我们的自定义配置项,但环境变量的话就不应该写到if里面,因为有些环境变量在脚本形式也是需要读取的。
如何让修改后的配置生效?:
- 1、对于config.fish,与
.bashrc
和.zshrc
一样,使用source加载即可:source ~/.config/fish/config.fish
; - 2、functions配置修改后会直接生效,不需要手动加载(但有时候也不是那么的“自动”,比如需要你执行一下
clear
,按几下回车才会生效); - 3、通过
set -U
设置的,会直接生效,同时也会保存到~/.config/fish/fish_variables
,以持久化该设置; - 3、个别配置既不会自动生效,用source也无法生效,那就关掉终端重新登录即可;
- 4、由于我们的配置项只放在config.fish和fish_variables中,如果你发现某个配置明明删掉了还是存在,请检查fish_variables,大概率是在该文件下没删掉,因为fish_variables是命令设置进去的,有时候并不是那么的“可读”(比如横杠会被显示成
\x2d
,等号会显示成\x3d
)。
让vim支持fish语法高亮显示
前面已经讲了如何修改配置,接着我们就来修改配置,个性化定制主题,不过在修改配置之前,先配置一下让vim支持fish文件语法高亮,否则修改配置的时候一片灰色,很难看。
创建~/.vim/
目录,如果已经有了,可以忽略这一步
mkdir -p ~/.vim
把vim-fish下载到~/.vim
目录下
git clone https://github.com/dag/vim-fish ~/.vim/vim-fish
在~/.vimrc
文件中添加以下这句即可
set rtp+=~/.vim/vim-fish
当然如果你安装了插件管理器,那就使用插件管理器来安装,或者手动把它下载到插件管理器要求你放置的地方就好了,比如我安装了pathogen插件管理器,我就只需要把它克隆到~/.vim/bundle/
下,并且也不需要在~/.vimrc
中添加rtp了,因为插件管理器会自动加载。
修改bobthefish主题的配置
bobthefish是一个主题插件,由于它有非常多的配置项,方便各种自定义配置,所以我安装了该主题,如果你喜欢其它主题,也可以安装你喜欢的,一般主题都是开源在github上,它有自己的配置文档。以下是bobthefish主题的配置过程。
bobthefish主题目前有3个问题:
- ① 当你进入多级目录后,它会把除末级外的其它全部只显示成一个字母,而我希望它显示完整路径;
- ②
whoami
显示当前为root用户,然而前面的$
让我觉得当前是普通用户(因为Linux下普通用户都是用$
表示); - ③ 没有当前用户名和主机名显示,比如
root@debian
。
通过查bobthefish主题的readme.md的configuration可知,问题①可通过在config.fish
中添加以下设置项来关闭这种显示单个字母的模式
# 0表示关闭,1,2,3,……分别表示只显示1个,2个,3个,……字母
set -g fish_prompt_pwd_dir_length 0
问题③可通过在config.fish
中添加以下设置项来解决
set -g theme_display_user yes
set -g theme_display_hostname yes
而问题②经过查文档发现并没有配置项可以设置,那我们只能修改源码了,根据前面使用omf安装主题可知,该主题被安装到了以下目录
~/.local/share/omf/themes/bobthefish/
查看该目录发现它只有两个文件夹,可知它的代码都是写在“functions”目录下的(其实fish插件都是通过写functions来实现的)
> ls -l ~/.local/share/omf/themes/bobthefish/ Sun Feb 19 16:07:22 2023
total 28
-rw-r--r-- 1 root root 1086 Feb 18 01:26 LICENSE
-rw-r--r-- 1 root root 14325 Feb 18 01:26 README.md
drwxr-xr-x 2 root root 4096 Feb 19 13:43 functions/
drwxr-xr-x 2 root root 4096 Feb 18 12:24 hooks/
查看functions目录,由于我们不知道前面问题②那个$
符号在哪里设置的,所以只能一个一个文件找(其实也可以通过vscode打开这个文件夹,然后全文查找$
符,这样更容易找到)
ls -l ~/.local/share/omf/themes/bobthefish/functions/ Sun Feb 19 16:09:12 2023
total 108
-rw-r--r-- 1 root root 34289 Feb 18 01:26 __bobthefish_colors.fish
-rw-r--r-- 1 root root 127 Feb 18 01:26 __bobthefish_display_colors.fish
-rw-r--r-- 1 root root 3362 Feb 18 01:26 __bobthefish_glyphs.fish
-rw-r--r-- 1 root root 4264 Feb 18 01:26 bobthefish_display_colors.fish
-rw-r--r-- 1 root root 266 Feb 18 01:26 fish_greeting.fish
-rw-r--r-- 1 root root 1186 Feb 18 01:26 fish_mode_prompt.fish
-rw-r--r-- 1 root root 37193 Feb 18 01:26 fish_prompt.fish
-rw-r--r-- 1 root root 2492 Feb 18 01:26 fish_right_prompt.fish
-rw-r--r-- 1 root root 968 Feb 18 01:26 fish_title.fish
最终我们找到是在__bobthefish_glyphs.fish
文件中的superscript_glyph
设置项
直接修改它当然是可以,但是下次插件更新又会被覆盖,正确方式是把__bobthefish_glyphs.fish
文件copy一份到用户自己的functions配置目录下
cd ~/.local/share/omf/themes/bobthefish/functions/
cp __bobthefish_glyphs.fish ~/.config/fish/functions/
然后修改~/.config/fish/functions/
下的__bobthefish_glyphs.fish
文件中的选项,保存直接生效(如果不生效可能执行个clear
再敲几个回车就生效了),我是把它改成了“⚡️”
注意:如果你是通过macOS的control+optoin+空格
添加的“⚡️”符号,它会带有一个未知字符(会被显示为空格),记得回删一下,否则会导致在超级用户下路径箭头右侧多一个空格,因为本来就有一个空格,多一个空格就是两个空格,这样看起来很难受。
通过以上设置,现在问题①②③都解决了,路径显示全名了,“用户名@主机名”也有了,前面的符号也变成我喜欢的⚡️了
通过以上设置,我们知道了,修改配置,要不就找插件自己提供的设置项放到~/.config/fish/config.fish
文件中,要不就是通过修改插件源码(function文件)的方式,但修改源码我们不是直接在原地修改,而是复制一份到~/.config/fish/functions/
目录下再修改。同理,其它插件需要修改配置项,都是采用这种模式。
特别注意:通过source加载配置后,你无法通过“注释并再次source”来取消该配置,什么意思呢?
比如你用以下设置显示当前路径命名,source一下生效了,显示命名了
set -g fish_prompt_pwd_dir_length 0
此时你再把它注释掉,再souce,由于你已经设置过了,就算你注释掉这个选项,该设置还是会存在的,当然是仅存在于当前终端tab中,所以你新开一个终端tab再次登录才能看到效果
# set -g fish_prompt_pwd_dir_length 0
又或者你不要取消注释,而是直接设置回它的默认值,即
set -g fish_prompt_pwd_dir_length 1
source一下就能生效,也就是回到之前的只显示一个字母的形式。
修改bobthefish主题配色
根据bobthefish主题的文档:Custom color schemes,我们需要在自定义函数文件夹~/.config/fish/functions/
创建一个函数文件bobthefish_colors.fish
touch ~/.config/fish/functions/bobthefish_colors.fish
然后把以下函数放进文件中,然后修改该文件即可(该函数是我已经调过色的了)
function bobthefish_colors -S -d 'Define a custom bobthefish color scheme'
# Optionally include a base color scheme
__bobthefish_colors default
# Then override everything you want!
# Note that these must be defined with `set -x`
#-----------
set -x color_initial_segment_exit black red --bold
set -x color_initial_segment_su black green --bold
set -x color_initial_segment_jobs black green --bold
set -x color_path 1EB0FC black
set -x color_path_basename 1EB0FC black
set -x color_path_nowrite 1EB0FC black
set -x color_path_nowrite_basename 1EB0FC black
#------
set -x color_repo green black
set -x color_repo_work_tree black black --bold
set -x color_repo_dirty brred black
set -x color_repo_staged yellow black
set -x color_vi_mode_default brblue black --bold
set -x color_vi_mode_insert brgreen black --bold
set -x color_vi_mode_visual bryellow black --bold
set -x color_vagrant brcyan black
set -x color_k8s magenta white --bold
if fish_is_root_user
set -x color_username 0A5F5F yellow
set -x color_hostname 0A5F5F yellow
else
set -x color_username 0A5F5F white
set -x color_hostname 0A5F5F white
end
set -x color_rvm brmagenta black --bold
set -x color_virtualfish brblue black --bold
set -x color_virtualgo brblue black --bold
set -x color_desk brblue black --bold
end
不同变量代表不同区域的颜色,以下面一句为例
set -x color_initial_segment_exit black red --bold
set -x
表示设置变量,-x
表示exported,即导出变量,导出的变量才会被放到环境变量中(即env
或export
命令输出的环境变量);color_initial_segment_exit
表示要设置颜色的区域(下面会详细说明是哪个区域);black red --bold
三个参数依次表示:背景色、前景色(即文字颜色)、文字是否加粗(如果不加粗可以不用第三个参数);- 颜色可以用英文也可以用十六进制(但开头不能带
#
号),十六进制色码对应什么颜色,可以去这里查询,或者去颜色对照表中查找。
以下详细说明颜色区域对应的变量,注意每段区域的结尾都是那个尖角,所以下图包含三段大区域,分别为①红色区域、③黄色区域、⑤浅蓝色区域,只不过每个区域内部又可以有更详细的设置
– ① color_initial_segment_exit:initial_segment表示起始区域,图中的颜色为red white --bold
,其中“感叹号”表示exit
(退出的意思,比如末尾加&
运行的后台任务运行完之后退出,或者输入不存在的命令按回车也表示退出);
– ② color_initial_segment_su:su是superuser(超级用户),即该选项用于设置在超级用户下显示的符号、颜色和底色,图中的颜色为blue green --bold
,如果符号是emoji,则第二个参数(green)无效;
– ③ color_username,理论上包含当前用户名+主机名整段颜色,图中颜色为yellow black
,实际上由于主机名的颜色另有变量,所以主机名部分的颜色会被另一个变量覆盖;
– ④ color_hostname,主机名颜色,图中颜色为blue white
;
– ⑤ color_path,当前路径颜色,图中配色为1EB0FC black
(其中1EB0FC为天蓝色);
– ⑥ color_path_basename,指当前路径中最后一级的颜色,上图中就是指etc
这一级,图中颜色为yellow black
;
注:fish中支持一种br开头的颜色,比如red是红色,brred就是亮(鲜)红色,brgreen鲜绿色,(br我猜是bright的意思),是否支持加br,都可以自己在原有颜色英文前面加一下试试看。
测试后台任务符号颜色:创建一个sh文件+赋予可执行权限+后台执行(即末尾加&
),可以发现它会出现下图的百分号%
,这个百分号的颜色和背景色,是用color_initial_segment_jobs
变量来设置的(后台任务英文就叫“jobs”)
echo '#!/usr/bin/env fish' > job.sh && chmod u+x job.sh && ./job.sh &
当前用户对当前文件夹无写入权限时,显示的颜色(深紫)
set -x color_path_nowrite BF00BF white
set -x color_path_nowrite_basename BF00BF white
BashCopy
以下是我的bobthefish_colors.fish
中修改过的配置项(对应路径从左到右)
# 退出符号(敲不存在的命令按回车就会有)
set -x color_initial_segment_exit black red --bold
# 超级用户符号的颜色(在最左侧)
set -x color_initial_segment_su black green --bold
# 后台任务的符号
set -x color_initial_segment_jobs black green --bold
# 如果是超级用户
if fish_is_root_user
# 用户名颜色
set -x color_username 0A5F5F yellow
# 主机名颜色
set -x color_hostname 0A5F5F yellow
else
# 用户名颜色
set -x color_username 0A5F5F white
# 主机名颜色
set -x color_hostname 0A5F5F white
end
# 整个路径的颜色
set -x color_path 1EB0FC black
# 最后一级路径的颜色
set -x color_path_basename 1EB0FC black
# 无写入权限路径的颜色
set -x color_path_nowrite 1EB0FC black
# 无写入权限路径最后一级的颜色
set -x color_path_nowrite_basename 1EB0FC black
这是最终显示效果
通过fish_config修改命令颜色
无论是zsh还是fish,都有以颜色来提示命令是否存在的功能:就是你输入一个命令,如果该命令存在,它会显示一种颜色,如果不存在,它会显示另一种颜色(通常是红色)。
在终端执行fish_config
命令,会输出以下提示,它一般会自动打开第一个文件,但是第一个文件一般是无法打开的,所以我们要自己点击第二个地址就可以在网页上打开(此时它是挂起状态,相当于开启一个web服务器,如果要结束可以按回车)
打开后如下图所示,①点击右侧的“Customize”→②选中你要设置颜色的部分→③选择颜色→④点击“Set Theme”保存
点“Set Theme”后它会在fish_config挂起的界面输出设置项,这些设置项都是加了-U
选项的,-U
表示universal,有了-U
的选项都会被自动保存到~/.config/fish/fish_variables
文件中(所以fish_variables
文件是不能手动编辑的,它是fish用于自动保存变量用的),而-g
(global)虽然指全局变量,但这个全局只会在当前窗口中,不会被保存,-g
这个“全局”只是相对于函数内部的局部变量来说是全局变量而已。
通过web页面修改的颜色,本质上还是通过set改变某些变量的值来设置,所以如果有些你不喜欢,你还是可以通过set
命令来设置,而且实际上有些部分的配色是无法通过web页面修改的。
至于配置要放在哪里,前面修改fish/omf配置的方法说过,保存配置的有两个文件:~/.config/fish/config.fish
和~/.config/fish/fish_variables
,前者是直接在文件中修改,后面不能直接在文件中修改,而是需要通过set -U
来设置对应变量。
如果是服务器,它无法打开web页面,直接在终端中执行以下配置即可(它会保存到~/.config/fish/fish_variables
文件中)
set -U fish_color_autosuggestion afafaf
set -U fish_color_cancel --reverse
set -U fish_color_command 00ff00
set -U fish_color_comment FF9640
set -U fish_color_cwd green
set -U fish_color_cwd_root red
set -U fish_color_end FFB273
set -U fish_color_error FF7400
set -U fish_color_escape 00a6b2
set -U fish_color_history_current --bold
set -U fish_color_host normal
set -U fish_color_match --background=brblue
set -U fish_color_normal normal
set -U fish_color_operator 00a6b2
set -U fish_color_param 33CCCC
set -U fish_color_quote 5CCCCC
set -U fish_color_redirection BF7130
set -U fish_color_search_match bryellow --background=brblack
set -U fish_color_selection white --bold --background=brblack
set -U fish_color_status red
set -U fish_color_user brgreen
set -U fish_color_valid_path --underline
设置Tab自动完成颜色
本部分内容文档为:Pager color variables。
首先,我有一个images文件夹,里面有非常多图片,然后我输入ls -l images
,按一下tab键,就会出来images/
文件夹下的所有图片(本质上应该说是文件和文件夹),继续按tab(或用方向键),光标会自动在文件列表中选择(如下图所示)
在~/.config/fish/config.fish
中使用以下配置可以调出上图颜色,如果你不喜欢,可以修改对应的颜色(可以用十六进制但最好不要用#号,因为#号是注释符号,容易造成错误)
# 控制上图白色部分的颜色
set -g fish_pager_color_prefix white --bold
# 控制上图白色部分被选中后会变成什么颜色
set -g fish_pager_color_selected_prefix green
# 控制上图黄色部分颜色(默认为normal)
set -g fish_pager_color_completion yellow
# 控制上图中黄色部分被选中后会变成什么颜色
set -g fish_pager_color_selected_completion white
# 控制上图中光标未选中部分的背景颜色(其实就是列表背景,因为被选中的只会有一个)
set -g fish_pager_color_background --background=black
# 控制上图中光标选中部分的背景颜色
set -g fish_pager_color_selected_background --background=brred
# 选项提示颜色(输入“ls -”后按tab,会列出ls有哪个“-”开头的参数)
set -g fish_pager_color_description yellow
# 选项提示被选中后的颜色
set -g fish_pager_color_selected_description black
# 含secondary的有四个,其实就是前面的四个加了secondary,它们的意思,其实跟不加secondary是一样的
# 只不过加了secondary只会作用于偶数行(因为secondary是“第二位的”,在这里理解为偶数)
set -g fish_pager_color_secondary_prefix
set -g fish_pager_color_secondary_completion
set -g fish_pager_color_secondary_background --background=646464
set -g fish_pager_color_secondary_description
# 左下角翻页进度文字颜色+背景色(#21C5C6),文件多才会出现
set -g fish_pager_color_progress FFFFFF --background=21C5C6
输入“ls -”后按tab,会列出ls有哪个“-”开头的参数以及参数的解释
特别注意!!!
特别注意!!!
特别注意!!!
如果~/.config/fish/fish_variables
中已存在某个选项(假设为fish_pager_color_completion
),那么以下两句的作用是有区别的
# 没有参数,会直接修改fish_variables中该选项的值
set fish_pager_color_completion green
# 带有-g,不修改fish_variables中的值,而是覆盖它的值
set -g fish_pager_color_completion green
所以如果fish_variables中真的有该选项,而你又刚好用了set没加-g
,结果就是你即使把你自己的设置删掉,或者重启终端,之前没加-g
的那个设置还会存在,就有种“怎么都无法清除”的感觉,如果出现这种情况,记得去fish_variables文件中找,一定找的到那个选项,也可以直接输入set
回车,这样可以输出全部set的变量,包括fish_variables中的也会被输出。
export/env/set/declare的区别
export:
export这个单词的意思是“导出”,它有两个用法:
- 1、定义导出变量:执行
export aaa=111
,定义了一个aaa变量,可用echo $aaa
打印它的值; - 2、查看导出变量:直接执行
export
即可输出当前导出的变量(即环境变量);
env:
env是environment的缩写,意思就是环境变量,它有三种用法:
- 1、执行程序:执行
env bash
,可把当前环境变量带给后面的bash(bash可以换成其它程序),如果带上参数,根据参数的不同,可提供你所需要的环境变量给后面的程序; - 2、我们经常使用
#!/usr/bin/env bash
、#!/usr/bin/env python
用于指定脚本的执行程序,比起直接指定bash或python路径,使用env可避免在不同环境中路径不一致时无法执行的问题; - 2、查看环境变量:直接执行
env
,用于输出当前的环境变量,env
的输出结果和export
的输出结果是一样的,都表示当前的环境变量(不过顺序会有不同);
注:其实前两种用法属于同一种用法,只是用在不同的地方而已。
declare:
在bash中用于定义变量,比如declare bb=22
,然后用echo $bb
即可打印出来,但是这样设置的变量不是导出变量(即不是环境变量),执行export
(或env
)的输出结果,是不会有aa
这个变量存在的。
如果想要把定义的变量设置为导出变量,可以加个-x
,即declare -x cc=33
,这样用export
或env
都能打印出cc
变量。在bash中,export设置变量,它其实是会调用declare -x
来设置的。
注意:fish中不存在declare关键字,改为用set
代替。
set:
set在bash只用于设置局部变量,它设置的变量无法用echo
打印出来,也不会存在于环境变量中,但在fish中,set代替了declare
(只不过名称和值之间用空格,而不用等号),fish中没有declare,即你可以用set dd 33
来设置一个非导出变量(不会存在于环境变量中),也可以用set -x ee 44
来设置一个导出变量,它会存在于环境变量中(env
或export
的输出结果能看到它)。
注意:从以上可知,设置一个环境变量可用export
和declare
(或set
),但它们设置的值都仅存在于当前终端窗口中,你新开一个Tab标签或新开一个窗口,它们是不会存在的。
如果想要它们在任何窗口中都存在,需要在每个窗口中都重复设置一遍,但是这样太麻烦了,所以我们可以把它们加入到配置文件中,由于每打开一个终端窗口,配置文件都会被执行一次,所以你定义的变量自然就会被加入到该窗口所在的环境变量中。
对于bash,可把设置语句加入到~/.bashrc
文件中,对于zsh,可以把设置语句加入到~/.zshrc
文件中,对于fish,可把配置文件加入到~/.config/fish/config.fish
中,当然修改后,要记得使用source
命令加载一下,否则是不会马上在当前窗口生效的,除非你新开一个窗口。
总结:export/declare/set都可以用于定义环境变量,bash中export定义变量是调用declare -x
来定义的,fish中没有declare,改为使用set
代替,fish中set -gx
定义的变量与export
定义的变量一样,都会被放入环境变量中。
在fish中添加环境变量
文档:path variables。
fish的环境变量可以用export
和set
的方式添加,在~/.config/fish/config.fish
中添加以下两个环境变量
# 使用export设置一个环境变量
export aa=1
# 使用set命令设置一个变量,与export不同的是,它使用空格而不使用等号
set -gx bb 2
注:-g
表示global,-x
表示export,如果不用-x
,设置的变量就不会被放到环境变量中。
source加载一下刚刚的配置
source ~/.config/fish/config.fish
BashCopy
输出两个环境变量的值,输出1 2
,这是正常的,都明两种方式都可以
echo $aa $bb
在export
或env
或set
的输出结果中,都能找到前面设置aa
和bb
变量
export | grep aa
export | grep bb
env | grep aa
env | grep bb
set | grep aa
set | grep bb
向$PATH
添加路径(在~/.config/fish/config.fish
文件中添加)
# 方式一:使用"set -gx"定义
set -gx PATH "$PATH:/usr/local/bin"
# 方式二:使用export
export PATH="$PATH:/usr/local/bin"
输出$PATH
看看当前环境变量,这样看是没有冒号(:
)分隔的
> echo $PATH
/usr/local/sbin /usr/local/bin /usr/sbin /usr/bin /sbin /bin
如果你想要输出有冒号分隔的格式,可以用以下命令
env | grep PATH
另一种添加变量的方法,是使用fish_add_path
命令来添加,如下所示(其它参数看这里)
fish_add_path /opt/mycoolthing/bin
上述添加PATH环境变量命令会向~/.config/fish/fish_variables
文件中添加一条命令,如下所示
SETUVAR fish_user_paths:/usr/local/bin
fish_variables用于存放fish的环境变量,该文件不能直接编辑,因为它是存放你用命令添加的数据的,就算你编辑了也会在你下次用命令修改变量时被覆盖的。
比alias更好用的abbr
我们知道,在bash和zsh中,有alias
命令,可以把一些长命令设置为短命令,比如alias ll="ls -l"
,就可以用ll
代替”ls -l”,对于频繁使用的命令来说,用alias定义一个短名简化命令,敲起来更方便。
而abbr是abbreviation的缩写,该单词的意思就是“缩写”,它的功能其实跟alias
差不多,不过又有所区别,当然fish也是可以使用alias
的,只不过它又多了一种abbr
而已。
在~/.config/fish/config.fish
中添加以下命令
# 用gco代替git checkout
abbr --add gco git checkout
# 用ll代替ls -l
abbr --add ll ls -l
加载一下,让前面添加的配置生效
source ~/.config/fish/config.fish
测试:输入gco
(或ll
),按一下空格(或回车),它会自动把命令展开为git checkout
(或ls -l
),这与alias方式不一样,这样的好处是既可以以缩略形式输入,又能展开原形式,让你或别人不至于不知道你敲的是啥命令(因为你可能写博客文章要放截图、github提issue要放截图、或录视频教程)。
其它abbr的相关参数
# 删除,可删除多个
abbr --erase <abbr1> <abbr2>
# 重命名
abbr --rename OLD_WORD NEW_WORD
# 显示你已经定义过的abbr
abbr -l
# 以详细形式显示你已经定义过的abbr(输出的命令可直接用于执行)
abbr --show
其实删除的话,我觉得没啥必要,因为如果你要删除,直接注释或去掉配置文件中相关配置就好了,当然需要新开窗口才能生效(source是不会生效的,因为它已经在当前session中了),如果要立刻生效,还是得用--erase
选项
让fish支持autojump
安装autojump
# macOS
brew install autojump
# centos
sudo yum -y install autojump
# debian
sudo apt-get install autojump
在config.fish中引入autojump.fish:请在~/.config/fish/config.fish
中添加下面这句
# macOS
. /usr/local/share/autojump/autojump.fish
# Linux
. /usr/share/autojump/autojump.fish
然后source加载一下让前面添加的配置生效
source ~/.config/fish/config.fish
然后就有j
命令可以用了。
修改ls输出的目录颜色
ls输出目录要有彩色,必须满足两个条件:
- 1、定义了彩色环境变量:LS_COLORS(Linux),LSCOLORS(macOS);
- 2、打开了ls的彩色输出开关:Linux可通过添加
--color=auto
(auto也可以为yes,tty,aways等等)选项,而macOS有两个打开彩色输出的开关:设置CLICOLOR=1
或添加-G
选项。
如果未定义彩色环境变量,但是打开了ls的彩色输出开关,那么它会输出系统默认的“彩色”(这种颜色一般是深蓝色,如下图,根本看不清)
以下我会从bash说起,然后再说到fish,原因下边会讲。
Linux:
对于Linux(我这边是Debian11),看下图应该就能明白了(下图使用的shell为bash,不是fish)
– ① 直接用ls
,理论上来说我没有用--color=auto
打开彩色输出开关它不应该输出彩色的,但事实上却输出了,原因往下看;
– ② 用/bin/ls
,这次没有彩色了,这是正常的;
– ③ 用/bin/ls
并且添加了--color=auto
,输出了彩色,这是正常的,因为--color=auto
就是用于打开彩色输出开关的;
– ④ 由于前面ls
和/bin/ls
结果不一样,所以我们怀疑ls
被设置了别名(即alias),用alias ls
查看,果然是设置了alias ls='ls --color=auto'
;
– ⑤ 查看~/.bashrc
中是否有关于ls
的alias,果然找到了有这个定义,如⑥所示。
当然echo $LS_COLORS
还能看到该变量是有值的,这些值就是用于设置彩色显示时具体显示什么颜色,至于具体怎么设置,可以用man DIR_COLORS
查看使用手册,它一般是通过创建/etc/DIR_COLORS
文件并在该文件中设置的
macOS在bash下:
如下图所示
– ① 直接用ls,不显示颜色,这是正常的,因为没有打开彩色显示开关;
– ② 添加-G
,打开了彩色显示,有颜色了,只不过颜色是默认的颜色(深蓝色),所以看不清(但它总归是显示了颜色);
– ③ 使用export CLICOLOR=1
向环境变量中添加CLICOLOR=1
;
– ④ 确认CLICOLOR=1
环境变量添加成功;
– ⑤ 再次使用ls,不用-G
也能输出彩色。
自定义彩色:以上虽然输出了彩色,但由于是默认的颜色,很难看,所以我们希望自己定义,执行man ls
并搜索“LSCOLORS”,可以找到相关的定义,我这里直接给出有一种不错的颜色。
在~/.bashrc
中添加以下环境变量,source ~/.bashrc
让它生效,即可看到好看的颜色
export LSCOLORS=GxFxCxDxBxegedabagaced
如下图所示,这个目录的颜色就清晰多了
macOS在fish下:如下图所示
- ① 可以看到,ls不加
-G
,就已经有彩色显示了; - ② 用
/bin/ls
却没有颜色,由此可知直接敲的ls
与/bin/ls
并非同一个; - ③ 用
/bin/ls
添加了-G
选项,有颜色,这是正常的,因为-G
是开启彩色显示的; - ④ 用
export CLICOLOR=1
定义环境变量CLICOLOR
为1; - ⑤ 这次用
/bin/ls
不加-G
也有颜色了,因为前面定义了CLICOLOR
为1; - ⑥ 我们用fish的
functions
命令查看ls
,发现它重新定义了一个ls函数,并且还给出了该函数的路径,所以我们直接执行ls,其实是用的fish的ls,而不是系统的ls;
在上边第⑥步输出的函数的末尾,其实是可以看到有set -lx CLICOLOR 1
这句的(我就不截图了,自己执行functions ls
命令就能看到),这句就是用于设置CLICOLOR
环境变量为1,所以这就是为什么直接用ls
时它会显示彩色的原因。
自定义ls函数:自定义一个ls函数,覆盖fish自带的ls函数。
复制以下我们自定义的ls
函数代码到终端中(处于fish下),然后按回车,就能覆盖fish自带的ls(当然它只会作用于当前终端,不会永久覆盖)
function ls
command ls $argv
end
如下图所示
– ① 查看CLICOLOR
环境变量,发现它没有值;
– ② 即使CLICOLOR
环境变量没有值,并且没有加-G
,但是默认也有颜色,原因在前面第⑥步下面已经说过;
– ③ 我们运行一下自定义的ls函数,它会覆盖fish自带的ls;
– ④ 再次运行ls
,发现目录已经没有颜色了,这次就对了。
现在已经知道fish默认就会显示彩色(因为fish的ls函数中默认设置了CLICOLOR=1
),但是默认的颜色很难看,前面说bash的时候我们已经说过,我们可以自定义这个颜色,在~/.config/fish/config.fish
中添加LSCOLORS
环境变量为以下值
# 可以这样设置(bash,zsh,fish都可以)
export LSCOLORS=gxfxbEaEBxxEhEhBaDaCaD
# fish也可以这样设置(在config.fish中添加),一定要用-x,-x表示export,如果不用,是无法被导出到环境变量中的
set -gx LSCOLORS gxfxbEaEBxxEhEhBaDaCaD
特别注意:前面说了CLICOLOR=1
可以开启ls彩色显示目录,但实际上我发现它根本不看这个值,只看它是否存在,什么意思呢?就是当我们自定义ls函数执行后,本来ls不会显示彩色目录了,但是如果此时你设置一个export CLICOLOR=0
或export CLICOLOR=false
,再执行ls,你会发现它又显示彩色目录了,也就是说,只要CLICOLOR
存在,无论它是空,是0还是false,都会被认为已开启ls的彩色显示目录开关。
fish自定义function
前面我们在终端中(fish环境下)执行过一个自定义的ls函数(如下所示),而且我也说了它只能作用于执行它的那个终端窗口(新开一个窗口它是不会起作用的)
function ls
command ls $argv
end
如果要使该函数持久起作用,需要保存它,执行funcsave ls
即可保存,它会提示保存路径,其实就是在~/.config/fish/functions/
下,当然你也可以直接去~/.config/fish/functions/
下创建ls.fish
文件,它都是直接生效的,不需要source之类的。
查看函数及其路径:fish都是一个函数一个文件,通过functions ls
能输出整个ls
函数以及它的路径,通过这种方法,你可以查看任意一个fish内置函数的路径,当你需要对内置函数进行覆盖修改时,你可以用这种方法输出它的路径,然后拷贝到~/.config/fish/functions/