Browse Source

More project cleanup, getting there, soon done

merge-requests/365/head
eidheim 10 years ago
parent
commit
e9cc73471d
  1. 3
      src/dialogs.cc
  2. 3
      src/juci.cc
  3. 9
      src/notebook.h
  4. 230
      src/project.cc
  5. 71
      src/project.h
  6. 199
      src/window.cc
  7. 19
      src/window.h

3
src/dialogs.cc

@ -1,5 +1,6 @@
#include "dialogs.h" #include "dialogs.h"
#include "window.h" #include "window.h"
#include "notebook.h"
#include <cmath> #include <cmath>
namespace sigc { namespace sigc {
@ -34,7 +35,7 @@ std::string Dialog::gtk_dialog(const std::string &title,
dialog.set_transient_for(Window::get()); dialog.set_transient_for(Window::get());
auto current_path=Window::get().notebook.get_current_folder(); auto current_path=Notebook::get().get_current_folder();
boost::system::error_code ec; boost::system::error_code ec;
if(current_path.empty()) if(current_path.empty())
current_path=boost::filesystem::current_path(ec); current_path=boost::filesystem::current_path(ec);

3
src/juci.cc

@ -1,5 +1,6 @@
#include "juci.h" #include "juci.h"
#include "window.h" #include "window.h"
#include "notebook.h"
#include "directories.h" #include "directories.h"
#include "menu.h" #include "menu.h"
#include "config.h" #include "config.h"
@ -68,7 +69,7 @@ void Application::on_activate() {
} }
for(auto &file: files) for(auto &file: files)
Window::get().notebook.open(file); Notebook::get().open(file);
for(auto &error: errors) for(auto &error: errors)
Terminal::get().print(error, true); Terminal::get().print(error, true);

9
src/notebook.h

@ -16,8 +16,15 @@ class Notebook : public Gtk::Notebook {
Gtk::Label label; Gtk::Label label;
Gtk::Button button; Gtk::Button button;
}; };
public:
private:
Notebook(); Notebook();
public:
static Notebook &get() {
static Notebook singleton;
return singleton;
}
Source::View* get_view(int page); Source::View* get_view(int page);
size_t get_index(int page); size_t get_index(int page);
int size(); int size();

230
src/project.cc

@ -3,16 +3,98 @@
#include "terminal.h" #include "terminal.h"
#include "filesystem.h" #include "filesystem.h"
#include <fstream> #include <fstream>
#include "menu.h"
#ifdef JUCI_ENABLE_DEBUG #ifdef JUCI_ENABLE_DEBUG
#include "debug.h" #include "debug.h"
#endif #endif
std::unordered_map<std::string, std::string> Project::run_arguments; Project::Project() : notebook(Notebook::get()), compiling(false), debugging(false) {
std::unordered_map<std::string, std::string> Project::debug_run_arguments; debug_update_stop.connect([this](){
std::atomic<bool> Project::compiling(false); debug_stop_mutex.lock();
std::atomic<bool> Project::debugging(false); for(int c=0;c<notebook.size();c++) {
auto view=notebook.get_view(c);
if(view->file_path==debug_last_stop_file_path) {
view->get_source_buffer()->remove_source_marks(view->get_buffer()->begin(), view->get_buffer()->end(), "debug_stop");
break;
}
}
//Add debug stop source mark
for(int c=0;c<notebook.size();c++) {
auto view=notebook.get_view(c);
if(view->file_path==debug_stop.first) {
if(debug_stop.second.first-1<view->get_buffer()->get_line_count()) {
view->get_source_buffer()->create_source_mark("debug_stop", view->get_buffer()->get_iter_at_line(debug_stop.second.first-1));
debug_last_stop_file_path=debug_stop.first;
}
break;
}
}
if(notebook.get_current_page()!=-1)
notebook.get_current_view()->get_buffer()->place_cursor(notebook.get_current_view()->get_buffer()->get_insert()->get_iter());
debug_stop_mutex.unlock();
});
#ifdef JUCI_ENABLE_DEBUG
auto &menu=Menu::get();
menu.actions["debug_stop"]->set_enabled(false);
menu.actions["debug_kill"]->set_enabled(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_show_variables"]->set_enabled(false);
menu.actions["debug_run_command"]->set_enabled(false);
menu.actions["debug_goto_stop"]->set_enabled(false);
#endif
debug_update_status.connect([this](){
debug_status_mutex.lock();
if(debug_status.empty()) {
debug_status_label.set_text("");
auto &menu=Menu::get();
menu.actions["debug_stop"]->set_enabled(false);
menu.actions["debug_kill"]->set_enabled(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_show_variables"]->set_enabled(false);
menu.actions["debug_run_command"]->set_enabled(false);
menu.actions["debug_goto_stop"]->set_enabled(false);
}
else {
debug_status_label.set_text("debug: "+debug_status);
auto &menu=Menu::get();
menu.actions["debug_stop"]->set_enabled();
menu.actions["debug_kill"]->set_enabled();
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_show_variables"]->set_enabled();
menu.actions["debug_run_command"]->set_enabled();
menu.actions["debug_goto_stop"]->set_enabled();
}
debug_status_mutex.unlock();
});
}
std::unique_ptr<Project::Language> Project::get_language() {
if(notebook.get_current_page()!=-1) {
auto language_id=notebook.get_current_view()->language->get_id();
if(language_id=="markdown")
return std::unique_ptr<Project::Language>(new Project::Markdown());
if(language_id=="python")
return std::unique_ptr<Project::Language>(new Project::Python());
if(language_id=="js")
return std::unique_ptr<Project::Language>(new Project::JavaScript());
if(language_id=="html")
return std::unique_ptr<Project::Language>(new Project::HTML());
}
std::unique_ptr<CMake> ProjectClang::get_cmake() { return std::unique_ptr<Project::Language>(new Project::Clang());
}
std::unique_ptr<CMake> Project::Clang::get_cmake() {
boost::filesystem::path path; boost::filesystem::path path;
if(notebook.get_current_page()!=-1) if(notebook.get_current_page()!=-1)
path=notebook.get_current_view()->file_path.parent_path(); path=notebook.get_current_view()->file_path.parent_path();
@ -28,15 +110,15 @@ std::unique_ptr<CMake> ProjectClang::get_cmake() {
return cmake; return cmake;
} }
std::pair<std::string, std::string> ProjectClang::get_run_arguments() { std::pair<std::string, std::string> Project::Clang::get_run_arguments() {
auto cmake=get_cmake(); auto cmake=get_cmake();
if(!cmake) if(!cmake)
return {"", ""}; return {"", ""};
auto project_path=cmake->project_path.string(); auto project_path=cmake->project_path.string();
auto run_arguments_it=run_arguments.find(project_path); auto run_arguments_it=Project::get().run_arguments.find(project_path);
std::string arguments; std::string arguments;
if(run_arguments_it!=run_arguments.end()) if(run_arguments_it!=Project::get().run_arguments.end())
arguments=run_arguments_it->second; arguments=run_arguments_it->second;
if(arguments.empty()) { if(arguments.empty()) {
@ -59,7 +141,7 @@ std::pair<std::string, std::string> ProjectClang::get_run_arguments() {
return {project_path, arguments}; return {project_path, arguments};
} }
void ProjectClang::compile() { void Project::Clang::compile() {
auto cmake=get_cmake(); auto cmake=get_cmake();
if(!cmake) if(!cmake)
return; return;
@ -67,14 +149,14 @@ void ProjectClang::compile() {
auto default_build_path=CMake::get_default_build_path(cmake->project_path); auto default_build_path=CMake::get_default_build_path(cmake->project_path);
if(default_build_path.empty()) if(default_build_path.empty())
return; return;
compiling=true; Project::get().compiling=true;
Terminal::get().print("Compiling project "+cmake->project_path.string()+"\n"); Terminal::get().print("Compiling project "+cmake->project_path.string()+"\n");
Terminal::get().async_process(Config::get().terminal.make_command, default_build_path, [this](int exit_status) { Terminal::get().async_process(Config::get().terminal.make_command, default_build_path, [this](int exit_status) {
compiling=false; Project::get().compiling=false;
}); });
} }
void ProjectClang::compile_and_run() { void Project::Clang::compile_and_run() {
auto cmake=get_cmake(); auto cmake=get_cmake();
if(!cmake) if(!cmake)
return; return;
@ -84,9 +166,9 @@ void ProjectClang::compile_and_run() {
if(default_build_path.empty()) if(default_build_path.empty())
return; return;
auto run_arguments_it=run_arguments.find(project_path.string()); auto run_arguments_it=Project::get().run_arguments.find(project_path.string());
std::string arguments; std::string arguments;
if(run_arguments_it!=run_arguments.end()) if(run_arguments_it!=Project::get().run_arguments.end())
arguments=run_arguments_it->second; arguments=run_arguments_it->second;
if(arguments.empty()) { if(arguments.empty()) {
@ -104,10 +186,10 @@ void ProjectClang::compile_and_run() {
arguments=filesystem::escape_argument(arguments); arguments=filesystem::escape_argument(arguments);
} }
compiling=true; Project::get().compiling=true;
Terminal::get().print("Compiling and running "+arguments+"\n"); Terminal::get().print("Compiling and running "+arguments+"\n");
Terminal::get().async_process(Config::get().terminal.make_command, default_build_path, [this, arguments, default_build_path](int exit_status){ Terminal::get().async_process(Config::get().terminal.make_command, default_build_path, [this, arguments, default_build_path](int exit_status){
compiling=false; Project::get().compiling=false;
if(exit_status==EXIT_SUCCESS) { if(exit_status==EXIT_SUCCESS) {
Terminal::get().async_process(arguments, default_build_path, [this, arguments](int exit_status){ Terminal::get().async_process(arguments, default_build_path, [this, arguments](int exit_status){
Terminal::get().async_print(arguments+" returned: "+std::to_string(exit_status)+'\n'); Terminal::get().async_print(arguments+" returned: "+std::to_string(exit_status)+'\n');
@ -117,15 +199,15 @@ void ProjectClang::compile_and_run() {
} }
#ifdef JUCI_ENABLE_DEBUG #ifdef JUCI_ENABLE_DEBUG
std::pair<std::string, std::string> ProjectClang::debug_get_run_arguments() { std::pair<std::string, std::string> Project::Clang::debug_get_run_arguments() {
auto cmake=get_cmake(); auto cmake=get_cmake();
if(!cmake) if(!cmake)
return {"", ""}; return {"", ""};
auto project_path=cmake->project_path.string(); auto project_path=cmake->project_path.string();
auto run_arguments_it=debug_run_arguments.find(project_path); auto run_arguments_it=Project::get().debug_run_arguments.find(project_path);
std::string arguments; std::string arguments;
if(run_arguments_it!=debug_run_arguments.end()) if(run_arguments_it!=Project::get().debug_run_arguments.end())
arguments=run_arguments_it->second; arguments=run_arguments_it->second;
if(arguments.empty()) { if(arguments.empty()) {
@ -148,8 +230,7 @@ std::pair<std::string, std::string> ProjectClang::debug_get_run_arguments() {
return {project_path, arguments}; return {project_path, arguments};
} }
void ProjectClang::debug_start(std::function<void(const std::string &status)> status_callback, void Project::Clang::debug_start() {
std::function<void(const boost::filesystem::path &file_path, int line_nr, int line_index)> stop_callback) {
auto cmake=get_cmake(); auto cmake=get_cmake();
if(!cmake) if(!cmake)
return; return;
@ -161,9 +242,9 @@ void ProjectClang::debug_start(std::function<void(const std::string &status)> st
if(!CMake::create_debug_build(project_path)) if(!CMake::create_debug_build(project_path))
return; return;
auto run_arguments_it=debug_run_arguments.find(project_path.string()); auto run_arguments_it=Project::get().debug_run_arguments.find(project_path.string());
std::string run_arguments; std::string run_arguments;
if(run_arguments_it!=debug_run_arguments.end()) if(run_arguments_it!=Project::get().debug_run_arguments.end())
run_arguments=run_arguments_it->second; run_arguments=run_arguments_it->second;
if(run_arguments.empty()) { if(run_arguments.empty()) {
@ -193,53 +274,67 @@ void ProjectClang::debug_start(std::function<void(const std::string &status)> st
} }
} }
debugging=true; Project::get().debugging=true;
Terminal::get().print("Compiling and debugging "+run_arguments+"\n"); 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){ Terminal::get().async_process(Config::get().terminal.make_command, debug_build_path, [this, breakpoints, run_arguments, debug_build_path](int exit_status){
if(exit_status!=EXIT_SUCCESS) if(exit_status!=EXIT_SUCCESS)
debugging=false; Project::get().debugging=false;
else { else {
debug_start_mutex.lock(); debug_start_mutex.lock();
Debug::get().start(run_arguments, debug_build_path, *breakpoints, [this, run_arguments](int exit_status){ Debug::get().start(run_arguments, debug_build_path, *breakpoints, [this, run_arguments](int exit_status){
debugging=false; Project::get().debugging=false;
Terminal::get().async_print(run_arguments+" returned: "+std::to_string(exit_status)+'\n'); Terminal::get().async_print(run_arguments+" returned: "+std::to_string(exit_status)+'\n');
}, status_callback, stop_callback); }, [this](const std::string &status) {
auto &project=Project::get();
project.debug_status_mutex.lock();
project.debug_status=status;
project.debug_status_mutex.unlock();
project.debug_update_status();
}, [this](const boost::filesystem::path &file_path, int line_nr, int line_index) {
auto &project=Project::get();
project.debug_stop_mutex.lock();
project.debug_stop.first=file_path;
project.debug_stop.second.first=line_nr;
project.debug_stop.second.second=line_index;
project.debug_stop_mutex.unlock();
project.debug_update_stop();
});
debug_start_mutex.unlock(); debug_start_mutex.unlock();
} }
}); });
} }
void ProjectClang::debug_continue() { void Project::Clang::debug_continue() {
Debug::get().continue_debug(); Debug::get().continue_debug();
} }
void ProjectClang::debug_stop() { void Project::Clang::debug_stop() {
if(debugging) if(Project::get().debugging)
Debug::get().stop(); Debug::get().stop();
} }
void ProjectClang::debug_kill() { void Project::Clang::debug_kill() {
if(debugging) if(Project::get().debugging)
Debug::get().kill(); Debug::get().kill();
} }
void ProjectClang::debug_step_over() { void Project::Clang::debug_step_over() {
if(debugging) if(Project::get().debugging)
Debug::get().step_over(); Debug::get().step_over();
} }
void ProjectClang::debug_step_into() { void Project::Clang::debug_step_into() {
if(debugging) if(Project::get().debugging)
Debug::get().step_into(); Debug::get().step_into();
} }
void ProjectClang::debug_step_out() { void Project::Clang::debug_step_out() {
if(debugging) if(Project::get().debugging)
Debug::get().step_out(); Debug::get().step_out();
} }
void ProjectClang::debug_backtrace() { void Project::Clang::debug_backtrace() {
if(debugging && notebook.get_current_page()!=-1) { if(Project::get().debugging && notebook.get_current_page()!=-1) {
auto backtrace=Debug::get().get_backtrace(); auto backtrace=Debug::get().get_backtrace();
auto view=notebook.get_current_view(); auto view=notebook.get_current_view();
@ -288,8 +383,8 @@ void ProjectClang::debug_backtrace() {
} }
} }
void ProjectClang::debug_show_variables() { void Project::Clang::debug_show_variables() {
if(debugging && notebook.get_current_page()!=-1) { if(Project::get().debugging && notebook.get_current_page()!=-1) {
auto variables=Debug::get().get_variables(); auto variables=Debug::get().get_variables();
auto view=notebook.get_current_view(); auto view=notebook.get_current_view();
@ -366,29 +461,62 @@ void ProjectClang::debug_show_variables() {
} }
} }
void ProjectClang::debug_run_command(const std::string &command) { void Project::Clang::debug_run_command(const std::string &command) {
if(debugging) { if(Project::get().debugging) {
auto command_return=Debug::get().run_command(command); auto command_return=Debug::get().run_command(command);
Terminal::get().async_print(command_return.first); Terminal::get().async_print(command_return.first);
Terminal::get().async_print(command_return.second, true); Terminal::get().async_print(command_return.second, true);
} }
} }
void ProjectClang::debug_delete() { void Project::Clang::debug_goto_stop() {
if(Project::get().debugging) {
auto &project=Project::get();
project.debug_stop_mutex.lock();
auto debug_stop_copy=project.debug_stop;
project.debug_stop_mutex.unlock();
if(!debug_stop_copy.first.empty()) {
notebook.open(debug_stop_copy.first);
if(notebook.get_current_page()!=-1) {
auto view=notebook.get_current_view();
int line_nr=debug_stop_copy.second.first-1;
int line_index=debug_stop_copy.second.second-1;
if(line_nr<view->get_buffer()->get_line_count()) {
auto iter=view->get_buffer()->get_iter_at_line(line_nr);
auto end_line_iter=iter;
while(!iter.ends_line() && iter.forward_char()) {}
auto line=view->get_buffer()->get_text(iter, end_line_iter);
if(static_cast<size_t>(line_index)>=line.bytes())
line_index=0;
view->get_buffer()->place_cursor(view->get_buffer()->get_iter_at_line_index(line_nr, line_index));
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);
}
project.debug_update_stop();
}
}
}
}
void Project::Clang::debug_delete() {
debug_start_mutex.lock(); debug_start_mutex.lock();
Debug::get().delete_debug(); Debug::get().delete_debug();
debug_start_mutex.unlock(); debug_start_mutex.unlock();
} }
#endif #endif
ProjectMarkdown::~ProjectMarkdown() { Project::Markdown::~Markdown() {
if(!last_temp_path.empty()) { if(!last_temp_path.empty()) {
boost::filesystem::remove(last_temp_path); boost::filesystem::remove(last_temp_path);
last_temp_path=boost::filesystem::path(); last_temp_path=boost::filesystem::path();
} }
} }
void ProjectMarkdown::compile_and_run() { void Project::Markdown::compile_and_run() {
if(!last_temp_path.empty()) { if(!last_temp_path.empty()) {
boost::filesystem::remove(last_temp_path); boost::filesystem::remove(last_temp_path);
last_temp_path=boost::filesystem::path(); last_temp_path=boost::filesystem::path();
@ -424,7 +552,7 @@ void ProjectMarkdown::compile_and_run() {
} }
} }
void ProjectPython::compile_and_run() { void Project::Python::compile_and_run() {
auto command="python "+notebook.get_current_view()->file_path.string(); auto command="python "+notebook.get_current_view()->file_path.string();
Terminal::get().print("Running "+command+"\n"); Terminal::get().print("Running "+command+"\n");
Terminal::get().async_process(command, notebook.get_current_view()->file_path.parent_path(), [command](int exit_status) { Terminal::get().async_process(command, notebook.get_current_view()->file_path.parent_path(), [command](int exit_status) {
@ -432,7 +560,7 @@ void ProjectPython::compile_and_run() {
}); });
} }
void ProjectJavaScript::compile_and_run() { void Project::JavaScript::compile_and_run() {
auto command="node "+notebook.get_current_view()->file_path.string(); auto command="node "+notebook.get_current_view()->file_path.string();
Terminal::get().print("Running "+command+"\n"); Terminal::get().print("Running "+command+"\n");
Terminal::get().async_process(command, notebook.get_current_view()->file_path.parent_path(), [command](int exit_status) { Terminal::get().async_process(command, notebook.get_current_view()->file_path.parent_path(), [command](int exit_status) {
@ -440,7 +568,7 @@ void ProjectJavaScript::compile_and_run() {
}); });
} }
void ProjectHTML::compile_and_run() { void Project::HTML::compile_and_run() {
auto uri=notebook.get_current_view()->file_path.string(); auto uri=notebook.get_current_view()->file_path.string();
#ifdef __APPLE__ #ifdef __APPLE__
Terminal::get().process("open \""+uri+"\""); Terminal::get().process("open \""+uri+"\"");

71
src/project.h

@ -1,6 +1,7 @@
#ifndef JUCI_PROJECT_H_ #ifndef JUCI_PROJECT_H_
#define JUCI_PROJECT_H_ #define JUCI_PROJECT_H_
#include <gtkmm.h>
#include "notebook.h" #include "notebook.h"
#include "cmake.h" #include "cmake.h"
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
@ -10,16 +11,35 @@
#include "tooltips.h" #include "tooltips.h"
class Project { class Project {
private:
std::pair<boost::filesystem::path, std::pair<int, int> > debug_stop;
std::mutex debug_stop_mutex;
boost::filesystem::path debug_last_stop_file_path;
Glib::Dispatcher debug_update_stop;
std::string debug_status;
std::mutex debug_status_mutex;
Glib::Dispatcher debug_update_status;
Project();
Notebook &notebook; //convenience reference
public: public:
Project(Notebook &notebook) : notebook(notebook) {} static Project &get() {
virtual ~Project() {} static Project singleton;
return singleton;
Notebook &notebook; }
static std::unordered_map<std::string, std::string> run_arguments; Gtk::Label debug_status_label;
static std::unordered_map<std::string, std::string> debug_run_arguments; std::unordered_map<std::string, std::string> run_arguments;
static std::atomic<bool> compiling; std::unordered_map<std::string, std::string> debug_run_arguments;
static std::atomic<bool> debugging; std::atomic<bool> compiling;
std::atomic<bool> debugging;
class Language {
protected:
Notebook &notebook; //convenience reference
public:
Language() : notebook(Notebook::get()) {}
virtual ~Language() {}
virtual std::pair<std::string, std::string> get_run_arguments() {return {"", ""};} virtual std::pair<std::string, std::string> get_run_arguments() {return {"", ""};}
virtual void compile() {} virtual void compile() {}
@ -27,8 +47,7 @@ public:
virtual std::pair<std::string, std::string> debug_get_run_arguments() {return {"", ""};} virtual std::pair<std::string, std::string> debug_get_run_arguments() {return {"", ""};}
Tooltips debug_variable_tooltips; Tooltips debug_variable_tooltips;
virtual void debug_start(std::function<void(const std::string &status)> status_callback, virtual void debug_start() {}
std::function<void(const boost::filesystem::path &file_path, int line_nr, int line_index)> stop_callback) {}
virtual void debug_continue() {} virtual void debug_continue() {}
virtual void debug_stop() {} virtual void debug_stop() {}
virtual void debug_kill() {} virtual void debug_kill() {}
@ -38,12 +57,13 @@ public:
virtual void debug_backtrace() {} virtual void debug_backtrace() {}
virtual void debug_show_variables() {} virtual void debug_show_variables() {}
virtual void debug_run_command(const std::string &command) {} virtual void debug_run_command(const std::string &command) {}
virtual void debug_goto_stop() {}
virtual void debug_delete() {} virtual void debug_delete() {}
}; };
class ProjectClang : public Project { class Clang : public Language {
public: public:
ProjectClang(Notebook &notebook) : Project(notebook) {} Clang() : Language() {}
std::unique_ptr<CMake> get_cmake(); std::unique_ptr<CMake> get_cmake();
@ -54,8 +74,7 @@ public:
std::mutex debug_start_mutex; std::mutex debug_start_mutex;
#ifdef JUCI_ENABLE_DEBUG #ifdef JUCI_ENABLE_DEBUG
std::pair<std::string, std::string> debug_get_run_arguments() override; std::pair<std::string, std::string> debug_get_run_arguments() override;
void debug_start(std::function<void(const std::string &status)> status_callback, void debug_start() override;
std::function<void(const boost::filesystem::path &file_path, int line_nr, int line_index)> stop_callback) override;
void debug_continue() override; void debug_continue() override;
void debug_stop() override; void debug_stop() override;
void debug_kill() override; void debug_kill() override;
@ -65,38 +84,42 @@ public:
void debug_backtrace() override; void debug_backtrace() override;
void debug_show_variables() override; void debug_show_variables() override;
void debug_run_command(const std::string &command) override; void debug_run_command(const std::string &command) override;
void debug_goto_stop() override;
void debug_delete() override; void debug_delete() override;
#endif #endif
}; };
class ProjectMarkdown : public Project { class Markdown : public Language {
public: public:
ProjectMarkdown(Notebook &notebook) : Project(notebook) {} Markdown() : Language() {}
~ProjectMarkdown(); ~Markdown();
boost::filesystem::path last_temp_path; boost::filesystem::path last_temp_path;
void compile_and_run() override; void compile_and_run() override;
}; };
class ProjectPython : public Project { class Python : public Language {
public: public:
ProjectPython(Notebook &notebook) : Project(notebook) {} Python() : Language() {}
void compile_and_run() override; void compile_and_run() override;
}; };
class ProjectJavaScript : public Project { class JavaScript : public Language {
public: public:
ProjectJavaScript(Notebook &notebook) : Project(notebook) {} JavaScript() : Language() {}
void compile_and_run() override; void compile_and_run() override;
}; };
class ProjectHTML : public Project { class HTML : public Language {
public: public:
ProjectHTML(Notebook &notebook) : Project(notebook) {} HTML() : Language() {}
void compile_and_run() override; void compile_and_run() override;
}; };
std::unique_ptr<Language> get_language();
};
#endif // JUCI_PROJECT_H_ #endif // JUCI_PROJECT_H_

199
src/window.cc

@ -24,7 +24,7 @@ namespace sigc {
#endif #endif
} }
Window::Window() { Window::Window() : notebook(Notebook::get()) {
JDEBUG("start"); JDEBUG("start");
set_title("juCi++"); set_title("juCi++");
set_events(Gdk::POINTER_MOTION_MASK|Gdk::FOCUS_CHANGE_MASK|Gdk::SCROLL_MASK|Gdk::LEAVE_NOTIFY_MASK); set_events(Gdk::POINTER_MOTION_MASK|Gdk::FOCUS_CHANGE_MASK|Gdk::SCROLL_MASK|Gdk::LEAVE_NOTIFY_MASK);
@ -50,7 +50,7 @@ Window::Window() {
info_and_status_hbox.pack_start(notebook.info, Gtk::PACK_SHRINK); info_and_status_hbox.pack_start(notebook.info, Gtk::PACK_SHRINK);
#if GTK_VERSION_GE(3, 12) #if GTK_VERSION_GE(3, 12)
info_and_status_hbox.set_center_widget(debug_status_label); info_and_status_hbox.set_center_widget(Project::get().debug_status_label);
#else #else
debug_status_label.set_halign(Gtk::Align::ALIGN_CENTER); debug_status_label.set_halign(Gtk::Align::ALIGN_CENTER);
info_and_status_hbox.pack_start(debug_status_label); info_and_status_hbox.pack_start(debug_status_label);
@ -121,74 +121,6 @@ Window::Window() {
about.hide(); about.hide();
}); });
debug_update_stop.connect([this](){
debug_stop_mutex.lock();
for(int c=0;c<notebook.size();c++) {
auto view=notebook.get_view(c);
if(view->file_path==debug_last_stop_file_path) {
view->get_source_buffer()->remove_source_marks(view->get_buffer()->begin(), view->get_buffer()->end(), "debug_stop");
break;
}
}
//Add debug stop source mark
for(int c=0;c<notebook.size();c++) {
auto view=notebook.get_view(c);
if(view->file_path==debug_stop.first) {
if(debug_stop.second.first-1<view->get_buffer()->get_line_count()) {
view->get_source_buffer()->create_source_mark("debug_stop", view->get_buffer()->get_iter_at_line(debug_stop.second.first-1));
debug_last_stop_file_path=debug_stop.first;
}
break;
}
}
if(notebook.get_current_page()!=-1)
notebook.get_current_view()->get_buffer()->place_cursor(notebook.get_current_view()->get_buffer()->get_insert()->get_iter());
debug_stop_mutex.unlock();
});
#ifdef JUCI_ENABLE_DEBUG
auto &menu=Menu::get();
menu.actions["debug_stop"]->set_enabled(false);
menu.actions["debug_kill"]->set_enabled(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_show_variables"]->set_enabled(false);
menu.actions["debug_run_command"]->set_enabled(false);
menu.actions["debug_goto_stop"]->set_enabled(false);
#endif
debug_update_status.connect([this](){
debug_status_mutex.lock();
if(debug_status.empty()) {
debug_status_label.set_text("");
auto &menu=Menu::get();
menu.actions["debug_stop"]->set_enabled(false);
menu.actions["debug_kill"]->set_enabled(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_show_variables"]->set_enabled(false);
menu.actions["debug_run_command"]->set_enabled(false);
menu.actions["debug_goto_stop"]->set_enabled(false);
}
else {
debug_status_label.set_text("debug: "+debug_status);
auto &menu=Menu::get();
menu.actions["debug_stop"]->set_enabled();
menu.actions["debug_kill"]->set_enabled();
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_show_variables"]->set_enabled();
menu.actions["debug_run_command"]->set_enabled();
menu.actions["debug_goto_stop"]->set_enabled();
}
debug_status_mutex.unlock();
});
about.set_version(Config::get().window.version); about.set_version(Config::get().window.version);
about.set_authors({"(in order of appearance)", about.set_authors({"(in order of appearance)",
"Ted Johan Kristoffersen", "Ted Johan Kristoffersen",
@ -575,8 +507,8 @@ void Window::set_menu_actions() {
}); });
menu.add_action("project_set_run_arguments", [this]() { menu.add_action("project_set_run_arguments", [this]() {
project=get_project(); auto project_language=Project::get().get_language();
auto run_arguments=std::make_shared<std::pair<std::string, std::string> >(project->get_run_arguments()); auto run_arguments=std::make_shared<std::pair<std::string, std::string> >(project_language->get_run_arguments());
if(run_arguments->second.empty()) if(run_arguments->second.empty())
return; return;
@ -588,7 +520,7 @@ void Window::set_menu_actions() {
}; };
label_it->update(0, ""); label_it->update(0, "");
entry_box.entries.emplace_back(run_arguments->second, [this, run_arguments](const std::string& content){ entry_box.entries.emplace_back(run_arguments->second, [this, run_arguments](const std::string& content){
Project::run_arguments[run_arguments->first]=content; Project::get().run_arguments[run_arguments->first]=content;
entry_box.hide(); entry_box.hide();
}, 50); }, 50);
auto entry_it=entry_box.entries.begin(); auto entry_it=entry_box.entries.begin();
@ -599,24 +531,24 @@ void Window::set_menu_actions() {
entry_box.show(); entry_box.show();
}); });
menu.add_action("compile_and_run", [this]() { menu.add_action("compile_and_run", [this]() {
if(Project::compiling) if(Project::get().compiling)
return; return;
if(Config::get().window.save_on_compile_or_run) if(Config::get().window.save_on_compile_or_run)
notebook.save_project_files(); notebook.save_project_files();
project=get_project(); project_language=Project::get().get_language();
project->compile_and_run(); project_language->compile_and_run();
}); });
menu.add_action("compile", [this]() { menu.add_action("compile", [this]() {
if(Project::compiling) if(Project::get().compiling)
return; return;
if(Config::get().window.save_on_compile_or_run) if(Config::get().window.save_on_compile_or_run)
notebook.save_project_files(); notebook.save_project_files();
project=get_project(); project_language=Project::get().get_language();
project->compile(); project_language->compile();
}); });
menu.add_action("run_command", [this]() { menu.add_action("run_command", [this]() {
@ -656,8 +588,8 @@ void Window::set_menu_actions() {
#ifdef JUCI_ENABLE_DEBUG #ifdef JUCI_ENABLE_DEBUG
menu.add_action("debug_set_run_arguments", [this]() { menu.add_action("debug_set_run_arguments", [this]() {
project=get_project(); auto project_language=Project::get().get_language();
auto run_arguments=std::make_shared<std::pair<std::string, std::string> >(project->debug_get_run_arguments()); auto run_arguments=std::make_shared<std::pair<std::string, std::string> >(project_language->debug_get_run_arguments());
if(run_arguments->second.empty()) if(run_arguments->second.empty())
return; return;
@ -669,7 +601,7 @@ void Window::set_menu_actions() {
}; };
label_it->update(0, ""); label_it->update(0, "");
entry_box.entries.emplace_back(run_arguments->second, [this, run_arguments](const std::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; Project::get().debug_run_arguments[run_arguments->first]=content;
entry_box.hide(); entry_box.hide();
}, 50); }, 50);
auto entry_it=entry_box.entries.begin(); auto entry_it=entry_box.entries.begin();
@ -680,64 +612,52 @@ void Window::set_menu_actions() {
entry_box.show(); entry_box.show();
}); });
menu.add_action("debug_start_continue", [this](){ menu.add_action("debug_start_continue", [this](){
if(Project::debugging) { if(Project::get().debugging) {
project->debug_continue(); project_language->debug_continue();
return; return;
} }
if(Config::get().window.save_on_compile_or_run) if(Config::get().window.save_on_compile_or_run)
notebook.save_project_files(); notebook.save_project_files();
project=get_project(); project_language=Project::get().get_language();
project->debug_start([this](const std::string &status) { project_language->debug_start();
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]() { menu.add_action("debug_stop", [this]() {
if(project) if(project_language)
project->debug_stop(); project_language->debug_stop();
}); });
menu.add_action("debug_kill", [this]() { menu.add_action("debug_kill", [this]() {
if(project) if(project_language)
project->debug_kill(); project_language->debug_kill();
}); });
menu.add_action("debug_step_over", [this]() { menu.add_action("debug_step_over", [this]() {
if(project) if(project_language)
project->debug_step_over(); project_language->debug_step_over();
}); });
menu.add_action("debug_step_into", [this]() { menu.add_action("debug_step_into", [this]() {
if(project) if(project_language)
project->debug_step_into(); project_language->debug_step_into();
}); });
menu.add_action("debug_step_out", [this]() { menu.add_action("debug_step_out", [this]() {
if(project) if(project_language)
project->debug_step_out(); project_language->debug_step_out();
}); });
menu.add_action("debug_backtrace", [this]() { menu.add_action("debug_backtrace", [this]() {
if(project) if(project_language)
project->debug_backtrace(); project_language->debug_backtrace();
}); });
menu.add_action("debug_show_variables", [this]() { menu.add_action("debug_show_variables", [this]() {
if(project) if(project_language)
project->debug_show_variables(); project_language->debug_show_variables();
}); });
menu.add_action("debug_run_command", [this]() { menu.add_action("debug_run_command", [this]() {
entry_box.clear(); entry_box.clear();
entry_box.entries.emplace_back(last_run_debug_command, [this](const std::string& content){ entry_box.entries.emplace_back(last_run_debug_command, [this](const std::string& content){
if(content!="") { if(content!="") {
if(project) if(project_language)
project->debug_run_command(content); project_language->debug_run_command(content);
last_run_debug_command=content; last_run_debug_command=content;
} }
entry_box.hide(); entry_box.hide();
@ -773,35 +693,8 @@ void Window::set_menu_actions() {
} }
}); });
menu.add_action("debug_goto_stop", [this](){ menu.add_action("debug_goto_stop", [this](){
if(project && project->debugging) { if(project_language)
debug_stop_mutex.lock(); project_language->debug_goto_stop();
auto debug_stop_copy=debug_stop;
debug_stop_mutex.unlock();
if(!debug_stop_copy.first.empty()) {
notebook.open(debug_stop_copy.first);
if(notebook.get_current_page()!=-1) {
auto view=notebook.get_current_view();
int line_nr=debug_stop_copy.second.first-1;
int line_index=debug_stop_copy.second.second-1;
if(line_nr<view->get_buffer()->get_line_count()) {
auto iter=view->get_buffer()->get_iter_at_line(line_nr);
auto end_line_iter=iter;
while(!iter.ends_line() && iter.forward_char()) {}
auto line=view->get_buffer()->get_text(iter, end_line_iter);
if(static_cast<size_t>(line_index)>=line.bytes())
line_index=0;
view->get_buffer()->place_cursor(view->get_buffer()->get_iter_at_line_index(line_nr, line_index));
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);
}
debug_update_stop();
}
}
}
}); });
#endif #endif
@ -899,8 +792,8 @@ bool Window::on_delete_event(GdkEventAny *event) {
} }
Terminal::get().kill_async_processes(); Terminal::get().kill_async_processes();
#ifdef JUCI_ENABLE_DEBUG #ifdef JUCI_ENABLE_DEBUG
if(project) if(project_language)
project->debug_delete(); project_language->debug_delete();
#endif #endif
return false; return false;
} }
@ -1126,19 +1019,3 @@ void Window::rename_token_entry() {
} }
} }
} }
std::unique_ptr<Project> Window::get_project() {
if(notebook.get_current_page()!=-1) {
auto language_id=notebook.get_current_view()->language->get_id();
if(language_id=="markdown")
return std::unique_ptr<Project>(new ProjectMarkdown(notebook));
if(language_id=="python")
return std::unique_ptr<Project>(new ProjectPython(notebook));
if(language_id=="js")
return std::unique_ptr<Project>(new ProjectJavaScript(notebook));
if(language_id=="html")
return std::unique_ptr<Project>(new ProjectHTML(notebook));
}
return std::unique_ptr<Project>(new ProjectClang(notebook));
}

19
src/window.h

@ -1,7 +1,7 @@
#ifndef JUCI_WINDOW_H_ #ifndef JUCI_WINDOW_H_
#define JUCI_WINDOW_H_ #define JUCI_WINDOW_H_
#include "gtkmm.h" #include <gtkmm.h>
#include "entrybox.h" #include "entrybox.h"
#include "notebook.h" #include "notebook.h"
#include "cmake.h" #include "cmake.h"
@ -11,14 +11,13 @@
class Window : public Gtk::ApplicationWindow { class Window : public Gtk::ApplicationWindow {
private: private:
Window(); Window();
Notebook &notebook; //convenience reference
public: public:
static Window &get() { static Window &get() {
static Window singleton; static Window singleton;
return singleton; return singleton;
} }
Notebook notebook;
protected: protected:
bool on_key_press_event(GdkEventKey *event) override; bool on_key_press_event(GdkEventKey *event) override;
bool on_delete_event(GdkEventAny *event) override; bool on_delete_event(GdkEventAny *event) override;
@ -34,17 +33,7 @@ private:
Gtk::AboutDialog about; Gtk::AboutDialog about;
EntryBox entry_box; EntryBox entry_box;
std::unique_ptr<Project> project; std::unique_ptr<Project::Language> project_language;
Gtk::Label debug_status_label;
std::pair<boost::filesystem::path, std::pair<int, int> > debug_stop;
boost::filesystem::path debug_last_stop_file_path;
std::mutex debug_stop_mutex;
Glib::Dispatcher debug_update_stop;
std::string debug_status;
std::mutex debug_status_mutex;
Glib::Dispatcher debug_update_status;
void configure(); void configure();
void set_menu_actions(); void set_menu_actions();
@ -60,8 +49,6 @@ private:
bool case_sensitive_search=true; bool case_sensitive_search=true;
bool regex_search=false; bool regex_search=false;
bool search_entry_shown=false; bool search_entry_shown=false;
std::unique_ptr<Project> get_project();
}; };
#endif // JUCI_WINDOW_H #endif // JUCI_WINDOW_H

Loading…
Cancel
Save