<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="">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>as I find it more readable.</div><div><br class=""></div><div>Greg</div><div><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="">https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev<br class=""></div></blockquote></div><br class=""></div></body></html>