在二部曲系列文章的第二部分關于偉大的指令行 ui 終端應用文章中,我們探索了“提示工具包”,“指令行界面建立工具包“,“pygments”和“模糊搜尋”。
這是我的二部曲終端應用程式與偉大的指令行界面的第二部分。 在第一篇文章中,我介紹了幾個能使使用指令行程式充滿樂趣的功能。
在第二部分中,我将介紹如何在幾個 python 庫的幫助下實作這些功能。 在本文結尾,讀者應該很好地了解如何使用 prompt
toolkit,click(指令行界面建立工具包),pygments 和 fuzzy finder 來實作一個易于使用的
repl(互動式解釋器)。
我計劃用少于 20 行的 python 代碼中實作這一點。 讓我們開始。
python 提示工具包
我喜歡将這個庫看作是像瑞士軍刀那樣集大成者的指令行應用程式,它可以替代 readline,curses 等等。 讓我們來安裝這個庫并開始使用:
pip install prompt_toolkit
我們将從簡單的 repl 開始。 通常 repl 将接受使用者輸入,執行操作并列印結果。 對于我們的例子,我們要建構一個“echo”repl。 它隻是列印出使用者輸入的内容:
互動式解釋器
from prompt_toolkit import prompt
while 1:
user_input = prompt('>')
print(user_input)
這就是實作 repl 所需要的。它可以讀取使用者輸入并列印輸入的内容。此代碼段中使用的提示函數來自 prompt_toolkit 庫;它是 readline 庫的替代者。
曆史記錄
為了增強我們的repl,我們可以添加曆史指令:
from prompt_toolkit.history import filehistory
user_input = prompt('>',
history=filehistory('history.txt'),
)
print(user_input)
我們剛剛向repl添加了持久的曆史記錄。現在我們可以使用向上/向下箭頭浏覽曆史記錄,并使用 ctrl + r 搜尋曆史。這符合指令行的基本習慣。
自動提示
我在第一部分中介紹的技巧之一是自動提示曆史指令。(我們看到這個功能最先在 fish shell中推出。)讓我們把這個功能添加到我們的repl中:
from prompt_toolkit.auto_suggest import autosuggestfromhistory
auto_suggest=autosuggestfromhistory(),
我們隻需要在 prompt() api 調用中添加一個新的參數。現在我們的 repl 已經可以支援類似 fish shell 那樣的曆史指令自動提示功能了。
自動補全
現在我們通過 tab 增強來實作自動補全,當使用者開始鍵入輸入時,它彈出可能的建議。
我們的 repl 是如何知道要給出什麼提示的? 我們提供了一個可能名目提示的字典。
假設我們正在為 sql 實作 repl。我們可以使用 sql 關鍵字存儲我們的自動完成字典。讓我們看看如何做到這一點:
from prompt_toolkit.contrib.completers import wordcompleter
sqlcompleter = wordcompleter(['select', 'from', 'insert', 'update', 'delete', 'drop'],
ignore_case=true)
user_input = prompt('sql>',
completer=sqlcompleter,
)
再次,我們隻需使用一個名為 wordcompleter 的 prompt-toolkit 的内置例程,它将使用者輸入與可能提示的字典進行比對,并提供一個清單。
我們現在有一個 repl,它可以自動補全,fish 式的曆史提示,以及曆史指令的上下浏覽。 所有這些都在不到 10 行的實際代碼中。
指令行界面建立工具包
click 是一個指令行建立工具包,可以友善地解析程式的指令行選項參數和參數。 本節不介紹如何作為參數解析器使用click;取而代之的是我将研究一些 click 庫的其他功能的。
安裝 click 很簡單
pip install click
分頁器
分頁器是在 unix 上用來一次性長輸出顯示的實用程式。分頁器包括一些 less, more, most等。通過分頁器顯示指令不僅僅是友好的設計,而且也是需要的。
讓我們進一步來看以上的例子。我們可以用 click.echo_via_pager() 來代替預設的 print()
語句。這将通過分頁器将輸出傳遞給 stdout,這和平台無關,是以可以在 windows 或者 unix
上運作。click.echo_via_pager() 将嘗試用預設的分頁器來輸出,以便在需要的時候顯示有顔色的代碼:
import click
user_input = prompt(u'sql>',
click.echo_via_pager(user_input)
編輯器
在我之前的文章中提到一個細節,就是當指令變得太複雜時就會回到編輯器,同樣的 click 提供了一個簡單的 api 可以來啟動編輯器,并将編輯器中輸入的文本傳回到應用中:
message = click.edit()
模糊搜尋
模糊搜尋是一種讓使用者通過最少的輸入來縮小提示。同樣有一個模糊搜尋庫,讓我們安裝這個庫:
pip install fuzzyfinder
模糊搜尋的api很簡單,你傳遞進部分字元串和一個可能選擇的清單,模糊搜尋将傳回一個新的清單,它和使用了按相關性排序的迷糊算法的字元串進行比對,例如:
>>> from fuzzyfinder import fuzzyfinder
>>> suggestions = fuzzyfinder('abc', ['abcd', 'defabca', 'aagbec', 'xyz', 'qux'])
>>> list(suggestions)
['abcd', 'defabca', 'aagbec']
現在我們有了模糊搜尋,我們将它加入到我們的 sql 互動式解釋器中。這樣就定義了一個完成器,而不是 prompt-toolkit 附帶的 wordcompleter。例如:
from prompt_toolkit.completion import completer, completion
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))
completer=sqlcompleter(),
pygments
現在我們來給使用者輸入添加文法高亮顯示。我們正在建構 sql 互動式解釋器,并且擁有彩色的 sql 語句會很好。
pygments 是一個文法高亮庫,内置支援300多種語言。添加文法高亮使得應用程式變成彩色的,可以幫助使用者在執行 sql 之前發現一些例如打字錯誤或者無法比對的引号和括号。
首先安裝 pygments
pip install pygments
讓我們用 pygments 給我們的 sql 互動式解釋器添加顔色:
from pygments.lexers.sql import sqllexer
lexer=sqllexer,
提示工具包适用于 pygments 庫。我們選擇 pygments 提供的 sqllexer 并将其從提示工具包傳遞給 api 。現在所有的使用者輸入都會被當作 sql 語句并且添上了顔色。
結論
我們本次成果的結論是通過建立一個強大的互動式解釋器,擁有常見 shell 的所有功能,例如曆史記錄,鍵綁定,和很友好的自動完成,模糊搜尋,分頁器,編輯器和文法高亮的功能。我們用少于 20 個 python 語句實作了所有這些。
不是很容易嗎?現在你還有什麼理由寫不出一個優秀的指令行應用程式呢,這裡有一些可能有幫助的資源:
click (指令行界面建立工具包)
提示工具包
請參閱 prompt toolkit 教程和 prompt-toolkit 中的例子
2017年5月20日,amjith ramanujam在俄勒岡州波特蘭市舉辦的美國 2017 pycon 大會上做了名為《超棒的指令行工具》的演講,你可以通過這個演講了解更多内容。
作者:佚名
來源:51cto