SuggestionManager.h 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  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(const String& completion)
  24. : CompletionSuggestion(completion, "", {})
  25. {
  26. }
  27. CompletionSuggestion(const String& completion, ForSearchTag)
  28. : text_string(completion)
  29. {
  30. }
  31. CompletionSuggestion(const StringView& completion, const StringView& trailing_trivia)
  32. : CompletionSuggestion(completion, trailing_trivia, {})
  33. {
  34. }
  35. CompletionSuggestion(const StringView& completion, const StringView& trailing_trivia, Style style);
  36. bool operator==(const CompletionSuggestion& suggestion) const
  37. {
  38. return suggestion.text_string == text_string;
  39. }
  40. Vector<u32> text;
  41. Vector<u32> trailing_trivia;
  42. Style style;
  43. size_t start_index { 0 };
  44. size_t input_offset { 0 };
  45. Utf32View text_view;
  46. Utf32View trivia_view;
  47. String text_string;
  48. bool is_valid { false };
  49. };
  50. class SuggestionManager {
  51. friend class Editor;
  52. public:
  53. void set_suggestions(Vector<CompletionSuggestion>&& suggestions);
  54. void set_current_suggestion_initiation_index(size_t start_index);
  55. size_t count() const { return m_suggestions.size(); }
  56. size_t display_length() const { return m_last_shown_suggestion_display_length; }
  57. size_t start_index() const { return m_last_displayed_suggestion_index; }
  58. size_t next_index() const { return m_next_suggestion_index; }
  59. void set_start_index(size_t index) const { m_last_displayed_suggestion_index = index; }
  60. size_t for_each_suggestion(Function<IterationDecision(const CompletionSuggestion&, size_t)>) const;
  61. enum CompletionMode {
  62. DontComplete,
  63. CompletePrefix,
  64. ShowSuggestions,
  65. CycleSuggestions,
  66. };
  67. class CompletionAttemptResult {
  68. public:
  69. CompletionMode new_completion_mode;
  70. ssize_t new_cursor_offset { 0 };
  71. struct {
  72. size_t start;
  73. size_t end;
  74. } offset_region_to_remove { 0, 0 }; // The region to remove as defined by [start, end) translated by (old_cursor + new_cursor_offset)
  75. Vector<Utf32View> insert {};
  76. Optional<Style> style_to_apply {};
  77. };
  78. CompletionAttemptResult attempt_completion(CompletionMode, size_t initiation_start_index);
  79. void next();
  80. void previous();
  81. void set_suggestion_variants(size_t static_offset, size_t invariant_offset, size_t suggestion_index) const
  82. {
  83. m_next_suggestion_index = suggestion_index;
  84. m_next_suggestion_static_offset = static_offset;
  85. m_next_suggestion_invariant_offset = invariant_offset;
  86. }
  87. const CompletionSuggestion& suggest();
  88. const CompletionSuggestion& current_suggestion() const { return m_last_shown_suggestion; }
  89. bool is_current_suggestion_complete() const { return m_last_shown_suggestion_was_complete; }
  90. void reset()
  91. {
  92. m_last_shown_suggestion = String::empty();
  93. m_last_shown_suggestion_display_length = 0;
  94. m_suggestions.clear();
  95. m_last_displayed_suggestion_index = 0;
  96. }
  97. private:
  98. SuggestionManager()
  99. {
  100. }
  101. Vector<CompletionSuggestion> m_suggestions;
  102. CompletionSuggestion m_last_shown_suggestion { String::empty() };
  103. size_t m_last_shown_suggestion_display_length { 0 };
  104. bool m_last_shown_suggestion_was_complete { false };
  105. mutable size_t m_next_suggestion_index { 0 };
  106. mutable size_t m_next_suggestion_invariant_offset { 0 };
  107. mutable size_t m_next_suggestion_static_offset { 0 };
  108. size_t m_largest_common_suggestion_prefix_length { 0 };
  109. mutable size_t m_last_displayed_suggestion_index { 0 };
  110. size_t m_selected_suggestion_index { 0 };
  111. };
  112. }