Add the ability to define custom completers to the parsed_cmd template. (#109062)

If your arguments or option values are of a type that naturally uses one
of our common completion mechanisms, you will get completion for free.
But if you have your own custom values or if you want to do fancy things
like have `break set -s foo.dylib -n ba<TAB>` only complete on symbols
in foo.dylib, you can use this new mechanism to achieve that.
This commit is contained in:
jimingham
2024-09-24 10:00:00 -07:00
committed by GitHub
parent c6bf59f26b
commit 04b443e778
14 changed files with 771 additions and 82 deletions

View File

@@ -667,6 +667,79 @@ lldb_private::python::SWIGBridge::LLDBSwigPythonGetRepeatCommandForScriptedComma
return result.Str().GetString().str();
}
StructuredData::DictionarySP
lldb_private::python::SWIGBridge::LLDBSwigPythonHandleArgumentCompletionForScriptedCommand(PyObject *implementor,
std::vector<llvm::StringRef> &args_vec, size_t args_pos, size_t pos_in_arg) {
PyErr_Cleaner py_err_cleaner(true);
PythonObject self(PyRefType::Borrowed, implementor);
auto pfunc = self.ResolveName<PythonCallable>("handle_argument_completion");
// If this isn't implemented, return an empty dict to signal falling back to default completion:
if (!pfunc.IsAllocated())
return {};
PythonList args_list(PyInitialValue::Empty);
for (auto elem : args_vec)
args_list.AppendItem(PythonString(elem));
PythonObject result = pfunc(args_list, PythonInteger(args_pos), PythonInteger(pos_in_arg));
// Returning None means do the ordinary completion
if (result.IsNone())
return {};
// Convert the return dictionary to a DictionarySP.
StructuredData::ObjectSP result_obj_sp = result.CreateStructuredObject();
if (!result_obj_sp)
return {};
StructuredData::DictionarySP dict_sp(new StructuredData::Dictionary(result_obj_sp));
if (dict_sp->GetType() == lldb::eStructuredDataTypeInvalid)
return {};
return dict_sp;
}
StructuredData::DictionarySP
lldb_private::python::SWIGBridge::LLDBSwigPythonHandleOptionArgumentCompletionForScriptedCommand(PyObject *implementor,
llvm::StringRef &long_option, size_t pos_in_arg) {
PyErr_Cleaner py_err_cleaner(true);
PythonObject self(PyRefType::Borrowed, implementor);
auto pfunc = self.ResolveName<PythonCallable>("handle_option_argument_completion");
// If this isn't implemented, return an empty dict to signal falling back to default completion:
if (!pfunc.IsAllocated())
return {};
PythonObject result = pfunc(PythonString(long_option), PythonInteger(pos_in_arg));
// Returning None means do the ordinary completion
if (result.IsNone())
return {};
// Returning a boolean:
// True means the completion was handled, but there were no completions
// False means that the completion was not handled, again, do the ordinary completion:
if (result.GetObjectType() == PyObjectType::Boolean) {
if (!result.IsTrue())
return {};
// Make up a completion dictionary with the right element:
StructuredData::DictionarySP dict_sp(new StructuredData::Dictionary());
dict_sp->AddBooleanItem("no-completion", true);
return dict_sp;
}
// Convert the return dictionary to a DictionarySP.
StructuredData::ObjectSP result_obj_sp = result.CreateStructuredObject();
if (!result_obj_sp)
return {};
StructuredData::DictionarySP dict_sp(new StructuredData::Dictionary(result_obj_sp));
if (dict_sp->GetType() == lldb::eStructuredDataTypeInvalid)
return {};
return dict_sp;
}
#include "lldb/Interpreter/CommandReturnObject.h"
bool lldb_private::python::SWIGBridge::LLDBSwigPythonCallParsedCommandObject(