diff options
Diffstat (limited to 'examples/prompts/regular-language.py')
-rwxr-xr-x | examples/prompts/regular-language.py | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/examples/prompts/regular-language.py b/examples/prompts/regular-language.py new file mode 100755 index 0000000..cbe7256 --- /dev/null +++ b/examples/prompts/regular-language.py @@ -0,0 +1,108 @@ +#!/usr/bin/env python +""" +This is an example of "prompt_toolkit.contrib.regular_languages" which +implements a little calculator. + +Type for instance:: + + > add 4 4 + > sub 4 4 + > sin 3.14 + +This example shows how you can define the grammar of a regular language and how +to use variables in this grammar with completers and tokens attached. +""" +import math + +from prompt_toolkit import prompt +from prompt_toolkit.completion import WordCompleter +from prompt_toolkit.contrib.regular_languages.compiler import compile +from prompt_toolkit.contrib.regular_languages.completion import GrammarCompleter +from prompt_toolkit.contrib.regular_languages.lexer import GrammarLexer +from prompt_toolkit.lexers import SimpleLexer +from prompt_toolkit.styles import Style + +operators1 = ["add", "sub", "div", "mul"] +operators2 = ["cos", "sin"] + + +def create_grammar(): + return compile( + r""" + (\s* (?P<operator1>[a-z]+) \s+ (?P<var1>[0-9.]+) \s+ (?P<var2>[0-9.]+) \s*) | + (\s* (?P<operator2>[a-z]+) \s+ (?P<var1>[0-9.]+) \s*) + """ + ) + + +example_style = Style.from_dict( + { + "operator": "#33aa33 bold", + "number": "#ff0000 bold", + "trailing-input": "bg:#662222 #ffffff", + } +) + + +if __name__ == "__main__": + g = create_grammar() + + lexer = GrammarLexer( + g, + lexers={ + "operator1": SimpleLexer("class:operator"), + "operator2": SimpleLexer("class:operator"), + "var1": SimpleLexer("class:number"), + "var2": SimpleLexer("class:number"), + }, + ) + + completer = GrammarCompleter( + g, + { + "operator1": WordCompleter(operators1), + "operator2": WordCompleter(operators2), + }, + ) + + try: + # REPL loop. + while True: + # Read input and parse the result. + text = prompt( + "Calculate: ", lexer=lexer, completer=completer, style=example_style + ) + m = g.match(text) + if m: + vars = m.variables() + else: + print("Invalid command\n") + continue + + print(vars) + if vars.get("operator1") or vars.get("operator2"): + try: + var1 = float(vars.get("var1", 0)) + var2 = float(vars.get("var2", 0)) + except ValueError: + print("Invalid command (2)\n") + continue + + # Turn the operator string into a function. + operator = { + "add": (lambda a, b: a + b), + "sub": (lambda a, b: a - b), + "mul": (lambda a, b: a * b), + "div": (lambda a, b: a / b), + "sin": (lambda a, b: math.sin(a)), + "cos": (lambda a, b: math.cos(a)), + }[vars.get("operator1") or vars.get("operator2")] + + # Execute and print the result. + print("Result: %s\n" % (operator(var1, var2))) + + elif vars.get("operator2"): + print("Operator 2") + + except EOFError: + pass |