Browse Source

WIP: project cleanup, added project classes so that the hard dependency towards clang is removed in Window. In this way, one can add run commands for other project and file types.

merge-requests/365/head
eidheim 10 years ago
parent
commit
07a43c6bd8
  1. 2
      src/CMakeLists.txt
  2. 8
      src/notebook.cc
  3. 2
      src/notebook.h
  4. 113
      src/project.cc
  5. 50
      src/project.h
  6. 99
      src/window.cc
  7. 3
      src/window.h

2
src/CMakeLists.txt

@ -84,6 +84,8 @@ set(source_files juci.h
cmake.h cmake.h
cmake.cc cmake.cc
dialogs.cc dialogs.cc
project.h
project.cc
../libclangmm/src/CodeCompleteResults.cc ../libclangmm/src/CodeCompleteResults.cc
../libclangmm/src/CompilationDatabase.cc ../libclangmm/src/CompilationDatabase.cc

8
src/notebook.cc

@ -354,6 +354,14 @@ boost::filesystem::path Notebook::get_current_folder() {
return current_path; return current_path;
} }
std::unique_ptr<Project> Notebook::get_project() {
boost::filesystem::path file_path;
if(get_current_page()!=-1)
file_path=get_current_view()->file_path;
return std::unique_ptr<Project>(new ProjectClang(file_path));
}
bool Notebook::save_modified_dialog(int page) { bool Notebook::save_modified_dialog(int page) {
Gtk::MessageDialog dialog((Gtk::Window&)(*get_toplevel()), "Save file!", false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_YES_NO); Gtk::MessageDialog dialog((Gtk::Window&)(*get_toplevel()), "Save file!", false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_YES_NO);
dialog.set_default_response(Gtk::RESPONSE_YES); dialog.set_default_response(Gtk::RESPONSE_YES);

2
src/notebook.h

@ -5,6 +5,7 @@
#include "gtkmm.h" #include "gtkmm.h"
#include "source.h" #include "source.h"
#include "source_clang.h" #include "source_clang.h"
#include "project.h"
#include <type_traits> #include <type_traits>
#include <map> #include <map>
#include <sigc++/sigc++.h> #include <sigc++/sigc++.h>
@ -30,6 +31,7 @@ public:
void save_project_files(); void save_project_files();
void configure(int view_nr); void configure(int view_nr);
boost::filesystem::path get_current_folder(); boost::filesystem::path get_current_folder();
std::unique_ptr<Project> get_project();
Gtk::Label info; Gtk::Label info;
Gtk::Label status; Gtk::Label status;

113
src/project.cc

@ -0,0 +1,113 @@
#include "project.h"
#include "config.h"
#include "terminal.h"
#include "filesystem.h"
std::unordered_map<std::string, std::string> Project::run_arguments;
std::unordered_map<std::string, std::string> Project::debug_run_arguments;
std::atomic<bool> Project::compiling(false);
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();
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;
}
std::pair<std::string, std::string> ProjectClang::get_run_arguments() {
auto cmake=get_cmake();
if(!cmake)
return {"", ""};
auto project_path=cmake->project_path.string();
auto run_arguments_it=run_arguments.find(project_path);
std::string arguments;
if(run_arguments_it!=run_arguments.end())
arguments=run_arguments_it->second;
if(arguments.empty()) {
auto executable=cmake->get_executable(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()) {
size_t pos=executable.find(project_path.string());
if(pos!=std::string::npos)
executable.replace(pos, project_path.string().size(), default_build_path.string());
}
arguments=filesystem::escape_argument(executable);
}
else
arguments=filesystem::escape_argument(CMake::get_default_build_path(cmake->project_path));
}
return {project_path, arguments};
}
void ProjectClang::compile() {
auto cmake=get_cmake();
if(!cmake)
return;
auto default_build_path=CMake::get_default_build_path(cmake->project_path);
if(default_build_path.empty())
return;
compiling=true;
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) {
compiling=false;
});
}
void ProjectClang::compile_and_run() {
auto cmake=get_cmake();
if(!cmake)
return;
auto project_path=cmake->project_path;
auto default_build_path=CMake::get_default_build_path(project_path);
if(default_build_path.empty())
return;
auto run_arguments_it=run_arguments.find(project_path.string());
std::string arguments;
if(run_arguments_it!=run_arguments.end())
arguments=run_arguments_it->second;
if(arguments.empty()) {
arguments=cmake->get_executable(file_path).string();
if(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 Project Set Run Arguments, or open a source file within a directory where add_executable is set.\n", true);
return;
}
size_t pos=arguments.find(project_path.string());
if(pos!=std::string::npos)
arguments.replace(pos, project_path.string().size(), default_build_path.string());
arguments=filesystem::escape_argument(arguments);
}
compiling=true;
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){
compiling=false;
if(exit_status==EXIT_SUCCESS) {
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');
});
}
});
}

50
src/project.h

@ -0,0 +1,50 @@
#ifndef JUCI_PROJECT_H_
#define JUCI_PROJECT_H_
#include "cmake.h"
#include <boost/filesystem.hpp>
#include "directories.h"
#include <atomic>
class Project {
public:
Project(const boost::filesystem::path &file_path) : file_path(file_path) {}
virtual ~Project() {}
boost::filesystem::path file_path;
static std::unordered_map<std::string, std::string> run_arguments;
static std::unordered_map<std::string, std::string> debug_run_arguments;
static std::atomic<bool> compiling;
static std::atomic<bool> debugging;
virtual std::pair<std::string, std::string> get_run_arguments() {return {"", ""};}
virtual void compile() {}
virtual void compile_and_run() {}
virtual std::pair<std::string, std::string> debug_get_run_arguments() {return {"", ""};}
virtual void debug_start_continue() {}
virtual void debug_stop() {}
virtual void debug_kill() {}
virtual void debug_step_over() {}
virtual void debug_step_into() {}
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() {}
};
class ProjectClang : public Project {
public:
ProjectClang(const boost::filesystem::path &file_path) : Project(file_path) {}
std::unique_ptr<CMake> get_cmake();
std::pair<std::string, std::string> get_run_arguments() override;
void compile() override;
void compile_and_run() override;
};
#endif // JUCI_PROJECT_H_

99
src/window.cc

@ -591,33 +591,11 @@ void Window::set_menu_actions() {
}); });
menu.add_action("project_set_run_arguments", [this]() { menu.add_action("project_set_run_arguments", [this]() {
auto cmake=get_cmake(); project=notebook.get_project();
if(!cmake) auto run_arguments=std::make_shared<std::pair<std::string, std::string> >(project->get_run_arguments());
if(run_arguments->second.empty())
return; return;
auto project_path=std::make_shared<boost::filesystem::path>(cmake->project_path);
auto run_arguments_it=project_run_arguments.find(project_path->string());
std::string run_arguments;
if(run_arguments_it!=project_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 default_build_path=CMake::get_default_build_path(project_path);
if(!default_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());
}
run_arguments=filesystem::escape_argument(executable);
}
else
run_arguments=filesystem::escape_argument(CMake::get_default_build_path(cmake->project_path));
}
entry_box.clear(); entry_box.clear();
entry_box.labels.emplace_back(); entry_box.labels.emplace_back();
auto label_it=entry_box.labels.begin(); auto label_it=entry_box.labels.begin();
@ -625,8 +603,8 @@ void Window::set_menu_actions() {
label_it->set_text("Set empty to let juCi++ deduce executable"); label_it->set_text("Set empty to let juCi++ deduce executable");
}; };
label_it->update(0, ""); label_it->update(0, "");
entry_box.entries.emplace_back(run_arguments, [this, project_path](const std::string& content){ entry_box.entries.emplace_back(run_arguments->second, [this, run_arguments](const std::string& content){
project_run_arguments[project_path->string()]=content; Project::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();
@ -637,75 +615,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(compiling) if(Project::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();
auto cmake=get_cmake(); project=notebook.get_project();
if(!cmake) project->compile_and_run();
return;
auto project_path=cmake->project_path;
auto default_build_path=CMake::get_default_build_path(project_path);
if(default_build_path.empty())
return;
auto run_arguments_it=project_run_arguments.find(project_path.string());
std::string run_arguments;
if(run_arguments_it!=project_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 Project 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(), default_build_path.string());
command=filesystem::escape_argument(command);
}
compiling=true;
Terminal::get().print("Compiling and running "+command+"\n");
Terminal::get().async_process(Config::get().terminal.make_command, default_build_path, [this, command, default_build_path](int exit_status){
compiling=false;
if(exit_status==EXIT_SUCCESS) {
Terminal::get().async_process(command, default_build_path, [this, command](int exit_status){
Terminal::get().async_print(command+" returned: "+std::to_string(exit_status)+'\n');
});
}
});
}); });
menu.add_action("compile", [this]() { menu.add_action("compile", [this]() {
if(compiling) if(Project::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();
auto cmake=get_cmake(); project=notebook.get_project();
if(!cmake) project->compile();
return;
auto default_build_path=CMake::get_default_build_path(cmake->project_path);
if(default_build_path.empty())
return;
compiling=true;
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){
compiling=false;
});
}); });
menu.add_action("run_command", [this]() { menu.add_action("run_command", [this]() {

3
src/window.h

@ -6,6 +6,7 @@
#include "notebook.h" #include "notebook.h"
#include "cmake.h" #include "cmake.h"
#include "tooltips.h" #include "tooltips.h"
#include "project.h"
#include <atomic> #include <atomic>
class Window : public Gtk::ApplicationWindow { class Window : public Gtk::ApplicationWindow {
@ -34,6 +35,8 @@ private:
Gtk::AboutDialog about; Gtk::AboutDialog about;
EntryBox entry_box; EntryBox entry_box;
std::unique_ptr<Project> project;
std::atomic<bool> compiling; std::atomic<bool> compiling;
std::atomic<bool> debugging; std::atomic<bool> debugging;

Loading…
Cancel
Save