SuggestionManager.h 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. /*
  2. * Copyright (c) 2020, the SerenityOS developers.
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/DeprecatedString.h>
  8. #include <AK/Forward.h>
  9. #include <AK/Utf32View.h>
  10. #include <AK/Utf8View.h>
  11. #include <LibLine/Style.h>
  12. namespace Line {
  13. // FIXME: These objects are pretty heavy since they store two copies of text
  14. // somehow get rid of one.
  15. struct CompletionSuggestion {
  16. private:
  17. struct ForSearchTag {
  18. };
  19. public:
  20. static constexpr ForSearchTag ForSearch {};
  21. // Intentionally not explicit. (To allow suggesting bare strings)
  22. CompletionSuggestion(DeprecatedString const& completion)
  23. : CompletionSuggestion(completion, ""sv, {})
  24. {
  25. }
  26. CompletionSuggestion(DeprecatedString const& completion, ForSearchTag)
  27. : text_string(completion)
  28. {
  29. }
  30. CompletionSuggestion(StringView completion, StringView trailing_trivia, StringView display_trivia = ""sv)
  31. : CompletionSuggestion(completion, trailing_trivia, display_trivia, {})
  32. {
  33. }
  34. CompletionSuggestion(StringView completion, StringView trailing_trivia, StringView display_trivia, Style style);
  35. bool operator==(CompletionSuggestion const& suggestion) const
  36. {
  37. return suggestion.text_string == text_string;
  38. }
  39. Vector<u32> text;
  40. Vector<u32> trailing_trivia;
  41. Vector<u32> display_trivia;
  42. Style style;
  43. size_t start_index { 0 };
  44. size_t input_offset { 0 };
  45. size_t static_offset { 0 };
  46. size_t invariant_offset { 0 };
  47. bool allow_commit_without_listing { true };
  48. Utf32View text_view;
  49. Utf32View trivia_view;
  50. Utf32View display_trivia_view;
  51. DeprecatedString text_string;
  52. DeprecatedString display_trivia_string;
  53. bool is_valid { false };
  54. };
  55. class SuggestionManager {
  56. friend class Editor;
  57. public:
  58. void set_suggestions(Vector<CompletionSuggestion>&& suggestions);
  59. void set_current_suggestion_initiation_index(size_t start_index);
  60. size_t count() const { return m_suggestions.size(); }
  61. size_t display_length() const { return m_last_shown_suggestion_display_length; }
  62. size_t start_index() const { return m_last_displayed_suggestion_index; }
  63. size_t next_index() const { return m_next_suggestion_index; }
  64. void set_start_index(size_t index) const { m_last_displayed_suggestion_index = index; }
  65. ErrorOr<size_t> for_each_suggestion(Function<ErrorOr<IterationDecision>(CompletionSuggestion const&, size_t)>) const;
  66. enum CompletionMode {
  67. DontComplete,
  68. CompletePrefix,
  69. ShowSuggestions,
  70. CycleSuggestions,
  71. };
  72. class CompletionAttemptResult {
  73. public:
  74. CompletionMode new_completion_mode;
  75. ssize_t new_cursor_offset { 0 };
  76. struct {
  77. size_t start;
  78. size_t end;
  79. } offset_region_to_remove { 0, 0 }; // The region to remove as defined by [start, end) translated by (old_cursor + new_cursor_offset)
  80. // This bit of data will be removed, but restored if the suggestion is rejected.
  81. size_t static_offset_from_cursor { 0 };
  82. Vector<Utf32View> insert {};
  83. Optional<Style> style_to_apply {};
  84. bool avoid_committing_to_single_suggestion { false };
  85. };
  86. CompletionAttemptResult attempt_completion(CompletionMode, size_t initiation_start_index);
  87. void next();
  88. void previous();
  89. CompletionSuggestion const& suggest();
  90. CompletionSuggestion const& current_suggestion() const { return m_last_shown_suggestion; }
  91. bool is_current_suggestion_complete() const { return m_last_shown_suggestion_was_complete; }
  92. void reset()
  93. {
  94. m_last_shown_suggestion = DeprecatedString::empty();
  95. m_last_shown_suggestion_display_length = 0;
  96. m_suggestions.clear();
  97. m_last_displayed_suggestion_index = 0;
  98. m_next_suggestion_index = 0;
  99. }
  100. private:
  101. SuggestionManager()
  102. {
  103. }
  104. Vector<CompletionSuggestion> m_suggestions;
  105. CompletionSuggestion m_last_shown_suggestion { DeprecatedString::empty() };
  106. size_t m_last_shown_suggestion_display_length { 0 };
  107. bool m_last_shown_suggestion_was_complete { false };
  108. mutable size_t m_next_suggestion_index { 0 };
  109. size_t m_largest_common_suggestion_prefix_length { 0 };
  110. mutable size_t m_last_displayed_suggestion_index { 0 };
  111. size_t m_selected_suggestion_index { 0 };
  112. };
  113. }