Browse Source

Finished project cleanup

merge-requests/365/head
eidheim 10 years ago
parent
commit
35ab881071
  1. 16
      src/debug.cc
  2. 2
      src/debug.h
  3. 8
      src/notebook.cc
  4. 2
      src/notebook.h
  5. 284
      src/project.cc
  6. 38
      src/project.h
  7. 305
      src/window.cc
  8. 11
      src/window.h

16
src/debug.cc

@ -36,7 +36,7 @@ Debug::Debug(): state(lldb::StateType::eStateInvalid), buffer_size(131072) {
}
void Debug::start(const std::string &command, const boost::filesystem::path &path,
std::shared_ptr<std::vector<std::pair<boost::filesystem::path, int> > > breakpoints,
const std::vector<std::pair<boost::filesystem::path, int> > &breakpoints,
std::function<void(int exit_status)> callback,
std::function<void(const std::string &status)> status_callback,
std::function<void(const boost::filesystem::path &file_path, int line_nr, int line_index)> stop_callback) {
@ -88,14 +88,12 @@ void Debug::start(const std::string &command, const boost::filesystem::path &pat
}
//Set breakpoints
if(breakpoints) {
for(auto &breakpoint: *breakpoints) {
if(!(target.BreakpointCreateByLocation(breakpoint.first.string().c_str(), breakpoint.second)).IsValid()) {
Terminal::get().async_print("Error (debug): Could not create breakpoint at: "+breakpoint.first.string()+":"+std::to_string(breakpoint.second)+'\n', true);
if(callback)
callback(-1);
return;
}
for(auto &breakpoint: breakpoints) {
if(!(target.BreakpointCreateByLocation(breakpoint.first.string().c_str(), breakpoint.second)).IsValid()) {
Terminal::get().async_print("Error (debug): Could not create breakpoint at: "+breakpoint.first.string()+":"+std::to_string(breakpoint.second)+'\n', true);
if(callback)
callback(-1);
return;
}
}

2
src/debug.h

@ -39,7 +39,7 @@ public:
}
void start(const std::string &command, const boost::filesystem::path &path="",
std::shared_ptr<std::vector<std::pair<boost::filesystem::path, int> > > breakpoints=nullptr,
const std::vector<std::pair<boost::filesystem::path, int> > &breakpoints={},
std::function<void(int exit_status)> callback=nullptr,
std::function<void(const std::string &status)> status_callback=nullptr,
std::function<void(const boost::filesystem::path &file_path, int line_nr, int line_index)> stop_callback=nullptr);

8
src/notebook.cc

@ -355,17 +355,13 @@ boost::filesystem::path Notebook::get_current_folder() {
}
std::unique_ptr<Project> Notebook::get_project() {
boost::filesystem::path file_path;
if(get_current_page()!=-1)
file_path=get_current_view()->file_path;
if(get_current_page()!=-1) {
if(get_current_view()->language->get_id()=="markdown") {
return std::unique_ptr<Project>(new ProjectMarkDown(file_path));
return std::unique_ptr<Project>(new ProjectMarkDown(*this));
}
}
return std::unique_ptr<Project>(new ProjectClang(file_path));
return std::unique_ptr<Project>(new ProjectClang(*this));
}
bool Notebook::save_modified_dialog(int page) {

2
src/notebook.h

@ -10,6 +10,8 @@
#include <map>
#include <sigc++/sigc++.h>
class Project; //Avoiding this would lead to bloated code
class Notebook : public Gtk::Notebook {
class TabLabel : public Gtk::Box {
public:

284
src/project.cc

@ -3,6 +3,9 @@
#include "terminal.h"
#include "filesystem.h"
#include <fstream>
#ifdef JUCI_ENABLE_DEBUG
#include "debug.h"
#endif
std::unordered_map<std::string, std::string> Project::run_arguments;
std::unordered_map<std::string, std::string> Project::debug_run_arguments;
@ -11,8 +14,8 @@ std::atomic<bool> Project::debugging(false);
std::unique_ptr<CMake> ProjectClang::get_cmake() {
boost::filesystem::path path;
if(!file_path.empty())
path=file_path.parent_path();
if(notebook.get_current_page()!=-1)
path=notebook.get_current_view()->file_path.parent_path();
else
path=Directories::get().current_path;
if(path.empty())
@ -37,15 +40,15 @@ std::pair<std::string, std::string> ProjectClang::get_run_arguments() {
arguments=run_arguments_it->second;
if(arguments.empty()) {
auto executable=cmake->get_executable(file_path).string();
auto executable=cmake->get_executable(notebook.get_current_page()!=-1?notebook.get_current_view()->file_path:"").string();
if(executable!="") {
auto project_path=cmake->project_path;
auto default_build_path=CMake::get_default_build_path(project_path);
if(!default_build_path.empty()) {
auto build_path=CMake::get_default_build_path(project_path);
if(!build_path.empty()) {
size_t pos=executable.find(project_path.string());
if(pos!=std::string::npos)
executable.replace(pos, project_path.string().size(), default_build_path.string());
executable.replace(pos, project_path.string().size(), build_path.string());
}
arguments=filesystem::escape_argument(executable);
}
@ -87,7 +90,7 @@ void ProjectClang::compile_and_run() {
arguments=run_arguments_it->second;
if(arguments.empty()) {
arguments=cmake->get_executable(file_path).string();
arguments=cmake->get_executable(notebook.get_current_page()!=-1?notebook.get_current_view()->file_path:"").string();
if(arguments.empty()) {
Terminal::get().print("Could not find add_executable in the following paths:\n");
for(auto &path: cmake->paths)
@ -113,6 +116,271 @@ void ProjectClang::compile_and_run() {
});
}
#ifdef JUCI_ENABLE_DEBUG
std::pair<std::string, std::string> ProjectClang::debug_get_run_arguments() {
auto cmake=get_cmake();
if(!cmake)
return {"", ""};
auto project_path=cmake->project_path.string();
auto run_arguments_it=debug_run_arguments.find(project_path);
std::string arguments;
if(run_arguments_it!=debug_run_arguments.end())
arguments=run_arguments_it->second;
if(arguments.empty()) {
auto executable=cmake->get_executable(notebook.get_current_page()!=-1?notebook.get_current_view()->file_path:"").string();
if(executable!="") {
auto project_path=cmake->project_path;
auto build_path=CMake::get_debug_build_path(project_path);
if(!build_path.empty()) {
size_t pos=executable.find(project_path.string());
if(pos!=std::string::npos)
executable.replace(pos, project_path.string().size(), build_path.string());
}
arguments=filesystem::escape_argument(executable);
}
else
arguments=filesystem::escape_argument(CMake::get_debug_build_path(cmake->project_path));
}
return {project_path, arguments};
}
void ProjectClang::debug_start(std::function<void(const std::string &status)> status_callback,
std::function<void(const boost::filesystem::path &file_path, int line_nr, int line_index)> stop_callback) {
auto cmake=get_cmake();
if(!cmake)
return;
auto project_path=cmake->project_path;
auto debug_build_path=CMake::get_debug_build_path(project_path);
if(debug_build_path.empty())
return;
if(!CMake::create_debug_build(project_path))
return;
auto run_arguments_it=debug_run_arguments.find(project_path.string());
std::string run_arguments;
if(run_arguments_it!=debug_run_arguments.end())
run_arguments=run_arguments_it->second;
if(run_arguments.empty()) {
run_arguments=cmake->get_executable(notebook.get_current_page()!=-1?notebook.get_current_view()->file_path:"").string();
if(run_arguments.empty()) {
Terminal::get().print("Could not find add_executable in the following paths:\n");
for(auto &path: cmake->paths)
Terminal::get().print(" "+path.string()+"\n");
Terminal::get().print("Solution: either use Debug Set Run Arguments, or open a source file within a directory where add_executable is set.\n", true);
return;
}
size_t pos=run_arguments.find(project_path.string());
if(pos!=std::string::npos)
run_arguments.replace(pos, project_path.string().size(), debug_build_path.string());
run_arguments=filesystem::escape_argument(run_arguments);
}
auto breakpoints=std::make_shared<std::vector<std::pair<boost::filesystem::path, int> > >();
for(int c=0;c<notebook.size();c++) {
auto view=notebook.get_view(c);
if(project_path==view->project_path) {
auto iter=view->get_buffer()->begin();
if(view->get_source_buffer()->get_source_marks_at_iter(iter, "debug_breakpoint").size()>0)
breakpoints->emplace_back(view->file_path, iter.get_line()+1);
while(view->get_source_buffer()->forward_iter_to_source_mark(iter, "debug_breakpoint"))
breakpoints->emplace_back(view->file_path, iter.get_line()+1);
}
}
debugging=true;
Terminal::get().print("Compiling and debugging "+run_arguments+"\n");
Terminal::get().async_process(Config::get().terminal.make_command, debug_build_path, [this, breakpoints, run_arguments, debug_build_path, status_callback, stop_callback](int exit_status){
if(exit_status!=EXIT_SUCCESS)
debugging=false;
else {
debug_start_mutex.lock();
Debug::get().start(run_arguments, debug_build_path, *breakpoints, [this, run_arguments](int exit_status){
debugging=false;
Terminal::get().async_print(run_arguments+" returned: "+std::to_string(exit_status)+'\n');
}, status_callback, stop_callback);
debug_start_mutex.unlock();
}
});
}
void ProjectClang::debug_continue() {
Debug::get().continue_debug();
}
void ProjectClang::debug_stop() {
if(debugging)
Debug::get().stop();
}
void ProjectClang::debug_kill() {
if(debugging)
Debug::get().kill();
}
void ProjectClang::debug_step_over() {
if(debugging)
Debug::get().step_over();
}
void ProjectClang::debug_step_into() {
if(debugging)
Debug::get().step_into();
}
void ProjectClang::debug_step_out() {
if(debugging)
Debug::get().step_out();
}
void ProjectClang::debug_backtrace() {
if(debugging && notebook.get_current_page()!=-1) {
auto backtrace=Debug::get().get_backtrace();
auto view=notebook.get_current_view();
auto iter=view->get_iter_for_dialog();
view->selection_dialog=std::unique_ptr<SelectionDialog>(new SelectionDialog(*view, view->get_buffer()->create_mark(iter), true, true));
auto rows=std::make_shared<std::unordered_map<std::string, Debug::Frame> >();
if(backtrace.size()==0)
return;
for(auto &frame: backtrace) {
std::string row="<i>"+frame.module_filename+"</i>";
//Shorten frame.function_name if it is too long
if(frame.function_name.size()>120) {
frame.function_name=frame.function_name.substr(0, 58)+"...."+frame.function_name.substr(frame.function_name.size()-58);
}
if(frame.file_path.empty())
row+=" - "+Glib::Markup::escape_text(frame.function_name);
else {
auto file_path=boost::filesystem::path(frame.file_path).filename().string();
row+=":<b>"+Glib::Markup::escape_text(file_path)+":"+std::to_string(frame.line_nr)+"</b> - "+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();
Debug::get().select_frame(frame.index);
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();
}
}
void ProjectClang::debug_show_variables() {
if(debugging && notebook.get_current_page()!=-1) {
auto variables=Debug::get().get_variables();
auto view=notebook.get_current_view();
auto iter=view->get_iter_for_dialog();
view->selection_dialog=std::unique_ptr<SelectionDialog>(new SelectionDialog(*view, view->get_buffer()->create_mark(iter), true, true));
auto rows=std::make_shared<std::unordered_map<std::string, Debug::Variable> >();
if(variables.size()==0)
return;
for(auto &variable: variables) {
std::string row="#"+std::to_string(variable.thread_index_id)+":#"+std::to_string(variable.frame_index)+":"+variable.file_path.filename().string()+":"+std::to_string(variable.line_nr)+" - <b>"+Glib::Markup::escape_text(variable.name)+"</b>";
(*rows)[row]=variable;
view->selection_dialog->add_row(row);
}
view->selection_dialog->on_select=[this, rows](const std::string& selected, bool hide_window) {
auto variable=rows->at(selected);
if(!variable.file_path.empty()) {
notebook.open(variable.file_path);
if(notebook.get_current_page()!=-1) {
auto view=notebook.get_current_view();
Debug::get().select_frame(variable.frame_index, variable.thread_index_id);
view->get_buffer()->place_cursor(view->get_buffer()->get_iter_at_line_index(variable.line_nr-1, variable.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->on_hide=[this]() {
debug_variable_tooltips.hide();
debug_variable_tooltips.clear();
};
view->selection_dialog->on_changed=[this, rows, iter](const std::string &selected) {
if(selected.empty()) {
debug_variable_tooltips.hide();
return;
}
if(notebook.get_current_page()!=-1) {
auto view=notebook.get_current_view();
debug_variable_tooltips.clear();
auto create_tooltip_buffer=[this, rows, view, selected]() {
auto variable=rows->at(selected);
auto tooltip_buffer=Gtk::TextBuffer::create(view->get_buffer()->get_tag_table());
Glib::ustring value=variable.value;
if(!value.empty()) {
Glib::ustring::iterator iter;
while(!value.validate(iter)) {
auto next_char_iter=iter;
next_char_iter++;
value.replace(iter, next_char_iter, "?");
}
tooltip_buffer->insert_with_tag(tooltip_buffer->get_insert()->get_iter(), value.substr(0, value.size()-1), "def:note");
}
return tooltip_buffer;
};
debug_variable_tooltips.emplace_back(create_tooltip_buffer, *view, view->get_buffer()->create_mark(iter), view->get_buffer()->create_mark(iter));
debug_variable_tooltips.show(true);
}
};
view->selection_dialog->show();
}
}
void ProjectClang::debug_run_command(const std::string &command) {
if(debugging) {
auto command_return=Debug::get().run_command(command);
Terminal::get().async_print(command_return.first);
Terminal::get().async_print(command_return.second, true);
}
}
void ProjectClang::debug_delete() {
debug_start_mutex.lock();
Debug::get().delete_debug();
debug_start_mutex.unlock();
}
#endif
ProjectMarkDown::~ProjectMarkDown() {
if(!last_temp_path.empty()) {
boost::filesystem::remove(last_temp_path);
@ -127,7 +395,7 @@ void ProjectMarkDown::compile_and_run() {
}
std::stringstream stdin_stream, stdout_stream;
auto exit_status=Terminal::get().process(stdin_stream, stdout_stream, "markdown "+file_path.string(), this->file_path.parent_path());
auto exit_status=Terminal::get().process(stdin_stream, stdout_stream, "markdown "+notebook.get_current_view()->file_path.string());
if(exit_status==0) {
boost::system::error_code ec;
auto temp_path=boost::filesystem::temp_directory_path(ec);

38
src/project.h

@ -1,17 +1,22 @@
#ifndef JUCI_PROJECT_H_
#define JUCI_PROJECT_H_
#include "notebook.h" //Avoiding this circular include would lead to bloated code
#include "cmake.h"
#include <boost/filesystem.hpp>
#include "directories.h"
#include <atomic>
#include <mutex>
#include "tooltips.h"
class Notebook; //Avoiding this circular include would lead to bloated code
class Project {
public:
Project(const boost::filesystem::path &file_path) : file_path(file_path) {}
Project(Notebook &notebook) : notebook(notebook) {}
virtual ~Project() {}
boost::filesystem::path file_path;
Notebook &notebook;
static std::unordered_map<std::string, std::string> run_arguments;
static std::unordered_map<std::string, std::string> debug_run_arguments;
@ -23,7 +28,10 @@ public:
virtual void compile_and_run() {}
virtual std::pair<std::string, std::string> debug_get_run_arguments() {return {"", ""};}
virtual void debug_start_continue() {}
Tooltips debug_variable_tooltips;
virtual void debug_start(std::function<void(const std::string &status)> status_callback,
std::function<void(const boost::filesystem::path &file_path, int line_nr, int line_index)> stop_callback) {}
virtual void debug_continue() {}
virtual void debug_stop() {}
virtual void debug_kill() {}
virtual void debug_step_over() {}
@ -31,25 +39,39 @@ public:
virtual void debug_step_out() {}
virtual void debug_backtrace() {}
virtual void debug_show_variables() {}
virtual void debug_run_command() {}
virtual void debug_toggle_breakpoint() {}
virtual void debug_goto_stop() {}
virtual void debug_run_command(const std::string &command) {}
virtual void debug_delete() {}
};
class ProjectClang : public Project {
public:
ProjectClang(const boost::filesystem::path &file_path) : Project(file_path) {}
ProjectClang(Notebook &notebook) : Project(notebook) {}
std::unique_ptr<CMake> get_cmake();
std::pair<std::string, std::string> get_run_arguments() override;
void compile() override;
void compile_and_run() override;
std::pair<std::string, std::string> debug_get_run_arguments() override;
std::mutex debug_start_mutex;
void debug_start(std::function<void(const std::string &status)> status_callback,
std::function<void(const boost::filesystem::path &file_path, int line_nr, int line_index)> stop_callback) override;
void debug_continue() override;
void debug_stop() override;
void debug_kill() override;
void debug_step_over() override;
void debug_step_into() override;
void debug_step_out() override;
void debug_backtrace() override;
void debug_show_variables() override;
void debug_run_command(const std::string &command) override;
void debug_delete() override;
};
class ProjectMarkDown : public Project {
public:
ProjectMarkDown(const boost::filesystem::path &file_path) : Project(file_path) {}
ProjectMarkDown(Notebook &notebook) : Project(notebook) {}
~ProjectMarkDown();
boost::filesystem::path last_temp_path;

305
src/window.cc

@ -24,7 +24,7 @@ namespace sigc {
#endif
}
Window::Window() : compiling(false), debugging(false) {
Window::Window() {
JDEBUG("start");
set_title("juCi++");
set_events(Gdk::POINTER_MOTION_MASK|Gdk::FOCUS_CHANGE_MASK|Gdk::SCROLL_MASK|Gdk::LEAVE_NOTIFY_MASK);
@ -203,22 +203,6 @@ Window::Window() : compiling(false), debugging(false) {
JDEBUG("end");
} // Window constructor
std::unique_ptr<CMake> Window::get_cmake() {
boost::filesystem::path path;
if(notebook.get_current_page()!=-1)
path=notebook.get_current_view()->file_path.parent_path();
else
path=Directories::get().current_path;
if(path.empty())
return nullptr;
auto cmake=std::unique_ptr<CMake>(new CMake(path));
if(cmake->project_path.empty())
return nullptr;
if(!CMake::create_default_build(cmake->project_path))
return nullptr;
return cmake;
}
void Window::configure() {
Config::get().load();
auto style_context = Gtk::StyleContext::create();
@ -672,32 +656,10 @@ void Window::set_menu_actions() {
#ifdef JUCI_ENABLE_DEBUG
menu.add_action("debug_set_run_arguments", [this]() {
auto cmake=get_cmake();
if(!cmake)
project=notebook.get_project();
auto run_arguments=std::make_shared<std::pair<std::string, std::string> >(project->debug_get_run_arguments());
if(run_arguments->second.empty())
return;
auto project_path=std::make_shared<boost::filesystem::path>(cmake->project_path);
auto run_arguments_it=debug_run_arguments.find(project_path->string());
std::string run_arguments;
if(run_arguments_it!=debug_run_arguments.end())
run_arguments=run_arguments_it->second;
if(run_arguments.empty()) {
auto executable=cmake->get_executable(notebook.get_current_page()!=-1?notebook.get_current_view()->file_path:"").string();
if(executable!="") {
auto project_path=cmake->project_path;
auto debug_build_path=CMake::get_debug_build_path(project_path);
if(!debug_build_path.empty()) {
size_t pos=executable.find(project_path.string());
if(pos!=std::string::npos)
executable.replace(pos, project_path.string().size(), debug_build_path.string());
}
run_arguments=filesystem::escape_argument(executable);
}
else
run_arguments=filesystem::escape_argument(CMake::get_debug_build_path(cmake->project_path));
}
entry_box.clear();
entry_box.labels.emplace_back();
@ -706,258 +668,76 @@ void Window::set_menu_actions() {
label_it->set_text("Set empty to let juCi++ deduce executable");
};
label_it->update(0, "");
entry_box.entries.emplace_back(run_arguments, [this, project_path](const std::string& content){
debug_run_arguments[project_path->string()]=content;
entry_box.entries.emplace_back(run_arguments->second, [this, run_arguments](const std::string& content){
Project::debug_run_arguments[run_arguments->first]=content;
entry_box.hide();
}, 50);
auto entry_it=entry_box.entries.begin();
entry_it->set_placeholder_text("Project: Set Run Arguments");
entry_box.buttons.emplace_back("Project: set run arguments", [this, entry_it](){
entry_it->set_placeholder_text("Debug: Set Run Arguments");
entry_box.buttons.emplace_back("Debug: set run arguments", [this, entry_it](){
entry_it->activate();
});
entry_box.show();
});
menu.add_action("debug_start_continue", [this](){
if(debugging) {
Debug::get().continue_debug();
if(Project::debugging) {
project->debug_continue();
return;
}
if(Config::get().window.save_on_compile_or_run)
notebook.save_project_files();
auto cmake=get_cmake();
if(!cmake)
return;
auto project_path=cmake->project_path;
auto debug_build_path=CMake::get_debug_build_path(project_path);
if(debug_build_path.empty())
return;
if(!CMake::create_debug_build(project_path))
return;
auto run_arguments_it=debug_run_arguments.find(project_path.string());
std::string run_arguments;
if(run_arguments_it!=debug_run_arguments.end())
run_arguments=run_arguments_it->second;
std::string command;
if(!run_arguments.empty()) {
command=run_arguments;
}
else {
command=cmake->get_executable(notebook.get_current_page()!=-1?notebook.get_current_view()->file_path:"").string();
if(command.empty()) {
Terminal::get().print("Could not find add_executable in the following paths:\n");
for(auto &path: cmake->paths)
Terminal::get().print(" "+path.string()+"\n");
Terminal::get().print("Solution: either use Debug Set Run Arguments, or open a source file within a directory where add_executable is set.\n", true);
return;
}
size_t pos=command.find(project_path.string());
if(pos!=std::string::npos)
command.replace(pos, project_path.string().size(), debug_build_path.string());
command=filesystem::escape_argument(command);
}
auto breakpoints=std::make_shared<std::vector<std::pair<boost::filesystem::path, int> > >();
for(int c=0;c<notebook.size();c++) {
auto view=notebook.get_view(c);
if(project_path==view->project_path) {
auto iter=view->get_buffer()->begin();
if(view->get_source_buffer()->get_source_marks_at_iter(iter, "debug_breakpoint").size()>0)
breakpoints->emplace_back(view->file_path, iter.get_line()+1);
while(view->get_source_buffer()->forward_iter_to_source_mark(iter, "debug_breakpoint"))
breakpoints->emplace_back(view->file_path, iter.get_line()+1);
}
}
project=notebook.get_project();
debugging=true;
Terminal::get().print("Compiling and debugging "+command+"\n");
Terminal::get().async_process(Config::get().terminal.make_command, debug_build_path, [this, breakpoints, command, debug_build_path](int exit_status){
if(exit_status!=EXIT_SUCCESS)
debugging=false;
else {
debug_start_mutex.lock();
Debug::get().start(command, debug_build_path, breakpoints, [this, command](int exit_status){
debugging=false;
Terminal::get().async_print(command+" returned: "+std::to_string(exit_status)+'\n');
}, [this](const std::string &status) {
debug_status_mutex.lock();
debug_status=status;
debug_status_mutex.unlock();
debug_update_status();
}, [this](const boost::filesystem::path &file_path, int line_nr, int line_index) {
debug_stop_mutex.lock();
debug_stop.first=file_path;
debug_stop.second.first=line_nr;
debug_stop.second.second=line_index;
debug_stop_mutex.unlock();
debug_update_stop();
//Remove debug stop source mark
});
debug_start_mutex.unlock();
}
project->debug_start([this](const std::string &status) {
debug_status_mutex.lock();
debug_status=status;
debug_status_mutex.unlock();
debug_update_status();
}, [this](const boost::filesystem::path &file_path, int line_nr, int line_index) {
debug_stop_mutex.lock();
debug_stop.first=file_path;
debug_stop.second.first=line_nr;
debug_stop.second.second=line_index;
debug_stop_mutex.unlock();
debug_update_stop();
});
});
menu.add_action("debug_stop", [this]() {
if(debugging) {
Debug::get().stop();
}
if(project)
project->debug_stop();
});
menu.add_action("debug_kill", [this]() {
if(debugging) {
Debug::get().kill();
}
if(project)
project->debug_kill();
});
menu.add_action("debug_step_over", [this]() {
if(debugging)
Debug::get().step_over();
if(project)
project->debug_step_over();
});
menu.add_action("debug_step_into", [this]() {
if(debugging)
Debug::get().step_into();
if(project)
project->debug_step_into();
});
menu.add_action("debug_step_out", [this]() {
if(debugging)
Debug::get().step_out();
if(project)
project->debug_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 iter=view->get_iter_for_dialog();
view->selection_dialog=std::unique_ptr<SelectionDialog>(new SelectionDialog(*view, view->get_buffer()->create_mark(iter), true, true));
auto rows=std::make_shared<std::unordered_map<std::string, Debug::Frame> >();
if(backtrace.size()==0)
return;
for(auto &frame: backtrace) {
std::string row="<i>"+frame.module_filename+"</i>";
//Shorten frame.function_name if it is too long
if(frame.function_name.size()>120) {
frame.function_name=frame.function_name.substr(0, 58)+"...."+frame.function_name.substr(frame.function_name.size()-58);
}
if(frame.file_path.empty())
row+=" - "+Glib::Markup::escape_text(frame.function_name);
else {
auto file_path=boost::filesystem::path(frame.file_path).filename().string();
row+=":<b>"+Glib::Markup::escape_text(file_path)+":"+std::to_string(frame.line_nr)+"</b> - "+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();
Debug::get().select_frame(frame.index);
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();
}
if(project)
project->debug_backtrace();
});
menu.add_action("debug_show_variables", [this]() {
if(debugging && notebook.get_current_page()!=-1) {
auto variables=Debug::get().get_variables();
auto view=notebook.get_current_view();
auto iter=view->get_iter_for_dialog();
view->selection_dialog=std::unique_ptr<SelectionDialog>(new SelectionDialog(*view, view->get_buffer()->create_mark(iter), true, true));
auto rows=std::make_shared<std::unordered_map<std::string, Debug::Variable> >();
if(variables.size()==0)
return;
for(auto &variable: variables) {
std::string row="#"+std::to_string(variable.thread_index_id)+":#"+std::to_string(variable.frame_index)+":"+variable.file_path.filename().string()+":"+std::to_string(variable.line_nr)+" - <b>"+Glib::Markup::escape_text(variable.name)+"</b>";
(*rows)[row]=variable;
view->selection_dialog->add_row(row);
}
view->selection_dialog->on_select=[this, rows](const std::string& selected, bool hide_window) {
auto variable=rows->at(selected);
if(!variable.file_path.empty()) {
notebook.open(variable.file_path);
if(notebook.get_current_page()!=-1) {
auto view=notebook.get_current_view();
Debug::get().select_frame(variable.frame_index, variable.thread_index_id);
view->get_buffer()->place_cursor(view->get_buffer()->get_iter_at_line_index(variable.line_nr-1, variable.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->on_hide=[this]() {
debug_variable_tooltips.hide();
debug_variable_tooltips.clear();
};
view->selection_dialog->on_changed=[this, rows, iter](const std::string &selected) {
if(selected.empty()) {
debug_variable_tooltips.hide();
return;
}
if(notebook.get_current_page()!=-1) {
auto view=notebook.get_current_view();
debug_variable_tooltips.clear();
auto create_tooltip_buffer=[this, rows, view, selected]() {
auto variable=rows->at(selected);
auto tooltip_buffer=Gtk::TextBuffer::create(view->get_buffer()->get_tag_table());
Glib::ustring value=variable.value;
if(!value.empty()) {
Glib::ustring::iterator iter;
while(!value.validate(iter)) {
auto next_char_iter=iter;
next_char_iter++;
value.replace(iter, next_char_iter, "?");
}
tooltip_buffer->insert_with_tag(tooltip_buffer->get_insert()->get_iter(), value.substr(0, value.size()-1), "def:note");
}
return tooltip_buffer;
};
debug_variable_tooltips.emplace_back(create_tooltip_buffer, *view, view->get_buffer()->create_mark(iter), view->get_buffer()->create_mark(iter));
debug_variable_tooltips.show(true);
}
};
view->selection_dialog->show();
}
if(project)
project->debug_show_variables();
});
menu.add_action("debug_run_command", [this]() {
entry_box.clear();
entry_box.entries.emplace_back(last_run_debug_command, [this](const std::string& content){
if(content!="") {
if(debugging) {
auto command_return=Debug::get().run_command(content);
Terminal::get().async_print(command_return.first);
Terminal::get().async_print(command_return.second, true);
}
if(project)
project->debug_run_command(content);
last_run_debug_command=content;
}
entry_box.hide();
@ -993,7 +773,7 @@ void Window::set_menu_actions() {
}
});
menu.add_action("debug_goto_stop", [this](){
if(debugging) {
if(project && project->debugging) {
debug_stop_mutex.lock();
auto debug_stop_copy=debug_stop;
debug_stop_mutex.unlock();
@ -1119,9 +899,8 @@ bool Window::on_delete_event(GdkEventAny *event) {
}
Terminal::get().kill_async_processes();
#ifdef JUCI_ENABLE_DEBUG
debug_start_mutex.lock();
Debug::get().delete_debug();
debug_start_mutex.unlock();
if(project)
project->debug_delete();
#endif
return false;
}

11
src/window.h

@ -5,7 +5,6 @@
#include "entrybox.h"
#include "notebook.h"
#include "cmake.h"
#include "tooltips.h"
#include "project.h"
#include <atomic>
@ -37,12 +36,8 @@ private:
std::unique_ptr<Project> project;
std::atomic<bool> compiling;
std::atomic<bool> debugging;
Gtk::Label debug_status_label;
std::mutex debug_start_mutex;
std::pair<boost::filesystem::path, std::pair<int, int> > debug_stop;
boost::filesystem::path debug_last_stop_file_path;
std::mutex debug_stop_mutex;
@ -50,12 +45,6 @@ private:
std::string debug_status;
std::mutex debug_status_mutex;
Glib::Dispatcher debug_update_status;
Tooltips debug_variable_tooltips;
std::unique_ptr<CMake> get_cmake();
std::unordered_map<std::string, std::string> project_run_arguments;
std::unordered_map<std::string, std::string> debug_run_arguments;
void configure();
void set_menu_actions();

Loading…
Cancel
Save