开发者社区> 知与谁同> 正文

那个极爽的命令行纠错软件 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中国”

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
手撸一款简单高效的线程池(一)
线程池大家应该都用过,不过如何从 0 到 1 的设计一款简单好用且性能较好的线程池?我们在接下来的几篇文章中,为您一一介绍。
4 0
python自动化办公之使用xlrd读取excel文件
python自动化办公之使用xlrd读取excel文件
6 0
手撸一款简单高效的线程池(三)—— 性能优化!
在上一章中,我们给大家介绍了一些 C++线程池中的优化思路和实现方案。这一章中,我们将继续这个主题,接着聊线程池中还有可以“压榨”的空间。为实现我们吹过的牛 B,而继续编程
5 0
手撸一款简单高效的线程池(五)
在之前的内容中,我们给大家介绍了 C++实现线程池过程中的一些常用线优化方案,并分析了不同机制使用时的利弊。这一篇,是线程池系列的最后一章。我们会介绍一下 CGraph 中的 threadpool 如何使用,给出性能对比,并对接下来的工作做一些展望。让我们在线程池性能优化和功能提升的道路上,越走越远。
5 0
记住这两个二分模板,秒杀所有二分查找算法题!
二分查找是一种在每次比较之后将查找空间一分为二的算法。当我们要处理的问题具备单调性,或者要搜寻序列的边界时,应该考虑使用二分查找算法
9 0
变量、常量
变量、常量
5 0
Travis CI简介
什么是持续集成? Travis CI 提供的是持续集成服务(Continuous Integration,简称 CI)。它绑定 Github 上面的项目,只要有新的代码,就会自动抓取。然后,提供一个运行环境,执行测试,完成构建,还能部署到服务器。
9 0
+关注
10077
文章
2994
问答
文章排行榜
最热
最新
相关电子书
更多
OceanBase 入门到实战教程
立即下载
阿里云图数据库GDB,加速开启“图智”未来.ppt
立即下载
实时数仓Hologres技术实战一本通2.0版(下)
立即下载