diff --git a/src/notebook.cc b/src/notebook.cc index 71ec3ed..af4f449 100644 --- a/src/notebook.cc +++ b/src/notebook.cc @@ -4,6 +4,9 @@ #include "singletons.h" #include +#include //TODO: remove +using namespace std; //TODO: remove + namespace sigc { SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE } @@ -52,8 +55,12 @@ void Notebook::open(std::string path) { tmp_project_path=boost::filesystem::path(path).parent_path().string(); } auto language=Source::guess_language(path); - if(language && (language->get_id()=="chdr" || language->get_id()=="c" || language->get_id()=="cpp" || language->get_id()=="objc")) + if(language && (language->get_id()=="chdr" || language->get_id()=="c" || language->get_id()=="cpp" || language->get_id()=="objc")) { + if(boost::filesystem::exists(tmp_project_path+"/CMakeLists.txt") && !boost::filesystem::exists(tmp_project_path+"/compile_commands.json")) { + make_compile_commands(); + } source_views.emplace_back(new Source::ClangView(path, tmp_project_path)); + } else source_views.emplace_back(new Source::GenericView(path, tmp_project_path, language)); @@ -102,10 +109,38 @@ bool Notebook::save(int page) { if(juci::filesystem::write(view->file_path, view->get_buffer())) { view->get_buffer()->set_modified(false); Singleton::terminal()->print("File saved to: " +view->file_path+"\n"); + + //If CMakeLists.txt have been modified: + if(boost::filesystem::path(view->file_path).filename().string()=="CMakeLists.txt") { + if(make_compile_commands()) { + for(auto source_view: source_views) { + if(auto source_clang_view=dynamic_cast(source_view)) { + if(project_path==source_view->project_path) { + if(source_clang_view->restart_parse()) + Singleton::terminal()->print("Reparsing "+source_clang_view->file_path+"\n"); + else + Singleton::terminal()->print("Already reparsing "+source_clang_view->file_path+". Please reopen the file manually.\n"); + } + } + } + } + } + + return true; + } + Singleton::terminal()->print("Error: could not save file " +view->file_path+"\n"); + } + return false; +} + +bool Notebook::make_compile_commands() { + if(project_path.size()>0) { + Singleton::terminal()->print("Creating "+boost::filesystem::path(project_path+"/compile_commands.json").string()+"\n"); + if(Singleton::terminal()->execute(project_path, "cmake . -DCMAKE_EXPORT_COMPILE_COMMANDS=ON 2>&1")) { + //TODO: refresh directories return true; } } - Singleton::terminal()->print("Error: could not save file " +view->file_path+"\n"); return false; } diff --git a/src/notebook.h b/src/notebook.h index be21b0b..43254f6 100644 --- a/src/notebook.h +++ b/src/notebook.h @@ -22,6 +22,7 @@ public: std::string project_path; private: + bool make_compile_commands(); bool save_modified_dialog(); std::vector source_views; //Is NOT freed in destructor, this is intended for quick program exit. std::vector > scrolled_windows; diff --git a/src/source.cc b/src/source.cc index 783ad12..b78c6f9 100644 --- a/src/source.cc +++ b/src/source.cc @@ -278,8 +278,7 @@ Source::GenericView::GenericView(const std::string& file_path, const std::string clang::Index Source::ClangViewParse::clang_index(0, 0); Source::ClangViewParse::ClangViewParse(const std::string& file_path, const std::string& project_path): -Source::View(file_path, project_path), -parse_thread_go(true), parse_thread_mapped(false), parse_thread_stop(false) { +Source::View(file_path, project_path) { override_font(Pango::FontDescription(Singleton::Config::source()->font)); override_background_color(Gdk::RGBA(Singleton::Config::source()->background)); override_background_color(Gdk::RGBA(Singleton::Config::source()->background_selected), Gtk::StateFlags::STATE_FLAG_SELECTED); @@ -308,6 +307,28 @@ parse_thread_go(true), parse_thread_mapped(false), parse_thread_stop(false) { } //TODO: clear tag_class and param_spec? + parsing_in_progress=Singleton::terminal()->print_in_progress("Parsing "+file_path); + init_parse(); + + get_buffer()->signal_changed().connect([this]() { + start_reparse(); + type_tooltips.hide(); + diagnostic_tooltips.hide(); + }); + + get_buffer()->signal_mark_set().connect(sigc::mem_fun(*this, &Source::ClangViewParse::on_mark_set), false); +} + +void Source::ClangViewParse::init_parse() { + type_tooltips.hide(); + diagnostic_tooltips.hide(); + get_buffer()->remove_all_tags(get_buffer()->begin(), get_buffer()->end()); + clang_readable=false; + parse_thread_go=true; + parse_thread_mapped=false; + parse_thread_stop=false; + + int start_offset = get_source_buffer()->begin().get_offset(); int end_offset = get_source_buffer()->end().get_offset(); auto buffer_map=get_buffer_map(); @@ -340,7 +361,6 @@ parse_thread_go(true), parse_thread_mapped(false), parse_thread_stop(false) { parse_thread_go=true; }); - parsing_in_progress=Singleton::terminal()->print_in_progress("Parsing "+file_path); parse_done.connect([this](){ if(parse_thread_mapped) { if(parsing_mutex.try_lock()) { @@ -361,6 +381,8 @@ parse_thread_go(true), parse_thread_mapped(false), parse_thread_stop(false) { }); set_status("parsing..."); + if(parse_thread.joinable()) + parse_thread.join(); parse_thread=std::thread([this]() { while(true) { while(!parse_thread_go && !parse_thread_stop) @@ -380,14 +402,6 @@ parse_thread_go(true), parse_thread_mapped(false), parse_thread_stop(false) { } } }); - - get_buffer()->signal_changed().connect([this]() { - start_reparse(); - type_tooltips.hide(); - diagnostic_tooltips.hide(); - }); - - get_buffer()->signal_mark_set().connect(sigc::mem_fun(*this, &Source::ClangViewParse::on_mark_set), false); } void Source::ClangViewParse:: @@ -1048,6 +1062,10 @@ Source::ClangView::ClangView(const std::string& file_path, const std::string& pr delete_thread.join(); delete this; }); + do_restart_parse.connect([this](){ + init_parse(); + restart_parse_running=false; + }); } void Source::ClangView::delete_object() { @@ -1055,10 +1073,30 @@ void Source::ClangView::delete_object() { parse_thread_stop=true; delete_thread=std::thread([this](){ //TODO: Is it possible to stop the clang-process in progress? + if(restart_parse_thread.joinable()) + restart_parse_thread.join(); if(parse_thread.joinable()) parse_thread.join(); if(autocomplete_thread.joinable()) autocomplete_thread.join(); do_delete_object(); }); +} + +bool Source::ClangView::restart_parse() { + if(!restart_parse_running) { + restart_parse_running=true; + parse_thread_stop=true; + if(restart_parse_thread.joinable()) + restart_parse_thread.join(); + restart_parse_thread=std::thread([this](){ + if(parse_thread.joinable()) + parse_thread.join(); + if(autocomplete_thread.joinable()) + autocomplete_thread.join(); + do_restart_parse(); + }); + return true; + } + return false; } \ No newline at end of file diff --git a/src/source.h b/src/source.h index 83f4e24..4c6b8cc 100644 --- a/src/source.h +++ b/src/source.h @@ -91,13 +91,14 @@ namespace Source { public: ClangViewParse(const std::string& file_path, const std::string& project_path); protected: + void init_parse(); void start_reparse(); bool on_key_press_event(GdkEventKey* key); bool on_focus_out_event(GdkEventFocus* event); std::unique_ptr clang_tu; std::mutex parsing_mutex; std::unique_ptr clang_tokens; - bool clang_readable=false; + bool clang_readable; sigc::connection delayed_reparse_connection; sigc::connection delayed_tooltips_connection; @@ -169,9 +170,13 @@ namespace Source { public: ClangView(const std::string& file_path, const std::string& project_path); void delete_object(); + bool restart_parse(); private: Glib::Dispatcher do_delete_object; + Glib::Dispatcher do_restart_parse; std::thread delete_thread; + std::thread restart_parse_thread; + bool restart_parse_running=false; }; }; // class Source #endif // JUCI_SOURCE_H_ diff --git a/src/terminal.cc b/src/terminal.cc index 5f36da1..9eeb84d 100644 --- a/src/terminal.cc +++ b/src/terminal.cc @@ -56,6 +56,38 @@ Terminal::Terminal() { }); } +bool Terminal::execute(const std::string &path, const std::string &command) { + boost::filesystem::path boost_path; + if(path=="") + boost_path=boost::filesystem::current_path(); + else + boost_path=boost::filesystem::path(path); + + auto cd_path_and_command="cd "+boost_path.string()+" 2>&1 && "+command; + + FILE* p = NULL; + 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) { + print(buffer); + } + 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(); diff --git a/src/terminal.h b/src/terminal.h index 026884c..d7865c5 100644 --- a/src/terminal.h +++ b/src/terminal.h @@ -31,23 +31,25 @@ public: }; Terminal(); - void set_change_folder_command(boost::filesystem::path CMake_path); - void run(std::string executable); - void compile(); + 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 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); + void execute_command(std::string command, std::string mode); //TODO: remove Gtk::TextView text_view; Gtk::ScrolledWindow scrolled_window; - std::string change_folder_command; - std::string path; - const std::string cmake_sucsess = "Build files have been written to:"; - const std::string make_built = "Built target"; - const std::string make_executable = "Linking CXX executable"; + 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 }; #endif // JUCI_TERMINAL_H_ diff --git a/src/window.cc b/src/window.cc index 35c6902..b999717 100644 --- a/src/window.cc +++ b/src/window.cc @@ -5,6 +5,9 @@ #include "config.h" #include "api.h" +#include //TODO: remove +using namespace std; //TODO: remove + namespace sigc { SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE } @@ -82,6 +85,9 @@ Window::Window() : box(Gtk::ORIENTATION_VERTICAL) { Singleton::status()->set_text(notebook.get_current_view()->status); } }); + notebook.signal_page_removed().connect([this](Gtk::Widget* page, guint page_num) { + entry_box.hide(); + }); INFO("Window created"); } // Window constructor