[Lldb-commits] [PATCH] D108545: [LLDB][GUI] Add initial searcher support
OmarEmaraDev created this revision. OmarEmaraDev added a reviewer: clayborg. Herald added a reviewer: teemperor. OmarEmaraDev requested review of this revision. Herald added a project: LLDB. Herald added a subscriber: lldb-commits. This patch adds a new type of reusable UI components. Searcher Windows contain a text field to enter a search keyword and a list of scrollable matches are presented. The target match can be selected and executed which invokes a user callback to do something with the match. This patch also adds one searcher delegate, which wraps the common command completion searchers for simple use cases. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D108545 Files: lldb/source/Core/IOHandlerCursesGUI.cpp Index: lldb/source/Core/IOHandlerCursesGUI.cpp === --- lldb/source/Core/IOHandlerCursesGUI.cpp +++ lldb/source/Core/IOHandlerCursesGUI.cpp @@ -3558,6 +3558,232 @@ EnvironmentVariableListFieldDelegate *m_inherited_environment_field; }; + +// Searchers + + +class SearcherDelegate { +public: + SearcherDelegate() {} + + virtual ~SearcherDelegate() = default; + + virtual int GetNumberOfMatches() = 0; + + // Get the string that will be displayed for the match at the input index. + virtual const std::string &GetMatchTextAtIndex(int index) = 0; + + // Update the matches of the search. This is executed every time the text + // field handles an event. + virtual void UpdateMatches(const std::string &text) = 0; + + // Execute the user callback given the index of some match. This is executed + // once the user selects a match. + virtual void ExecuteCallback(int match_index) = 0; +}; + +typedef std::shared_ptr SearcherDelegateSP; + +class SearcherWindowDelegate : public WindowDelegate { +public: + SearcherWindowDelegate(SearcherDelegateSP &delegate_sp) + : m_delegate_sp(delegate_sp), m_text_field("Search", "", false), +m_selected_match(0), m_first_visible_match(0) { +; + } + + // A completion window is padded by one character from all sides. A text field + // is first drawn for inputting the searcher request, then a list of matches + // are displayed in a scrollable list. + // + // ___ + // | | + // | __[Search]___ | + // | | | | + // | |___| | + // | - Match 1.| + // | - Match 2.| + // | - ... | + // | | + // |[Press Esc to Cancel]__| + // + + // Get the index of the last visible match. Assuming at least one match + // exists. + int GetLastVisibleMatch(int height) { +int index = m_first_visible_match + height; +return std::min(index, m_delegate_sp->GetNumberOfMatches()) - 1; + } + + int GetNumberOfVisibleMatches(int height) { +return GetLastVisibleMatch(height) - m_first_visible_match + 1; + } + + void UpdateScrolling(Surface &surface) { +if (m_selected_match < m_first_visible_match) { + m_first_visible_match = m_selected_match; + return; +} + +int height = surface.GetHeight(); +int last_visible_match = GetLastVisibleMatch(height); +if (m_selected_match > last_visible_match) { + m_first_visible_match = m_selected_match - height + 1; +} + } + + void DrawMatches(Surface &surface) { +if (m_delegate_sp->GetNumberOfMatches() == 0) + return; + +UpdateScrolling(surface); + +int count = GetNumberOfVisibleMatches(surface.GetHeight()); +for (int i = 0; i < count; i++) { + surface.MoveCursor(1, i); + int current_match = m_first_visible_match + i; + if (current_match == m_selected_match) +surface.AttributeOn(A_REVERSE); + surface.PutCString( + m_delegate_sp->GetMatchTextAtIndex(current_match).c_str()); + if (current_match == m_selected_match) +surface.AttributeOff(A_REVERSE); +} + } + + void DrawContent(Surface &surface) { +Rect content_bounds = surface.GetFrame(); +Rect text_field_bounds, matchs_bounds; +content_bounds.HorizontalSplit(m_text_field.FieldDelegateGetHeight(), + text_field_bounds, matchs_bounds); +Surface text_field_surface = surface.SubSurface(text_field_bounds); +Surface matches_surface = surface.SubSurface(matchs_bounds); + +m_text_field.FieldDelegateDraw(text_field_surface, true); +DrawMatches(matches_surface); + } + + bool WindowDelegateDraw(Window &window, bool force) override { +window.Erase(); + +window.DrawTitleBox(window.GetName(), "Press Esc to Cancel"); + +Rect content_bounds = window.GetFrame(); +content_bounds.Inset(2,
[Lldb-commits] [PATCH] D108545: [LLDB][GUI] Add initial searcher support
OmarEmaraDev added a comment. Herald added a subscriber: JDevlieghere. An example searcher window for source files: F18633042: 20210823-141344.mp4 <https://reviews.llvm.org/F18633042> Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D108545/new/ https://reviews.llvm.org/D108545 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D108548: [lldb] Support "eflags" register name in generic reg fallback
mgorny created this revision. mgorny added reviewers: labath, krytarowski, jasonmolenda, JDevlieghere, emaste. mgorny requested review of this revision. Enhance the generic register fallback code to support "eflags" register name in addition to "rflags", as the former is used by gdbserver. This permits lldb-server to recognize the generic flags register when interfacing with gdbserver-style target.xml (i.e. without generic="" attributes), and therefore aligns ABI plugins' AugmentRegisterInfo() between lldb-server and gdbserver. https://reviews.llvm.org/D108548 Files: lldb/source/Plugins/ABI/X86/ABISysV_x86_64.cpp lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp Index: lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp === --- lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp +++ lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp @@ -603,6 +603,7 @@ (strcmp(reg.name, "fp") == 0)) reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; else if ((strcmp(reg.name, "rflags") == 0) || + (strcmp(reg.name, "eflags") == 0) || (strcmp(reg.name, "flags") == 0)) reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS; } Index: lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp === --- lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp +++ lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp @@ -806,6 +806,8 @@ .Case("rsp", LLDB_REGNUM_GENERIC_SP) .Case("rbp", LLDB_REGNUM_GENERIC_FP) .Case("rflags", LLDB_REGNUM_GENERIC_FLAGS) + // gdbserver uses eflags + .Case("eflags", LLDB_REGNUM_GENERIC_FLAGS) .Case("rcx", LLDB_REGNUM_GENERIC_ARG1) .Case("rdx", LLDB_REGNUM_GENERIC_ARG2) .Case("r8", LLDB_REGNUM_GENERIC_ARG3) Index: lldb/source/Plugins/ABI/X86/ABISysV_x86_64.cpp === --- lldb/source/Plugins/ABI/X86/ABISysV_x86_64.cpp +++ lldb/source/Plugins/ABI/X86/ABISysV_x86_64.cpp @@ -933,6 +933,8 @@ .Case("rsp", LLDB_REGNUM_GENERIC_SP) .Case("rbp", LLDB_REGNUM_GENERIC_FP) .Case("rflags", LLDB_REGNUM_GENERIC_FLAGS) + // gdbserver uses eflags + .Case("eflags", LLDB_REGNUM_GENERIC_FLAGS) .Case("rdi", LLDB_REGNUM_GENERIC_ARG1) .Case("rsi", LLDB_REGNUM_GENERIC_ARG2) .Case("rdx", LLDB_REGNUM_GENERIC_ARG3) Index: lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp === --- lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp +++ lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp @@ -603,6 +603,7 @@ (strcmp(reg.name, "fp") == 0)) reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; else if ((strcmp(reg.name, "rflags") == 0) || + (strcmp(reg.name, "eflags") == 0) || (strcmp(reg.name, "flags") == 0)) reg.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS; } Index: lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp === --- lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp +++ lldb/source/Plugins/ABI/X86/ABIWindows_x86_64.cpp @@ -806,6 +806,8 @@ .Case("rsp", LLDB_REGNUM_GENERIC_SP) .Case("rbp", LLDB_REGNUM_GENERIC_FP) .Case("rflags", LLDB_REGNUM_GENERIC_FLAGS) + // gdbserver uses eflags + .Case("eflags", LLDB_REGNUM_GENERIC_FLAGS) .Case("rcx", LLDB_REGNUM_GENERIC_ARG1) .Case("rdx", LLDB_REGNUM_GENERIC_ARG2) .Case("r8", LLDB_REGNUM_GENERIC_ARG3) Index: lldb/source/Plugins/ABI/X86/ABISysV_x86_64.cpp === --- lldb/source/Plugins/ABI/X86/ABISysV_x86_64.cpp +++ lldb/source/Plugins/ABI/X86/ABISysV_x86_64.cpp @@ -933,6 +933,8 @@ .Case("rsp", LLDB_REGNUM_GENERIC_SP) .Case("rbp", LLDB_REGNUM_GENERIC_FP) .Case("rflags", LLDB_REGNUM_GENERIC_FLAGS) + // gdbserver uses eflags + .Case("eflags", LLDB_REGNUM_GENERIC_FLAGS) .Case("rdi", LLDB_REGNUM_GENERIC_ARG1) .Case("rsi", LLDB_REGNUM_GENERIC_ARG2) .Case("rdx", LLDB_REGNUM_GENERIC_ARG3) ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D108554: [lldb] Support querying registers via generic names without alt_names
mgorny created this revision. mgorny added reviewers: labath, emaste, krytarowski, jasonmolenda, JDevlieghere. mgorny requested review of this revision. Update GetRegisterInfoByName() methods to support getting registers by a generic name independently of alt_name entries in the register context. This makes it possible to use generic names when interacting with gdbserver (that does not supply alt_names). It also makes it possible to remove some of the duplicated information from register context declarations and/or use alt_names for another purpose. https://reviews.llvm.org/D108554 Files: lldb/source/Host/common/NativeRegisterContext.cpp lldb/source/Target/RegisterContext.cpp lldb/test/API/functionalities/gdb_remote_client/TestGDBServerTargetXML.py Index: lldb/test/API/functionalities/gdb_remote_client/TestGDBServerTargetXML.py === --- lldb/test/API/functionalities/gdb_remote_client/TestGDBServerTargetXML.py +++ lldb/test/API/functionalities/gdb_remote_client/TestGDBServerTargetXML.py @@ -20,8 +20,16 @@ i386:x86-64 GNU/Linux + + + + + + + + @@ -59,8 +67,16 @@ def readRegisters(self): return ( -"0102030405060708" # rsp -"1112131415161718" # rip +"0102030405060708" # rcx +"1112131415161718" # rdx +"2122232425262728" # rsi +"3132333435363738" # rdi +"4142434445464748" # rbp +"5152535455565758" # rsp +"6162636465666768" # r8 +"7172737475767778" # r9 +"8182838485868788" # rip +"91929394" # eflags "0102030405060708090a" # st0 "1112131415161718191a" + # st1 "2122232425262728292a" * 6 + # st2..st7 @@ -81,9 +97,31 @@ # rsp and rip should be displayed as uints self.match("register read rsp", - ["rsp = 0x0807060504030201"]) + ["rsp = 0x5857565554535251"]) self.match("register read rip", - ["rip = 0x1817161514131211"]) + ["rip = 0x8887868584838281"]) + +# test generic aliases +self.match("register read arg4", + ["rcx = 0x0807060504030201"]) +self.match("register read arg3", + ["rdx = 0x1817161514131211"]) +self.match("register read arg2", + ["rsi = 0x2827262524232221"]) +self.match("register read arg1", + ["rdi = 0x3837363534333231"]) +self.match("register read fp", + ["rbp = 0x4847464544434241"]) +self.match("register read sp", + ["rsp = 0x5857565554535251"]) +self.match("register read arg5", + ["r8 = 0x6867666564636261"]) +self.match("register read arg6", + ["r9 = 0x7877767574737271"]) +self.match("register read pc", + ["rip = 0x8887868584838281"]) +self.match("register read flags", + ["eflags = 0x94939291"]) # both stX and xmmX should be displayed as vectors self.match("register read st0", Index: lldb/source/Target/RegisterContext.cpp === --- lldb/source/Target/RegisterContext.cpp +++ lldb/source/Target/RegisterContext.cpp @@ -62,6 +62,13 @@ reg_name.equals_insensitive(reg_info->alt_name)) return reg_info; } + + // if none of the register entries matched directly, try matching + // using a generic register name. + uint32_t generic_reg = Args::StringToGenericRegister(reg_name); + if (generic_reg != LLDB_INVALID_REGNUM) +return GetRegisterInfo(eRegisterKindGeneric, generic_reg); + return nullptr; } Index: lldb/source/Host/common/NativeRegisterContext.cpp === --- lldb/source/Host/common/NativeRegisterContext.cpp +++ lldb/source/Host/common/NativeRegisterContext.cpp @@ -64,6 +64,13 @@ reg_name.equals_insensitive(reg_info->alt_name)) return reg_info; } + + // if none of the register entries matched directly, try matching + // using a generic register name. + uint32_t generic_reg = Args::StringToGenericRegister(reg_name); + if (generic_reg != LLDB_INVALID_REGNUM) +return GetRegisterInfo(eR
[Lldb-commits] [PATCH] D108233: WIP: Add minidump save-core functionality to ELF object files
Aj0SK updated this revision to Diff 368110. Aj0SK added a comment. Herald added a subscriber: dang. Move minidump save-core functionality to separate plugin Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D108233/new/ https://reviews.llvm.org/D108233 Files: lldb/include/lldb/Core/PluginManager.h lldb/source/API/SBProcess.cpp lldb/source/Commands/CommandObjectProcess.cpp lldb/source/Commands/Options.td lldb/source/Core/PluginManager.cpp lldb/source/Plugins/ObjectFile/CMakeLists.txt lldb/source/Plugins/ObjectFile/Minidump/CMakeLists.txt lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.h lldb/source/Plugins/ObjectFile/Minidump/ObjectFileMinidump.cpp lldb/source/Plugins/ObjectFile/Minidump/ObjectFileMinidump.h lldb/test/API/functionalities/process_save_core_minidump/Makefile lldb/test/API/functionalities/process_save_core_minidump/TestProcessSaveCoreMinidump.py lldb/test/API/functionalities/process_save_core_minidump/main.cpp Index: lldb/test/API/functionalities/process_save_core_minidump/main.cpp === --- /dev/null +++ lldb/test/API/functionalities/process_save_core_minidump/main.cpp @@ -0,0 +1,30 @@ +#include +#include +#include + +using namespace std; + +void g() { assert(false); } + +void f() { g(); } + +size_t h() { + size_t sum = 0; + for (size_t i = 0; i < 100; ++i) +for (size_t j = 0; j < 100; ++j) + if ((i * j) % 2 == 0) { +sum += 1; + } + return sum; +} + +int main() { + thread t1(f); + + size_t x = h(); + + t1.join(); + + cout << "X is " << x << "\n"; + return 0; +} \ No newline at end of file Index: lldb/test/API/functionalities/process_save_core_minidump/TestProcessSaveCoreMinidump.py === --- /dev/null +++ lldb/test/API/functionalities/process_save_core_minidump/TestProcessSaveCoreMinidump.py @@ -0,0 +1,78 @@ +""" +Test saving a mini dump. +""" + + +import os +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class ProcessSaveCoreMinidumpTestCase(TestBase): + +mydir = TestBase.compute_mydir(__file__) + +@skipUnlessPlatform(['linux']) +def test_save_linux_mini_dump(self): +"""Test that we can save a Linux mini dump.""" +self.build() +exe = self.getBuildArtifact("a.out") +core = self.getBuildArtifact("core.dmp") +try: +target = self.dbg.CreateTarget(exe) +process = target.LaunchSimple( +None, None, self.get_process_working_directory()) +self.assertEqual(process.GetState(), lldb.eStateStopped) + +# get neccessary data for the verification phase +process_info = process.GetProcessInfo() +expected_pid = process_info.GetProcessID() if process_info.IsValid() else -1 +expected_number_of_modules = target.GetNumModules() +expected_modules = target.modules +expected_number_of_threads = process.GetNumThreads() +expected_threads = [] + +for thread_idx in range(process.GetNumThreads()): +thread = process.GetThreadAtIndex(thread_idx) +thread_id = thread.GetThreadID() +expected_threads.append(thread_id) + +# save core and, kill process and verify corefile existence +self.runCmd("process save-core --plugin-name=minidump " + core) +self.assertTrue(os.path.isfile(core)) +self.assertTrue(process.Kill().Success()) + +# To verify, we'll launch with the mini dump +target = self.dbg.CreateTarget(None) +process = target.LoadCore(core) + +# check if the core is in desired state +self.assertTrue(process, PROCESS_IS_VALID) +self.assertTrue(process.GetProcessInfo().IsValid()) +self.assertEqual(process.GetProcessInfo().GetProcessID(), expected_pid) +self.assertTrue(target.GetTriple().find("linux") != -1) +self.assertTrue(target.GetNumModules(), expected_number_of_modules) +self.assertEqual(process.GetNumThreads(), expected_number_of_threads) + +for module, expected in zip(target.modules, expected_modules): +self.assertTrue(module.IsValid()) +module_file_name = module.GetFileSpec().GetFilename() +expected_file_name = expected.GetFileSpec().GetFilename() +# skip kernel virtual dynamic shared objects +if "vdso" in expected_file_name: +continue +self.assertEqual(module_file_name, expected_file_name) +self.assertEqual(module.GetUUIDString(), expected.GetUUIDString()) + +for
[Lldb-commits] [PATCH] D108515: [lldb/lua] Force Lua version to be 5.3
tammela accepted this revision. tammela added a comment. This revision is now accepted and ready to land. LGTM Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D108515/new/ https://reviews.llvm.org/D108515 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D104281: [lldb][docs] Add reference docs for Lua scripting
tammela accepted this revision. tammela added a comment. LGTM Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D104281/new/ https://reviews.llvm.org/D104281 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D108229: [lldb] Refactor Module::LookupInfo constructor
bulbazord added a comment. ping! Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D108229/new/ https://reviews.llvm.org/D108229 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] 23c1939 - [lldb][NFC] Remove unused method RichManglingContext::IsFunction
Author: Alex Langford Date: 2021-08-23T11:45:55-07:00 New Revision: 23c19395c085306cf229341523b6a8909b3b70a9 URL: https://github.com/llvm/llvm-project/commit/23c19395c085306cf229341523b6a8909b3b70a9 DIFF: https://github.com/llvm/llvm-project/commit/23c19395c085306cf229341523b6a8909b3b70a9.diff LOG: [lldb][NFC] Remove unused method RichManglingContext::IsFunction Added: Modified: lldb/include/lldb/Core/RichManglingContext.h lldb/source/Core/RichManglingContext.cpp lldb/unittests/Core/RichManglingContextTest.cpp Removed: diff --git a/lldb/include/lldb/Core/RichManglingContext.h b/lldb/include/lldb/Core/RichManglingContext.h index 48102ec0b1cf8..a6b7af8d8d7ec 100644 --- a/lldb/include/lldb/Core/RichManglingContext.h +++ b/lldb/include/lldb/Core/RichManglingContext.h @@ -42,9 +42,6 @@ class RichManglingContext { /// If this symbol describes a constructor or destructor. bool IsCtorOrDtor() const; - /// If this symbol describes a function. - bool IsFunction() const; - /// Get the base name of a function. This doesn't include trailing template /// arguments, ie "a::b" gives "b". The result will overwrite the /// internal buffer. It can be obtained via GetBufferRef(). diff --git a/lldb/source/Core/RichManglingContext.cpp b/lldb/source/Core/RichManglingContext.cpp index 2dcb1407e6c74..63170feb6231c 100644 --- a/lldb/source/Core/RichManglingContext.cpp +++ b/lldb/source/Core/RichManglingContext.cpp @@ -83,19 +83,6 @@ bool RichManglingContext::IsCtorOrDtor() const { llvm_unreachable("Fully covered switch above!"); } -bool RichManglingContext::IsFunction() const { - assert(m_provider != None && "Initialize a provider first"); - switch (m_provider) { - case ItaniumPartialDemangler: -return m_ipd.isFunction(); - case PluginCxxLanguage: -return get(m_cxx_method_parser)->IsValid(); - case None: -return false; - } - llvm_unreachable("Fully covered switch above!"); -} - void RichManglingContext::processIPDStrResult(char *ipd_res, size_t res_size) { // Error case: Clear the buffer. if (LLVM_UNLIKELY(ipd_res == nullptr)) { diff --git a/lldb/unittests/Core/RichManglingContextTest.cpp b/lldb/unittests/Core/RichManglingContextTest.cpp index f8a0bbf9102b5..89e9ef03650f9 100644 --- a/lldb/unittests/Core/RichManglingContextTest.cpp +++ b/lldb/unittests/Core/RichManglingContextTest.cpp @@ -20,7 +20,6 @@ TEST(RichManglingContextTest, Basic) { ConstString mangled("_ZN3foo3barEv"); EXPECT_TRUE(RMC.FromItaniumName(mangled)); - EXPECT_TRUE(RMC.IsFunction()); EXPECT_FALSE(RMC.IsCtorOrDtor()); RMC.ParseFunctionDeclContextName(); @@ -42,7 +41,6 @@ TEST(RichManglingContextTest, FromCxxMethodName) { ConstString demangled("foo::bar()"); EXPECT_TRUE(CxxMethodRMC.FromCxxMethodName(demangled)); - EXPECT_TRUE(ItaniumRMC.IsFunction() == CxxMethodRMC.IsFunction()); EXPECT_TRUE(ItaniumRMC.IsCtorOrDtor() == CxxMethodRMC.IsCtorOrDtor()); ItaniumRMC.ParseFunctionDeclContextName(); @@ -61,9 +59,6 @@ TEST(RichManglingContextTest, FromCxxMethodName) { { RichManglingContext CxxMethodRMC; EXPECT_TRUE(CxxMethodRMC.FromCxxMethodName(ConstString("X"))); - -// We expect it is not a function. -EXPECT_FALSE(CxxMethodRMC.IsFunction()); } // Construct with a function without a context. @@ -72,9 +67,6 @@ TEST(RichManglingContextTest, FromCxxMethodName) { EXPECT_TRUE(CxxMethodRMC.FromCxxMethodName( ConstString("void * operator new(unsigned __int64)"))); -// We expect it is a function. -EXPECT_TRUE(CxxMethodRMC.IsFunction()); - // We expect its context is empty. CxxMethodRMC.ParseFunctionDeclContextName(); EXPECT_TRUE(CxxMethodRMC.GetBufferRef().empty()); ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D108228: Fix error handling in the libcxx std::string formatter
jingham added a comment. Raphael's analysis of what the test needs is right. We always check pointers for validity before we do operations on them, so we wouldn't have tried to get the summary. The reason I passed the string reference to a function and check it there is because from many years of experience, I don't trust compilers even at -O0 not to elide references to silly unused variables. But at -O0 a function argument is never going away. But if folks think this is over paranoid on my part, I can simplify the test. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D108228/new/ https://reviews.llvm.org/D108228 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D108510: [lldb] Allow to register frame recognizers applied beyond the first instruction
jingham added a comment. One of the key reasons to use "frame recognizers" is to provide argument values to functions that don't have debug information. That generally only works when stopped at the first instruction, since otherwise you have to follow the value as it moves through the code, which in the absence of debug information isn't entirely trivial. A naive user might think reporting `expr (SomeType *) $arg1` is going to always work, but in fact it only works reliably on the first instruction. I don't think that possible incorrect usage means we should only allow frame recognizers on the first instruction. But I do think we should say something more in the help for this flag, like "remember that $arg is only reliable on the first instruction" to warn folks in advance of this pitfall. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D108510/new/ https://reviews.llvm.org/D108510 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D108335: [lldb] Move UnixSignals subclasses to lldbTarget
jingham added a comment. I appreciate the aim, but I don't think moving a whole bunch of platform specific files from Plugins/Process/Utility to Target is the right way to go. If anything that's moving platform specific files further up into generic code. Since the list of valid signals and their numberings are really platform specific, those files should go into their appropriate Platform. Then when lldb needs the signal mapping, it should ask the current target's Platform for the right Signals object, and the platform should hand you that. Since generic code only ever needs the UnixSignals APIs, UnixSignals.h would properly go in include/lldb/Target, but all the other ones would live in their platforms. The Signals API needs a little reworking. Because the Signals are gotten from the Process, you can't set signal handling till you have a running process. That's annoying because it means you can't configure signal behaviors in your .lldbinit, you have to do it from a breakpoint on main or something dopey like that. The Target really needs to have a general interface that only knows about signals by text name, so it can register the "process handle" settings in the dummy target, propagate them to new Targets which then ask the current UnixSignals object for name -> signal number. So maybe we should do a UnixSignals object that just has a list of signal names and behaviors. Then it would be the one that "has a" Platform Specific signals object, and uses that both to do name->number lookups for the current platform, and report any operations on signals that aren't supported by the current platform. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D108335/new/ https://reviews.llvm.org/D108335 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D108229: [lldb] Refactor Module::LookupInfo constructor
jingham accepted this revision. jingham added a comment. This revision is now accepted and ready to land. I like the change in general, anywhere that we're explicitly listing languages in generic code we're probably doing it wrong... So far as I can tell you've reconstructed the old behaviors correctly in the new setup. I left one trivial comment, but really this LGTM. Comment at: lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp:73 + llvm::StringRef basename = method.GetBasename(); + if (basename.empty()) { +if (CPlusPlusLanguage::ExtractContextAndIdentifier( The old code checked method.IsValid before pulling out the base name. It seems sensible that an invalid MethodName would return an empty base name, but that does seem to rely a little on implicit behavior? Not sure that's a big deal. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D108229/new/ https://reviews.llvm.org/D108229 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D108061: [lldb] Add support for shared library load when executable called through ld.
clayborg accepted this revision. clayborg added a comment. This revision is now accepted and ready to land. I am so happy that the memory region trick worked! Thanks for working on this and trying out the extra fixes, we now have great support for debugging via the dynamic linker! Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D108061/new/ https://reviews.llvm.org/D108061 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D108385: [LLDB][GUI] Add extra keys to text field
clayborg accepted this revision. clayborg added a comment. This revision is now accepted and ready to land. Finally got to try this out. Works great. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D108385/new/ https://reviews.llvm.org/D108385 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] d95d2a8 - [LLDB][GUI] Add extra keys to text field
Author: Omar Emara Date: 2021-08-23T21:16:48-07:00 New Revision: d95d2a8e4aaae9521278c2968fb6f1baa820b817 URL: https://github.com/llvm/llvm-project/commit/d95d2a8e4aaae9521278c2968fb6f1baa820b817 DIFF: https://github.com/llvm/llvm-project/commit/d95d2a8e4aaae9521278c2968fb6f1baa820b817.diff LOG: [LLDB][GUI] Add extra keys to text field This patch adds many new keys to the text field and implements new behaviors as follows: ``` case KEY_HOME: case KEY_CTRL_A: MoveCursorToStart(); case KEY_END: case KEY_CTRL_E: MoveCursorToEnd(); case KEY_RIGHT: case KEY_SF: MoveCursorRight(); case KEY_LEFT: case KEY_SR: MoveCursorLeft(); case KEY_BACKSPACE: case KEY_DELETE: RemovePreviousChar(); case KEY_DC: RemoveNextChar(); case KEY_EOL: case KEY_CTRL_K: ClearToEnd(); case KEY_DL: case KEY_CLEAR: Clear(); ``` This patch also refactors scrolling to be dynamic at draw time for easier handing. Differential Revision: https://reviews.llvm.org/D108385 Added: Modified: lldb/source/Core/IOHandlerCursesGUI.cpp Removed: diff --git a/lldb/source/Core/IOHandlerCursesGUI.cpp b/lldb/source/Core/IOHandlerCursesGUI.cpp index 9dc13ccbb4764..1539175fb60ec 100644 --- a/lldb/source/Core/IOHandlerCursesGUI.cpp +++ b/lldb/source/Core/IOHandlerCursesGUI.cpp @@ -85,8 +85,12 @@ using llvm::StringRef; // we may want curses to be disabled for some builds for instance, windows #if LLDB_ENABLE_CURSES +#define KEY_CTRL_A 1 +#define KEY_CTRL_E 5 +#define KEY_CTRL_K 11 #define KEY_RETURN 10 #define KEY_ESCAPE 27 +#define KEY_DELETE 127 #define KEY_SHIFT_TAB (KEY_MAX + 1) @@ -1106,10 +1110,11 @@ class TextFieldDelegate : public FieldDelegate { int GetContentLength() { return m_content.length(); } void DrawContent(Surface &surface, bool is_selected) { +UpdateScrolling(surface.GetWidth()); + surface.MoveCursor(0, 0); const char *text = m_content.c_str() + m_first_visibile_char; surface.PutCString(text, surface.GetWidth()); -m_last_drawn_content_width = surface.GetWidth(); // Highlight the cursor. surface.MoveCursor(GetCursorXPosition(), 0); @@ -1156,6 +1161,22 @@ class TextFieldDelegate : public FieldDelegate { DrawError(error_surface); } + // Get the position of the last visible character. + int GetLastVisibleCharPosition(int width) { +int position = m_first_visibile_char + width - 1; +return std::min(position, GetContentLength()); + } + + void UpdateScrolling(int width) { +if (m_cursor_position < m_first_visibile_char) { + m_first_visibile_char = m_cursor_position; + return; +} + +if (m_cursor_position > GetLastVisibleCharPosition(width)) + m_first_visibile_char = m_cursor_position - (width - 1); + } + // The cursor is allowed to move one character past the string. // m_cursor_position is in range [0, GetContentLength()]. void MoveCursorRight() { @@ -1168,42 +1189,54 @@ class TextFieldDelegate : public FieldDelegate { m_cursor_position--; } - // If the cursor moved past the last visible character, scroll right by one - // character. - void ScrollRightIfNeeded() { -if (m_cursor_position - m_first_visibile_char == m_last_drawn_content_width) - m_first_visibile_char++; - } + void MoveCursorToStart() { m_cursor_position = 0; } + + void MoveCursorToEnd() { m_cursor_position = GetContentLength(); } void ScrollLeft() { if (m_first_visibile_char > 0) m_first_visibile_char--; } - // If the cursor moved past the first visible character, scroll left by one - // character. - void ScrollLeftIfNeeded() { -if (m_cursor_position < m_first_visibile_char) - m_first_visibile_char--; - } - - // Insert a character at the current cursor position, advance the cursor - // position, and make sure to scroll right if needed. + // Insert a character at the current cursor position and advance the cursor + // position. void InsertChar(char character) { m_content.insert(m_cursor_position, 1, character); m_cursor_position++; -ScrollRightIfNeeded(); +ClearError(); } // Remove the character before the cursor position, retreat the cursor - // position, and make sure to scroll left if needed. - void RemoveChar() { + // position, and scroll left. + void RemovePreviousChar() { if (m_cursor_position == 0) return; m_content.erase(m_cursor_position - 1, 1); m_cursor_position--; ScrollLeft(); +ClearError(); + } + + // Remove the character after the cursor position. + void RemoveNextChar() { +if (m_cursor_position == GetContentLength()) + return; + +m_content.erase(m_cursor_position, 1); +ClearError(); + } + + // Clear characters from the current cursor position to the end. + void ClearToEnd() { +m_content.erase(m_cursor_position); +ClearError(); + } + + void Clear() { +m_content.clear(); +
[Lldb-commits] [PATCH] D108385: [LLDB][GUI] Add extra keys to text field
This revision was landed with ongoing or failed builds. This revision was automatically updated to reflect the committed changes. Closed by commit rGd95d2a8e4aaa: [LLDB][GUI] Add extra keys to text field (authored by OmarEmaraDev, committed by clayborg). Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D108385/new/ https://reviews.llvm.org/D108385 Files: lldb/source/Core/IOHandlerCursesGUI.cpp Index: lldb/source/Core/IOHandlerCursesGUI.cpp === --- lldb/source/Core/IOHandlerCursesGUI.cpp +++ lldb/source/Core/IOHandlerCursesGUI.cpp @@ -85,8 +85,12 @@ // we may want curses to be disabled for some builds for instance, windows #if LLDB_ENABLE_CURSES +#define KEY_CTRL_A 1 +#define KEY_CTRL_E 5 +#define KEY_CTRL_K 11 #define KEY_RETURN 10 #define KEY_ESCAPE 27 +#define KEY_DELETE 127 #define KEY_SHIFT_TAB (KEY_MAX + 1) @@ -1106,10 +1110,11 @@ int GetContentLength() { return m_content.length(); } void DrawContent(Surface &surface, bool is_selected) { +UpdateScrolling(surface.GetWidth()); + surface.MoveCursor(0, 0); const char *text = m_content.c_str() + m_first_visibile_char; surface.PutCString(text, surface.GetWidth()); -m_last_drawn_content_width = surface.GetWidth(); // Highlight the cursor. surface.MoveCursor(GetCursorXPosition(), 0); @@ -1156,6 +1161,22 @@ DrawError(error_surface); } + // Get the position of the last visible character. + int GetLastVisibleCharPosition(int width) { +int position = m_first_visibile_char + width - 1; +return std::min(position, GetContentLength()); + } + + void UpdateScrolling(int width) { +if (m_cursor_position < m_first_visibile_char) { + m_first_visibile_char = m_cursor_position; + return; +} + +if (m_cursor_position > GetLastVisibleCharPosition(width)) + m_first_visibile_char = m_cursor_position - (width - 1); + } + // The cursor is allowed to move one character past the string. // m_cursor_position is in range [0, GetContentLength()]. void MoveCursorRight() { @@ -1168,42 +1189,54 @@ m_cursor_position--; } - // If the cursor moved past the last visible character, scroll right by one - // character. - void ScrollRightIfNeeded() { -if (m_cursor_position - m_first_visibile_char == m_last_drawn_content_width) - m_first_visibile_char++; - } + void MoveCursorToStart() { m_cursor_position = 0; } + + void MoveCursorToEnd() { m_cursor_position = GetContentLength(); } void ScrollLeft() { if (m_first_visibile_char > 0) m_first_visibile_char--; } - // If the cursor moved past the first visible character, scroll left by one - // character. - void ScrollLeftIfNeeded() { -if (m_cursor_position < m_first_visibile_char) - m_first_visibile_char--; - } - - // Insert a character at the current cursor position, advance the cursor - // position, and make sure to scroll right if needed. + // Insert a character at the current cursor position and advance the cursor + // position. void InsertChar(char character) { m_content.insert(m_cursor_position, 1, character); m_cursor_position++; -ScrollRightIfNeeded(); +ClearError(); } // Remove the character before the cursor position, retreat the cursor - // position, and make sure to scroll left if needed. - void RemoveChar() { + // position, and scroll left. + void RemovePreviousChar() { if (m_cursor_position == 0) return; m_content.erase(m_cursor_position - 1, 1); m_cursor_position--; ScrollLeft(); +ClearError(); + } + + // Remove the character after the cursor position. + void RemoveNextChar() { +if (m_cursor_position == GetContentLength()) + return; + +m_content.erase(m_cursor_position, 1); +ClearError(); + } + + // Clear characters from the current cursor position to the end. + void ClearToEnd() { +m_content.erase(m_cursor_position); +ClearError(); + } + + void Clear() { +m_content.clear(); +m_cursor_position = 0; +ClearError(); } // True if the key represents a char that can be inserted in the field @@ -1224,17 +1257,36 @@ } switch (key) { +case KEY_HOME: +case KEY_CTRL_A: + MoveCursorToStart(); + return eKeyHandled; +case KEY_END: +case KEY_CTRL_E: + MoveCursorToEnd(); + return eKeyHandled; case KEY_RIGHT: +case KEY_SF: MoveCursorRight(); - ScrollRightIfNeeded(); return eKeyHandled; case KEY_LEFT: +case KEY_SR: MoveCursorLeft(); - ScrollLeftIfNeeded(); return eKeyHandled; case KEY_BACKSPACE: - ClearError(); - RemoveChar(); +case KEY_DELETE: + RemovePreviousChar(); + return eKeyHandled; +case KEY_DC: + RemoveNextChar(); + return eKeyHandled; +case KEY_EOL: +case KEY_CTRL_K: + ClearToEnd(); +
[Lldb-commits] [PATCH] D108410: [LLDB][GUI] Add submit form key combination
clayborg accepted this revision. clayborg added a comment. This revision is now accepted and ready to land. Just tried it out. Works nicely. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D108410/new/ https://reviews.llvm.org/D108410 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [lldb] 945cde8 - [LLDB][GUI] Add submit form key combination
Author: Omar Emara Date: 2021-08-23T22:07:04-07:00 New Revision: 945cde8b6a4579406886d08f803b632e00f0b1ec URL: https://github.com/llvm/llvm-project/commit/945cde8b6a4579406886d08f803b632e00f0b1ec DIFF: https://github.com/llvm/llvm-project/commit/945cde8b6a4579406886d08f803b632e00f0b1ec.diff LOG: [LLDB][GUI] Add submit form key combination This patch adds a new key ALt+Enter key combination to form windows. Once invoked, the first action is executed without having to navigate to its button. Field exit callbacks are now also invoked on validation to support this aforementioned key combination. One concern for this key combination is its potential use by the window manager of the host. I am not sure if this will be a problem, but it is worth putting in consideration. Differential Revision: https://reviews.llvm.org/D108410 Added: Modified: lldb/source/Core/IOHandlerCursesGUI.cpp Removed: diff --git a/lldb/source/Core/IOHandlerCursesGUI.cpp b/lldb/source/Core/IOHandlerCursesGUI.cpp index 1539175fb60ec..ca06a332e4edd 100644 --- a/lldb/source/Core/IOHandlerCursesGUI.cpp +++ b/lldb/source/Core/IOHandlerCursesGUI.cpp @@ -93,6 +93,7 @@ using llvm::StringRef; #define KEY_DELETE 127 #define KEY_SHIFT_TAB (KEY_MAX + 1) +#define KEY_ALT_ENTER (KEY_MAX + 2) namespace curses { class Menu; @@ -2315,6 +2316,7 @@ class FormDelegate { // action that requires valid fields. bool CheckFieldsValidity() { for (int i = 0; i < GetNumberOfFields(); i++) { + GetField(i)->FieldDelegateExitCallback(); if (GetField(i)->FieldDelegateHasError()) { SetError("Some fields are invalid!"); return false; @@ -2649,13 +2651,24 @@ class FormWindowDelegate : public WindowDelegate { Size(width, copy_height)); } + void DrawSubmitHint(Surface &surface, bool is_active) { +surface.MoveCursor(2, surface.GetHeight() - 1); +if (is_active) + surface.AttributeOn(A_BOLD | COLOR_PAIR(BlackOnWhite)); +surface.Printf("[Press Alt+Enter to %s]", + m_delegate_sp->GetAction(0).GetLabel().c_str()); +if (is_active) + surface.AttributeOff(A_BOLD | COLOR_PAIR(BlackOnWhite)); + } + bool WindowDelegateDraw(Window &window, bool force) override { m_delegate_sp->UpdateFieldsVisibility(); window.Erase(); window.DrawTitleBox(m_delegate_sp->GetName().c_str(), -"Press Esc to cancel"); +"Press Esc to Cancel"); +DrawSubmitHint(window, window.IsActive()); Rect content_bounds = window.GetFrame(); content_bounds.Inset(2, 2); @@ -2778,8 +2791,8 @@ class FormWindowDelegate : public WindowDelegate { return eKeyHandled; } - void ExecuteAction(Window &window) { -FormAction &action = m_delegate_sp->GetAction(m_selection_index); + void ExecuteAction(Window &window, int index) { +FormAction &action = m_delegate_sp->GetAction(index); action.Execute(window); if (m_delegate_sp->HasError()) { m_first_visible_line = 0; @@ -2794,10 +2807,13 @@ class FormWindowDelegate : public WindowDelegate { case '\n': case KEY_ENTER: if (m_selection_type == SelectionType::Action) { -ExecuteAction(window); +ExecuteAction(window, m_selection_index); return eKeyHandled; } break; +case KEY_ALT_ENTER: + ExecuteAction(window, 0); + return eKeyHandled; case '\t': return SelectNext(key); case KEY_SHIFT_TAB: @@ -7458,6 +7474,7 @@ void IOHandlerCursesGUI::Activate() { static_assert(LastColorPairIndex == 18, "Color indexes do not match."); define_key("\033[Z", KEY_SHIFT_TAB); +define_key("\033\015", KEY_ALT_ENTER); } } ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D108410: [LLDB][GUI] Add submit form key combination
This revision was landed with ongoing or failed builds. This revision was automatically updated to reflect the committed changes. Closed by commit rG945cde8b6a45: [LLDB][GUI] Add submit form key combination (authored by OmarEmaraDev, committed by clayborg). Changed prior to commit: https://reviews.llvm.org/D108410?vs=367612&id=368273#toc Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D108410/new/ https://reviews.llvm.org/D108410 Files: lldb/source/Core/IOHandlerCursesGUI.cpp Index: lldb/source/Core/IOHandlerCursesGUI.cpp === --- lldb/source/Core/IOHandlerCursesGUI.cpp +++ lldb/source/Core/IOHandlerCursesGUI.cpp @@ -93,6 +93,7 @@ #define KEY_DELETE 127 #define KEY_SHIFT_TAB (KEY_MAX + 1) +#define KEY_ALT_ENTER (KEY_MAX + 2) namespace curses { class Menu; @@ -2315,6 +2316,7 @@ // action that requires valid fields. bool CheckFieldsValidity() { for (int i = 0; i < GetNumberOfFields(); i++) { + GetField(i)->FieldDelegateExitCallback(); if (GetField(i)->FieldDelegateHasError()) { SetError("Some fields are invalid!"); return false; @@ -2649,13 +2651,24 @@ Size(width, copy_height)); } + void DrawSubmitHint(Surface &surface, bool is_active) { +surface.MoveCursor(2, surface.GetHeight() - 1); +if (is_active) + surface.AttributeOn(A_BOLD | COLOR_PAIR(BlackOnWhite)); +surface.Printf("[Press Alt+Enter to %s]", + m_delegate_sp->GetAction(0).GetLabel().c_str()); +if (is_active) + surface.AttributeOff(A_BOLD | COLOR_PAIR(BlackOnWhite)); + } + bool WindowDelegateDraw(Window &window, bool force) override { m_delegate_sp->UpdateFieldsVisibility(); window.Erase(); window.DrawTitleBox(m_delegate_sp->GetName().c_str(), -"Press Esc to cancel"); +"Press Esc to Cancel"); +DrawSubmitHint(window, window.IsActive()); Rect content_bounds = window.GetFrame(); content_bounds.Inset(2, 2); @@ -2778,8 +2791,8 @@ return eKeyHandled; } - void ExecuteAction(Window &window) { -FormAction &action = m_delegate_sp->GetAction(m_selection_index); + void ExecuteAction(Window &window, int index) { +FormAction &action = m_delegate_sp->GetAction(index); action.Execute(window); if (m_delegate_sp->HasError()) { m_first_visible_line = 0; @@ -2794,10 +2807,13 @@ case '\n': case KEY_ENTER: if (m_selection_type == SelectionType::Action) { -ExecuteAction(window); +ExecuteAction(window, m_selection_index); return eKeyHandled; } break; +case KEY_ALT_ENTER: + ExecuteAction(window, 0); + return eKeyHandled; case '\t': return SelectNext(key); case KEY_SHIFT_TAB: @@ -7458,6 +7474,7 @@ static_assert(LastColorPairIndex == 18, "Color indexes do not match."); define_key("\033[Z", KEY_SHIFT_TAB); +define_key("\033\015", KEY_ALT_ENTER); } } Index: lldb/source/Core/IOHandlerCursesGUI.cpp === --- lldb/source/Core/IOHandlerCursesGUI.cpp +++ lldb/source/Core/IOHandlerCursesGUI.cpp @@ -93,6 +93,7 @@ #define KEY_DELETE 127 #define KEY_SHIFT_TAB (KEY_MAX + 1) +#define KEY_ALT_ENTER (KEY_MAX + 2) namespace curses { class Menu; @@ -2315,6 +2316,7 @@ // action that requires valid fields. bool CheckFieldsValidity() { for (int i = 0; i < GetNumberOfFields(); i++) { + GetField(i)->FieldDelegateExitCallback(); if (GetField(i)->FieldDelegateHasError()) { SetError("Some fields are invalid!"); return false; @@ -2649,13 +2651,24 @@ Size(width, copy_height)); } + void DrawSubmitHint(Surface &surface, bool is_active) { +surface.MoveCursor(2, surface.GetHeight() - 1); +if (is_active) + surface.AttributeOn(A_BOLD | COLOR_PAIR(BlackOnWhite)); +surface.Printf("[Press Alt+Enter to %s]", + m_delegate_sp->GetAction(0).GetLabel().c_str()); +if (is_active) + surface.AttributeOff(A_BOLD | COLOR_PAIR(BlackOnWhite)); + } + bool WindowDelegateDraw(Window &window, bool force) override { m_delegate_sp->UpdateFieldsVisibility(); window.Erase(); window.DrawTitleBox(m_delegate_sp->GetName().c_str(), -"Press Esc to cancel"); +"Press Esc to Cancel"); +DrawSubmitHint(window, window.IsActive()); Rect content_bounds = window.GetFrame(); content_bounds.Inset(2, 2); @@ -2778,8 +2791,8 @@ return eKeyHandled; } - void ExecuteAction(Window &window) { -FormAction &action = m_delegate_sp->GetAction(m_selection_index); + void ExecuteAction(Window &window, int index) { +FormAction &action = m_delegate_sp->GetAction(index); action.Execute(window); if (m_deleg
[Lldb-commits] [lldb] 292f013 - [LLDB][GUI] Handle extra navigation keys in forms
Author: Omar Emara Date: 2021-08-23T22:42:57-07:00 New Revision: 292f013395f2e2eafd803b787a33eddfc5cc4918 URL: https://github.com/llvm/llvm-project/commit/292f013395f2e2eafd803b787a33eddfc5cc4918 DIFF: https://github.com/llvm/llvm-project/commit/292f013395f2e2eafd803b787a33eddfc5cc4918.diff LOG: [LLDB][GUI] Handle extra navigation keys in forms This patch handles the up and down keys if they weren't handled by the selected field. Moreover, it makes sure the form always absorb the key to take full control until the form is canceled or submitted. Differential Revision: https://reviews.llvm.org/D108414 Added: Modified: lldb/source/Core/IOHandlerCursesGUI.cpp Removed: diff --git a/lldb/source/Core/IOHandlerCursesGUI.cpp b/lldb/source/Core/IOHandlerCursesGUI.cpp index ca06a332e4ed..ef4f5c3d35f6 100644 --- a/lldb/source/Core/IOHandlerCursesGUI.cpp +++ b/lldb/source/Core/IOHandlerCursesGUI.cpp @@ -2801,6 +2801,8 @@ class FormWindowDelegate : public WindowDelegate { } } + // Always return eKeyHandled to absorb all events since forms are always + // added as pop-ups that should take full control until canceled or submitted. HandleCharResult WindowDelegateHandleChar(Window &window, int key) override { switch (key) { case '\r': @@ -2815,9 +2817,11 @@ class FormWindowDelegate : public WindowDelegate { ExecuteAction(window, 0); return eKeyHandled; case '\t': - return SelectNext(key); + SelectNext(key); + return eKeyHandled; case KEY_SHIFT_TAB: - return SelectPrevious(key); + SelectPrevious(key); + return eKeyHandled; case KEY_ESCAPE: window.GetParent()->RemoveSubWindow(&window); return eKeyHandled; @@ -2829,10 +2833,24 @@ class FormWindowDelegate : public WindowDelegate { // to that field. if (m_selection_type == SelectionType::Field) { FieldDelegate *field = m_delegate_sp->GetField(m_selection_index); - return field->FieldDelegateHandleChar(key); + if (field->FieldDelegateHandleChar(key) == eKeyHandled) +return eKeyHandled; } -return eKeyNotHandled; +// If the key wasn't handled by the possibly selected field, handle some +// extra keys for navigation. +switch (key) { +case KEY_DOWN: + SelectNext(key); + return eKeyHandled; +case KEY_UP: + SelectPrevious(key); + return eKeyHandled; +default: + break; +} + +return eKeyHandled; } protected: ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D108414: [LLDB][GUI] Handle extra navigation keys in forms
This revision was landed with ongoing or failed builds. This revision was automatically updated to reflect the committed changes. Closed by commit rG292f013395f2: [LLDB][GUI] Handle extra navigation keys in forms (authored by OmarEmaraDev, committed by clayborg). Changed prior to commit: https://reviews.llvm.org/D108414?vs=367629&id=368277#toc Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D108414/new/ https://reviews.llvm.org/D108414 Files: lldb/source/Core/IOHandlerCursesGUI.cpp Index: lldb/source/Core/IOHandlerCursesGUI.cpp === --- lldb/source/Core/IOHandlerCursesGUI.cpp +++ lldb/source/Core/IOHandlerCursesGUI.cpp @@ -2801,6 +2801,8 @@ } } + // Always return eKeyHandled to absorb all events since forms are always + // added as pop-ups that should take full control until canceled or submitted. HandleCharResult WindowDelegateHandleChar(Window &window, int key) override { switch (key) { case '\r': @@ -2815,9 +2817,11 @@ ExecuteAction(window, 0); return eKeyHandled; case '\t': - return SelectNext(key); + SelectNext(key); + return eKeyHandled; case KEY_SHIFT_TAB: - return SelectPrevious(key); + SelectPrevious(key); + return eKeyHandled; case KEY_ESCAPE: window.GetParent()->RemoveSubWindow(&window); return eKeyHandled; @@ -2829,10 +2833,24 @@ // to that field. if (m_selection_type == SelectionType::Field) { FieldDelegate *field = m_delegate_sp->GetField(m_selection_index); - return field->FieldDelegateHandleChar(key); + if (field->FieldDelegateHandleChar(key) == eKeyHandled) +return eKeyHandled; } -return eKeyNotHandled; +// If the key wasn't handled by the possibly selected field, handle some +// extra keys for navigation. +switch (key) { +case KEY_DOWN: + SelectNext(key); + return eKeyHandled; +case KEY_UP: + SelectPrevious(key); + return eKeyHandled; +default: + break; +} + +return eKeyHandled; } protected: Index: lldb/source/Core/IOHandlerCursesGUI.cpp === --- lldb/source/Core/IOHandlerCursesGUI.cpp +++ lldb/source/Core/IOHandlerCursesGUI.cpp @@ -2801,6 +2801,8 @@ } } + // Always return eKeyHandled to absorb all events since forms are always + // added as pop-ups that should take full control until canceled or submitted. HandleCharResult WindowDelegateHandleChar(Window &window, int key) override { switch (key) { case '\r': @@ -2815,9 +2817,11 @@ ExecuteAction(window, 0); return eKeyHandled; case '\t': - return SelectNext(key); + SelectNext(key); + return eKeyHandled; case KEY_SHIFT_TAB: - return SelectPrevious(key); + SelectPrevious(key); + return eKeyHandled; case KEY_ESCAPE: window.GetParent()->RemoveSubWindow(&window); return eKeyHandled; @@ -2829,10 +2833,24 @@ // to that field. if (m_selection_type == SelectionType::Field) { FieldDelegate *field = m_delegate_sp->GetField(m_selection_index); - return field->FieldDelegateHandleChar(key); + if (field->FieldDelegateHandleChar(key) == eKeyHandled) +return eKeyHandled; } -return eKeyNotHandled; +// If the key wasn't handled by the possibly selected field, handle some +// extra keys for navigation. +switch (key) { +case KEY_DOWN: + SelectNext(key); + return eKeyHandled; +case KEY_UP: + SelectPrevious(key); + return eKeyHandled; +default: + break; +} + +return eKeyHandled; } protected: ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
[Lldb-commits] [PATCH] D108545: [LLDB][GUI] Add initial searcher support
clayborg added a comment. I like the look of this. It seems we would want this kind of auto complete in many fields that we already have, like the file or directory dialogs to start with. My main question is do we need a full window for this, or can be paint a window that is just the search results? My thinking is that the right arrow key could be used to auto complete a text field if we are at the end of the input. If we have a file dialog and you type "~/" and then RIGHT arrow, it would be great if this window could appear right at the correct location and not look like a complete new window, but just a popup window that augments an existing Field (not necessarily a text field!) right below with minimal bordering so that it blends into the current form. You can select things using the up and down arrows, press enter to update the text, or keep typing to filter more. Maybe we can: - Maybe we add a "SearcherWindowDelegate *m_search_window;" member to FormDelegate so that this helper UI can appear when needed for any FieldDelegate that requests/needs it - "m_search_window" can be set to a non NULL value when one of the FieldDelegates in the FormDelegate asks for auto completion and provides a SearcherDelegate to use and a pointer to the FieldDelegate itself so that the SearcherWindowDelegate can be positioned correctly - If "m_search_window" is NULL, then never show this UI - If "m_search_window" is not NULL, then some keys get sent to the searcher delegate before or after the field gets them so it can do the choices UI - if the user hits ENTER, then the Field is asked to update its value via some API in FieldDelegate, and the GUI for the matches disappears and m_search_window is freed and set to NULL again We should hook up at least one of the FieldDelegate objects so that it uses this functionality so we can play with it in this patch to make sure it works. Let me know if you had other plans for this window and how it would be used. Comment at: lldb/source/Core/IOHandlerCursesGUI.cpp:3592 +m_selected_match(0), m_first_visible_match(0) { +; + } Should we be doing just like any other dialog that we have created and be constructing these items on the fly? ``` m_text_field = AddTextField("Search", "", true); ``` It seems the matches could use a modified ChoicesField for the matches? Are you currently drawing the choices (matches) manually? Comment at: lldb/source/Core/IOHandlerCursesGUI.cpp:3635 + + void DrawMatches(Surface &surface) { +if (m_delegate_sp->GetNumberOfMatches() == 0) Seems like this could be done using a ChoicesField no instead of drawing manually? Comment at: lldb/source/Core/IOHandlerCursesGUI.cpp:3731 + SearcherDelegateSP m_delegate_sp; + TextFieldDelegate m_text_field; + // The index of the currently selected match. Is this a new text field itself, or designed to be a reference to an existing text field? Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D108545/new/ https://reviews.llvm.org/D108545 ___ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits