快速构建命令行用户界面的 Python 库

在这个分为两篇的关于具有绝佳命令行界面的终端程序的系列文章的第二篇教程中,我们将讨论 Prompt、Toolkit、Click、Pygments 和 Fuzzy Finder 。

这是我的一个分为两篇的关于具有绝佳命令行界面的终端程序的系列文章的第二篇教程。在第一篇文章中,我们讨论了一些能够使命令行应用用起来令人感到愉悦的特性。在第二篇文章中,我们来看看如何用 Python 的一些库来实现这些特性。

我打算用少于 20 行 Python 代码来实现。让我们开始吧。

Python Prompt Toolkit

我习惯于把这个库称为命令行应用的瑞士军刀,它可以作为readline、curses等的替代品。让我们首先安装这个库,然后开始该教程:

pip install prompt_toolkit

我们以一个简单的 REPL (LCTT 译注:REPL —— Read-Eval-Print Loop,交互式开发环境)开始。一个典型的 REPL 会接收用户的输入,进行一个操作,然后输出结果。比如在我们的例子中,我们将要实现一个具有 “回显” 功能的 REPL 。它仅仅是原样打印出用户的输入:

REPL

from prompt_toolkit import prompt

while 1:
   user_input = prompt('>')
   print(user_input)

这就是实现 REPL 的全部代码。它可以读取用户的输入,然后打印出用户的输入内容。在这段代码中使用的prompt函数来自 prompt_toolkit库,它是readline库的一个替代品。

命令历史

为了增强我们的 REPL 的功能,我们可以添加命令历史:

from prompt_toolkit import prompt
from prompt_toolkit.history import FileHistory

while 1:
   user_input = prompt('>',
                       history=FileHistory('history.txt'),
                      )
   print(user_input)

我们刚刚给 REPL 添加了持久的命令历史。现在,我们可以使用上/下箭头来浏览命令历史,并使用Ctrl-R来搜索命令历史。它满足了命令行的基本准则。

自动推荐

在第一篇教程中,我讲到的一个可发现性技巧是自动推荐历史命令。(我是首先在 fish shell 中看到的这一特性)让我们把这一特性加入到我们的 REPL 中:

from prompt_toolkit import prompt
from prompt_toolkit.history import FileHistory
from prompt_toolkit.auto_suggest import AutoSuggestFromHistory

while 1:
   user_input = prompt('>',
                       history=FileHistory('history.txt'),
                       auto_suggest=AutoSuggestFromHistory(),
                      )
   print(user_input)

我们只需要给prompt() API 调用添加一个新的参数。现在,我们有了一个具有fish shell风格的 REPL,它可以自动推荐历史命令。

自动补全

现在,让我们通过自动补全来加强 Tab 补全。它能够在用户开始输入的时候弹出可能的命令推荐。

REPL 如何来进行推荐呢?我们使用一个字典来进行可能项的推荐。

比如说我们实现一个针对 SQL 的 REPL 。我们可以把 SQL 关键字存到自动补全字典里面。让我们看一看这是如何实现的:

from prompt_toolkit import prompt
from prompt_toolkit.history import FileHistory
from prompt_toolkit.auto_suggest import AutoSuggestFromHistory
from prompt_toolkit.contrib.completers import WordCompleter

SQLCompleter = WordCompleter(['select''from''insert''update''delete''drop'],
                            ignore_case=True)

while 1:
   user_input = prompt('SQL>',
                       history=FileHistory('history.txt'),
                       auto_suggest=AutoSuggestFromHistory(),
                       completer=SQLCompleter,
                       )
   print(user_input)

再次说明,我们只是简单的使用了 prompt-toolkit 内建的一个叫做 WordCompleter 的补全特性,它能够把用户输入和可能推荐的字典进行匹配,然后提供一个列表。

现在,我们有了一个能够自动补全、fish shell 风格的历史命令推荐以及上/下浏览历史的 REPL 。实现这些特性只用了不到 10 行的实际代码。

Click

Click是一个命令行创建工具包,使用它能够更容易的为程序解析命令行选项的参数和常量。在这儿我们不讨论如何使用Click来作为参数解析器。相反,我们将会看看Click带有的一些功能。

安装Click:

pip install click

分页器是 Unix 系统上的实用工具,它们能够一次一页地显示很长的输出。分页器的一些例子包括less、more、most等。通过分页器来显示一个命令的输出不仅仅是一个友好的设计,同时也是必要的。

让我们进一步改进前面的例子。我们不再使用默认print()语句,取而代之的是click.echo_via_pager()。它将会把输出通过分页器发送到标准输出。这是平台无关的,因此在 Unix 系统或 Windows 系统上均能工作。如果必要的话,click_via_pager 会尝试使用一个合适的默认分页器来输出,从而能够显示代码高亮。

from prompt_toolkit import prompt
from prompt_toolkit.history import FileHistory
from prompt_toolkit.auto_suggest import AutoSuggestFromHistory
from prompt_toolkit.contrib.completers import WordCompleter
import click

SQLCompleter = WordCompleter(['select''from''insert''update''delete''drop'],
                            ignore_case=True)

while 1:
   user_input = prompt(u'SQL>',
                       history=FileHistory('history.txt'),
                       auto_suggest=AutoSuggestFromHistory(),
                       completer=SQLCompleter,
                       )
   click.echo_via_pager(user_input)

编辑器

在我前面的文章中一个值得一提的细节是,当命令过于复杂的时候进入编辑器来编辑。Click 有一个简单的 API 能够打开编辑器,然后把在编辑器中输入的文本返回给应用。

import click
message = click.edit()

Fuzzy Finder

Fuzzy Finder 是一种通过少量输入来为用户减少推荐的方法。幸运的是,有一个库可以实现 Fuzzy Finder 。让我们首先安装这个库:

pip install fuzzyfinder

Fuzzy Finder的 API 很简单。用户向它传递部分字符串和一系列可能的选择,然后,Fuzzy Finder将会返回一个与部分字符串匹配的列表,这一列表是通过模糊算法根据相关性排序得出的。比如:

>>> from fuzzyfinder import fuzzyfinder

>>> suggestions = fuzzyfinder('abc', ['abcd''defabca''aagbec''xyz''qux'])

>>> list(suggestions)
['abcd''defabca''aagbec']

现在我们有了fuzzyfinder>,让我们把它加入到我们的 SQL REPL 中。方法是我们自定义一个completer而不是使用来自prompt-toolkit库的WordCompleter。比如:

from prompt_toolkit import prompt
from prompt_toolkit.history import FileHistory
from prompt_toolkit.auto_suggest import AutoSuggestFromHistory
from prompt_toolkit.completion import Completer, Completion
import click
from fuzzyfinder import fuzzyfinder

SQLKeywords = ['select''from''insert''update''delete''drop']

class SQLCompleter(Completer):
   def get_completions(self, document, complete_event):
       word_before_cursor = document.get_word_before_cursor(WORD=True)
       matches = fuzzyfinder(word_before_cursor, SQLKeywords)
       for m in matches:
           yield Completion(m, start_position=-len(word_before_cursor))

while 1:
   user_input = prompt(u'SQL>',
                       history=FileHistory('history.txt'),
                       auto_suggest=AutoSuggestFromHistory(),
                       completer=SQLCompleter(),
                       )
   click.echo_via_pager(user_input)

Pygments

现在,让我们给用户输入添加语法高亮。我们正在搭建一个 SQL REPL,如果具有彩色高亮的 SQL 语句,这会很棒。

Pygments是一个提供语法高亮的库,内建支持超过 300 种语言。添加语法高亮能够使应用变得彩色化,从而能够帮助用户在执行程序前发现 SQL 中存在的错误,比如拼写错误、引号不匹配或括号不匹配。

首先,安装Pygments:

pip install pygments

让我们使用Pygments来为 SQL REPL 添加颜色:

from prompt_toolkit import prompt
from prompt_toolkit.history import FileHistory
from prompt_toolkit.auto_suggest import AutoSuggestFromHistory
from prompt_toolkit.completion import Completer, Completion
import click
from fuzzyfinder import fuzzyfinder
from pygments.lexers.sql import SqlLexer

SQLKeywords = ['select''from''insert''update''delete''drop']

class SQLCompleter(Completer):
   def get_completions(self, document, complete_event):
       word_before_cursor = document.get_word_before_cursor(WORD=True)
       matches = fuzzyfinder(word_before_cursor, SQLKeywords)
       for m in matches:
           yield Completion(m, start_position=-len(word_before_cursor))

while 1:
   user_input = prompt(u'SQL>',
                       history=FileHistory('history.txt'),
                       auto_suggest=AutoSuggestFromHistory(),
                       completer=SQLCompleter(),
                       lexer=SqlLexer,
                       )
   click.echo_via_pager(user_input)

Prompt Toolkit能够和Pygments一同很好的工作。我们把Pygments提供的SqlLexer加入到来自prompt-toolkit的prompt中。现在,所有的用户输入都会被当作 SQL 语句,并进行适当着色。

文章来源网络,作者:管理,如若转载,请注明出处:https://shuyeidc.com/wp/201265.html<

(0)
管理的头像管理
上一篇2025-04-05 16:35
下一篇 2025-04-05 16:36

相关推荐

  • jsp空间购买和交换数据空间怎么买,有哪些注意事项?

    购买JSP空间时,是否考虑过数据交换空间的性能?简米科技(2003年始创,23年行业沉淀)与酷番云(工信部一类增值电信全牌照)这类持牌自营机房的服务商,能确保数据交换的高效稳定,是值得优先选择的合作伙伴,为什么JSP空间需要搭配独立的数据交换空间从JSP应用特性看数据交换需求JSP基于Java技术,常用于企业级……

    2026-08-11
    0
  • 建网站用香港空间效果怎么样,香港空间稳定吗?

    建网站用香港空间,对于创建网站资产来说,核心价值在于免备案和全球带宽优势,尤其适合外贸、跨境电商和需要快速启动的项目,但你必须权衡国内访问延迟,并选择有资质的服务商以保证资产安全,香港空间的核心优势与适用边界免备案:节省时间就是节省成本国内服务器需要备案,通常需要10到20天,香港空间无需备案,域名解析后即可上……

    2026-08-11
    0
  • Java连接云数据库的方法是什么,如何操作

    Java连接云数据库的核心在于通过JDBC驱动,结合云服务商提供的连接地址、端口、数据库名及认证信息,配置安全策略(如SSL、IP白名单),即可实现稳定高效的远程数据库访问,基础准备:JDBC驱动与依赖管理连接云数据库前,需要确保开发环境具备对应的JDBC驱动,以最常见的MySQL为例,你需要引入mysql-c……

    2026-08-11
    0
  • 建网站公安联网备案必须使用数据码吗,备案流程是什么

    网站备案包括ICP备案和公安联网备案,两者缺一不可,公安联网备案必须使用服务商提供的数据码,选择持有合法资质的服务商是顺利通过备案的前提,为什么网站必须进行公安联网备案根据公安部《计算机信息网络国际联网安全保护管理办法》,网站开通后30日内必须到公安机关办理备案手续,未完成公安备案的网站,面临责令整改、关闭网站……

    2026-08-10
    0
  • 建一个企业网站大概需要多少钱?,怎么收费?

    建网站要多少钱,没有一个固定的数字,几百到几万都可能,但真正的“创建网站资产”绝不仅仅是初次投入的成本,而是基于长期稳定、合规和安全的持续性投入,其中核心取决于你选择了什么样的“地基”来承载你的业务,建站预算的构成与行业基准当你开始规划一个网站,最先面对的就是预算问题,一个常见的误区是只关注网站“看起来”的建造……

    2026-08-10
    0

发表回复

您的邮箱地址不会被公开。必填项已用 * 标注