diff options
author | Raphael Isemann <teemperor@gmail.com> | 2019-08-27 11:32:22 +0000 |
---|---|---|
committer | Raphael Isemann <teemperor@gmail.com> | 2019-08-27 11:32:22 +0000 |
commit | 5edee822d2f80e23c9e465394bac6d9c31468406 (patch) | |
tree | ae5e04768f5a6f64bab9f0786945e12f0d330f2d | |
parent | b1f29cec251188a594148f7a53d063281d4ef155 (diff) | |
download | bcm5719-llvm-5edee822d2f80e23c9e465394bac6d9c31468406.tar.gz bcm5719-llvm-5edee822d2f80e23c9e465394bac6d9c31468406.zip |
[lldb] Allow partial completions to fix directory completion.
On the command line we usually insert a space after a completion to indicate that
the completion was successful. After the completion API refactoring, this also
happens with directories which essentially breaks file path completion (as
adding a space terminates the path and starts a new arg). This patch restores the old
behavior by again allowing partial completions. Also extends the iohandler
and SB API tests as the implementation for this is different in Editline
and SB API.
llvm-svn: 370043
5 files changed, 53 insertions, 9 deletions
diff --git a/lldb/include/lldb/Utility/CompletionRequest.h b/lldb/include/lldb/Utility/CompletionRequest.h index 88ee3344a3f..28ac78a8756 100644 --- a/lldb/include/lldb/Utility/CompletionRequest.h +++ b/lldb/include/lldb/Utility/CompletionRequest.h @@ -17,7 +17,15 @@ namespace lldb_private { enum class CompletionMode { + // The current token has been completed. Normal, + // The current token has been partially completed. This means that we found + // a completion, but that the completed token is still incomplete. Examples + // for this are file paths, where we want to complete "/bi" to "/bin/", but + // the file path token is still incomplete after the completion. Clients + // should not indicate to the user that this is a full completion (e.g. by + // not inserting the usual trailing space after a successful completion). + Partial, // The full line has been rewritten by the completion. RewriteLine, }; diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/completion/TestCompletion.py b/lldb/packages/Python/lldbsuite/test/functionalities/completion/TestCompletion.py index b95d490c887..0b5b3a416a0 100644 --- a/lldb/packages/Python/lldbsuite/test/functionalities/completion/TestCompletion.py +++ b/lldb/packages/Python/lldbsuite/test/functionalities/completion/TestCompletion.py @@ -137,6 +137,13 @@ class CommandLineCompletionTestCase(TestBase): self.complete_from_to('log enable lldb expr -f ' + src_dir, ['main.cpp']) + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_log_file(self): + # Complete in our source directory which contains a 'main.cpp' file. + src_dir = os.path.dirname(os.path.realpath(__file__)) + self.complete_from_to('log enable lldb expr -f ' + src_dir, + [src_dir + "/"]) + # <rdar://problem/11052829> @skipIfFreeBSD # timing out on the FreeBSD buildbot def test_infinite_loop_while_completing(self): diff --git a/lldb/packages/Python/lldbsuite/test/iohandler/completion/TestIOHandlerCompletion.py b/lldb/packages/Python/lldbsuite/test/iohandler/completion/TestIOHandlerCompletion.py index 26805bfb07c..a6748c65619 100644 --- a/lldb/packages/Python/lldbsuite/test/iohandler/completion/TestIOHandlerCompletion.py +++ b/lldb/packages/Python/lldbsuite/test/iohandler/completion/TestIOHandlerCompletion.py @@ -2,6 +2,8 @@ Test completion in our IOHandlers. """ +import os + import lldb from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * @@ -48,6 +50,18 @@ class IOHandlerCompletionTest(TestBase): self.expect_string(prompt + "register") self.child.send("\n") + # Try tab completing directories and files. Also tests the partial + # completion where LLDB shouldn't print a space after the directory + # completion (as it didn't completed the full token). + dir_without_slashes = os.path.realpath(os.path.dirname(__file__)).rstrip("/") + self.child.send("file " + dir_without_slashes + "\t") + self.expect_string("iohandler/completion/") + # If we get a correct partial completion without a trailing space, then this + # should complete the current test file. + self.child.send("TestIOHandler\t") + self.expect_string("TestIOHandlerCompletion.py") + self.child.send("\n") + # Start tab completion and abort showing more commands with 'n'. self.child.send("\t") self.expect_string("More (Y/n/a)") diff --git a/lldb/source/Commands/CommandCompletions.cpp b/lldb/source/Commands/CommandCompletions.cpp index a06f9a4db53..f00a35d3d81 100644 --- a/lldb/source/Commands/CommandCompletions.cpp +++ b/lldb/source/Commands/CommandCompletions.cpp @@ -87,10 +87,9 @@ void CommandCompletions::SourceFiles(CommandInterpreter &interpreter, } static void DiskFilesOrDirectories(const llvm::Twine &partial_name, - bool only_directories, StringList &matches, + bool only_directories, + CompletionRequest &request, TildeExpressionResolver &Resolver) { - matches.Clear(); - llvm::SmallString<256> CompletionBuffer; llvm::SmallString<256> Storage; partial_name.toVector(CompletionBuffer); @@ -124,7 +123,7 @@ static void DiskFilesOrDirectories(const llvm::Twine &partial_name, for (const auto &S : MatchSet) { Resolved = S.getKey(); path::append(Resolved, path::get_separator()); - matches.AppendString(Resolved); + request.AddCompletion(Resolved, "", CompletionMode::Partial); } } return; @@ -136,7 +135,7 @@ static void DiskFilesOrDirectories(const llvm::Twine &partial_name, if (FirstSep == llvm::StringRef::npos) { // Make sure it ends with a separator. path::append(CompletionBuffer, path::get_separator()); - matches.AppendString(CompletionBuffer); + request.AddCompletion(CompletionBuffer, "", CompletionMode::Partial); return; } @@ -217,17 +216,27 @@ static void DiskFilesOrDirectories(const llvm::Twine &partial_name, path::append(CompletionBuffer, path::get_separator()); } - matches.AppendString(CompletionBuffer); + CompletionMode mode = + is_dir ? CompletionMode::Partial : CompletionMode::Normal; + request.AddCompletion(CompletionBuffer, "", mode); } } +static void DiskFilesOrDirectories(const llvm::Twine &partial_name, + bool only_directories, StringList &matches, + TildeExpressionResolver &Resolver) { + CompletionResult result; + std::string partial_name_str = partial_name.str(); + CompletionRequest request(partial_name_str, partial_name_str.size(), result); + DiskFilesOrDirectories(partial_name, only_directories, request, Resolver); + result.GetMatches(matches); +} + static void DiskFilesOrDirectories(CompletionRequest &request, bool only_directories) { StandardTildeExpressionResolver resolver; - StringList matches; DiskFilesOrDirectories(request.GetCursorArgumentPrefix(), only_directories, - matches, resolver); - request.AddCompletions(matches); + request, resolver); } void CommandCompletions::DiskFiles(CommandInterpreter &interpreter, diff --git a/lldb/source/Host/common/Editline.cpp b/lldb/source/Host/common/Editline.cpp index a2e8773f8f1..0a95dffa40e 100644 --- a/lldb/source/Host/common/Editline.cpp +++ b/lldb/source/Host/common/Editline.cpp @@ -954,6 +954,12 @@ unsigned char Editline::TabCommand(int ch) { el_insertstr(m_editline, to_add.c_str()); break; } + case CompletionMode::Partial: { + std::string to_add = completion.GetCompletion(); + to_add = to_add.substr(request.GetCursorArgumentPrefix().size()); + el_insertstr(m_editline, to_add.c_str()); + break; + } case CompletionMode::RewriteLine: { el_deletestr(m_editline, line_info->cursor - line_info->buffer); el_insertstr(m_editline, completion.GetCompletion().c_str()); |