Index: lldb/include/lldb/Interpreter/CommandCompletions.h =================================================================== --- lldb/include/lldb/Interpreter/CommandCompletions.h +++ lldb/include/lldb/Interpreter/CommandCompletions.h @@ -38,10 +38,11 @@ eBreakpointCompletion = (1u << 10), eBreakpointNameCompletion = (1u << 11), eProcessPluginCompletion = (1u << 12), + eProcessIDCompletion = (1u << 13), // This item serves two purposes. It is the last element in the enum, so // you can add custom enums starting from here in your Option class. Also // if you & in this bit the base code will not process the option. - eCustomCompletion = (1u << 13) + eCustomCompletion = (1u << 14) }; static bool InvokeCommonCompletionCallbacks( @@ -98,6 +99,10 @@ static void ProcessPluginNames(CommandInterpreter &interpreter, CompletionRequest &request, SearchFilter *searcher); + + static void ProcessIDs(CommandInterpreter &interpreter, + CompletionRequest &request, + SearchFilter *searcher); }; } // namespace lldb_private Index: lldb/source/Commands/CommandCompletions.cpp =================================================================== --- lldb/source/Commands/CommandCompletions.cpp +++ lldb/source/Commands/CommandCompletions.cpp @@ -60,6 +60,7 @@ {eBreakpointCompletion, CommandCompletions::Breakpoints}, {eBreakpointNameCompletion, CommandCompletions::BreakpointNames}, {eProcessPluginCompletion, CommandCompletions::ProcessPluginNames}, + {eProcessIDCompletion, CommandCompletions::ProcessIDs}, {eNoCompletion, nullptr} // This one has to be last in the list. }; @@ -605,4 +606,26 @@ SearchFilter *searcher) { PluginManager::AutoCompleteProcessName(request.GetCursorArgumentPrefix(), request); +} + +void CommandCompletions::ProcessIDs(CommandInterpreter &interpreter, + CompletionRequest &request, + SearchFilter *searcher) { + lldb::PlatformSP platform_sp(interpreter.GetPlatform(true)); + if (!platform_sp) + return; + ProcessInstanceInfoList process_infos; + ProcessInstanceInfoMatch match_info; + platform_sp->FindProcesses(match_info, process_infos); + const size_t num_matches = process_infos.size(); + if (num_matches == 0) + return; + for (size_t i = 0; i < num_matches; ++i) { + const llvm::StringRef process_name = + process_infos[i].GetNameAsStringRef(); + if (process_name.empty()) + continue; + request.TryCompleteCurrentArg( + std::to_string(process_infos[i].GetProcessID()), process_name); + } } \ No newline at end of file Index: lldb/source/Commands/CommandObjectProcess.cpp =================================================================== --- lldb/source/Commands/CommandObjectProcess.cpp +++ lldb/source/Commands/CommandObjectProcess.cpp @@ -357,6 +357,12 @@ interpreter, CommandCompletions::eProcessPluginCompletion, request, nullptr); break; + + case 'p': + CommandCompletions::InvokeCommonCompletionCallbacks( + interpreter, CommandCompletions::eProcessIDCompletion, request, + nullptr); + break; } } Index: lldb/test/API/functionalities/completion/TestCompletion.py =================================================================== --- lldb/test/API/functionalities/completion/TestCompletion.py +++ lldb/test/API/functionalities/completion/TestCompletion.py @@ -5,6 +5,7 @@ import os +from multiprocessing import Process import lldb from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * @@ -92,6 +93,17 @@ self.complete_from_to('process ' + subcommand + ' mac', 'process ' + subcommand + ' mach-o-core') + def test_process_attach_dash_p(self): + def test(): + while True: + pass + + p = Process(target=test) + p.daemon = True + p.start() + self.complete_from_to('process attach -p ', [str(p.pid)]) + p.terminate() + def test_process_signal(self): # The tab completion for "process signal" won't work without a running process. self.complete_from_to('process signal ',