fish shell的配置和使用

fish shell的配置和使用

我之前写过一篇文章:Mac/Linux下配置iTerm2+zsh+powerline美化终端窗口,文章介绍了使用zsh后,使我们敲命令更加的便捷,看上去也更加的美观。

本文将介绍另一种很受欢迎的shell,它叫fish,它在一些管理和配置上比zsh更方便更好用。

shell简介

sh和bash的

  • 1、UNIX诞生于1969年,由Bell Labs的Dennis Ritchie和Ken Thompson编写;
  • 2、但其实在他们两个编写UNIX之前,他们是跟着贝尔实验室一起参加Multics项目的,Shell的概念、用途、从内核中分离出来单独成为一个用户程序都是在Multics时期有的;
  • 3、Thompson在UNIX的开发过程中,写了thompson shell,在1971年,随第一个版本的UNIX发布。路径就是/bin/sh,在thompson shell的时代 ,就已经有了管道、通配符的概念;
  • 4、后来,在1979年发布的第7版本UNIX中,sh换成了同是贝尔实验室的Stephen Bourne编写的Bourne sh,后来缩写就是bsh;
  • 5、在1980年代,Richard Stallman发起了自由软件运动,目的是为了让人们可以自由的获取和使用软件。在GNU项目中,Brian Fox重写了Shell的部分,取名为Bourne Again Shell,读起来像Born again,重生的意思,这就是我们现在Linux上最多使用的Bash了。

sh,ash和dash

  • 1、目前在debian和ubuntu上,sh其实是一个指向dash的软链接;
  • 2、Almquist shell(ash)是一个轻量级的Unix shell,最初由Kenneth Almquist编写于80年代末,它是Bourne shell(bsh)在Unix System V.4系统上的一个变体,在90年代初发行的Unix BSD系统中,它(ash)代替了Bourne shell(bsh);
  • 3、1997年Herbert Xu将ash从NetBSD移植到Debian Linux。2002年9月,在Debian 0.4.1版本中,这个移植被重命名为Dash (Debian Almquist shell)。Xu的主要目的是POSIX一致性和瘦身(即缩减dash的大小)。

zsh shell简介

Paul Falstad于1990年在普林斯顿大学求学时编写了zsh的初版,zsh这个名称源于耶鲁大学教授邵中(Zhong Shao,后转为普林斯顿大学教授),保罗将教授的用户名”zsh”作为此Shell的名称。

Zsh对Bourne shell做出了大量改进,同时加入了Bash、ksh及tcsh的某些功能。自2019年起,macOS的默认Shell已从bash改为zsh。zsh有Oh My Zsh插件,该插件能大大提升zsh的使用体验。

fish有哪些优点

  • 1、样式美观且可高度定制,包含选项提示
    选项提示.gif

  • 2、按Tab键可列出当前文件夹下的文件(夹),继续按可在文件列表中跳转选中(也可直接用方向键选择);
    Tab list.gif

  • 3、快速回到上一个/下一个文件夹(其实用cd -更方便,zsh也支持cd -)
    prevd-nextd.gif
  • 4、能以不同的颜色提示你敲的命令是否存在(不存在是红色,存在的话你可以自己调颜色)
    if-command-exists.gif
  • 5、输入命令时会显示历史执行过的命令,显示后按一下方向键右键,直接就输入了,免去重新输入的麻烦,这里以cd命令为例,但绝不限于cd,任何命令都可以
    command-history.gif
  • 6、可以用不同符号显示git分支上发生的一些事,比如有新文件未加入暂存区、加入了暂存区但未提交、全部文件已提交、当前有冲突等等
    git status.gif
  • 7、回删更方便,按command+w(macOS)或ctrl+w(Linux)可一段一段的回删(如果bash的话,是直接整段回删的,不能一节一节的删除)
    section-del-back.gif
  • 8、可定义abbr,一种比alias更好用的命令缩写方法(输入缩写后按空格或回车,它能展开成原形)
    abbr.gif
  • 9、可以很方便的自定义函数(命令),就比如最常见的cd,ls这些命令,你都可以轻易的重定义,当然你也可以定义你自己的函数(一个函数就是一个命令)。

fish的缺点:不兼容bash。
目前fish的一个bug:ls或cd之类的命令后面跟上带路径后,按tab,会列出该路径下的所有文件和文件夹,但是fish无法配置文件和文件夹分别显示不同颜色,而zsh默认就是分别显示不同颜色的。

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和oh-my-fish的安装

几个相关链接:fish官网fish官方文档fish官方配置文档fish githuboh-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 fish

brew安装后也会有配置文件,不过是在/usr/local/etc/fish/下,这是brew安装软件的惯例。


无论是macOS还是Linux,安装好之后,都要设置默认shell为fish

# 首先查看fish被安装在哪儿
which fish

# 然后用切换(记得把/path/to/fish换成which fish输出的路径)
chsh -s /path/to/fish

注意chsh -s可能提示

chsh: /opt/homebrew/bin/fish: non-standard shell

出现这个问题的原因是/etc/shells中没有把fish的路径添加进去,你只要打开这个文件把fish的路径添加到最后即可(一般brew安装的话, 添加它的符号链接路径即可),如下所示

# List of acceptable shells for chpass(1).
# Ftpd will not allow users to connect who are not using
# one of these shells.

/bin/bash
/bin/csh
/bin/dash
/bin/ksh
/bin/sh
/bin/tcsh
/bin/zsh
# 这是苹果M系芯片的路径,如果是Intel,路径是/usr/local/bin/fish
/opt/homebrew/bin/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

让vim支持fish语法高亮显示中也需要把做类似的操作,否则会导致普通用户下vim编辑fish是高亮的,但是到了root用户下就不高亮了。

对于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-fonts
nerd有技术迷,电脑迷的意思,所以nerd-fonts意思就是给开发者使用的字体(这些字体都是一些开发者群体常用的一些符号)。

关于powerline字体在macOS/Linux的安装,之前zsh的文章已经讲过,请看:四、配置powerline

而nerd-fonts我这边没有安装过,请直接看nerd-fonts安装文档

修改fish/omf配置的方法

修改配置无非是两种需求

  • 1、主题(theme)的配置:包括配色、一些提示符号等等;
  • 2、添加环境变量:有时候如果安装的软件不在标准可执行文件路径下,就需要手动把它们添加到环境变量中;

fish/omf的配置主要有三种修改方法

  • 1、一般情况下,配置都会放到~/.config/fish/config.fish文件下,其作用相当于zsh.zshrcbash.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
    

如果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也涉及到多用户,如果是自己的机器,一般是一个普通用户+root用户,为了让普通用户和root用户都可用,请在普通用户下执行以下命令,最后创建符号链接,链接到root用户下即可,这跟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了,因为插件管理器会自动加载。

关于vim插件的管理以及配置文件的存放位置等等,可查看:vim配置文件结构


使root用户也生效,把普通用户下的.vim文件夹和.vimrc命令都做一个符号链接到/root/下,这样前面的配置在root用户下也能生效,就免费了配置两次的麻烦

ln -s /home/用户名/.vim /root/.vim
ln -s /home/用户名/.vimrc /root/.vimrc

修改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,即导出变量,导出的变量才会被放到环境变量中(即envexport命令输出的环境变量);
  • 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

以下是我的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,这样用exportenv都能打印出cc变量。在bash中,export设置变量,它其实是会调用declare -x来设置的。

注意:fish中不存在declare关键字,改为用set代替。


set
set在bash只用于设置局部变量,它设置的变量无法用echo打印出来,也不会存在于环境变量中,但在fish中,set代替了declare(只不过名称和值之间用空格,而不用等号),fish中没有declare,即你可以用set dd 33来设置一个非导出变量(不会存在于环境变量中),也可以用set -x ee 44来设置一个导出变量,它会存在于环境变量中(envexport的输出结果能看到它)。


注意:从以上可知,设置一个环境变量可用exportdeclare(或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的环境变量可以用exportset的方式添加,在~/.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

输出两个环境变量的值,输出1 2,这是正常的,都明两种方式都可以

echo $aa $bb

exportenvset的输出结果中,都能找到前面设置aabb变量

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命令可以用了,至于autojump的具体用法,我之前在介绍zsh的时候已经讲过,这里就不重复讲,请直接去看我的zsh文章:autojump基本用法

修改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=0export 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/下进行修改。


参考:
Interactive use
How to enable colorized output for ls command in macOS X Terminal

打赏
订阅评论
提醒
guest

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据

2 评论
内联反馈
查看所有评论
trackback

[…] fish shell 的配置和使用 […]

trackback

[…] fish shell 的配置和使用 […]

2
0
希望看到您的想法,请您发表评论x

扫码在手机查看
iPhone请用自带相机扫
安卓用UC/QQ浏览器扫

fish shell的配置和使用