原文参考Build a REPL With Python Prompt Toolkit,很喜欢这篇教程,清晰简单,读起来十分舒服,翻译过来分析给大家
前言
正式开始翻译之前,我们先了解一些背景知识
python-prompt-toolkit是一个用于构建强大交互式命令行的 Python 工具库,许多好用而智能的命令行工具都构建在它上边
- ipython
- ptpython
- mycli
- pgcli
- xonsh
- gitsome
- http-prompt
- aws-shell
- haxor-news
如果你用过其中的一些,你会惊叹于他们的智能和良好的交互式体验(就像fish), 这些工具的背后便是我们今天的主角:python-prompt-toolkit
REPL
全称Read-Eval-Print Loop(“读取-求值-输出"循环),是一个简单的,交互式的编程环境.
REPL使得探索性的编程和调试更加便捷,因为“读取-求值-输出”循环通常会比经典的“编辑-编译-运行-调试”模式要更快
译文
本文教你使用prompt_toolkit来构建SQLite数据库的命令行工具
prompt_toolkit是一个用于构建强大交互式命令行的 Python 工具库
首先让我们用pip安装它:
pip install prompt_toolkit
搞起!
读取用户输入
使用prompt
方法接收用户输入
1
2
3
4
5
6
7
8
9
|
from __future__ import unicode_literals
from prompt_toolkit import prompt
def main():
text = prompt("> ")
print('You entered:', text)
if __name__ == '__main__':
main()
|
REPL循环
现在让我们在一个while循环里调用prompt
方法,同时将输入历史保存在InMemoryHistory
对象里
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
from __future__ import unicode_literals
from prompt_toolkit import prompt
from prompt_toolkit.history import InMemoryHistory
def main():
history = InMemoryHistory()
while True:
text = prompt("> ", history=history)
print('You entered:', text)
print('GoodBye!')
if __name__ == '__main__':
main()
|
语法高亮
我们已经做了一些基础工作,现在让我们将语法高亮加入到用户的输入中。我们知道用户将会输入sql语句,我们可以使用Pygments来高亮用户的输入.lexer
参数允许你设置词法分析器(译者注:lexical analyzer,简称lexer),我们将使用Pygments 库的SqlLexer
来对输入做高亮处理:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
from __future__ import unicode_literals
from prompt_toolkit import prompt
from prompt_toolkit.history import InMemoryHistory
from pygments.lexers import SqlLexer
def main():
history = InMemoryHistory()
while True:
text = prompt('> ', lexer=SqlLexer, history=history)
print('You entered:', text)
print('GoodBye!')
if __name__ == '__main__':
main()
|
自动补全
语法高亮屌爆啦!你造什么更牛一些吗?自动补全!开干!
使用WordCompleter
类创建一个叫做sql_completer
的实例,初始化的时候,定义一组关键字集合,它们将用于自动补全
sql_completer
实例将被传递到prompt
函数里
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
from __future__ import unicode_literals
from prompt_toolkit import prompt
from prompt_toolkit.history import InMemoryHistory
from prompt_toolkit.contrib.completers import WordCompleter
from pygments.lexers import SqlLexer
sql_completer = WordCompleter(['create', 'select', 'insert', 'drop',
'delete', 'from', 'where', 'table'], ignore_case=True)
def main():
history = InMemoryHistory()
while True:
text = prompt('> ', lexer=SqlLexer, completer=sql_completer, history=history)
print('You entered:', text)
print('GoodBye!')
if __name__ == '__main__':
main()
|
大约用了30行代码我们就得到了一个拥有自动补全和语法高亮的REPL。 再接再厉!
修改菜单样式
自动补全菜单忒丑,让我们给它点"颜色"看看!创建DocumentStyle
,使它成为pygments.style的子类. 定制自动补全菜单的颜色,并把样式作为参数传到prompt
函数里:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
from __future__ import unicode_literals
from prompt_toolkit import prompt
from prompt_toolkit.history import InMemoryHistory
from prompt_toolkit.contrib.completers import WordCompleter
from pygments.lexers import SqlLexer
from pygments.style import Style
from pygments.token import Token
from pygments.styles.default import DefaultStyle
sql_completer = WordCompleter(['create', 'select', 'insert', 'drop',
'delete', 'from', 'where', 'table'], ignore_case=True)
class DocumentStyle(Style):
styles = {
Token.Menu.Completions.Completion.Current: 'bg:#00aaaa #000000',
Token.Menu.Completions.Completion: 'bg:#008888 #ffffff',
Token.Menu.Completions.ProgressButton: 'bg:#003333',
Token.Menu.Completions.ProgressBar: 'bg:#00aaaa',
}
styles.update(DefaultStyle.styles)
def main():
history = InMemoryHistory()
while True:
text = prompt('> ', lexer=SqlLexer, completer=sql_completer,
style=DocumentStyle, history=history)
print('You entered:', text)
print('GoodBye!')
if __name__ == '__main__':
main()
|
剩下的工作就是如何对接到sqlite后端,作为读者的家庭作业好了。哈哈开玩笑啦…我们继续
对接到Sqlite
这一步是可选的 ;) 之前我们一直在关注如何构建REPL. 现在是时候将输入传给SQLite
显然我没有考虑错误处理,但它或许可以作为你们的起步参考
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
from __future__ import unicode_literals
import sys
import sqlite3
from prompt_toolkit import prompt, AbortAction
from prompt_toolkit.history import InMemoryHistory
from prompt_toolkit.contrib.completers import WordCompleter
from pygments.lexers import SqlLexer
from pygments.style import Style
from pygments.token import Token
from pygments.styles.default import DefaultStyle
sql_completer = WordCompleter(['create', 'select', 'insert', 'drop',
'delete', 'from', 'where', 'table'], ignore_case=True)
class DocumentStyle(Style):
styles = {
Token.Menu.Completions.Completion.Current: 'bg:#00aaaa #000000',
Token.Menu.Completions.Completion: 'bg:#008888 #ffffff',
Token.Menu.Completions.ProgressButton: 'bg:#003333',
Token.Menu.Completions.ProgressBar: 'bg:#00aaaa',
}
styles.update(DefaultStyle.styles)
def main(database):
history = InMemoryHistory()
connection = sqlite3.connect(database)
while True:
try:
text = prompt('> ', lexer=SqlLexer, completer=sql_completer,
style=DocumentStyle, history=history,
on_abort=AbortAction.RETRY)
except EOFError:
break # Control-D pressed.
with connection:
messages = connection.execute(text)
for message in messages:
print(message)
print('GoodBye!')
if __name__ == '__main__':
if len(sys.argv) < 2:
db = ':memory:'
else:
db = sys.argv[1]
main(db)
|
希望这篇文章能给你一些启发去构建命令行工具
以上
附录
unicode
在python2中使用from __future__ import unicode_literals
,这样一来所有字符串将被解释为unicode,无论是否有u''
,这样一来和python3保持了一致
example
python-prompt-toolkit的教程写得极好,通过examples,花很短的时间,我们就能学会如何使用python-prompt-toolkit的丰富特性