prompt.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. from __future__ import unicode_literals
  2. from six import text_type
  3. from prompt_toolkit.enums import IncrementalSearchDirection, SEARCH_BUFFER
  4. from prompt_toolkit.token import Token
  5. from .utils import token_list_len
  6. from .processors import Processor, Transformation
  7. __all__ = (
  8. 'DefaultPrompt',
  9. )
  10. class DefaultPrompt(Processor):
  11. """
  12. Default prompt. This one shows the 'arg' and reverse search like
  13. Bash/readline normally do.
  14. There are two ways to instantiate a ``DefaultPrompt``. For a prompt
  15. with a static message, do for instance::
  16. prompt = DefaultPrompt.from_message('prompt> ')
  17. For a dynamic prompt, generated from a token list function::
  18. def get_tokens(cli):
  19. return [(Token.A, 'text'), (Token.B, 'text2')]
  20. prompt = DefaultPrompt(get_tokens)
  21. """
  22. def __init__(self, get_tokens):
  23. assert callable(get_tokens)
  24. self.get_tokens = get_tokens
  25. @classmethod
  26. def from_message(cls, message='> '):
  27. """
  28. Create a default prompt with a static message text.
  29. """
  30. assert isinstance(message, text_type)
  31. def get_message_tokens(cli):
  32. return [(Token.Prompt, message)]
  33. return cls(get_message_tokens)
  34. def apply_transformation(self, cli, document, lineno, source_to_display, tokens):
  35. # Get text before cursor.
  36. if cli.is_searching:
  37. before = _get_isearch_tokens(cli)
  38. elif cli.input_processor.arg is not None:
  39. before = _get_arg_tokens(cli)
  40. else:
  41. before = self.get_tokens(cli)
  42. # Insert before buffer text.
  43. shift_position = token_list_len(before)
  44. # Only show the prompt before the first line. For the following lines,
  45. # only indent using spaces.
  46. if lineno != 0:
  47. before = [(Token.Prompt, ' ' * shift_position)]
  48. return Transformation(
  49. tokens=before + tokens,
  50. source_to_display=lambda i: i + shift_position,
  51. display_to_source=lambda i: i - shift_position)
  52. def has_focus(self, cli):
  53. # Obtain focus when the CLI is searching.
  54. # Usually, when using this `DefaultPrompt`, we don't have a
  55. # `BufferControl` instance that displays the content of the search
  56. # buffer. Instead the search text is displayed before the current text.
  57. # So, we can still show the cursor here, while it's actually not this
  58. # buffer that's focussed.
  59. return cli.is_searching
  60. def _get_isearch_tokens(cli):
  61. def before():
  62. if cli.search_state.direction == IncrementalSearchDirection.BACKWARD:
  63. text = 'reverse-i-search'
  64. else:
  65. text = 'i-search'
  66. return [(Token.Prompt.Search, '(%s)`' % text)]
  67. def text():
  68. return [(Token.Prompt.Search.Text, cli.buffers[SEARCH_BUFFER].text)]
  69. def after():
  70. return [(Token.Prompt.Search, '`: ')]
  71. return before() + text() + after()
  72. def _get_arg_tokens(cli):
  73. """
  74. Tokens for the arg-prompt.
  75. """
  76. arg = cli.input_processor.arg
  77. return [
  78. (Token.Prompt.Arg, '(arg: '),
  79. (Token.Prompt.Arg.Text, str(arg)),
  80. (Token.Prompt.Arg, ') '),
  81. ]