在這個分為兩篇的關於具有絕佳命令列介面的終端程式的系列文章的第二篇教程中,我們將討論 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 。它只是原樣列印出使用者的輸入:
REPLfrom 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 行的實際程式碼。
ClickClick是一個命令列建立工具包,使用它能夠更容易的為程式解析命令列選項的參數和常數。在這兒我們不討論如何使用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 语句,并进行适当着色。
结论我们的“旅途”通过创建一个强大的 REPL 结束,这个 REPL 具有常见的 shell 的全部特性,比如历史命令,键位绑定,用户友好性比如自动补全、模糊查找、分页器支持、编辑器支持和语法高亮。我们仅用少于 20 行 Python 代码就实现了这个 REPL 。
不是很简单吗?现在,你没有理由不会写一个自己的命令行应用了。
以上是建立高品質的 Python 命令列使用者介面的庫的詳細內容。更多資訊請關注PHP中文網其他相關文章!