CompletionRequest.h 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. //===-- CompletionRequest.h -------------------------------------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #ifndef LLDB_UTILITY_COMPLETIONREQUEST_H
  9. #define LLDB_UTILITY_COMPLETIONREQUEST_H
  10. #include "lldb/Utility/Args.h"
  11. #include "lldb/Utility/LLDBAssert.h"
  12. #include "lldb/Utility/StringList.h"
  13. #include "llvm/ADT/StringRef.h"
  14. #include "llvm/ADT/StringSet.h"
  15. namespace lldb_private {
  16. enum class CompletionMode {
  17. /// The current token has been completed. The client should indicate this
  18. /// to the user (usually this is done by adding a trailing space behind the
  19. /// token).
  20. /// Example: "command sub" -> "command subcommand " (note the trailing space).
  21. Normal,
  22. /// The current token has been partially completed. This means that we found
  23. /// a completion, but that the token is still incomplete. Examples
  24. /// for this are file paths, where we want to complete "/bi" to "/bin/", but
  25. /// the file path token is still incomplete after the completion. Clients
  26. /// should not indicate to the user that this is a full completion (e.g. by
  27. /// not inserting the usual trailing space after a successful completion).
  28. /// Example: "file /us" -> "file /usr/" (note the missing trailing space).
  29. Partial,
  30. /// The full line has been rewritten by the completion.
  31. /// Example: "alias name" -> "other_command full_name".
  32. RewriteLine,
  33. };
  34. class CompletionResult {
  35. public:
  36. /// A single completion and all associated data.
  37. class Completion {
  38. /// The actual text that should be completed. The meaning of this text
  39. /// is defined by the CompletionMode.
  40. /// \see m_mode
  41. std::string m_completion;
  42. /// The description that should be displayed to the user alongside the
  43. /// completion text.
  44. std::string m_descripton;
  45. CompletionMode m_mode;
  46. public:
  47. Completion(llvm::StringRef completion, llvm::StringRef description,
  48. CompletionMode mode)
  49. : m_completion(completion.str()), m_descripton(description.str()),
  50. m_mode(mode) {}
  51. const std::string &GetCompletion() const { return m_completion; }
  52. const std::string &GetDescription() const { return m_descripton; }
  53. CompletionMode GetMode() const { return m_mode; }
  54. /// Generates a string that uniquely identifies this completion result.
  55. std::string GetUniqueKey() const;
  56. };
  57. private:
  58. /// List of found completions.
  59. std::vector<Completion> m_results;
  60. /// A set of the unique keys of all found completions so far. Used to filter
  61. /// out duplicates.
  62. /// \see CompletionResult::Completion::GetUniqueKey
  63. llvm::StringSet<> m_added_values;
  64. public:
  65. void AddResult(llvm::StringRef completion, llvm::StringRef description,
  66. CompletionMode mode);
  67. llvm::ArrayRef<Completion> GetResults() const { return m_results; }
  68. /// Adds all collected completion matches to the given list.
  69. /// The list will be cleared before the results are added. The number of
  70. /// results here is guaranteed to be equal to GetNumberOfResults().
  71. void GetMatches(StringList &matches) const;
  72. /// Adds all collected completion descriptions to the given list.
  73. /// The list will be cleared before the results are added. The number of
  74. /// results here is guaranteed to be equal to GetNumberOfResults().
  75. void GetDescriptions(StringList &descriptions) const;
  76. std::size_t GetNumberOfResults() const { return m_results.size(); }
  77. };
  78. /// \class CompletionRequest CompletionRequest.h
  79. /// "lldb/Utility/ArgCompletionRequest.h"
  80. ///
  81. /// Contains all information necessary to complete an incomplete command
  82. /// for the user. Will be filled with the generated completions by the different
  83. /// completions functions.
  84. ///
  85. class CompletionRequest {
  86. public:
  87. /// Constructs a completion request.
  88. ///
  89. /// \param [in] command_line
  90. /// The command line the user has typed at this point.
  91. ///
  92. /// \param [in] raw_cursor_pos
  93. /// The position of the cursor in the command line string. Index 0 means
  94. /// the cursor is at the start of the line. The completion starts from
  95. /// this cursor position.
  96. ///
  97. /// \param [out] result
  98. /// The CompletionResult that will be filled with the results after this
  99. /// request has been handled.
  100. CompletionRequest(llvm::StringRef command_line, unsigned raw_cursor_pos,
  101. CompletionResult &result);
  102. /// Returns the raw user input used to create this CompletionRequest cut off
  103. /// at the cursor position. The cursor will be at the end of the raw line.
  104. llvm::StringRef GetRawLine() const {
  105. return m_command.substr(0, GetRawCursorPos());
  106. }
  107. /// Returns the full raw user input used to create this CompletionRequest.
  108. /// This string is not cut off at the cursor position and will include
  109. /// characters behind the cursor position.
  110. ///
  111. /// You should most likely *not* use this function unless the characters
  112. /// behind the cursor position influence the completion.
  113. llvm::StringRef GetRawLineWithUnusedSuffix() const { return m_command; }
  114. unsigned GetRawCursorPos() const { return m_raw_cursor_pos; }
  115. const Args &GetParsedLine() const { return m_parsed_line; }
  116. Args &GetParsedLine() { return m_parsed_line; }
  117. const Args::ArgEntry &GetParsedArg() {
  118. return GetParsedLine()[GetCursorIndex()];
  119. }
  120. /// Drops the first argument from the argument list.
  121. void ShiftArguments() {
  122. m_cursor_index--;
  123. m_parsed_line.Shift();
  124. }
  125. /// Adds an empty argument at the end of the argument list and moves
  126. /// the cursor to this new argument.
  127. void AppendEmptyArgument() {
  128. m_parsed_line.AppendArgument(llvm::StringRef());
  129. m_cursor_index++;
  130. m_cursor_char_position = 0;
  131. }
  132. size_t GetCursorIndex() const { return m_cursor_index; }
  133. /// Adds a possible completion string. If the completion was already
  134. /// suggested before, it will not be added to the list of results. A copy of
  135. /// the suggested completion is stored, so the given string can be free'd
  136. /// afterwards.
  137. ///
  138. /// \param completion The suggested completion.
  139. /// \param description An optional description of the completion string. The
  140. /// description will be displayed to the user alongside the completion.
  141. /// \param mode The CompletionMode for this completion.
  142. void AddCompletion(llvm::StringRef completion,
  143. llvm::StringRef description = "",
  144. CompletionMode mode = CompletionMode::Normal) {
  145. m_result.AddResult(completion, description, mode);
  146. }
  147. /// Adds a possible completion string if the completion would complete the
  148. /// current argument.
  149. ///
  150. /// \param completion The suggested completion.
  151. /// \param description An optional description of the completion string. The
  152. /// description will be displayed to the user alongside the completion.
  153. template <CompletionMode M = CompletionMode::Normal>
  154. void TryCompleteCurrentArg(llvm::StringRef completion,
  155. llvm::StringRef description = "") {
  156. // Trying to rewrite the whole line while checking for the current
  157. // argument never makes sense. Completion modes are always hardcoded, so
  158. // this can be a static_assert.
  159. static_assert(M != CompletionMode::RewriteLine,
  160. "Shouldn't rewrite line with this function");
  161. if (completion.startswith(GetCursorArgumentPrefix()))
  162. AddCompletion(completion, description, M);
  163. }
  164. /// Adds multiple possible completion strings.
  165. ///
  166. /// \param completions The list of completions.
  167. ///
  168. /// \see AddCompletion
  169. void AddCompletions(const StringList &completions) {
  170. for (const std::string &completion : completions)
  171. AddCompletion(completion);
  172. }
  173. /// Adds multiple possible completion strings alongside their descriptions.
  174. ///
  175. /// The number of completions and descriptions must be identical.
  176. ///
  177. /// \param completions The list of completions.
  178. /// \param descriptions The list of descriptions.
  179. ///
  180. /// \see AddCompletion
  181. void AddCompletions(const StringList &completions,
  182. const StringList &descriptions) {
  183. lldbassert(completions.GetSize() == descriptions.GetSize());
  184. for (std::size_t i = 0; i < completions.GetSize(); ++i)
  185. AddCompletion(completions.GetStringAtIndex(i),
  186. descriptions.GetStringAtIndex(i));
  187. }
  188. llvm::StringRef GetCursorArgumentPrefix() const {
  189. return GetParsedLine().GetArgumentAtIndex(GetCursorIndex());
  190. }
  191. private:
  192. /// The raw command line we are supposed to complete.
  193. llvm::StringRef m_command;
  194. /// The cursor position in m_command.
  195. unsigned m_raw_cursor_pos;
  196. /// The command line parsed as arguments.
  197. Args m_parsed_line;
  198. /// The index of the argument in which the completion cursor is.
  199. size_t m_cursor_index;
  200. /// The cursor position in the argument indexed by m_cursor_index.
  201. size_t m_cursor_char_position;
  202. /// The result this request is supposed to fill out.
  203. /// We keep this object private to ensure that no backend can in any way
  204. /// depend on already calculated completions (which would make debugging and
  205. /// testing them much more complicated).
  206. CompletionResult &m_result;
  207. };
  208. } // namespace lldb_private
  209. #endif // LLDB_UTILITY_COMPLETIONREQUEST_H