<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div class="">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. </div><div class=""><br class=""></div><div class="">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.</div><div class=""><br class=""></div><div class=""><div class="">Thanks,</div><div class=""><br class=""></div><div class="">Neal</div><div class=""><br class=""></div><div class=""><div class=""><div><blockquote type="cite" class=""><div class="">On May 4, 2021, at 4:42 PM, Greg Clayton <<a href="mailto:clayborg@gmail.com" class="">clayborg@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html; charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">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.<div class=""><br class=""></div><div class="">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:</div><div class=""><br class=""></div><div class="">createEditLineCommandDescriptor(“Command1", “Command1 help", &Foo::Foo1);</div><div class="">createEditLineCommandDescriptor(“Command2", “Command2 help", &Foo::Bar);</div><div class=""><br class=""><div class="">as I find it more readable.</div><div class=""><br class=""></div><div class="">Greg</div><div class=""><br class=""><blockquote type="cite" class=""><div class="">On Apr 30, 2021, at 9:35 PM, Neal Sidhwaney via lldb-dev <<a href="mailto:lldb-dev@lists.llvm.org" class="">lldb-dev@lists.llvm.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html; charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">Some comments in <a href="https://reviews.llvm.org/rGfd89af6880f33ead708abe2f7d88ecb687d4e0d2" class="">https://reviews.llvm.org/rGfd89af6880f33ead708abe2f7d88ecb687d4e0d2</a> 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.<div class=""><br class=""></div><div class="">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:</div><div class=""><br class=""></div><div class=""><font face="Courier New" class="">class Foo { // Imagine this is our Editline class that wraps libedit<br class="">public:<br class=""> unsigned char Foo1(int ch) { // These are member functions invoked by lambdas we pass to libedit<br class=""> return 'a';<br class=""> }<br class=""> unsigned char Bar(int ch) {<br class=""> return 'b';<br class=""> }<br class=""> unsigned char Baz(int ch) {<br class=""> return 'c';<br class=""> }<br class="">};<br class=""></font><br class=""></div><div class=""><div class=""><font face="Courier New" class="">typedef unsigned char (*elFnPtr)(EditLine*, int); // Signature of callbacks libedit takes (note Edit__L__ine is libedit, and Edit__l__ine is our wrapper)</font></div><div class=""><font face="Courier New" class="">typedef unsigned char (Foo::*FooMemPtr)(int ch); // Signature of member functions invoked</font></div><div class=""><font face="Courier New" class=""><br class=""></font></div><div class=""><font face="Courier New" class="">template<FooMemPtr callback, typename Fn = elFnPtr></font></div><div class=""><font face="Courier New" class="">tuple<const char*, const char*, Fn> createEditLineCommandDescriptor(const char* command, const char* helpText) {</font></div><div class=""><font face="Courier New" class=""> return make_tuple(command, helpText, [] (EditLine*, int ch) {</font></div><div class=""><font face="Courier New" class=""> cout << ch;</font></div><div class=""><font face="Courier New" class=""> Foo foo;</font></div><div class=""><font face="Courier New" class=""> ((&foo)->*callback)('a');</font></div><div class=""><font face="Courier New" class=""> return (unsigned char) ch;</font></div><div class=""><font face="Courier New" class=""> });</font></div><div class=""><font face="Courier New" class="">}</font></div><div class=""><font face="Courier New" class=""><br class=""></font></div><div class=""><font face="Courier New" class="">auto editlineCommands = {</font></div><div class=""><font face="Courier New" class=""> createEditLineCommandDescriptor<&Foo::Foo1>(“Command1", “Command1 help"),</font></div><div class=""><font face="Courier New" class=""> createEditLineCommandDescriptor<&Foo::Bar>(“Command2", “Command2 help")</font></div><div class=""><font face="Courier New" class="">};</font></div></div><div class=""><br class=""></div><div class=""><font face="Courier New" class="">for (auto editlineCommand : editLineCommands) {</font></div><div class=""><font face="Courier New" class=""> // call into libedit to add editlineCommand, e.g.:</font></div><div class=""><font face="Courier New" class=""> el_set(EL_ADDFN, editlineCommand.get<0>(), editLineCommand.get<1>(), editLineCommand.get<2>());</font></div><div class=""><font face="Courier New" class="">}</font></div><div class=""><br class=""></div><div class="">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.</div><div class=""><br class=""></div><div class="">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 ;-)</div><div class=""><br class=""></div><div class="">Thanks!</div><div class=""><br class=""></div><div class="">Neal</div></div>_______________________________________________<br class="">lldb-dev mailing list<br class=""><a href="mailto:lldb-dev@lists.llvm.org" class="">lldb-dev@lists.llvm.org</a><br class=""><a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev" class="">https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev</a><br class=""></div></blockquote></div><br class=""></div></div></div></blockquote></div><br class=""></div></div></div></body></html>