那个极爽的命令行纠错软件 The Fuck 是如何工作的

简介:

改好的命令

这里最重要的部分就是匹配规则了,规则是一个特殊模块集,它有两个方法:

  • match(command: Command) → bool – 匹配上规则则返回 True;
  • get_new_command(command: Command) → str|list[str] – 否则返回修改后的命令或命令列表(当有多个可能匹配项)

我想这个应用只是因为它的规则才这么有趣,编写自己的规则也很简单。目前有 75 条可用的规则,大都是有第三方贡献者写的。命令是一个类似命名元组namedtuple这样的数据结构:

 
  1. Command(script: str, stdout: str, stderr: str)

其中 script 是与 shell 类型无关的错误命令。

处理不同 Shell 类型

在不同的 shell 中,描述 alias 的方式不同、语法不同(比如在 fish 中 && 表示为 and)、历史命令的处理方法也不同,且 shell 还依赖特定的配置文件(.bashre ,.zshrc 等)。为了避免这些麻烦,在程序中有一个 shells 的模块把这些与特定 shell 相关的命令转化为与 sh 兼容的类型,并展开别名和环境变量。 所以我们使用shells.from_shell 方法来获得 Command(前面的章节提到过的)的实例,在 sh 里运行并且获得 stdout 和 stderr。

出错的命令 → from_shell 模块 → 与 shell 类型无关的命令 → (可以)在 sh 内运行 –> Command 实例

对修改好的命令也做了相似地处理,即把与特定 shell 无关的命令通过 shells.to_shell 模块转化为与 shell 相关的命令。

配置

The Fuck 是一个高可配置的应用,用户可以开启或关闭规则、配置 UI、设置规则选项还有进行其他的操作。用户可以通过修改 ~/.thefuck/settring.py 文件以及环境变量来配置应用:

默认配置 → 通过 setting.py 文件更新 → 通过环境变量更新

之前版本中,配置对象以参数的形式传递到所有需要的场合,虽然那样还不错并且能够测试,但存在过多的重复代码。而现在是一个单例(thefuck.conf.settings),类似 Django 中的 django.conf.settings

UI

The Fuck 的 UI 很简单,它允许用户通过(上下)箭头的方式在修正过的命令列表中进行选择,使用 Enter 来确认选择,Ctrl+C 来跳出程序。 美中不足的是在 Python 标准库中没有办法在非 Windows 下不通过 curses 来读取键盘输入,由于别名alias的特性我们又不能在这里使用 curses。但容易写出针对 Windows 的 msvrt.getch:

 
  1. import tty
  2. import termios
  3. def getch():
  4. fd = sys.stdin.fileno()
  5. old = termios.tcgetattr(fd)
  6. try:
  7. tty.setraw(fd)
  8. ch = sys.stdin.read(1)
  9. if ch == '\x03': # For compatibility with msvcrt.getch
  10. raise KeyboardInterrupt
  11. return ch
  12. finally:
  13. termios.tcsetattr(fd, termios.TCSADRAIN, old)

另外 UI 也需要修复好的程序命令组成的有序列表,且规则匹配耗时应该尽量较短。而加入简单的启发式算法后效果还不错,首先我们按照优先级来匹配规则,第一个返回的修复过的命令是有最大优先级的命令。当用户按下箭头按键时再选择其他的命令。所以在大多数的使用场景中都能很快完成任务。

整体来看

如果从整体来看一下这个应用,会发现它很简单:

其中 controller(控制器)是当用户使用 The Fuck 来修复错误命令时的程序入口,它初始化设置、准备 shells 的交互环境、从 Corrector (修正器)来获取修正过的命令并在 UI 中选择。Corrector 使用所有可用的规则来匹配当前命令并且返回所有可用的修复过的命令。关于UI、设置和规则就说到这里。

测试

测试是所有软件项目的最重要的部分之一。没有测试,软件可能会由于任一个改变而崩溃。我们使用 pytest 来进行单元测试。由于应用中存在规则,所以需要做很多测试来匹配和确认修正过的命令。所以,参数化的测试用例是很有用的,典型的测试是这样的:

 
  1. import pytest
  2. from thefuck.rules.cd_mkdir import match, get_new_command
  3. from tests.utils import Command
  4. @pytest.mark.parametrize('command', [
  5. Command(script='cd foo', stderr='cd: foo: No such file or directory'),
  6. Command(script='cd foo/bar/baz',
  7. stderr='cd: foo: No such file or directory'),
  8. Command(script='cd foo/bar/baz', stderr='cd: can\'t cd to foo/bar/baz')])
  9. def test_match(command):
  10. assert match(command)

The Fuck 可以与许多种类的 shell 共同工作,而每个 shell 又需要特定的别名。为了保证所有别名可用,需要用到功能测试,其中用到了我写的 pytest-docker-pexpect 模块,在一个 docker 容器内设置一个场景来测试所有支持的命令。

发布

The Fuck 应用的最麻烦的部分是它的安装,应用通过 pip 来发布,由此产生了一些问题:

  • 有些平台上依赖 python 的头文件(python-dev),所以我们需要告诉用户手动地安装;
  • pip 不支持安装后自动完成一些自定义操作,所以用户需要手动配置一个别名;
  • 有些用户使用不支持的 python 版本,应用只支持 2.7 或者 3.3+ 的版本;
  • 有些老版本的 pip 根本就不安装依赖项;
  • 有些版本的 pip 忽视 Python 版本的依赖关系,所以需要为早于 3.4 的版本安装 pathlib;
  • 有趣的是有人对这个名字感到很愤怒并且尝试从 pypi 中移除这个包;

原文发布时间为:2017-05-05

本文来自云栖社区合作伙伴“Linux中国”

相关文章
|
5月前
MacBook终端安装tree命令(保证好使)
MacBook终端安装tree命令(保证好使)
|
开发工具 C语言 数据安全/隐私保护
免杀工具 -- FourEye
免杀工具 -- FourEye
655 0
免杀工具 -- FourEye
|
6月前
|
Shell Linux 网络安全
[笔记]Linux Shell脚本实现自动输入 解放双手 自动测试
[笔记]Linux Shell脚本实现自动输入 解放双手 自动测试
|
6月前
|
网络安全 数据安全/隐私保护 Windows
[笔记] Windows VBS脚本实现自动输入 解放双手 自动测试
[笔记] Windows VBS脚本实现自动输入 解放双手 自动测试
128 0
|
8月前
|
Shell Perl
Shell基础学习---4、文本处理工具、综合应用案例(归档文件、发送信息)
Shell基础学习---4、文本处理工具、综合应用案例(归档文件、发送信息)
|
11月前
|
安全 Shell API
powershell红队免杀上线小Tips
powershell红队免杀上线小Tips
powershell红队免杀上线小Tips
|
Linux Shell
Linux常用指令指南,终端装逼利器
最近搞了台Macbook Pro,就学习了一下Linux命令,在网上查了些资料,看了本书叫《快乐的 Linux 命令行》,里面涉及到了各个方面的命令。 在此将常用的整理出来,以备将来使用。
Linux常用指令指南,终端装逼利器
|
监控 API Windows
好工具推荐系列:Wireshark v3.x可以捕捉本地数据了,WinPcap已替换为NPcap
好工具推荐系列:Wireshark v3.x可以捕捉本地数据了,WinPcap已替换为NPcap
757 0
好工具推荐系列:Wireshark v3.x可以捕捉本地数据了,WinPcap已替换为NPcap
|
NoSQL Ubuntu MongoDB
本地部署 explainshell (命令行解释服务)
前段时间我们分享了explainshell.com 一个命令行解释的网站,它会分析命令的帮助文档,根据你想查询的命令参数来抽取对应的解释,然后非常清晰地显示出来。
236 0
本地部署 explainshell (命令行解释服务)
|
缓存 网络协议 Linux
如何用九条命令在一分钟内检查Linux服务器性能?
一、uptime命令 这个命令可以快速查看机器的负载情况。在Linux系统中,这些数据表示等待CPU资源的进程和阻塞在不可中断IO进程(进程状态为D)的数量。这些数据可以让我们对系统资源使用有一个宏观的了解。
1030 0