diff --git a/src/debug.cc b/src/debug.cc index bf463bc..f35bac3 100644 --- a/src/debug.cc +++ b/src/debug.cc @@ -254,6 +254,33 @@ std::pair Debug::run_command(const std::string &comman return command_return; } +std::vector Debug::get_backtrace() { + std::vector backtrace; + event_mutex.lock(); + if(state==lldb::StateType::eStateStopped) { + auto thread=process->GetSelectedThread(); + for(uint32_t c_f=0;c_f class Debug { +public: + class Frame { + public: + std::string file_path; + std::string function_name; + int line_nr; + int line_index; + }; private: Debug(); public: @@ -30,6 +38,7 @@ public: void step_into(); void step_out(); std::pair run_command(const std::string &command); + std::vector get_backtrace(); void delete_debug(); //can't use delete as function name diff --git a/src/files.h b/src/files.h index 127816e..8f4af52 100644 --- a/src/files.h +++ b/src/files.h @@ -2,7 +2,7 @@ #define JUCI_FILES_H_ #include -#define JUCI_VERSION "1.1.0-2" +#define JUCI_VERSION "1.1.0-3" const std::string configjson = "{\n" @@ -106,6 +106,7 @@ const std::string configjson = " \"debug_step_over\": \"n\",\n" " \"debug_step_into\": \"t\",\n" " \"debug_step_out\": \"t\",\n" +" \"debug_backtrace\": \"n\",\n" " \"debug_run_command\": \"Return\",\n" " \"debug_toggle_breakpoint\": \"b\",\n" " \"debug_goto_stop\": \"l\",\n" diff --git a/src/menu.cc b/src/menu.cc index a7adb2d..3612c6c 100644 --- a/src/menu.cc +++ b/src/menu.cc @@ -316,6 +316,13 @@ Menu::Menu() { " " "
" " " + " _Backtrace" + " app.debug_backtrace" + +accels["debug_backtrace"]+ //For Ubuntu... + " " + "
" + "
" + " " " _Run Command" " app.debug_run_command" +accels["debug_run_command"]+ //For Ubuntu... diff --git a/src/window.cc b/src/window.cc index 8354b6d..96488e5 100644 --- a/src/window.cc +++ b/src/window.cc @@ -151,6 +151,7 @@ Window::Window() : compiling(false), debugging(false) { menu.actions["debug_step_over"]->set_enabled(false); menu.actions["debug_step_into"]->set_enabled(false); menu.actions["debug_step_out"]->set_enabled(false); + menu.actions["debug_backtrace"]->set_enabled(false); menu.actions["debug_run_command"]->set_enabled(false); menu.actions["debug_goto_stop"]->set_enabled(false); debug_update_status.connect([this](){ @@ -163,6 +164,7 @@ Window::Window() : compiling(false), debugging(false) { menu.actions["debug_step_over"]->set_enabled(false); menu.actions["debug_step_into"]->set_enabled(false); menu.actions["debug_step_out"]->set_enabled(false); + menu.actions["debug_backtrace"]->set_enabled(false); menu.actions["debug_run_command"]->set_enabled(false); menu.actions["debug_goto_stop"]->set_enabled(false); } @@ -174,6 +176,7 @@ Window::Window() : compiling(false), debugging(false) { menu.actions["debug_step_over"]->set_enabled(); menu.actions["debug_step_into"]->set_enabled(); menu.actions["debug_step_out"]->set_enabled(); + menu.actions["debug_backtrace"]->set_enabled(); menu.actions["debug_run_command"]->set_enabled(); menu.actions["debug_goto_stop"]->set_enabled(); } @@ -912,6 +915,68 @@ void Window::set_menu_actions() { if(debugging) Debug::get().step_out(); }); + menu.add_action("debug_backtrace", [this]() { + if(debugging && notebook.get_current_page()!=-1) { + auto backtrace=Debug::get().get_backtrace(); + + auto view=notebook.get_current_view(); + auto buffer=view->get_buffer(); + auto iter=buffer->get_insert()->get_iter(); + Gdk::Rectangle visible_rect; + view->get_visible_rect(visible_rect); + Gdk::Rectangle iter_rect; + view->get_iter_location(iter, iter_rect); + iter_rect.set_width(1); + if(!visible_rect.intersects(iter_rect)) { + view->get_iter_at_location(iter, 0, visible_rect.get_y()+visible_rect.get_height()/3); + } + view->selection_dialog=std::unique_ptr(new SelectionDialog(*view, buffer->create_mark(iter), true, true)); + auto rows=std::make_shared >(); + if(backtrace.size()==0) + return; + + std::string project_path; + auto cmake=get_cmake(); + if(cmake) + project_path=cmake->project_path.string(); + + for(auto &frame: backtrace) { + std::string row; + if(frame.file_path.empty()) + row=frame.function_name; + else { + auto file_path=frame.file_path; + if(!project_path.empty()) { + auto pos=file_path.find(project_path); + if(pos==0) + file_path.erase(0, project_path.size()+1); + } + + row=""+Glib::Markup::escape_text(file_path)+":"+std::to_string(frame.line_nr)+" "+Glib::Markup::escape_text(frame.function_name); + } + (*rows)[row]=frame; + view->selection_dialog->add_row(row); + } + + view->selection_dialog->on_select=[this, rows](const std::string& selected, bool hide_window) { + auto frame=rows->at(selected); + if(!frame.file_path.empty()) { + notebook.open(frame.file_path); + if(notebook.get_current_page()!=-1) { + auto view=notebook.get_current_view(); + + view->get_buffer()->place_cursor(view->get_buffer()->get_iter_at_line_index(frame.line_nr-1, frame.line_index-1)); + + while(g_main_context_pending(NULL)) + g_main_context_iteration(NULL, false); + if(notebook.get_current_page()!=-1 && notebook.get_current_view()==view) + view->scroll_to(view->get_buffer()->get_insert(), 0.0, 1.0, 0.5); + } + } + }; + view->selection_dialog->show(); + } + }); menu.add_action("debug_run_command", [this]() { entry_box.clear(); entry_box.entries.emplace_back(last_run_debug_command, [this](const std::string& content){