SuggestionManager.h 4.2 KB

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