1. 从零零散散的Shell配置,到如今这个开源小项目
先把话说明白:OpenShell是我花了大半年维护的一套开源Shell环境方案,准确说,它不是某个单一软件,而是一整套基于组件化思路搭建的Shell工作台,目标很直接——让你从打开终端的那个瞬间起,补全、高亮、历史记录、目录跳转、提示符这些环节都能快起来,而且跨平台可用。
开始动手之前,我的终端环境其实是标准的“能用,但处处别扭”状态。装了zsh,装了oh-my-zsh,主题换过好几个,补全卡顿,命令一长就眼花,来回cd目录像在走迷宫。真正让我下决心推倒重来的是某天下午:我需要在一个嵌套四五层的项目目录里反复切换,然后执行一串带环境变量的构建命令,结果光是敲错目录名、翻历史命令、等补全响应就浪费了十多分钟。那时候我意识到,问题不在我懒,而在Shell环境本身没有被认真设计过。
OpenShell这个名字,字面上是“开放的Shell”,我当时给它的定义有两层:一是整个环境的配置、脚本、插件体系全部开放源码,你拿到手能看懂,改起来不费劲;二是它在组件选择上保持开放心态——不绑定某一个发行版、某一种Shell、某一套框架,凡是好用的、能拆开组合的工具都可以进来。这一篇文章,我打算把OpenShell的完整设计思路、核心工作原理、落地配置、优化过程和踩坑经历一股脑写出来。如果你是那种每天要在终端里泡好几个小时的人,或者正在折腾自己的dotfiles但总感觉不得要领,这篇文章应该能帮你少走不少弯路。
需要先说清楚一个原则:OpenShell不是那种“一键安装、开箱即用”的黑盒产品。它更像一份你拿到手之后还要按自己习惯微调的半成品,但这份半成品已经把最脏最累的地基打好了,你只需要在预制好的骨架上做自己的个性化装修。这点我觉得很重要,因为每个开发者的工作流差异很大,硬要用一套统一配置去套所有人,最后的结果多半是“别人好用,自己憋屈”。
1.1 我决定重写Shell环境的三个理由
第一个理由是性能。我用oh-my-zsh大概两三年,好看是真好看,慢也是真慢。每次开一个新终端标签页,光标要空转小半秒到一秒才出现提示符。这个数字在单独一次操作里不痛不痒,但架不住一天几十次开关终端、跑脚本、进容器,积少成多之后体感非常糟糕。第二个理由是噪音,oh-my-zsh默认加载了一堆我并不需要的插件和函数库,而真正高频使用的功能(比如快速跳转、模糊搜索历史命令)反而做得不够深,属于“什么都有,但什么都没做到极致”。第三个理由是无法解释的黑盒行为。我遇到过一次更新后主题变量失效,去翻代码,发现一层套一层,加上各种版本兼容分支,最后也没彻底弄清楚到底哪里出了岔子。
这三个理由合在一起,指向同一个结论:我需要一套自己掌握每一个环节的Shell环境。于是OpenShell的雏形就出现了——它不追求大而全,只做几件事,但每件事都要做得扎实。
1.2 OpenShell开源之后,我给自己定的几条铁律
既然叫开源项目,就得有一点纪律感。我自己定了三条约束,后来发现这三条约束恰恰是OpenShell能保持健康的主要原因。
第一条,任何组件的集成必须有明确用途。今天加一个插件,必须能说清楚它解决什么痛点,如果只是“别人说好”,那就先放进实验分支,不进入主配置。第二条,所有配置都要带注释。无论是zshrc里的一个export变量,还是Starship主题里的一个分段,都得写明是干什么的。这条看起来简单,做起来极难,因为人在写配置的当下总觉得自己以后一定会记得。但实际上,三个月后你就忘光了。第三条,跨环境一致性优先。我自己的主力环境是macOS,但服务器是各种Linux发行版,日常也会用到WSL,所以任何配置改动都要保证在这三类环境里行为一致,不能出现“macOS下丝滑、WSL下崩成狗”的情况。
这三条约束直接影响了后面的组件选型和整体架构。比如有些终端工具用起来很爽但只支持Linux,我在引入之前就得先想清楚替代方案。这也是为什么OpenShell的核心组件都尽量选择跨平台支持度高的项目,后面你会反复看到这一点。
2. OpenShell的核心部件与工作原理解析
OpenShell的整体架构,说白了就是一套精心搭配的组件组合。基础Shell还是用zsh,但把oh-my-zsh这类重量级框架换掉了,取而代之的是一批职责单一、组合灵活的独立工具。下面我按实际承担的功能来拆解:提示符、补全、历史记录、目录跳转、语法高亮。这五块分别对应终端使用里最频繁的五个动作,每一项在OpenShell里都有明确的实现方案。
2.1 提示符引擎:Starship背后的思路
提示符这块我最终选了Starship。它是一个跨Shell的提示符工具,用Rust写的,速度极快,而且不只是zsh,连bash、fish、PowerShell都能用同一套配置。这对OpenShell的跨平台目标来说非常有利。
但我更看重的是它“分段渲染”的设计思路。Starship把提示符拆成一个个segment,每个segment可以单独控制显示条件、颜色、图标。比如在Git仓库里显示分支名和状态,检测到Python虚拟环境时显示环境名,当前目录有package.json时显示Node版本。这些信息是分别计算的,互不干扰。这意味着你可以把提示符做得信息密度很高,同时不会让渲染开销变大,因为没用到的segment根本不会执行。
有人可能会问,提示符这东西,默认主题改改颜色不就够了吗?我的体会是,当你的工作流涉及多个服务端项目、多个语言版本时,提示符就是你判断“现在在哪个环境里”的唯一快速入口。默认主题给不了这种粒度,需要自己组合。
2.2 补全系统:从compinit到异步补全
zsh原生的补全能力其实很强,弱点在于慢,准确说是补全函数初始化慢。每次Shell启动时,compinit要扫描所有补全函数文件,建立索引,这个过程中如果加载了大量插件,速度就会肉眼可见地变慢。
OpenShell的做法是分层处理。第一层,系统命令和常用命令的补全仍然走zsh原生compinit,但只加载实际需要的补全定义。第二层,针对fzf这种外部工具,使用fzf自带的补全集成,把“候选结果生成”和“交互式选择”分开——生成走命令本身,选择走fzf的模糊匹配。第三层,对极端场景(比如Docker容器内部没有完整zsh环境),直接回退到bash的basic补全,保证功能可用优先于体验完美。
异步补全是另一个关键点。zsh的默认行为是敲命令时阻塞等待补全结果,如果你在一个大项目里用ripgrep生成候选列表,阻塞时间可能达到几百毫秒。OpenShell引入了一个异步补全实现,让补全计算在后台进行,用户继续输入,等到结果好了再刷新显示。这个优化初看只是“快了那么一下”,实际上彻底改变了高频补全的手感,尤其是在目录层级深、文件数量多的仓库里差异非常明显。
2.3 历史命令与目录跳转:zoxide、fzf的角色
历史命令管理这块,我最开始觉得“history加搜索”就够了,但用下来发现普通grep式搜索效率太低。OpenShell的方案是:历史记录本身仍由zsh管理,但交互检索改用fzf,把历史命令按使用频率加权排序,再用模糊匹配过滤。这样你敲两个字母,基本就能定位到之前执行过的长命令,不用再看一整行上下文。
目录跳转是另一个重点。早期我依赖zsh的cdpath和alias,给常见路径设置别名,例如alias cdblog='cd ~/Projects/my-blog'。但这个方案遇到新目录就没辙了。OpenShell采用zoxide来做这件事,它的原理是记录你cd过的目录,根据访问频率和最近访问时间给每个目录打分,然后通过fzf做模糊匹配跳转。你用z foo就能跳转到“那个名字里带foo、你经常去的目录”,完全不需要记住完整路径。
这里值得展开说下zoxide的工作逻辑。它不像传统的方式那样直接匹配路径前缀,而是维护一个数据库,每条记录包含目录的绝对路径、访问频率、最近访问时间。当你输入一个关键词,它会把数据库里的所有路径按照相关性打分,然后取最高分的那个。相关性算法综合考虑了路径的字符串相似度、访问频次、时间衰减。这意味着你经常去、最近去过的目录会排在前面,而只去过一次的老油条目录会逐渐沉底。这个机制非常贴近真实使用习惯,比单纯的路径匹配聪明很多。
2.4 语法高亮与安全执行
OpenShell里的语法高亮用的是zsh-syntax-highlighting,它做的事情是:在命令还没执行的时候,提前对整条命令行做词法分析,然后给不同类型的关键字上色。比如可用命令显示成绿色,错误命令或不存在命令显示成红色,文件路径根据是否存在显示不同的下划线和颜色,引号、括号、参数扩展也各有各的颜色。这套机制帮你在Enter键按下去之前就发现三分之一的拼写错误和路径错误,实际用下来省了很多不必要的报错。
但这里有个非常关键的细节:zsh-syntax-highlighting的实现原理是在prompt绘制前和后hook住命令行缓冲区的变化,对你的每一条输入做语法树分析。这个分析过程不是零成本的,在非常长的管道命令或者复杂的重定向场景下,会产生可见的延迟。所以OpenShell里默认只启用关键语法高亮能力,关闭了那些视觉效果好但分析代价高的扩展选项。
还有一个安全相关的习惯值得一提:OpenShell默认给rm、mv这种破坏性命令配置了交互确认别名,但这只是第一层保护。真正的保护是上面那套语法高亮的“实时可见性”——当你看到一条命令里冒出来一个不认识的红色高亮,你会在执行前停下来想想是不是变量没展开、路径写错了。这不是什么高科技,但确确实实拦截了我不少低级的rm事故。
3. 一整套可复制的落地配置:OpenShell的目录结构与核心代码
原理讲清楚了,接下来上硬货。OpenShell的配置目录结构是这样设计的:
~/.openshell/ ├── init.zsh # 入口文件,所有环境共用的启动逻辑 ├── modules/ │ ├── prompt.zsh # 提示符分段配置 │ ├── completion.zsh # 补全相关配置 │ ├── history.zsh # 历史记录参数 │ ├── jump.zsh # zoxide目录跳转 │ ├── highlight.zsh # 语法高亮 │ └── aliases.zsh # 通用别名 ├── platform/ │ ├── darwin.zsh # macOS专用配置 │ ├── linux.zsh # Linux/服务器专用配置 │ └── wsl.zsh # WSL专用配置 └── plugins/ ├── fzf.zsh └── custom.zsh # 个人定制功能这套结构的核心思想是“入口负责调度,模块负责逻辑”。init.zsh先检测当前操作系统,然后按顺序加载platform对应文件,再加载modules和plugins。这样做的好处是:当你临时要在某台机器上调试某个模块,你可以直接注释掉入口里的对应行,不需要动其他任何文件。
3.1 入口文件init.zsh的关键分支逻辑
入口文件里最重要的部分是环境检测与路径归一化。下面这个片段展示了核心逻辑:
# 检测操作系统类型 case "$(uname -s)" in Darwin) export OPEN_SHELL_PLATFORM="darwin";; Linux) if grep -qi microsoft /proc/version 2>/dev/null; then export OPEN_SHELL_PLATFORM="wsl" else export OPEN_SHELL_PLATFORM="linux" fi ;; *) export OPEN_SHELL_PLATFORM="unknown";; esac # 按平台加载配置文件 source "$OPEN_SHELL_ROOT/platform/${OPEN_SHELL_PLATFORM}.zsh" # 加载核心模块 source "$OPEN_SHELL_ROOT/modules/history.zsh" source "$OPEN_SHELL_ROOT/modules/completion.zsh" source "$OPEN_SHELL_ROOT/modules/highlight.zsh" source "$OPEN_SHELL_ROOT/modules/jump.zsh" source "$OPEN_SHELL_ROOT/modules/prompt.zsh" source "$OPEN_SHELL_ROOT/modules/aliases.zsh"这里的wsl检测我特别说一下。如果你在WSL里跑zsh,但是没有区分这个环境,你会在路径处理上踩大坑。因为WSL可以用完整路径访问Windows文件系统,也可以访问Linux文件系统,两者之间的路径转换规则完全不同。一个在macOS上正常的路径拼接逻辑,到了WSL里可能拼出一个能执行但不合预期的路径。
3.2 核心补全与高亮配置
补全和高亮是使用频率最高的两块,我把关键配置放在一起说明。下面是completion.zsh的简化版本:
# 初始化补全系统,只缓存必要文件 autoload -Uz compinit compinit -i -d "$OPEN_SHELL_ROOT/cache/zcompdump" # 补全菜单默认开启 zstyle ':completion:*' menu select zstyle ':completion:*' verbose true # 大小写不敏感匹配 zstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}' 'r:|[._-]=* r:|=*' # 分组显示 zstyle ':completion:*' group-name '' zstyle ':completion:*:descriptions' format '%F{green}-- %d --%f'这里有个很多人不知道的点:compinit的转储文件(zcompdump)可以极大提升第二次及以后的启动速度。第一次运行时会生成这个文件,后续启动直接读缓存,再也不需要重新扫描全部补全函数。如果你的Shell配置了何时都感觉补全初始化慢,先检查你的zcompdump有没有配置到位,这是在根上解决速度问题的第一步。
而highlight.zsh的关键配置是下面几个开关:
ZSH_HIGHLIGHT_HIGHLIGHTERS=(main brackets) # 关闭开销较大的regexp高亮 ZSH_HIGHLIGHT_MAX_LENGTH=1024main这个高亮器负责命令名、参数、路径的基础着色,brackets负责括号配对检查,这就覆盖了日常95%的使用场景。把MAX_LENGTH设置成1024是为了避免极端长命令拖慢输入响应,算是一个自我保护机制。
3.3 按键映射与常用快捷键
OpenShell的按键映射沿用了大部分zsh默认习惯,同时增加了几个高频定制。下面这个表格列的是对我来说最有价值的几组快捷键:
| 快捷键 | 功能 | 说明 |
|---|---|---|
| Ctrl+T | 模糊搜索当前目录下的文件 | 基于fzf,选中后直接把路径插入命令行 |
| Ctrl+R | 模糊搜索历史命令 | 基于fzf,替代默认的反向搜索 |
| Alt+C | 模糊跳转到子目录 | 跳转后会替换当前目录,适合进入较深层项目目录 |
| Ctrl+G | Git状态概览 | 在当前项目里展示分支、改动文件、最近提交 |
| Ctrl+S | 插入sudo前缀 | 在当前命令前插入sudo,不用重新输入整条命令 |
这里面Ctrl+G和Ctrl+S是我自己写的插件逻辑,前者调用git status并做个简化输出,后者只是一个原地编辑操作。当初加Ctrl+S的动机特别朴素:有些命令你明明没有权限,得sudo,但命令已经敲完了,退回去再敲一遍又蠢又烦。一条快捷键解决这类高频小痛点,属于性价比极高的投资。
3.4 跨平台差异的处理思路
跨平台差异主要集中在这几个方面:路径风格、系统命令差异、包管理器差异、感知速度差异。OpenShell在每个平台文件里处理自己需要关心的部分,不搞统一兼容层,因为这会造成过度抽象。
darwin.zsh里我设置的是BSD版本的ls参数,比如alias ls='ls -G',而linux.zsh里就要换成alias ls='ls --color=auto'。wsl.zsh里需要额外处理的是Windows命令和Linux命令混用时的PATH顺序,以及Git仓库内换行符和文件权限的差异。
一个必须要提的经验是:不要在配置里直接写死/home/用户名这种路径,要用$HOME。你觉得自己机器上没毛病,但这份配置只要换个用户、换到一台服务器上,马上就会暴露问题。OpenShell里所有路径引用都通过变量传递,目的就是让整套环境在任何一台新机器上clone下来就能跑。
4. 实测性能数据与我的三项关键优化
配置做得再好,如果终端每天要转圈,那一切都是白搭。这一节我分享OpenShell在性能上的实测数据和优化过程。我以macOS上一个典型的zsh启动过程为基准,计时从创建新窗口到看到提示符。
4.1 启动耗时来源拆解
优化之前,OpenShell的启动耗时大约是420毫秒。这个数字分布大概是这样的:compinit初始化占最大头,约180毫秒;Starship提示符初始化约80毫秒;zoxide和fzf等工具的延迟加载判断约60毫秒;剩下的是框架类初始化、别名展开、环境变量检查等杂项目。
这里有个很反直觉的事实:420毫秒里,真正“执行命令”的耗时其实很小,大头都花在“加载和初始化”上。所以优化的方向不是让各条命令跑得更快,而是让它们“少干活”——能延迟加载的绝不预先加载,能缓存结果的绝不重新计算。
另一个关键点是:很多工具自带“初始化脚本”,你装完它,文档让你在.zshrc里source一行。如果装十个工具就source十行,每个都做自己的前后检查,叠加起来就是几百毫秒。OpenShell对这类工具的策略是:全部改成“使用时才加载”的懒加载模式。
4.2 三项关键优化的具体做法
第一项,给fzf的初始化脚本增加了触发条件判断。fzf的默认初始化脚本会注册一堆按键绑定和补全函数,这个加载过程有一定开销。我把它的初始化拆开,只有在第一次实际用到模糊搜索时才加载绑定。效果立竿见影,启动时间直接少了约100毫秒。
第二项,把Starship的初始化延后到提示符第一次需要渲染时。实际上Starship的初始化开销大部分花在检测当前环境、读取配置文件上,这些如果放到prompt第一次被调用时执行,能避开Shell启动的黄金时间。第一次显示提示符时会有几十毫秒的额外开销,但用户感知很弱,因为这时候他已经开始输命令了。
第三项,利用compinit的zcompdump机制把缓存做得更激进。我在缓存文件上增加了时效性校验,只有配置的补全函数文件发生变化时才重建缓存,否则直接用缓存加载。这意味着日常启动时补全初始化这部分直接被缓存干掉,实际耗时从180毫秒降到30毫秒左右。
4.3 优化前后的实测对比
我在统一环境条件下测了十次取平均值,结果如下:
| 阶段 | 优化前 | 优化后 | 提升幅度 |
|---|---|---|---|
| 补全初始化 | 185ms | 32ms | 82.7% |
| 提示符渲染 | 82ms | 15ms | 81.7% |
| 插件工具加载 | 95ms | 18ms | 81.1% |
| 总启动耗时 | 420ms | 96ms | 77.1% |
从420毫秒降到96毫秒,终端基本是秒开的。很多人对延迟不敏感,实际上终端启动从“转个圈”变成“点开就出现”,这个体感差别极其巨大。
我强调一下:这个优化思路不是OpenShell独有的,任何zsh环境都可以借鉴。你可以按照这个思路,把自己的启动过程计时拆解开,找到你环境里的最大头,而不是一味地换主题换框架。
5. 踩坑合集:那些差点让我放弃的细节
从OpenShell立项到现在,踩过的坑够写一篇小作文了。这里挑几个影响最大、也最有代表性的列出来,每个都有完整的排查链路和最终解法。
5.1 WSL里路径转换与命令混用引发的幽灵问题
我在WSL里遇到过一个非常诡异的现象:在某个Windows盘符下执行git status,速度慢到无法忍受,有时候还会报出奇怪的换行符警告。表面上看是git配置问题,换行符警告也确实和core.autocrlf相关,但速度慢这个现象我一直找不到原因。
后来我逐个排查git钩子、文件系统类型、杀毒软件扫描,最后发现锅在文件所在的目录层级太深,加上Windows文件系统(DrvFs)的元数据读写性能比Linux原生文件系统差一个数量级。在/mnt/c这种挂载点上跑git,大量小文件操作全都要经过Windows层的转换,自然慢。
这个案例给我的教训是:WSL里工作,项目文件尽量放在Linux文件系统一侧,Windows盘符下的文件只做数据交换用。这不是OpenShell能解决的问题,但OpenShell会在进入某个Windows目录时通过提示符分段显示警告标记,提醒你正在“慢速区域”。
5.2 LANG与中文乱码问题
这个坑很小,但遇到的时候极其折磨。现象是:在服务器上通过SSH连接时,终端里的中文文件名全部显示成问号,某些程序输出中文日志乱码。直觉会告诉你是编码问题,但你一遍遍改字符集,问题依旧。
排查过程是这样的:先确认本地终端编码是UTF-8,再确认服务器locale,然后发现问题不在locale,而在于SSH连接时没有正确传递LANG环境变量。简化说法是,服务器上的locale存在,但Shell启动时没有得到它,于是回退到C/POSIX,所有非ASCII字符全部成了问号。
解法也很直接:在服务器端的/etc/profile.d或者用户级配置里,显式export LANG和LC_ALL为UTF-8,而不是依赖SSH传入。
5.3 插件更新把配置改坏的事故
还有一次事故让我差点把OpenShell仓库回滚到上一个版本。某个插件做了一次不兼容更新,原本的配置字段被废弃了,我的配置里还在用旧语法。结果就是每次打开终端都刷出警告信息,补全功能时好时坏。
我把配置逐行排查,最终发现新版插件把旧字段直接无视了,不报错,不支持,单纯忽略。这种静默失效比报错更麻烦,因为你找不到问题在哪里。
从那之后,我给OpenShell加了一套“配置校验”逻辑:每次启动时检查关键插件的版本号,如果和配置文件头部的期望版本区间不匹配,就发出警告并建议先看更新日志。
5.4 多用户环境下的权限与路径坑
多用户环境的坑也很典型。在一台共享开发服务器上,我给普通用户配置OpenShell后,发现部分功能正常,另外一部分权限不正常。排查后发现是缓存目录和临时目录的权限问题。OpenShell运行过程中要写缓存文件,如果缓存目录是按当前用户创建在系统目录下,切换到其他用户时自然没有写权限。
解法是把所有运行时缓存都统一放在$HOME/.cache/openshell下,每个用户各用各的缓存,互不干扰。这个方案很简单,但它解决了一个看起来极其隐蔽、实际上非常影响多用户协作体验的问题。类似地,我自己写脚本时会习惯性把所有临时文件写到项目目录下,这在小规模自用时不存在问题,一旦多机同步或者共享目录就会出幺蛾子。
6. 插件生态:如何给OpenShell扩展新能力
OpenShell预留了插件机制,允许你在不改动核心模块的前提下扩展功能。插件的本质就是一个zsh脚本文件,放在plugins/目录下,入口文件启动时会自动加载所有非disabled的插件。
6.1 编写一个插件的最小示例
下面这是一个极简插件,功能是给当前项目生成一个常见的.gitignore快速入口:
# 插件名: gitignore # 功能: 输入gi参数时,调用gitignore.io生成指定类型的.gitignore文件 gi() { if [ $# -ne 1 ]; then echo "usage: gi <language>" >&2 return 1 fi curl -fsS "https://www.toptal.com/developers/gitignore/api/$1" > .gitignore echo ".gitignore generated for $1" }编写插件的要点是:不直接修改init.zsh,不要修改modules下面已存在的任何文件,保持插件与插件之间无依赖。如果两个插件有共享逻辑,把它拆成独立的模块放回modules目录。这个细节很多人不重视,结果就是插件之间互相踩变量名,最后排查到天亮。
6.2 几个值得一试的扩展场景
推荐两个扩展方向。第一个是“按项目类型激活配置”:你在Python项目根目录下放置一个.openshell-project文件,里面声明该项目需要的插件列表和特殊环境变量,OpenShell检测到该文件后自动加载对应配置。这个模式特别适合多语言、多框架开发的人,不同项目用不同的工具链,互不干扰。第二个是“终端会话复用”:写一个插件封装tmux的会话名和目录绑定逻辑,当你从某个目录启动终端时自动创建或接入对应命名的tmux会话,但注意要在WSL和macOS上分别测试,两个平台的tmux配置存在差异。
更多时候,OpenShell插件的价值不在于功能本身多强大,而在于它把“环境配置”和“业务逻辑”做了解耦。你可以拿它来做业务快捷入口,也可以拿它做团队机器的标准环境,全看你自己的想象力。
7. 一些个人体会和后续可扩展的方向
OpenShell这个项目做到现在的程度,我最深的体会是:一个好的Shell环境不是装出来的,是养出来的。你每次遇到一个痛点,就往里面加一点东西;每次觉得某个操作太繁琐,就做成快捷键。这样积累出来的配置,每一个文件、每一行配置都有它存在的理由,而不是从某个主题仓库里一键拉下来之后就再也没打开过。
如果你也想搭一套类似的环境,我的建议是从最小改起。先记录自己日常使用频率最高的五条命令和五个场景,然后针对这五个场景逐个优化,别一开始就追求大而全。你在OpenShell仓库里看到的那些模块,也都是从一行alias到复杂函数的生长过程。
另外有个小技巧我一直想分享:把历史记录数量写大一点。默认的历史记录只有几百条,实际使用中远远不够。我把HISTSIZE和SAVEHIST设置为100000以后,Ctrl+R搜索基本能覆盖我过去一整年的操作,找一条“当时试过但后来忘了具体参数”的命令变得非常容易。这个改动一行代码,但体感提升不亚于做一次性能优化。
至于后续扩展,我现在的想法是给OpenShell增加配置文件生成器,做成一个交互式脚本,根据用户对“风险偏好”“使用频率”“平台环境”这几个维度的回答,自动生成一份初始配置。这是一个偏长线的计划,但在那之前,你完全可以用现在这套组件自己组合出属于你自己的版本。复制过去,改一改,跑起来,用的过程里再微调,这套方法对于任何想折腾终端环境的人都适用。