From f83237275253047eebbe9a35687daae04150ab24 Mon Sep 17 00:00:00 2001 From: eidheim Date: Wed, 5 Aug 2015 14:42:27 +0200 Subject: [PATCH] Cleanup of terminal.*, and added cmake.* to parse CMakeLists.txt. Also fixed compile, and compile and run. Remember to remove ~/.juci/config/config.json to get this version to work. --- src/CMakeLists.txt | 4 +- src/cmake.cc | 260 +++++++++++++++++++++++++++++++++++++++++++++ src/cmake.h | 28 +++++ src/config.cc | 12 --- src/config.h | 1 - src/directories.cc | 76 ++----------- src/directories.h | 3 +- src/files.h | 21 ---- src/notebook.cc | 54 ++-------- src/notebook.h | 3 +- src/singletons.cc | 1 - src/singletons.h | 2 - src/terminal.cc | 117 ++++++++++---------- src/terminal.h | 27 ++--- src/window.cc | 60 ++++++----- src/window.h | 4 +- 16 files changed, 409 insertions(+), 264 deletions(-) create mode 100644 src/cmake.cc create mode 100644 src/cmake.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 54c9549..5f892eb 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -79,7 +79,9 @@ if(${validation}) tooltips.h tooltips.cc singletons.h - singletons.cc) + singletons.cc + cmake.h + cmake.cc) add_library(${module} SHARED api diff --git a/src/cmake.cc b/src/cmake.cc new file mode 100644 index 0000000..9095e73 --- /dev/null +++ b/src/cmake.cc @@ -0,0 +1,260 @@ +#include "cmake.h" +#include "sourcefile.h" +#include +#include "singletons.h" + +#include //TODO: remove +using namespace std; //TODO: remove + +CMake::CMake(const boost::filesystem::path &path) { + const auto find_cmake_project=[this](const boost::filesystem::path &cmake_path) { + for(auto &line: juci::filesystem::read_lines(cmake_path)) { + const std::regex project_regex("^ *project *\\(.*$"); + std::smatch sm; + if(std::regex_match(line, sm, project_regex)) { + return true; + } + } + return false; + }; + + auto search_path=boost::filesystem::path(path); + auto search_cmake_path=search_path; + search_cmake_path+="/CMakeLists.txt"; + if(boost::filesystem::exists(search_cmake_path)) + paths.emplace(paths.begin(), search_cmake_path); + if(find_cmake_project(search_cmake_path)) + project_path=search_path; + else { + do { + search_path=search_path.parent_path(); + search_cmake_path=search_path; + search_cmake_path+="/CMakeLists.txt"; + if(boost::filesystem::exists(search_cmake_path)) + paths.emplace(paths.begin(), search_cmake_path); + if(find_cmake_project(search_cmake_path)) { + project_path=search_path; + break; + } + } while(search_path!=search_path.root_directory()); + } + if(project_path!="") { + if(boost::filesystem::exists(project_path.string()+"/CMakeLists.txt") && !boost::filesystem::exists(project_path.string()+"/compile_commands.json")) + create_compile_commands(project_path.string()); + } +} + +bool CMake::create_compile_commands(const std::string &path) { + Singleton::terminal()->print("Creating "+boost::filesystem::path(path+"/compile_commands.json").string()+"\n"); + //TODO: Windows... + if(Singleton::terminal()->execute("cmake . -DCMAKE_EXPORT_COMPILE_COMMANDS=ON 2>&1", path)) + return true; + return false; +} + +void CMake::read_files() { + for(auto &path: paths) + files.emplace_back(juci::filesystem::read(path)); +} + +void CMake::remove_tabs() { + for(auto &file: files) { + for(auto &chr: file) { + if(chr=='\t') + chr=' '; + } + } +} + +void CMake::remove_comments() { + for(auto &file: files) { + size_t pos=0; + size_t comment_start; + bool inside_comment=false; + while(posstart_line) { + auto line=file.substr(start_line, end_line-start_line); + const std::regex set_regex("^ *set *\\( *([A-Za-z_][A-Za-z_0-9]*) +(.*)\\) *$"); + std::smatch sm; + if(std::regex_match(line, sm, set_regex)) { + std::string data=sm[2]; + while(data.size()>0 && data.back()==' ') + data.pop_back(); + parse_variable_parameters(data); + variables[sm[1]]=data; + } + } + pos=end_line+1; + } + } +} + +void CMake::parse_variable_parameters(std::string &data) { + size_t pos=0; + bool inside_quote=false; + char last_char=0; + while(pos CMake::get_function_parameters(std::string &data) { + std::vector parameters; + size_t pos=0; + size_t parameter_pos=0; + bool inside_quote=false; + char last_char=0; + while(pos > > CMake::get_functions_parameters(const std::string &name) { + if(!parsed) + parse(); + std::vector > > functions; + size_t file_c=0; + for(auto &file: files) { + size_t pos=0; + while(posstart_line) { + auto line=file.substr(start_line, end_line-start_line); + const std::regex function_regex("^ *"+name+" *\\( *(.*)\\) *$"); + std::smatch sm; + if(std::regex_match(line, sm, function_regex)) { + std::string data=sm[1]; + while(data.size()>0 && data.back()==' ') + data.pop_back(); + auto parameters=get_function_parameters(data); + functions.emplace(functions.begin(), paths[file_c], parameters); + } + } + pos=end_line+1; + } + file_c++; + } + return functions; +} diff --git a/src/cmake.h b/src/cmake.h new file mode 100644 index 0000000..f300f15 --- /dev/null +++ b/src/cmake.h @@ -0,0 +1,28 @@ +#ifndef JUCI_CMAKE_H_ +#define JUCI_CMAKE_H_ +#include +#include +#include + +class CMake { +public: + CMake(const boost::filesystem::path &path); + std::vector > > get_functions_parameters(const std::string &name); + static bool create_compile_commands(const std::string &path); + + std::vector paths; + std::vector files; + boost::filesystem::path project_path; + std::unordered_map variables; +private: + void read_files(); + void remove_tabs(); + void remove_comments(); + void remove_newlines_inside_parentheses(); + void find_variables(); + void parse_variable_parameters(std::string &data); + void parse(); + std::vector get_function_parameters(std::string &data); + bool parsed=false; +}; +#endif //JUCI_CMAKE_H_ diff --git a/src/config.cc b/src/config.cc index fd40399..c2bf32f 100644 --- a/src/config.cc +++ b/src/config.cc @@ -11,7 +11,6 @@ MainConfig::MainConfig(Menu &menu) : menu(menu) { GenerateSource(); GenerateKeybindings(); GenerateDirectoryFilter(); - GenerateTerminalCommands(); } void MainConfig::find_or_create_config_files() { @@ -59,17 +58,6 @@ void MainConfig::GenerateSource() { DEBUG("Source cfg fetched"); } -void MainConfig::GenerateTerminalCommands() { - auto terminal_cfg=Singleton::Config::terminal(); - boost::property_tree::ptree source_json = cfg.get_child("project"); - boost::property_tree::ptree compile_commands_json = source_json.get_child("compile_commands"); - boost::property_tree::ptree run_commands_json = source_json.get_child("run_commands"); - for (auto &i : compile_commands_json) - terminal_cfg->compile_commands.emplace_back(i.second.get_value()); - for (auto &i : run_commands_json) - terminal_cfg->run_command=(i.second.get_value()); //TODO: run_commands array->one run_command? -} - void MainConfig::GenerateKeybindings() { boost::filesystem::path path(Singleton::config_dir() + "menu.xml"); if (!boost::filesystem::is_regular_file(path)) { diff --git a/src/config.h b/src/config.h index d1ea90b..46f5142 100644 --- a/src/config.h +++ b/src/config.h @@ -12,7 +12,6 @@ public: void GenerateSource(); void GenerateKeybindings(); void GenerateDirectoryFilter(); - void GenerateTerminalCommands(); private: boost::property_tree::ptree cfg; boost::property_tree::ptree key_tree; diff --git a/src/directories.cc b/src/directories.cc index edac27b..587ce60 100644 --- a/src/directories.cc +++ b/src/directories.cc @@ -5,6 +5,9 @@ #include #include "boost/algorithm/string.hpp" +#include //TODO: remove +using namespace std; //TODO: remove + namespace sigc { SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE } @@ -47,7 +50,14 @@ void Directories::open_folder(const boost::filesystem::path& dir_path) { } tree_store->clear(); - tree_view.get_column(0)->set_title(get_cmakelists_variable(dir_path, "project")); + + if(last_dir_path!=dir_path) + cmake=std::unique_ptr(new CMake(dir_path)); + auto project=cmake->get_functions_parameters("project"); + if(project.size()>0 && project[0].second.size()>0) + tree_view.get_column(0)->set_title(project[0].second[0]); + else + tree_view.get_column(0)->set_title(""); add_paths(dir_path, Gtk::TreeModel::Row(), 0); for(auto &path: expanded_paths) @@ -118,67 +128,3 @@ void Directories::add_paths(const boost::filesystem::path& dir_path, const Gtk:: } } } - -std::string Directories::get_cmakelists_variable(const boost::filesystem::path& dir_path, std::string command_name) { - INFO("fetches cmake variable value for: "+command_name); - std::string project_name; - std::string project_name_var; - boost::filesystem::directory_iterator end_itr; - for (boost::filesystem::directory_iterator itr( dir_path );itr != end_itr;++itr ) { - if (itr->path().filename().string() == "CMakeLists.txt") { - for (auto &line : juci::filesystem::read_lines(itr->path())) { - if (line.find(command_name+"(", 0) != std::string::npos - || line.find(command_name+" (", 0) != std::string::npos ) { - size_t variable_start = line.find("{", 0); - size_t variable_end = line.find("}", variable_start); - project_name_var = line.substr(variable_start+1, - (variable_end)-variable_start-1); - boost::algorithm::trim(project_name_var); - if (variable_start == std::string::npos) { // not a variabel - variable_start = line.find("(", 0); - - variable_end = line.find(' ', variable_start); - if(variable_end != std::string::npos){ - return line.substr(variable_start+1, - (variable_end)-variable_start-1); - } - variable_end = line.find("#", variable_start); - if(variable_end != std::string::npos){ - return line.substr(variable_start+1, - (variable_end)-variable_start-1); - } - variable_end = line.find(")", variable_start); - return line.substr(variable_start+1, - (variable_end)-variable_start-1); - if (variable_start == std::string::npos) { // not a variable - variable_start = line.find("(", 0); - variable_end = line.find(")", variable_start); - INFO("Wasn't a variable, returning value"); - return line.substr(variable_start+1, - (variable_end)-variable_start-1); - } - break; - } - } - } - for (auto &line : juci::filesystem::read_lines(itr->path())) { - if (line.find("set(", 0) != std::string::npos - || line.find("set (", 0) != std::string::npos) { - if( line.find(project_name_var, 0) != std::string::npos) { - size_t variable_start = line.find(project_name_var, 0) - +project_name_var.length(); - size_t variable_end = line.find(")", variable_start); - project_name = line.substr(variable_start+1, - variable_end-variable_start-1); - boost::algorithm::trim(project_name); - INFO("found variable, returning value"); - return project_name; - } - } - } - break; - } - } - INFO("Couldn't find value in CMakeLists.txt"); - return "no project name"; -} diff --git a/src/directories.h b/src/directories.h index ba545ec..9f688fe 100644 --- a/src/directories.h +++ b/src/directories.h @@ -5,6 +5,7 @@ #include #include #include "boost/filesystem.hpp" +#include "cmake.h" class Directories : public Gtk::ScrolledWindow { public: @@ -29,9 +30,9 @@ public: Directories(); void open_folder(const boost::filesystem::path& dir_path); void select_path(const std::string &path); - std::string get_cmakelists_variable(const boost::filesystem::path& dir_path, std::string command_name); std::function on_row_activated; + std::unique_ptr cmake; private: void add_paths(const boost::filesystem::path& dir_path, const Gtk::TreeModel::Row &row, unsigned depth); diff --git a/src/files.h b/src/files.h index 6a34e45..14a3610 100644 --- a/src/files.h +++ b/src/files.h @@ -68,27 +68,6 @@ const std::string configjson = " \"cmakelists.txt\",\n" " \"in-lowercase.pls\"\n" " ]\n" -" },\n" -" \"project\": {\n" -" \"run_commands\": [\n" -" \"./.build/\"\n" -" ],\n" -" \"compile_commands\": [\n" -" \"rm -rf ./.build\",\n" -" \"mkdir ./.build\",\n" -" \"cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -B./.build -H.\",\n" -" \"cd ./.build/; make\",\n" -" \"cp ./.build/compile_commands.json compile_commands.json\"\n" -" ]\n" -" },\n" -" \"example\": {\n" -" \"key\": \"value\",\n" -" \"key2\": [\n" -" \"val1\",\n" -" \"val2\",\n" -" 3\n" -" ],\n" -" \"key3\": \"value\"\n" " }\n" "}\n"; diff --git a/src/notebook.cc b/src/notebook.cc index 4e18c1f..c66630f 100644 --- a/src/notebook.cc +++ b/src/notebook.cc @@ -4,6 +4,7 @@ #include "singletons.h" #include #include +#include "cmake.h" #include //TODO: remove using namespace std; //TODO: remove @@ -54,18 +55,19 @@ void Notebook::open(std::string path) { auto language=Source::guess_language(path); if(language && (language->get_id()=="chdr" || language->get_id()=="c" || language->get_id()=="cpp" || language->get_id()=="objc")) { auto view_project_path=project_path; + if(directories.cmake && directories.cmake->project_path!="") + view_project_path=directories.cmake->project_path.string(); if(view_project_path=="") { - view_project_path=boost::filesystem::path(path).parent_path().string(); - auto found_project_path=find_project_path(view_project_path); - if(found_project_path!="") { - view_project_path=found_project_path; + auto parent_path=boost::filesystem::path(path).parent_path(); + view_project_path=parent_path.string(); + CMake cmake(parent_path); + if(cmake.project_path!="") { + view_project_path=cmake.project_path.string(); Singleton::terminal()->print("Project path for "+path+" set to "+view_project_path+"\n"); } else Singleton::terminal()->print("Error: could not find project path for "+path+"\n"); } - if(boost::filesystem::exists(view_project_path+"/CMakeLists.txt") && !boost::filesystem::exists(view_project_path+"/compile_commands.json")) - make_compile_commands(view_project_path); source_views.emplace_back(new Source::ClangView(path, view_project_path)); } else { @@ -112,32 +114,6 @@ void Notebook::open(std::string path) { }; } -std::string Notebook::find_project_path(const std::string &path) { - const auto find_cmake_project=[this](const boost::filesystem::path &path) { - auto cmake_path=path; - cmake_path+="/CMakeLists.txt"; - for(auto &line: juci::filesystem::read_lines(cmake_path)) { - const std::regex cmake_project("^ *project *\\(.*$"); - std::smatch sm; - if(std::regex_match(line, sm, cmake_project)) { - return true; - } - } - return false; - }; - - auto boost_path=boost::filesystem::path(path); - if(find_cmake_project(boost_path)) - return boost_path.string(); - do { - boost_path=boost_path.parent_path(); - if(find_cmake_project(boost_path)) - return boost_path.string(); - } while(boost_path!=boost_path.root_directory()); - - return ""; -} - bool Notebook::save(int page) { if(page>=size()) return false; @@ -149,7 +125,8 @@ bool Notebook::save(int page) { //If CMakeLists.txt have been modified: if(boost::filesystem::path(view->file_path).filename().string()=="CMakeLists.txt") { - if(project_path!="" && make_compile_commands(project_path)) { + if(project_path!="" && directories.cmake && directories.cmake->project_path!="" && CMake::create_compile_commands(directories.cmake->project_path.string())) { + directories.open_folder(project_path); for(auto source_view: source_views) { if(auto source_clang_view=dynamic_cast(source_view)) { if(project_path==source_view->project_path) { @@ -170,17 +147,6 @@ bool Notebook::save(int page) { return false; } -bool Notebook::make_compile_commands(const std::string &path) { - Singleton::terminal()->print("Creating "+boost::filesystem::path(path+"/compile_commands.json").string()+"\n"); - //TODO: Windows... - if(Singleton::terminal()->execute(path, "cmake . -DCMAKE_EXPORT_COMPILE_COMMANDS=ON 2>&1")) { - if(project_path!="") - directories.open_folder(project_path); - return true; - } - return false; -} - bool Notebook::save_current() { INFO("Notebook save current file"); if(get_current_page()==-1) diff --git a/src/notebook.h b/src/notebook.h index ef95143..848c50c 100644 --- a/src/notebook.h +++ b/src/notebook.h @@ -20,10 +20,9 @@ public: void open(std::string filename); bool save(int page); bool save_current(); - std::string project_path; + std::string project_path; //TODO: remove, and also remove Source::View::project_path (project_path only needed in Source::ClangView) private: - std::string find_project_path(const std::string &path); bool make_compile_commands(const std::string &path); bool save_modified_dialog(); Directories &directories; diff --git a/src/singletons.cc b/src/singletons.cc index 076bf46..ace0668 100644 --- a/src/singletons.cc +++ b/src/singletons.cc @@ -1,7 +1,6 @@ #include "singletons.h" std::unique_ptr Singleton::Config::source_=std::unique_ptr(new Source::Config()); -std::unique_ptr Singleton::Config::terminal_=std::unique_ptr(new Terminal::Config()); std::unique_ptr Singleton::Config::directories_=std::unique_ptr(new Directories::Config()); std::unique_ptr Singleton::terminal_=std::unique_ptr(); diff --git a/src/singletons.h b/src/singletons.h index d305e85..e39453c 100644 --- a/src/singletons.h +++ b/src/singletons.h @@ -14,11 +14,9 @@ public: class Config { public: static Source::Config *source() {return source_.get();} - static Terminal::Config *terminal() {return terminal_.get();} static Directories::Config *directories() {return directories_.get();} private: static std::unique_ptr source_; - static std::unique_ptr terminal_; static std::unique_ptr directories_; }; static std::string config_dir() { return std::string(getenv("HOME")) + "/.juci/config/"; } diff --git a/src/terminal.cc b/src/terminal.cc index de42e7c..d406656 100644 --- a/src/terminal.cc +++ b/src/terminal.cc @@ -48,72 +48,82 @@ Terminal::Terminal() { scrolled_window.add(text_view); add(scrolled_window); - change_folder_command = ""; text_view.signal_size_allocate().connect([this](Gtk::Allocation& allocation){ auto end=text_view.get_buffer()->create_mark(text_view.get_buffer()->end()); text_view.scroll_to(end); text_view.get_buffer()->delete_mark(end); }); + + async_execute_print.connect([this](){ + print(async_execute_print_string); + async_execute_print_finished=true; + }); } -bool Terminal::execute(const std::string &path, const std::string &command) { +bool Terminal::execute(const std::string &command, const std::string &path) { boost::filesystem::path boost_path; - if(path=="") - boost_path=boost::filesystem::current_path(); - else + std::string cd_path_and_command; + if(path!="") { boost_path=boost::filesystem::path(path); - //TODO: Windows... - auto cd_path_and_command="cd "+boost_path.string()+" 2>&1 && "+command; + //TODO: Windows... + cd_path_and_command="cd "+boost_path.string()+" 2>&1 && "+command; + } + else + cd_path_and_command=command; - FILE* p = NULL; + FILE* p; p = popen(cd_path_and_command.c_str(), "r"); if (p == NULL) { print("Error: Failed to run command" + command + "\n"); return false; } else { - char buffer[1028]; - while (fgets(buffer, 1028, p) != NULL) { + char buffer[1024]; + while (fgets(buffer, 1024, p) != NULL) { print(buffer); + while(gtk_events_pending()) + gtk_main_iteration(); } - int exit_code=pclose(p); - if(exit_code==0) - return true; - else - return false; - } -} - -void Terminal::async_execute(const std::string &path, const std::string &command) { - -} - -void Terminal::set_change_folder_command(boost::filesystem::path CMake_path) { - INFO("Terminal: set_change_folder_command"); - path = CMake_path.string(); - change_folder_command = "cd "+ path + "; "; -} - -void Terminal::compile() { - INFO("Terminal: compile"); - text_view.get_buffer()->set_text(""); - DEBUG("Terminal: compile: running cmake command"); - std::vector commands = Singleton::Config::terminal()->compile_commands; - for (size_t it = 0; it < commands.size(); ++it) { - execute_command(commands.at(it), "r"); + return pclose(p)==0; } - print("\n"); - DEBUG("Terminal: compile: compile done"); } -void Terminal::run(std::string executable) { - INFO("Terminal: run"); - print("juCi++ execute: " + executable + "\n"); - DEBUG("Terminal: compile: running run command: "); - DEBUG_VAR(executable); - execute_command("cd "+Singleton::Config::terminal()->run_command + "; ./"+executable, "r"); - print("\n"); +void Terminal::async_execute(const std::string &command, const std::string &path, std::function callback) { + std::thread async_execute_thread([this, command, path, callback](){ + boost::filesystem::path boost_path; + std::string cd_path_and_command; + if(path!="") { + boost_path=boost::filesystem::path(path); + + //TODO: Windows... + cd_path_and_command="cd "+boost_path.string()+" 2>&1 && "+command; + } + else + cd_path_and_command=command; + + FILE* p; + p = popen(cd_path_and_command.c_str(), "r"); + if (p == NULL) { + async_execute_print_string="Error: Failed to run command" + command + "\n"; + async_execute_print_finished=false; + async_execute_print(); + } + else { + char buffer[1024]; + while (fgets(buffer, 1024, p) != NULL) { + async_execute_print_string=buffer; + async_execute_print_finished=false; + async_execute_print(); + while(!async_execute_print_finished) + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + } + int exit_code=pclose(p); + if(callback) + callback(exit_code==0); + } + }); + async_execute_thread.detach(); } int Terminal::print(std::string message){ @@ -134,22 +144,3 @@ std::shared_ptr Terminal::print_in_progress(std::string st std::shared_ptr in_progress=std::shared_ptr(new Terminal::InProgress(start_msg)); return in_progress; } - -void Terminal::execute_command(std::string command, std::string mode) { - INFO("Terminal: execute_command"); - command = change_folder_command+command; - DEBUG("Terminal: PrintMessage: running command"); - FILE* p = NULL; - std::cout << command << std::endl; - p = popen(command.c_str(), mode.c_str()); - if (p == NULL) { - print("juCi++ ERROR: Failed to run command" + command + "\n"); - } - else { - char buffer[1028]; - while (fgets(buffer, 1028, p) != NULL) { - print(buffer); - } - pclose(p); - } -} diff --git a/src/terminal.h b/src/terminal.h index d7865c5..fe7c4f0 100644 --- a/src/terminal.h +++ b/src/terminal.h @@ -9,13 +9,7 @@ #include class Terminal : public Gtk::HBox { -public: - class Config { - public: - std::vector compile_commands; - std::string run_command; - }; - +public: class InProgress { public: InProgress(const std::string& start_msg); @@ -31,25 +25,18 @@ public: }; Terminal(); - bool execute(const std::string &path, const std::string &command); - void async_execute(const std::string &path, const std::string &command); - void set_change_folder_command(boost::filesystem::path CMake_path); //TODO: remove - void run(std::string executable); //TODO: remove - void compile(); //TODO: remove + bool execute(const std::string &command, const std::string &path=""); + void async_execute(const std::string &command, const std::string &path="", std::function callback=nullptr); int print(std::string message); void print(int line_nr, std::string message); std::shared_ptr print_in_progress(std::string start_msg); private: - void execute_command(std::string command, std::string mode); //TODO: remove - Gtk::TextView text_view; Gtk::ScrolledWindow scrolled_window; - - std::string change_folder_command; //TODO: remove - std::string path; //TODO: remove - const std::string cmake_sucsess = "Build files have been written to:"; //TODO: remove - const std::string make_built = "Built target"; //TODO: remove - const std::string make_executable = "Linking CXX executable"; //TODO: remove + + Glib::Dispatcher async_execute_print; + std::string async_execute_print_string; + std::atomic async_execute_print_finished; }; #endif // JUCI_TERMINAL_H_ diff --git a/src/window.cc b/src/window.cc index 1c00711..ec369f9 100644 --- a/src/window.cc +++ b/src/window.cc @@ -12,7 +12,7 @@ namespace sigc { SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE } -Window::Window() : box(Gtk::ORIENTATION_VERTICAL), notebook(directories) { +Window::Window() : box(Gtk::ORIENTATION_VERTICAL), notebook(directories), compiling(false) { INFO("Create Window"); set_title("juCi++"); set_default_size(600, 400); @@ -194,41 +194,43 @@ void Window::create_menu() { }); menu.action_group->add(Gtk::Action::create("ProjectCompileAndRun", "Compile And Run"), Gtk::AccelKey(menu.key_map["compile_and_run"]), [this]() { - if(notebook.get_current_page()==-1) + if(notebook.get_current_page()==-1 || compiling) return; - notebook.save_current(); - if (running.try_lock()) { - std::thread execute([this]() { - std::string path = notebook.get_current_view()->file_path; - size_t pos = path.find_last_of("/\\"); - if(pos != std::string::npos) { - path.erase(path.begin()+pos,path.end()); - Singleton::terminal()->set_change_folder_command(path); - } - Singleton::terminal()->compile(); - std::string executable = directories.get_cmakelists_variable(path,"add_executable"); - Singleton::terminal()->run(executable); - running.unlock(); + CMake cmake(notebook.get_current_view()->file_path); + auto executables = cmake.get_functions_parameters("add_executable"); + std::string executable; + boost::filesystem::path path; + if(executables.size()>0 && executables[0].second.size()>0) { + executable=executables[0].second[0]; + path=executables[0].first.parent_path(); + path+="/"+executables[0].second[0]; + } + if(cmake.project_path!="") { + compiling=true; + if(path!="") + Singleton::terminal()->print("Compiling and executing "+path.string()+"\n"); + else + Singleton::terminal()->print("Could not find an executable, please use add_executable in CMakeLists.txt\n"); + //TODO: Windows... + Singleton::terminal()->async_execute("make 2>&1", cmake.project_path.string(), [this, path](int exit_code){ + compiling=false; + if(path!="") + //TODO: Windows... + Singleton::terminal()->async_execute(path.string()+" 2>&1", path.parent_path().string()); }); - execute.detach(); } }); menu.action_group->add(Gtk::Action::create("ProjectCompile", "Compile"), Gtk::AccelKey(menu.key_map["compile"]), [this]() { - if(notebook.get_current_page()==-1) + if(notebook.get_current_page()==-1 || compiling) return; - notebook.save_current(); - if (running.try_lock()) { - std::thread execute([this]() { - std::string path = notebook.get_current_view()->file_path; - size_t pos = path.find_last_of("/\\"); - if(pos != std::string::npos){ - path.erase(path.begin()+pos,path.end()); - Singleton::terminal()->set_change_folder_command(path); - } - Singleton::terminal()->compile(); - running.unlock(); + CMake cmake(notebook.get_current_view()->file_path); + if(cmake.project_path!="") { + compiling=true; + Singleton::terminal()->print("Compiling project "+cmake.project_path.string()+"\n"); + //TODO: Windows... + Singleton::terminal()->async_execute("make 2>&1", cmake.project_path.string(), [this](int exit_code){ + compiling=false; }); - execute.detach(); } }); diff --git a/src/window.h b/src/window.h index 7100de6..42ee93c 100644 --- a/src/window.h +++ b/src/window.h @@ -6,6 +6,7 @@ #include "entrybox.h" #include "notebook.h" #include "menu.h" +#include class Window : public Gtk::Window { public: @@ -23,8 +24,8 @@ private: Gtk::VBox terminal_vbox; Gtk::HBox status_hbox; EntryBox entry_box; - std::mutex running; Menu menu; + std::atomic compiling; void create_menu(); void hide(); @@ -41,7 +42,6 @@ private: bool case_sensitive_search=true; bool regex_search=false; bool search_entry_shown=false; - }; #endif // JUCI_WINDOW_H