auto_suggest.py 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. """
  2. `Fish-style <http://fishshell.com/>`_ like auto-suggestion.
  3. While a user types input in a certain buffer, suggestions are generated
  4. (asynchronously.) Usually, they are displayed after the input. When the cursor
  5. presses the right arrow and the cursor is at the end of the input, the
  6. suggestion will be inserted.
  7. """
  8. from __future__ import unicode_literals
  9. from abc import ABCMeta, abstractmethod
  10. from six import with_metaclass
  11. from .filters import to_cli_filter
  12. __all__ = (
  13. 'Suggestion',
  14. 'AutoSuggest',
  15. 'AutoSuggestFromHistory',
  16. 'ConditionalAutoSuggest',
  17. )
  18. class Suggestion(object):
  19. """
  20. Suggestion returned by an auto-suggest algorithm.
  21. :param text: The suggestion text.
  22. """
  23. def __init__(self, text):
  24. self.text = text
  25. def __repr__(self):
  26. return 'Suggestion(%s)' % self.text
  27. class AutoSuggest(with_metaclass(ABCMeta, object)):
  28. """
  29. Base class for auto suggestion implementations.
  30. """
  31. @abstractmethod
  32. def get_suggestion(self, cli, buffer, document):
  33. """
  34. Return `None` or a :class:`.Suggestion` instance.
  35. We receive both ``buffer`` and ``document``. The reason is that auto
  36. suggestions are retrieved asynchronously. (Like completions.) The
  37. buffer text could be changed in the meantime, but ``document`` contains
  38. the buffer document like it was at the start of the auto suggestion
  39. call. So, from here, don't access ``buffer.text``, but use
  40. ``document.text`` instead.
  41. :param buffer: The :class:`~prompt_toolkit.buffer.Buffer` instance.
  42. :param document: The :class:`~prompt_toolkit.document.Document` instance.
  43. """
  44. class AutoSuggestFromHistory(AutoSuggest):
  45. """
  46. Give suggestions based on the lines in the history.
  47. """
  48. def get_suggestion(self, cli, buffer, document):
  49. history = buffer.history
  50. # Consider only the last line for the suggestion.
  51. text = document.text.rsplit('\n', 1)[-1]
  52. # Only create a suggestion when this is not an empty line.
  53. if text.strip():
  54. # Find first matching line in history.
  55. for string in reversed(list(history)):
  56. for line in reversed(string.splitlines()):
  57. if line.startswith(text):
  58. return Suggestion(line[len(text):])
  59. class ConditionalAutoSuggest(AutoSuggest):
  60. """
  61. Auto suggest that can be turned on and of according to a certain condition.
  62. """
  63. def __init__(self, auto_suggest, filter):
  64. assert isinstance(auto_suggest, AutoSuggest)
  65. self.auto_suggest = auto_suggest
  66. self.filter = to_cli_filter(filter)
  67. def get_suggestion(self, cli, buffer, document):
  68. if self.filter(cli):
  69. return self.auto_suggest.get_suggestion(cli, buffer, document)