一个极简的REPL交互示范

  1. 示例
    1. 基本命令行与回显
    2. 添加分页效果
    3. 历史命令推荐
    4. 关键词补全
      1. WordCompleter
      2. fuzzyfinder
    5. 语法高亮

一个好的REPL(Read-Eval-Print Loop),交互式命令行程序,需要具备以下几个特点:

  1. 最基本的命令行与回显
  2. 回显带有分页效果,类似 more
  3. 带有历史命令推荐
  4. 关键词自动补全
  5. 语法高亮

示例

我们以模拟Sql的REPL来将这些特性一点点来累加起来

基本命令行与回显

from prompt_toolkit import prompt

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

添加分页效果

使用的是click.echo_via_pager

from prompt_toolkit import prompt
import click

while 1: user_input = prompt('>') click.echo_via_pager(user_input)

历史命令推荐

使用的是 prompt_toolkit.history 模块中的 FileHistory
会创建一个历史记录的文件,然后通过prompt_toolkit.auto_suggest.AutoSugguestFromHistory进行推荐。

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

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

关键词补全

关键词补全有两种方法:

  1. prompt_toolkit.completion.WordCompleter 直接定义单词
  2. prompt_toolkit.completion 中的 CompleterCompletion配合fuzzyfinder进行模糊查询,这种方法自定义程度更高

WordCompleter

from prompt_toolkit import prompt
from prompt_toolkit.history import FileHistory
from prompt_toolkit.auto_suggest import AutoSuggestFromHistory
import click
from prompt_toolkit.completion import WordCompleter

SQLCompleter = WordCompleter( ['select', 'from', 'insert', 'update', 'delete', 'drop'], ignore_case=True)
while 1: user_input = prompt('>', history=FileHistory('history.txt'), auto_suggest=AutoSuggestFromHistory(), completer=SQLCompleter, ) click.echo_via_pager(user_input)

fuzzyfinder

from prompt_toolkit import prompt
from prompt_toolkit.history import FileHistory
from prompt_toolkit.auto_suggest import AutoSuggestFromHistory
import click
from prompt_toolkit.completion import Completer, Completion
from fuzzyfinder.main 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('>', history=FileHistory('history.txt'), auto_suggest=AutoSuggestFromHistory(), completer=SQLCompleter(), ) click.echo_via_pager(user_input)

语法高亮

高亮可以使用Pygments.lexers 模块

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

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('SQL>', history=FileHistory('history.txt'), auto_suggest=AutoSuggestFromHistory(), completer=SQLCompleter(), lexer=PygmentsLexer(SqlLexer) ) click.echo_via_pager(user_input)

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 365433079@qq.com