system.py 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. from __future__ import annotations
  2. from prompt_toolkit.completion.filesystem import ExecutableCompleter, PathCompleter
  3. from prompt_toolkit.contrib.regular_languages.compiler import compile
  4. from prompt_toolkit.contrib.regular_languages.completion import GrammarCompleter
  5. __all__ = [
  6. "SystemCompleter",
  7. ]
  8. class SystemCompleter(GrammarCompleter):
  9. """
  10. Completer for system commands.
  11. """
  12. def __init__(self) -> None:
  13. # Compile grammar.
  14. g = compile(
  15. r"""
  16. # First we have an executable.
  17. (?P<executable>[^\s]+)
  18. # Ignore literals in between.
  19. (
  20. \s+
  21. ("[^"]*" | '[^']*' | [^'"]+ )
  22. )*
  23. \s+
  24. # Filename as parameters.
  25. (
  26. (?P<filename>[^\s]+) |
  27. "(?P<double_quoted_filename>[^\s]+)" |
  28. '(?P<single_quoted_filename>[^\s]+)'
  29. )
  30. """,
  31. escape_funcs={
  32. "double_quoted_filename": (lambda string: string.replace('"', '\\"')),
  33. "single_quoted_filename": (lambda string: string.replace("'", "\\'")),
  34. },
  35. unescape_funcs={
  36. "double_quoted_filename": (
  37. lambda string: string.replace('\\"', '"')
  38. ), # XXX: not entirely correct.
  39. "single_quoted_filename": (lambda string: string.replace("\\'", "'")),
  40. },
  41. )
  42. # Create GrammarCompleter
  43. super().__init__(
  44. g,
  45. {
  46. "executable": ExecutableCompleter(),
  47. "filename": PathCompleter(only_directories=False, expanduser=True),
  48. "double_quoted_filename": PathCompleter(
  49. only_directories=False, expanduser=True
  50. ),
  51. "single_quoted_filename": PathCompleter(
  52. only_directories=False, expanduser=True
  53. ),
  54. },
  55. )