validation.py 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. """
  2. Validator for a regular langage.
  3. """
  4. from __future__ import unicode_literals
  5. from prompt_toolkit.validation import Validator, ValidationError
  6. from prompt_toolkit.document import Document
  7. from .compiler import _CompiledGrammar
  8. __all__ = (
  9. 'GrammarValidator',
  10. )
  11. class GrammarValidator(Validator):
  12. """
  13. Validator which can be used for validation according to variables in
  14. the grammar. Each variable can have its own validator.
  15. :param compiled_grammar: `GrammarCompleter` instance.
  16. :param validators: `dict` mapping variable names of the grammar to the
  17. `Validator` instances to be used for each variable.
  18. """
  19. def __init__(self, compiled_grammar, validators):
  20. assert isinstance(compiled_grammar, _CompiledGrammar)
  21. assert isinstance(validators, dict)
  22. self.compiled_grammar = compiled_grammar
  23. self.validators = validators
  24. def validate(self, document):
  25. # Parse input document.
  26. # We use `match`, not `match_prefix`, because for validation, we want
  27. # the actual, unambiguous interpretation of the input.
  28. m = self.compiled_grammar.match(document.text)
  29. if m:
  30. for v in m.variables():
  31. validator = self.validators.get(v.varname)
  32. if validator:
  33. # Unescape text.
  34. unwrapped_text = self.compiled_grammar.unescape(v.varname, v.value)
  35. # Create a document, for the completions API (text/cursor_position)
  36. inner_document = Document(unwrapped_text, len(unwrapped_text))
  37. try:
  38. validator.validate(inner_document)
  39. except ValidationError as e:
  40. raise ValidationError(
  41. cursor_position=v.start + e.cursor_position,
  42. message=e.message)
  43. else:
  44. raise ValidationError(cursor_position=len(document.text),
  45. message='Invalid command')