mirror of
https://github.com/intel/llvm.git
synced 2026-01-24 08:30:34 +08:00
Summary:
This patch adds a framework for adding descriptions to the command completions we provide.
It also adds descriptions for completed top-level commands so that we can test this code.
Completions are in general supposed to be displayed alongside the completion itself. The descriptions
can be used to provide additional information about the completion to the user. Examples for descriptions
are function signatures when completing function calls in the expression command or the binary name
when providing completion for a symbol.
There is still some boilerplate code from the old completion API left in LLDB (mostly because the respective
APIs are reused for non-completion related purposes, so the CompletionRequest doesn't make sense to be
used), so that's why I still had to change some function signatures. Also, as the old API only passes around a
list of matches, and the descriptions are for these functions just another list, I had to add some code that
essentially just ensures that both lists are always the same side (e.g. all the manual calls to
`descriptions->AddString(X)` below a `matches->AddString(Y)` call).
The initial command descriptions that come with this patch are just reusing the existing
short help that is already added in LLDB.
An example completion with descriptions looks like this:
```
(lldb) pl
Available completions:
platform -- Commands to manage and create platforms.
plugin -- Commands for managing LLDB plugins.
```
Reviewers: #lldb, jingham
Reviewed By: #lldb, jingham
Subscribers: jingham, JDevlieghere, lldb-commits
Differential Revision: https://reviews.llvm.org/D51175
llvm-svn: 342181
94 lines
3.6 KiB
C++
94 lines
3.6 KiB
C++
//===-- CompletionRequest.cpp -----------------------------------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "lldb/Utility/CompletionRequest.h"
|
|
|
|
using namespace lldb;
|
|
using namespace lldb_private;
|
|
|
|
CompletionRequest::CompletionRequest(llvm::StringRef command_line,
|
|
unsigned raw_cursor_pos,
|
|
int match_start_point,
|
|
int max_return_elements,
|
|
CompletionResult &result)
|
|
: m_command(command_line), m_raw_cursor_pos(raw_cursor_pos),
|
|
m_match_start_point(match_start_point),
|
|
m_max_return_elements(max_return_elements), m_result(result) {
|
|
|
|
// We parse the argument up to the cursor, so the last argument in
|
|
// parsed_line is the one containing the cursor, and the cursor is after the
|
|
// last character.
|
|
m_parsed_line = Args(command_line);
|
|
m_partial_parsed_line = Args(command_line.substr(0, raw_cursor_pos));
|
|
|
|
m_cursor_index = m_partial_parsed_line.GetArgumentCount() - 1;
|
|
|
|
if (m_cursor_index == -1)
|
|
m_cursor_char_position = 0;
|
|
else
|
|
m_cursor_char_position =
|
|
strlen(m_partial_parsed_line.GetArgumentAtIndex(m_cursor_index));
|
|
|
|
const char *cursor = command_line.data() + raw_cursor_pos;
|
|
if (raw_cursor_pos > 0 && cursor[-1] == ' ') {
|
|
// We are just after a space. If we are in an argument, then we will
|
|
// continue parsing, but if we are between arguments, then we have to
|
|
// complete whatever the next element would be. We can distinguish the two
|
|
// cases because if we are in an argument (e.g. because the space is
|
|
// protected by a quote) then the space will also be in the parsed
|
|
// argument...
|
|
|
|
const char *current_elem =
|
|
m_partial_parsed_line.GetArgumentAtIndex(m_cursor_index);
|
|
if (m_cursor_char_position == 0 ||
|
|
current_elem[m_cursor_char_position - 1] != ' ') {
|
|
m_parsed_line.InsertArgumentAtIndex(m_cursor_index + 1, llvm::StringRef(),
|
|
'\0');
|
|
m_cursor_index++;
|
|
m_cursor_char_position = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
std::string CompletionResult::Completion::GetUniqueKey() const {
|
|
|
|
// We build a unique key for this pair of completion:description. We
|
|
// prefix the key with the length of the completion string. This prevents
|
|
// that we could get any collisions from completions pairs such as these:
|
|
// "foo:", "bar" would be "foo:bar", but will now be: "4foo:bar"
|
|
// "foo", ":bar" would be "foo:bar", but will now be: "3foo:bar"
|
|
|
|
std::string result;
|
|
result.append(std::to_string(m_completion.size()));
|
|
result.append(m_completion);
|
|
result.append(m_descripton);
|
|
return result;
|
|
}
|
|
|
|
void CompletionResult::AddResult(llvm::StringRef completion,
|
|
llvm::StringRef description) {
|
|
Completion r(completion, description);
|
|
|
|
// Add the completion if we haven't seen the same value before.
|
|
if (m_added_values.insert(r.GetUniqueKey()).second)
|
|
m_results.push_back(r);
|
|
}
|
|
|
|
void CompletionResult::GetMatches(StringList &matches) const {
|
|
matches.Clear();
|
|
for (const Completion &completion : m_results)
|
|
matches.AppendString(completion.m_completion);
|
|
}
|
|
|
|
void CompletionResult::GetDescriptions(StringList &descriptions) const {
|
|
descriptions.Clear();
|
|
for (const Completion &completion : m_results)
|
|
descriptions.AppendString(completion.m_descripton);
|
|
}
|