[lldb-dev] small Editline wrapper cleanup req for feedback
Neal Sidhwaney via lldb-dev
lldb-dev at lists.llvm.org
Wed May 5 23:30:48 PDT 2021
Sounds great. It’ll be useful to combine the function to describe EditLine commands, help text, and their callbacks with the logic to register keyboard commands for them, as well, so I’ll do both.
However, I couldn’t make the member function pointer a function argument, because then the lambda has to capture it, which made it uncastable to the signature for a libedit callback, a C function pointer.
Thanks,
Neal
> On May 4, 2021, at 4:42 PM, Greg Clayton <clayborg at gmail.com> wrote:
>
> As long as the solution matches "EditLine *" (C struct type from edit line library) to back to the C++ instance of "Editline" (lower case ell in "line" from LLDB). It should be easy to do with a template.
>
> I am fine with any new solution that makes it easier to add new commands. I would rather have a templated function argument over a template argument if possible. I am thinking of something like:
>
> createEditLineCommandDescriptor(“Command1", “Command1 help", &Foo::Foo1);
> createEditLineCommandDescriptor(“Command2", “Command2 help", &Foo::Bar);
>
> as I find it more readable.
>
> Greg
>
>> On Apr 30, 2021, at 9:35 PM, Neal Sidhwaney via lldb-dev <lldb-dev at lists.llvm.org <mailto:lldb-dev at lists.llvm.org>> wrote:
>>
>> Some comments in https://reviews.llvm.org/rGfd89af6880f33ead708abe2f7d88ecb687d4e0d2 <https://reviews.llvm.org/rGfd89af6880f33ead708abe2f7d88ecb687d4e0d2> prompted me to look more into potential simplifications of our EditLine wrapper and I wanted to run this by anyone who is interested before making the changes.
>>
>> Right now we set a bunch of callbacks in libedit that are captureless lambdas implicitly converted to C function pointers. The lambdas look up an instance of our Editline class and invoke member functions. The boilerplate that could be generated by templates is something like the following:
>>
>> class Foo { // Imagine this is our Editline class that wraps libedit
>> public:
>> unsigned char Foo1(int ch) { // These are member functions invoked by lambdas we pass to libedit
>> return 'a';
>> }
>> unsigned char Bar(int ch) {
>> return 'b';
>> }
>> unsigned char Baz(int ch) {
>> return 'c';
>> }
>> };
>>
>> typedef unsigned char (*elFnPtr)(EditLine*, int); // Signature of callbacks libedit takes (note Edit__L__ine is libedit, and Edit__l__ine is our wrapper)
>> typedef unsigned char (Foo::*FooMemPtr)(int ch); // Signature of member functions invoked
>>
>> template<FooMemPtr callback, typename Fn = elFnPtr>
>> tuple<const char*, const char*, Fn> createEditLineCommandDescriptor(const char* command, const char* helpText) {
>> return make_tuple(command, helpText, [] (EditLine*, int ch) {
>> cout << ch;
>> Foo foo;
>> ((&foo)->*callback)('a');
>> return (unsigned char) ch;
>> });
>> }
>>
>> auto editlineCommands = {
>> createEditLineCommandDescriptor<&Foo::Foo1>(“Command1", “Command1 help"),
>> createEditLineCommandDescriptor<&Foo::Bar>(“Command2", “Command2 help")
>> };
>>
>> for (auto editlineCommand : editLineCommands) {
>> // call into libedit to add editlineCommand, e.g.:
>> el_set(EL_ADDFN, editlineCommand.get<0>(), editLineCommand.get<1>(), editLineCommand.get<2>());
>> }
>>
>> The pointer to member function is a type parameter because otherwise the compiler complains about the lambda needing to capture it, in which case we could not pass it to libedit.
>>
>> I also plan to look into the wchar_t/char preprocessor logic that the original comment brought up but then I got distracted by shiny template stuff ;-)
>>
>> Thanks!
>>
>> Neal
>> _______________________________________________
>> lldb-dev mailing list
>> lldb-dev at lists.llvm.org <mailto:lldb-dev at lists.llvm.org>
>> https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-dev/attachments/20210506/74cf061b/attachment.html>
More information about the lldb-dev
mailing list