From 4a83a004f4ccca11c479657ecd98ca6c6c550d1f Mon Sep 17 00:00:00 2001 From: eidheim Date: Sun, 9 Aug 2015 14:12:06 +0200 Subject: [PATCH] Added run command, and kill process items in menu. Remember to delete ~/.juci. Also cleaned up use of std::string instead of boost::filesystem::path. --- src/cmake.cc | 8 ++++---- src/cmake.h | 2 +- src/directories.cc | 6 +++--- src/directories.h | 4 ++-- src/files.h | 8 +++++++- src/juci.cc | 6 +++++- src/notebook.cc | 47 ++++++++++++++++++++++------------------------ src/notebook.h | 3 +-- src/source.cc | 47 +++++++++++++++++++++++----------------------- src/source.h | 18 +++++++++--------- src/sourcefile.h | 2 ++ src/terminal.cc | 38 ++++++++++++++++++++++++------------- src/terminal.h | 11 ++++++----- src/window.cc | 42 ++++++++++++++++++++++++++++++----------- src/window.h | 1 + 15 files changed, 142 insertions(+), 101 deletions(-) diff --git a/src/cmake.cc b/src/cmake.cc index 0d9fefc..d2ecfe6 100644 --- a/src/cmake.cc +++ b/src/cmake.cc @@ -40,14 +40,14 @@ CMake::CMake(const boost::filesystem::path &path) { } 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()); + create_compile_commands(project_path); } } -bool CMake::create_compile_commands(const std::string &path) { - Singleton::terminal()->print("Creating "+boost::filesystem::path(path+"/compile_commands.json").string()+"\n"); +bool CMake::create_compile_commands(const boost::filesystem::path &path) { + Singleton::terminal()->print("Creating "+path.string()+"/compile_commands.json\n"); //TODO: Windows... - if(Singleton::terminal()->execute("cmake . -DCMAKE_EXPORT_COMPILE_COMMANDS=ON 2>&1", path)==EXIT_SUCCESS) + if(Singleton::terminal()->execute("cmake . -DCMAKE_EXPORT_COMPILE_COMMANDS=ON", path)==EXIT_SUCCESS) return true; return false; } diff --git a/src/cmake.h b/src/cmake.h index f300f15..8be9d13 100644 --- a/src/cmake.h +++ b/src/cmake.h @@ -8,7 +8,7 @@ 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); + static bool create_compile_commands(const boost::filesystem::path &path); std::vector paths; std::vector files; diff --git a/src/directories.cc b/src/directories.cc index 088a0f7..82d9dba 100644 --- a/src/directories.cc +++ b/src/directories.cc @@ -72,14 +72,14 @@ void Directories::open_folder(const boost::filesystem::path& dir_path) { current_path=new_path; - if(selected_path.size()>0) + if(selected_path!="") select_path(selected_path); DEBUG("Folder opened"); } -void Directories::select_path(const std::string &path) { +void Directories::select_path(const boost::filesystem::path &path) { tree_store->foreach_iter([this, &path](const Gtk::TreeModel::iterator& iter){ - if(iter->get_value(column_record.path)==path) { + if(iter->get_value(column_record.path)==path.string()) { auto tree_path=Gtk::TreePath(iter); tree_view.expand_to_path(tree_path); tree_view.set_cursor(tree_path); diff --git a/src/directories.h b/src/directories.h index 57d36da..d8dcb77 100644 --- a/src/directories.h +++ b/src/directories.h @@ -29,7 +29,7 @@ public: Directories(); void open_folder(const boost::filesystem::path& dir_path=""); - void select_path(const std::string &path); + void select_path(const boost::filesystem::path &path); std::function on_row_activated; std::unique_ptr cmake; @@ -41,7 +41,7 @@ private: Gtk::TreeView tree_view; Glib::RefPtr tree_store; ColumnRecord column_record; - std::string selected_path; + boost::filesystem::path selected_path; }; #endif // JUCI_DIRECTORIES_H_ diff --git a/src/files.h b/src/files.h index 14a3610..ee3bc53 100644 --- a/src/files.h +++ b/src/files.h @@ -53,7 +53,10 @@ const std::string configjson = " \"source_goto_method\": \"m\",\n" " \"source_rename\": \"r\",\n" " \"compile_and_run\": \"Return\",\n" -" \"compile\": \"Return\"\n" +" \"compile\": \"Return\",\n" +" \"run_command\": \"Return\",\n" +" \"kill_last_running\": \"Escape\",\n" +" \"force_kill_last_running\": \"Escape\"\n" " },\n" " \"directoryfilter\": {\n" " \"ignore\": [\n" @@ -103,6 +106,9 @@ const std::string menuxml = " \n" " \n" " \n" +" \n" +" \n" +" \n" " \n" " \n" " \n" diff --git a/src/juci.cc b/src/juci.cc index 83d8f14..4cdde32 100644 --- a/src/juci.cc +++ b/src/juci.cc @@ -1,5 +1,6 @@ #include "juci.h" #include "singletons.h" +#include void init_logging() { add_common_attributes(); @@ -18,13 +19,16 @@ int Juci::on_command_line(const Glib::RefPtr &cmd) ctx.parse(argc, argv); if(argc>=2) { for(int c=1;cfile_path) { + if(file_path==get_view(c)->file_path) { set_current_page(c); get_current_view()->grab_focus(); return; } } - std::ifstream can_read(path); + std::ifstream can_read(file_path.string()); if(!can_read) { - Singleton::terminal()->print("Error: could not open "+path+"\n"); + Singleton::terminal()->print("Error: could not open "+file_path.string()+"\n"); return; } can_read.close(); - auto language=Source::guess_language(path); + auto language=Source::guess_language(file_path); if(language && (language->get_id()=="chdr" || language->get_id()=="c" || language->get_id()=="cpp" || language->get_id()=="objc")) { - std::string project_path; + boost::filesystem::path project_path; if(directories.cmake && directories.cmake->project_path!="") - project_path=directories.cmake->project_path.string(); + project_path=directories.cmake->project_path; else { - auto parent_path=boost::filesystem::path(path).parent_path(); - project_path=parent_path.string(); - CMake cmake(parent_path); + project_path=file_path.parent_path(); + CMake cmake(project_path); if(cmake.project_path!="") { - project_path=cmake.project_path.string(); - Singleton::terminal()->print("Project path for "+path+" set to "+project_path+"\n"); + project_path=cmake.project_path; + Singleton::terminal()->print("Project path for "+file_path.string()+" set to "+project_path.string()+"\n"); } else - Singleton::terminal()->print("Error: could not find project path for "+path+"\n"); + Singleton::terminal()->print("Error: could not find project path for "+file_path.string()+"\n"); } - source_views.emplace_back(new Source::ClangView(path, project_path)); + source_views.emplace_back(new Source::ClangView(file_path, project_path)); } else - source_views.emplace_back(new Source::GenericView(path, language)); + source_views.emplace_back(new Source::GenericView(file_path, language)); scrolled_windows.emplace_back(new Gtk::ScrolledWindow()); hboxes.emplace_back(new Gtk::HBox()); scrolled_windows.back()->add(*source_views.back()); hboxes.back()->pack_start(*scrolled_windows.back(), true, true); - boost::filesystem::path file_path(source_views.back()->file_path); std::string title=file_path.filename().string(); append_page(*hboxes.back(), title); show_all_children(); @@ -89,8 +87,7 @@ void Notebook::open(std::string path) { //Add star on tab label when the page is not saved: auto source_view=get_current_view(); get_current_view()->get_buffer()->signal_modified_changed().connect([this, source_view]() { - boost::filesystem::path file_path(source_view->file_path); - std::string title=file_path.filename().string(); + std::string title=source_view->file_path.filename().string(); if(source_view->get_buffer()->get_modified()) title+="*"; int page=-1; @@ -117,20 +114,20 @@ bool Notebook::save(int page) { if (view->file_path != "" && view->get_buffer()->get_modified()) { 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"); + Singleton::terminal()->print("File saved to: " +view->file_path.string()+"\n"); //If CMakeLists.txt have been modified: //TODO: recreate cmake even without directories open? - if(boost::filesystem::path(view->file_path).filename().string()=="CMakeLists.txt") { - if(directories.cmake && directories.cmake->project_path!="" && boost::filesystem::path(view->file_path)>=directories.cmake->project_path && CMake::create_compile_commands(directories.cmake->project_path.string())) { + if(view->file_path.filename()=="CMakeLists.txt") { + if(directories.cmake && directories.cmake->project_path!="" && view->file_path>=directories.cmake->project_path && CMake::create_compile_commands(directories.cmake->project_path)) { directories.open_folder(); for(auto source_view: source_views) { if(auto source_clang_view=dynamic_cast(source_view)) { if(directories.cmake->project_path.string()==source_clang_view->project_path) { if(source_clang_view->restart_parse()) - Singleton::terminal()->print("Reparsing "+source_clang_view->file_path+"\n"); + Singleton::terminal()->async_print("Reparsing "+source_clang_view->file_path.string()+"\n"); else - Singleton::terminal()->print("Already reparsing "+source_clang_view->file_path+". Please reopen the file manually.\n"); + Singleton::terminal()->async_print("Already reparsing "+source_clang_view->file_path.string()+". Please reopen the file manually.\n"); } } } @@ -139,7 +136,7 @@ bool Notebook::save(int page) { return true; } - Singleton::terminal()->print("Error: could not save file " +view->file_path+"\n"); + Singleton::terminal()->print("Error: could not save file " +view->file_path.string()+"\n"); } return false; } @@ -177,7 +174,7 @@ bool Notebook::close_current_page() { bool Notebook::save_modified_dialog() { INFO("Notebook::save_modified_dialog"); Gtk::MessageDialog dialog((Gtk::Window&)(*get_toplevel()), "Save file!", false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_YES_NO); - dialog.set_secondary_text("Do you want to save: " + get_current_view()->file_path+" ?"); + dialog.set_secondary_text("Do you want to save: " + get_current_view()->file_path.string()+" ?"); int result = dialog.run(); if(result==Gtk::RESPONSE_YES) { save_current(); diff --git a/src/notebook.h b/src/notebook.h index 8ad8480..a77040f 100644 --- a/src/notebook.h +++ b/src/notebook.h @@ -17,12 +17,11 @@ public: int size(); Source::View* get_current_view(); bool close_current_page(); - void open(std::string filename); + void open(const boost::filesystem::path &file_path); bool save(int page); bool save_current(); private: - bool make_compile_commands(const std::string &path); bool save_modified_dialog(); Directories &directories; std::vector source_views; //Is NOT freed in destructor, this is intended for quick program exit. diff --git a/src/source.cc b/src/source.cc index 70df906..dc66986 100644 --- a/src/source.cc +++ b/src/source.cc @@ -15,18 +15,17 @@ namespace sigc { SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE } -Glib::RefPtr Source::guess_language(const std::string &file_path) { +Glib::RefPtr Source::guess_language(const boost::filesystem::path &file_path) { auto language_manager=Gsv::LanguageManager::get_default(); bool result_uncertain = false; - auto content_type = Gio::content_type_guess(file_path, NULL, 0, result_uncertain); + auto content_type = Gio::content_type_guess(file_path.string(), NULL, 0, result_uncertain); if(result_uncertain) { content_type.clear(); } - auto language=language_manager->guess_language(file_path, content_type); + auto language=language_manager->guess_language(file_path.string(), content_type); if(!language) { - auto path=boost::filesystem::path(file_path); - auto filename=path.filename().string(); - auto extension=path.extension(); + auto filename=file_path.filename().string(); + auto extension=file_path.extension(); if(filename=="CMakeLists.txt") language=language_manager->get_language("cmake"); } @@ -36,7 +35,7 @@ Glib::RefPtr Source::guess_language(const std::string &file_path) ////////////// //// View //// ////////////// -Source::View::View(const std::string& file_path): file_path(file_path) { +Source::View::View(const boost::filesystem::path &file_path): file_path(file_path) { set_smart_home_end(Gsv::SMART_HOME_END_BEFORE); set_show_line_numbers(Singleton::Config::source()->show_line_numbers); set_highlight_current_line(Singleton::Config::source()->highlight_current_line); @@ -247,7 +246,7 @@ bool Source::View::on_key_press_event(GdkEventKey* key) { ///////////////////// //// GenericView //// ///////////////////// -Source::GenericView::GenericView(const std::string& file_path, Glib::RefPtr language) : View(file_path) { +Source::GenericView::GenericView(const boost::filesystem::path &file_path, Glib::RefPtr language) : View(file_path) { auto style_scheme_manager=Gsv::StyleSchemeManager::get_default(); //TODO: add?: style_scheme_manager->prepend_search_path("~/.juci/"); auto scheme=style_scheme_manager->get_scheme("classic"); @@ -260,7 +259,7 @@ Source::GenericView::GenericView(const std::string& file_path, Glib::RefPtrset_language(language); - Singleton::terminal()->print("Language for file "+file_path+" set to "+language->get_name()+".\n"); + Singleton::terminal()->print("Language for file "+file_path.string()+" set to "+language->get_name()+".\n"); } auto completion=get_completion(); auto completion_words=Gsv::CompletionWords::create("", Glib::RefPtr()); @@ -276,7 +275,7 @@ Source::GenericView::GenericView(const std::string& file_path, Glib::RefPtrfont)); override_background_color(Gdk::RGBA(Singleton::Config::source()->background)); @@ -306,7 +305,7 @@ Source::View(file_path), project_path(project_path) { } //TODO: clear tag_class and param_spec? - parsing_in_progress=Singleton::terminal()->print_in_progress("Parsing "+file_path); + parsing_in_progress=Singleton::terminal()->print_in_progress("Parsing "+file_path.string()); //GTK-calls must happen in main thread, so the parse_thread //sends signals to the main thread that it is to call the following functions: parse_start.connect([this]{ @@ -360,7 +359,7 @@ void Source::ClangViewParse::init_parse() { int end_offset = get_source_buffer()->end().get_offset(); auto buffer_map=get_buffer_map(); //Remove includes for first parse for initial syntax highlighting - auto& str=buffer_map[file_path]; + auto& str=buffer_map[file_path.string()]; std::size_t pos=0; while((pos=str.find("#include", pos))!=std::string::npos) { auto start_pos=pos; @@ -408,15 +407,15 @@ init_syntax_highlighting(const std::map int end_offset) { std::vector arguments = get_compilation_commands(); clang_tu = std::unique_ptr(new clang::TranslationUnit(clang_index, - file_path, + file_path.string(), arguments, buffers)); - clang_tokens=clang_tu->get_tokens(0, buffers.find(file_path)->second.size()-1); + clang_tokens=clang_tu->get_tokens(0, buffers.find(file_path.string())->second.size()-1); } std::map Source::ClangViewParse::get_buffer_map() const { std::map buffer_map; - buffer_map[file_path]=get_source_buffer()->get_text().raw(); + buffer_map[file_path.string()]=get_source_buffer()->get_text().raw(); return buffer_map; } @@ -434,13 +433,13 @@ void Source::ClangViewParse::start_reparse() { int Source::ClangViewParse::reparse(const std::map &buffer) { int status = clang_tu->ReparseTranslationUnit(buffer); - clang_tokens=clang_tu->get_tokens(0, parse_thread_buffer_map.find(file_path)->second.size()-1); + clang_tokens=clang_tu->get_tokens(0, parse_thread_buffer_map.find(file_path.string())->second.size()-1); return status; } std::vector Source::ClangViewParse::get_compilation_commands() { - clang::CompilationDatabase db(project_path); - clang::CompileCommands commands(file_path, db); + clang::CompilationDatabase db(project_path.string()); + clang::CompileCommands commands(file_path.string(), db); std::vector cmds = commands.get_commands(); std::vector arguments; for (auto &i : cmds) { @@ -449,7 +448,7 @@ std::vector Source::ClangViewParse::get_compilation_commands() { arguments.emplace_back(lol[a]); } } - if(boost::filesystem::path(file_path).extension()==".h") //TODO: temporary fix for .h-files (parse as c++) + if(file_path.extension()==".h") //TODO: temporary fix for .h-files (parse as c++) arguments.emplace_back("-xc++"); return arguments; } @@ -496,7 +495,7 @@ void Source::ClangViewParse::update_diagnostics() { get_buffer()->remove_tag_by_name("diagnostic_error_underline", get_buffer()->begin(), get_buffer()->end()); auto diagnostics=clang_tu->get_diagnostics(); for(auto &diagnostic: diagnostics) { - if(diagnostic.path==file_path) { + if(diagnostic.path==file_path.string()) { auto start=get_buffer()->get_iter_at_offset(diagnostic.offsets.first); auto end=get_buffer()->get_iter_at_offset(diagnostic.offsets.second); std::string diagnostic_tag_name; @@ -701,7 +700,7 @@ bool Source::ClangViewParse::on_key_press_event(GdkEventKey* key) { ////////////////////////////// //// ClangViewAutocomplete /// ////////////////////////////// -Source::ClangViewAutocomplete::ClangViewAutocomplete(const std::string& file_path, const std::string& project_path): +Source::ClangViewAutocomplete::ClangViewAutocomplete(const boost::filesystem::path &file_path, const boost::filesystem::path& project_path): Source::ClangViewParse(file_path, project_path), autocomplete_cancel_starting(false) { get_buffer()->signal_changed().connect([this](){ if(completion_dialog_shown) @@ -862,7 +861,7 @@ void Source::ClangViewAutocomplete::autocomplete() { }); std::shared_ptr > buffer_map=std::make_shared >(); - auto& buffer=(*buffer_map)[this->file_path]; + auto& buffer=(*buffer_map)[this->file_path.string()]; buffer=get_buffer()->get_text(get_buffer()->begin(), get_buffer()->get_insert()->get_iter()); auto iter = get_source_buffer()->get_insert()->get_iter(); auto line_nr=iter.get_line()+1; @@ -921,7 +920,7 @@ get_autocomplete_suggestions(int line_number, int column, std::mapcreate_tag(); similar_tokens_tag->property_weight()=Pango::WEIGHT_BOLD; @@ -1053,7 +1052,7 @@ Source::ClangViewAutocomplete(file_path, project_path) { }; } -Source::ClangView::ClangView(const std::string& file_path, const std::string& project_path): ClangViewRefactor(file_path, project_path) { +Source::ClangView::ClangView(const boost::filesystem::path &file_path, const boost::filesystem::path& project_path): ClangViewRefactor(file_path, project_path) { do_delete_object.connect([this](){ if(delete_thread.joinable()) delete_thread.join(); diff --git a/src/source.h b/src/source.h index ed434cd..dba74ec 100644 --- a/src/source.h +++ b/src/source.h @@ -16,7 +16,7 @@ #include namespace Source { - Glib::RefPtr guess_language(const std::string &file_path); + Glib::RefPtr guess_language(const boost::filesystem::path &file_path); class Config { public: @@ -46,7 +46,7 @@ namespace Source { class View : public Gsv::View { public: - View(const std::string& file_path); + View(const boost::filesystem::path &file_path); ~View(); void search_highlight(const std::string &text, bool case_sensitive, bool regex); @@ -57,7 +57,7 @@ namespace Source { void replace_backward(const std::string &replacement); void replace_all(const std::string &replacement); - std::string file_path; + boost::filesystem::path file_path; std::function()> get_declaration_location; std::function goto_method; @@ -83,13 +83,13 @@ namespace Source { class GenericView : public View { public: - GenericView(const std::string& file_path, Glib::RefPtr language); + GenericView(const boost::filesystem::path &file_path, Glib::RefPtr language); }; class ClangViewParse : public View { public: - ClangViewParse(const std::string& file_path, const std::string& project_path); - std::string project_path; + ClangViewParse(const boost::filesystem::path &file_path, const boost::filesystem::path& project_path); + boost::filesystem::path project_path; protected: void init_parse(); void start_reparse(); @@ -136,7 +136,7 @@ namespace Source { class ClangViewAutocomplete : public ClangViewParse { public: - ClangViewAutocomplete(const std::string& file_path, const std::string& project_path); + ClangViewAutocomplete(const boost::filesystem::path &file_path, const boost::filesystem::path& project_path); protected: bool on_key_press_event(GdkEventKey* key); bool on_focus_out_event(GdkEventFocus* event); @@ -158,7 +158,7 @@ namespace Source { class ClangViewRefactor : public ClangViewAutocomplete { public: - ClangViewRefactor(const std::string& file_path, const std::string& project_path); + ClangViewRefactor(const boost::filesystem::path &file_path, const boost::filesystem::path& project_path); private: Glib::RefPtr similar_tokens_tag; std::string last_similar_tokens_tagged; @@ -168,7 +168,7 @@ namespace Source { class ClangView : public ClangViewRefactor { public: - ClangView(const std::string& file_path, const std::string& project_path); + ClangView(const boost::filesystem::path &file_path, const boost::filesystem::path& project_path); void async_delete(); bool restart_parse(); private: diff --git a/src/sourcefile.h b/src/sourcefile.h index aabe617..d1ee608 100644 --- a/src/sourcefile.h +++ b/src/sourcefile.h @@ -11,6 +11,7 @@ namespace juci { static std::string read(const std::string &path); static std::string read(const boost::filesystem::path &path) { return read(path.string()); } static bool read(const std::string &path, Glib::RefPtr text_buffer); + static bool read(const boost::filesystem::path &path, Glib::RefPtr text_buffer) { return read(path.string(), text_buffer); } static std::vector read_lines(const std::string &path); static std::vector read_lines(const boost::filesystem::path &path) { return read_lines(path.string()); }; @@ -20,6 +21,7 @@ namespace juci { static bool write(const std::string &path) { return write(path, ""); }; static bool write(const boost::filesystem::path &path) { return write(path, ""); }; static bool write(const std::string &path, Glib::RefPtr text_buffer); + static bool write(const boost::filesystem::path &path, Glib::RefPtr text_buffer) { return write(path.string(), text_buffer); } }; } // namepace juci #endif // JUCI_SOURCEFILE_H_ diff --git a/src/terminal.cc b/src/terminal.cc index 50d6990..2641b0b 100644 --- a/src/terminal.cc +++ b/src/terminal.cc @@ -125,14 +125,11 @@ Terminal::Terminal() { }); } -int Terminal::execute(const std::string &command, const std::string &path) { - boost::filesystem::path boost_path; +int Terminal::execute(const std::string &command, const boost::filesystem::path &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()+" && "+command; + cd_path_and_command="cd "+path.string()+" && "+command; } else cd_path_and_command=command; @@ -179,15 +176,13 @@ int Terminal::execute(const std::string &command, const std::string &path) { } } -void Terminal::async_execute(const std::string &command, const std::string &path, std::function callback) { +void Terminal::async_execute(const std::string &command, const boost::filesystem::path &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()+" && "+command; + cd_path_and_command="cd "+path.string()+" && "+command; } else cd_path_and_command=command; @@ -195,7 +190,7 @@ void Terminal::async_execute(const std::string &command, const std::string &path int stdin, stdout, stderr; async_execute_pids_mutex.lock(); auto pid=popen3(cd_path_and_command.c_str(), stdin, stdout, stderr); - async_execute_pids.emplace(pid); + async_execute_pids.emplace_back(pid); async_execute_pids_mutex.unlock(); if (pid<=0) { @@ -231,7 +226,12 @@ void Terminal::async_execute(const std::string &command, const std::string &path int exit_code; waitpid(pid, &exit_code, 0); async_execute_pids_mutex.lock(); - async_execute_pids.erase(pid); + for(auto it=async_execute_pids.begin();it!=async_execute_pids.end();it++) { + if(*it==pid) { + async_execute_pids.erase(it); + break; + } + } async_execute_pids_mutex.unlock(); close(stdin); close(stdout); @@ -244,10 +244,22 @@ void Terminal::async_execute(const std::string &command, const std::string &path async_execute_thread.detach(); } -void Terminal::kill_executing() { +void Terminal::kill_last_async_execute(bool force) { + async_execute_pids_mutex.lock(); + if(force) + kill(-async_execute_pids.back(), SIGTERM); + else + kill(-async_execute_pids.back(), SIGINT); + async_execute_pids_mutex.unlock(); +} + +void Terminal::kill_async_executes(bool force) { async_execute_pids_mutex.lock(); for(auto &pid: async_execute_pids) { - kill(-pid, SIGINT); + if(force) + kill(-pid, SIGTERM); + else + kill(-pid, SIGINT); } async_execute_pids_mutex.unlock(); } diff --git a/src/terminal.h b/src/terminal.h index 4559473..3b14de0 100644 --- a/src/terminal.h +++ b/src/terminal.h @@ -7,7 +7,7 @@ #include #include #include -#include +#include class Terminal : public Gtk::HBox { public: @@ -26,9 +26,10 @@ public: }; Terminal(); - int execute(const std::string &command, const std::string &path=""); - void async_execute(const std::string &command, const std::string &path="", std::function callback=nullptr); - void kill_executing(); + int execute(const std::string &command, const boost::filesystem::path &path=""); + void async_execute(const std::string &command, const boost::filesystem::path &path="", std::function callback=nullptr); + void kill_last_async_execute(bool force=false); + void kill_async_executes(bool force=false); int print(const std::string &message, bool bold=false); void print(int line_nr, const std::string &message, bool bold=false); @@ -44,7 +45,7 @@ private: Glib::RefPtr bold_tag; std::mutex async_execute_pids_mutex; - std::unordered_set async_execute_pids; + std::list async_execute_pids; }; #endif // JUCI_TERMINAL_H_ diff --git a/src/window.cc b/src/window.cc index 5f1ff4e..fb90243 100644 --- a/src/window.cc +++ b/src/window.cc @@ -204,24 +204,22 @@ void Window::create_menu() { CMake cmake(notebook.get_current_view()->file_path); directories.open_folder(); 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!="") { if(path!="") { compiling=true; - Singleton::terminal()->print("Compiling and executing "+path.string()+"\n"); + Singleton::terminal()->print("Compiling and running "+path.string()+"\n"); //TODO: Windows... - Singleton::terminal()->async_execute("make", cmake.project_path.string(), [this, path](int exit_code){ + Singleton::terminal()->async_execute("make", cmake.project_path, [this, path](int exit_code){ compiling=false; if(exit_code==EXIT_SUCCESS) { compile_success(); //TODO: Windows... - Singleton::terminal()->async_execute(path.string(), path.parent_path().string(), [this, path](int exit_code){ + Singleton::terminal()->async_execute(path.string(), "", [this, path](int exit_code){ Singleton::terminal()->async_print(path.string()+" returned: "+std::to_string(exit_code)+'\n'); }); } @@ -240,13 +238,37 @@ void Window::create_menu() { 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){ + Singleton::terminal()->async_execute("make", cmake.project_path, [this](int exit_code){ compiling=false; if(exit_code==EXIT_SUCCESS) compile_success(); }); } }); + menu.action_group->add(Gtk::Action::create("ProjectRunCommand", "Run Command"), Gtk::AccelKey(menu.key_map["run_command"]), [this]() { + entry_box.clear(); + entry_box.entries.emplace_back(last_run_command, [this](const std::string& content){ + if(content!="") { + last_run_command=content; + Singleton::terminal()->async_print("Running: "+content+'\n'); + Singleton::terminal()->async_execute(content, directories.current_path, [this, content](int exit_code){ + Singleton::terminal()->async_print(content+" returned: "+std::to_string(exit_code)+'\n'); + }); + } + entry_box.hide(); + }); + auto entry_it=entry_box.entries.begin(); + entry_box.buttons.emplace_back("Run command", [this, entry_it](){ + entry_it->activate(); + }); + entry_box.show(); + }); + menu.action_group->add(Gtk::Action::create("ProjectKillLastRunning", "Kill Last Process"), Gtk::AccelKey(menu.key_map["kill_last_running"]), [this]() { + Singleton::terminal()->kill_last_async_execute(); + }); + menu.action_group->add(Gtk::Action::create("ProjectForceKillLastRunning", "Force Kill Last Process"), Gtk::AccelKey(menu.key_map["force_kill_last_running"]), [this]() { + Singleton::terminal()->kill_last_async_execute(true); + }); menu.action_group->add(Gtk::Action::create("WindowCloseTab", "Close tab"), Gtk::AccelKey(menu.key_map["close_tab"]), [this]() { notebook.close_current_page(); @@ -258,8 +280,6 @@ void Window::create_menu() { bool Window::on_key_press_event(GdkEventKey *event) { if(event->keyval==GDK_KEY_Escape) { - if(entry_box.entries.size()==0) - Singleton::terminal()->kill_executing(); entry_box.hide(); } #ifdef __APPLE__ //For Apple's Command-left, right, up, down keys @@ -303,7 +323,7 @@ void Window::hide() { if(!notebook.close_current_page()) return; } - Singleton::terminal()->kill_executing(); + Singleton::terminal()->kill_async_executes(); Gtk::Window::hide(); } @@ -417,7 +437,7 @@ void Window::save_file_dialog() { if(directories.current_path!="") directories.open_folder(); notebook.open(path); - Singleton::terminal()->print("File saved to: " + notebook.get_current_view()->file_path+"\n"); + Singleton::terminal()->print("File saved to: " + notebook.get_current_view()->file_path.string()+"\n"); } else Singleton::terminal()->print("Error saving file\n"); @@ -564,7 +584,7 @@ void Window::rename_token_entry() { if(notebook.get_view(c)->rename_similar_tokens) { auto number=notebook.get_view(c)->rename_similar_tokens(*token, content); if(number>0) { - Singleton::terminal()->print("Replaced "+std::to_string(number)+" occurrences in file "+notebook.get_view(c)->file_path+"\n"); + Singleton::terminal()->print("Replaced "+std::to_string(number)+" occurrences in file "+notebook.get_view(c)->file_path.string()+"\n"); notebook.save(c); } } diff --git a/src/window.h b/src/window.h index f14f731..c5c0e09 100644 --- a/src/window.h +++ b/src/window.h @@ -40,6 +40,7 @@ private: void rename_token_entry(); std::string last_search; std::string last_replace; + std::string last_run_command; bool case_sensitive_search=true; bool regex_search=false; bool search_entry_shown=false;