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@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@lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev

_______________________________________________
lldb-dev mailing list
lldb-dev@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev

Reply via email to