diff --git a/docs/install.md b/docs/install.md index 9693755..fe1bdc4 100644 --- a/docs/install.md +++ b/docs/install.md @@ -4,6 +4,7 @@ Install dependencies: ```sh sudo apt-get install git cmake make g++ libclang-dev pkg-config libboost-system-dev libboost-thread-dev libboost-filesystem-dev libboost-log-dev libgtkmm-3.0-dev libgtksourceviewmm-3.0-dev aspell-en libaspell-dev +sudo apt-get install clang-format-3.6 || sudo apt-get install clang-format-3.5 ``` Get juCi++ source, compile and install: @@ -15,12 +16,6 @@ make sudo make install ``` -To use clang-format for auto-indentation of C++ files (replace \[version\] with an available clang-format version): -```sh -sudo apt-get install clang-format-[version] -sudo ln -s /usr/bin/clang-format-[version] /usr/local/bin/clang-format -``` - ## Ubuntu 14/Linux Mint 17 Install dependencies: ```sh @@ -28,7 +23,7 @@ sudo add-apt-repository ppa:ubuntu-toolchain-r/test sudo apt-get update sudo apt-get install g++-4.9 sudo apt-get remove g++-4.8 -sudo apt-get install git cmake make g++ libclang-3.6-dev pkg-config libboost-system1.55-dev libboost-thread1.55-dev libboost-filesystem1.55-dev libboost-log1.55-dev libgtkmm-3.0-dev libgtksourceviewmm-3.0-dev aspell-en libaspell-dev +sudo apt-get install git cmake make g++ libclang-3.6-dev clang-format-3.6 pkg-config libboost-system1.55-dev libboost-thread1.55-dev libboost-filesystem1.55-dev libboost-log1.55-dev libgtkmm-3.0-dev libgtksourceviewmm-3.0-dev aspell-en libaspell-dev ``` Get juCi++ source, compile and install: @@ -40,12 +35,6 @@ make sudo make install ``` -To use clang-format for auto-indentation of C++ files (replace \[version\] with an available clang-format version): -```sh -sudo apt-get install clang-format-[version] -sudo ln -s /usr/bin/clang-format-[version] /usr/local/bin/clang-format -``` - ## OS X with Homebrew (http://brew.sh/) Install dependencies (installing llvm may take some time): ```sh diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e5e7cdb..7c5bf99 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -72,6 +72,7 @@ set(source_files juci.h singletons.cc cmake.h cmake.cc + dialogs.cc ../libclangmm/src/CodeCompleteResults.cc ../libclangmm/src/CompilationDatabase.cc @@ -92,8 +93,8 @@ if(MSYS) list(APPEND source_files terminal_win.cc) list(APPEND source_files dialogs_win.cc) else() - list(APPEND source_files terminal.cc) - list(APPEND source_files dialogs.cc) + list(APPEND source_files terminal_unix.cc) + list(APPEND source_files dialogs_unix.cc) endif() add_executable(${project_name} ${source_files}) diff --git a/src/cmake.cc b/src/cmake.cc index 7304358..3e2f1c9 100644 --- a/src/cmake.cc +++ b/src/cmake.cc @@ -2,6 +2,7 @@ #include "singletons.h" #include "filesystem.h" #include +#include "dialogs.h" #include //TODO: remove using namespace std; //TODO: remove @@ -45,8 +46,10 @@ CMake::CMake(const boost::filesystem::path &path) { } bool CMake::create_compile_commands(const boost::filesystem::path &path) { - Singleton::terminal->print("Creating "+path.string()+"/compile_commands.json\n"); - if(Singleton::terminal->execute(Singleton::config->terminal.cmake_command+" . -DCMAKE_EXPORT_COMPILE_COMMANDS=ON", path)==EXIT_SUCCESS) { + Dialog::Message message("Creating "+path.string()+"/compile_commands.json"); + auto exit_code=Singleton::terminal->execute(Singleton::config->terminal.cmake_command+" . -DCMAKE_EXPORT_COMPILE_COMMANDS=ON", path); + message.hide(); + if(exit_code==EXIT_SUCCESS) { #ifdef _WIN32 //Temporary fix to MSYS2's libclang auto compile_commands_path=path; compile_commands_path+="/compile_commands.json"; diff --git a/src/config.cc b/src/config.cc index 94f9552..094d57e 100644 --- a/src/config.cc +++ b/src/config.cc @@ -89,8 +89,20 @@ void Config::retrieve_config() { window.default_size = {cfg.get("default_window_size.width"), cfg.get("default_window_size.height")}; terminal.make_command=cfg.get("project.make_command"); terminal.cmake_command=cfg.get("project.cmake_command"); - terminal.clang_format_command=cfg.get("project.clang_format_command", "clang-format"); terminal.history_size=cfg.get("terminal_history_size"); + + terminal.clang_format_command=cfg.get("project.clang_format_command", "clang-format"); +#ifdef __linux + if(terminal.clang_format_command=="clang-format" && + !boost::filesystem::exists("/usr/bin/clang-format") && !boost::filesystem::exists("/usr/local/bin/clang-format")) { + if(boost::filesystem::exists("/usr/bin/clang-format-3.7")) + terminal.clang_format_command="/usr/bin/clang-format-3.7"; + else if(boost::filesystem::exists("/usr/bin/clang-format-3.6")) + terminal.clang_format_command="/usr/bin/clang-format-3.6"; + else if(boost::filesystem::exists("/usr/bin/clang-format-3.5")) + terminal.clang_format_command="/usr/bin/clang-format-3.5"; + } +#endif } bool Config::check_config_file(const boost::property_tree::ptree &default_cfg, std::string parent_path) { @@ -146,6 +158,8 @@ void Config::get_source() { source.style=source_json.get("style"); source.font=source_json.get("font"); + source.cleanup_whitespace_characters=source_json.get("cleanup_whitespace_characters"); + source.show_map = source_json.get("show_map"); source.map_font_size = source_json.get("map_font_size"); diff --git a/src/config.h b/src/config.h index 71c9866..0bfb91d 100644 --- a/src/config.h +++ b/src/config.h @@ -49,6 +49,8 @@ public: std::string font; std::string spellcheck_language; + bool cleanup_whitespace_characters; + bool show_map; std::string map_font_size; diff --git a/src/dialogs.cc b/src/dialogs.cc index 8248443..8f66ab0 100644 --- a/src/dialogs.cc +++ b/src/dialogs.cc @@ -1,59 +1,56 @@ #include "dialogs.h" -#include "singletons.h" -#include -#include #include "juci.h" +#include "singletons.h" +#include + +namespace sigc { +#ifndef SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE + template + struct functor_trait { + typedef decltype (::sigc::mem_fun(std::declval(), + &Functor::operator())) _intermediate; + typedef typename _intermediate::result_type result_type; + typedef Functor functor_type; + }; +#else + SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE +#endif +} + +Dialog::Message::Message(const std::string &text): Gtk::MessageDialog(text, false, Gtk::MessageType::MESSAGE_INFO, Gtk::ButtonsType::BUTTONS_NONE, true) { + auto g_application=g_application_get_default(); + auto gio_application=Glib::wrap(g_application, true); + auto application=Glib::RefPtr::cast_static(gio_application); + set_transient_for(*application->window); + set_position(Gtk::WindowPosition::WIN_POS_CENTER_ON_PARENT); + + show_now(); + + while(g_main_context_pending(NULL)) + g_main_context_iteration(NULL, false); +} -std::string open_dialog(const std::string &title, +std::string Dialog::gtk_dialog(const std::string &title, const std::vector> &buttons, Gtk::FileChooserAction gtk_options, - const std::string &file_name = "") { + const std::string &file_name) { Gtk::FileChooserDialog dialog(title, gtk_options); - if(!Singleton::directories->current_path.empty()) - gtk_file_chooser_set_current_folder((GtkFileChooser*)dialog.gobj(), Singleton::directories->current_path.string().c_str()); - else - gtk_file_chooser_set_current_folder((GtkFileChooser*)dialog.gobj(), boost::filesystem::current_path().string().c_str()); - if (!file_name.empty()) - gtk_file_chooser_set_filename((GtkFileChooser*)dialog.gobj(), file_name.c_str()); - dialog.set_position(Gtk::WindowPosition::WIN_POS_CENTER_ALWAYS); auto g_application=g_application_get_default(); //TODO: Post issue that Gio::Application::get_default should return pointer and not Glib::RefPtr auto gio_application=Glib::wrap(g_application, true); auto application=Glib::RefPtr::cast_static(gio_application); dialog.set_transient_for(*application->window); + auto current_path=application->window->notebook.get_current_folder(); + if(current_path.empty()) + current_path=boost::filesystem::current_path(); + gtk_file_chooser_set_current_folder((GtkFileChooser*)dialog.gobj(), current_path.string().c_str()); + + if (!file_name.empty()) + gtk_file_chooser_set_filename((GtkFileChooser*)dialog.gobj(), file_name.c_str()); + dialog.set_position(Gtk::WindowPosition::WIN_POS_CENTER_ON_PARENT); + for (auto &button : buttons) dialog.add_button(button.first, button.second); return dialog.run() == Gtk::RESPONSE_OK ? dialog.get_filename() : ""; } - -std::string Dialog::open_folder() { - return open_dialog("Open Folder", - {std::make_pair("Cancel", Gtk::RESPONSE_CANCEL),std::make_pair("Open", Gtk::RESPONSE_OK)}, - Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER); -} - -std::string Dialog::new_file() { - return open_dialog("New File", - {std::make_pair("Cancel", Gtk::RESPONSE_CANCEL), std::make_pair("Save", Gtk::RESPONSE_OK)}, - Gtk::FILE_CHOOSER_ACTION_SAVE); -} - -std::string Dialog::new_folder() { - return open_dialog("New Folder", - {std::make_pair("Cancel", Gtk::RESPONSE_CANCEL),std::make_pair("Create", Gtk::RESPONSE_OK)}, - Gtk::FILE_CHOOSER_ACTION_CREATE_FOLDER); -} - -std::string Dialog::open_file() { - return open_dialog("Open File", - {std::make_pair("Cancel", Gtk::RESPONSE_CANCEL),std::make_pair("Select", Gtk::RESPONSE_OK)}, - Gtk::FILE_CHOOSER_ACTION_OPEN); -} - -std::string Dialog::save_file_as(const boost::filesystem::path &file_path) { - return open_dialog("Save File As", - {std::make_pair("Cancel", Gtk::RESPONSE_CANCEL),std::make_pair("Save", Gtk::RESPONSE_OK)}, - Gtk::FILE_CHOOSER_ACTION_SAVE, file_path.string()); -} - diff --git a/src/dialogs.h b/src/dialogs.h index 4977ce6..68e5d19 100644 --- a/src/dialogs.h +++ b/src/dialogs.h @@ -2,6 +2,8 @@ #define JUCI_DIALOG_H_ #include #include +#include +#include class Dialog { public: @@ -10,6 +12,17 @@ public: static std::string new_file(); static std::string new_folder(); static std::string save_file_as(const boost::filesystem::path &file_path); + + class Message : public Gtk::MessageDialog { + public: + Message(const std::string &text); + }; + +private: + static std::string gtk_dialog(const std::string &title, + const std::vector> &buttons, + Gtk::FileChooserAction gtk_options, + const std::string &file_name = ""); }; #endif //JUCI_DIALOG_H_ diff --git a/src/dialogs_unix.cc b/src/dialogs_unix.cc new file mode 100644 index 0000000..04aff01 --- /dev/null +++ b/src/dialogs_unix.cc @@ -0,0 +1,32 @@ +#include "dialogs.h" + +std::string Dialog::open_folder() { + return gtk_dialog("Open Folder", + {std::make_pair("Cancel", Gtk::RESPONSE_CANCEL),std::make_pair("Open", Gtk::RESPONSE_OK)}, + Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER); +} + +std::string Dialog::new_file() { + return gtk_dialog("New File", + {std::make_pair("Cancel", Gtk::RESPONSE_CANCEL), std::make_pair("Save", Gtk::RESPONSE_OK)}, + Gtk::FILE_CHOOSER_ACTION_SAVE); +} + +std::string Dialog::new_folder() { + return gtk_dialog("New Folder", + {std::make_pair("Cancel", Gtk::RESPONSE_CANCEL),std::make_pair("Create", Gtk::RESPONSE_OK)}, + Gtk::FILE_CHOOSER_ACTION_CREATE_FOLDER); +} + +std::string Dialog::open_file() { + return gtk_dialog("Open File", + {std::make_pair("Cancel", Gtk::RESPONSE_CANCEL),std::make_pair("Select", Gtk::RESPONSE_OK)}, + Gtk::FILE_CHOOSER_ACTION_OPEN); +} + +std::string Dialog::save_file_as(const boost::filesystem::path &file_path) { + return gtk_dialog("Save File As", + {std::make_pair("Cancel", Gtk::RESPONSE_CANCEL),std::make_pair("Save", Gtk::RESPONSE_OK)}, + Gtk::FILE_CHOOSER_ACTION_SAVE, file_path.string()); +} + diff --git a/src/dialogs_win.cc b/src/dialogs_win.cc index 967ba67..377bf16 100644 --- a/src/dialogs_win.cc +++ b/src/dialogs_win.cc @@ -1,5 +1,6 @@ #include "dialogs.h" #include "singletons.h" +#include "juci.h" #undef NTDDI_VERSION #define NTDDI_VERSION NTDDI_VISTA @@ -29,8 +30,7 @@ public: if(!set_title(title) || !add_option(option)) return ""; - auto dirs = Singleton::directories->current_path; - if(!set_folder(dirs.empty() ? boost::filesystem::current_path().native() : dirs.native())) + if(!set_folder()) return ""; return show(); @@ -42,10 +42,10 @@ public: if(!set_title(title) || !add_option(option)) return ""; + if(!set_folder()) + return ""; std::vector extensions; if(!file_path.empty()) { - if(!set_folder(file_path.parent_path().native())) - return ""; if(file_path.has_extension() && file_path.filename()!=file_path.extension()) { auto extension=(L"*"+file_path.extension().native()).c_str(); extensions.emplace_back(COMDLG_FILTERSPEC{extension, extension}); @@ -53,11 +53,6 @@ public: return ""; } } - else { - auto dirs = Singleton::directories->current_path; - if(!set_folder(dirs.empty() ? boost::filesystem::current_path().native() : dirs.native())) - return ""; - } extensions.emplace_back(COMDLG_FILTERSPEC{L"All files", L"*.*"}); if(dialog->SetFileTypes(extensions.size(), extensions.data())!=S_OK) return ""; @@ -98,8 +93,16 @@ private: } /** Sets the directory to start browsing */ - bool set_folder(const std::wstring &directory_path) { - std::wstring path=directory_path; + bool set_folder() { + auto g_application=g_application_get_default(); //TODO: Post issue that Gio::Application::get_default should return pointer and not Glib::RefPtr + auto gio_application=Glib::wrap(g_application, true); + auto application=Glib::RefPtr::cast_static(gio_application); + + auto current_path=application->window->notebook.get_current_folder(); + if(current_path.empty()) + current_path=boost::filesystem::current_path(); + + std::wstring path=current_path.native(); size_t pos=0; while((pos=path.find(L'/', pos))!=std::wstring::npos) {//TODO: issue bug report on boost::filesystem::path::native on MSYS2 path.replace(pos, 1, L"\\"); @@ -142,7 +145,10 @@ std::string Dialog::new_file() { } std::string Dialog::new_folder() { - return Win32Dialog().open(L"New Folder", FOS_PICKFOLDERS); //TODO: this is not working correctly yet + //Win32 (IFileDialog) does not support create folder... + return gtk_dialog("New Folder", + {std::make_pair("Cancel", Gtk::RESPONSE_CANCEL),std::make_pair("Create", Gtk::RESPONSE_OK)}, + Gtk::FILE_CHOOSER_ACTION_CREATE_FOLDER); } std::string Dialog::open_file() { diff --git a/src/files.h b/src/files.h index 954e322..a14f680 100644 --- a/src/files.h +++ b/src/files.h @@ -1,6 +1,6 @@ #include -#define JUCI_VERSION "0.9.4" +#define JUCI_VERSION "0.9.5" const std::string configjson = "{\n" @@ -29,6 +29,8 @@ const std::string configjson = " \"font\": \"Monospace\",\n" #endif #endif +" \"cleanup_whitespace_characters_comment\": \"Remove trailing whitespace characters on save, and add trailing newline if missing\",\n" +" \"cleanup_whitespace_characters\": false,\n" " \"show_map\": true,\n" " \"map_font_size\": \"1\",\n" " \"spellcheck_language_comment\": \"Use \\\"\\\" to set language from your locale settings\",\n" diff --git a/src/juci.cc b/src/juci.cc index 5dd0509..98125f1 100644 --- a/src/juci.cc +++ b/src/juci.cc @@ -29,8 +29,18 @@ int Application::on_command_line(const Glib::RefPtr else if(boost::filesystem::is_directory(p)) directories.emplace_back(p); } - else - std::cerr << "Path " << p << " does not exist." << std::endl; + else { //Open new file if parent path exists + auto parent_p=p.parent_path(); + boost::system::error_code ec; + auto new_p=boost::filesystem::canonical(parent_p, ec); + if(!ec && boost::filesystem::is_directory(new_p)) { + new_p+="/"; + new_p+=p.filename(); + files.emplace_back(new_p); + } + else + Singleton::terminal->print("Error: folder path "+parent_p.string()+" does not exist.\n", true); + } } } activate(); @@ -92,6 +102,9 @@ Application::Application() : Gtk::Application("no.sout.juci", Gio::APPLICATION_N Glib::set_application_name("juCi++"); + //Gtk::MessageDialog without buttons caused text to be selected, this prevents that + Gtk::Settings::get_default()->property_gtk_label_select_on_focus()=false; + window=std::unique_ptr(new Window()); } diff --git a/src/notebook.cc b/src/notebook.cc index 6119cfe..6fd29d9 100644 --- a/src/notebook.cc +++ b/src/notebook.cc @@ -65,12 +65,14 @@ void Notebook::open(const boost::filesystem::path &file_path) { } } - std::ifstream can_read(file_path.string()); - if(!can_read) { - Singleton::terminal->print("Error: could not open "+file_path.string()+"\n"); - return; + if(boost::filesystem::exists(file_path)) { + std::ifstream can_read(file_path.string()); + if(!can_read) { + Singleton::terminal->print("Error: could not open "+file_path.string()+"\n", true); + return; + } + can_read.close(); } - can_read.close(); auto language=Source::guess_language(file_path); boost::filesystem::path project_path; @@ -170,6 +172,32 @@ bool Notebook::save(int page, bool reparse_needed) { } auto view=get_view(page); if (view->file_path != "" && view->get_buffer()->get_modified()) { + //Remove trailing whitespace characters on save, and add trailing newline if missing + if(Singleton::config->source.cleanup_whitespace_characters) { + auto buffer=view->get_buffer(); + buffer->begin_user_action(); + for(int line=0;lineget_line_count();line++) { + auto iter=buffer->get_iter_at_line(line); + auto end_iter=iter; + while(!end_iter.ends_line()) + end_iter.forward_char(); + if(iter==end_iter) + continue; + iter=end_iter; + while(!iter.starts_line() && (*iter==' ' || *iter=='\t' || iter.ends_line())) + iter.backward_char(); + if(*iter!=' ' && *iter!='\t') + iter.forward_char(); + if(iter==end_iter) + continue; + buffer->erase(iter, end_iter); + } + auto iter=buffer->end(); + if(!iter.starts_line()) + buffer->insert(buffer->end(), "\n"); + buffer->end_user_action(); + } + if(filesystem::write(view->file_path, view->get_buffer())) { if(reparse_needed) { if(auto clang_view=dynamic_cast(view)) { @@ -206,7 +234,7 @@ bool Notebook::save(int page, bool reparse_needed) { if(source_clang_view->restart_parse()) Singleton::terminal->async_print("Reparsing "+source_clang_view->file_path.string()+"\n"); else - Singleton::terminal->async_print("Error: failed to reparse "+source_clang_view->file_path.string()+". Please reopen the file manually.\n"); + Singleton::terminal->async_print("Error: failed to reparse "+source_clang_view->file_path.string()+". Please reopen the file manually.\n", true); } } } @@ -215,7 +243,7 @@ bool Notebook::save(int page, bool reparse_needed) { JDEBUG("end true"); return true; } - Singleton::terminal->print("Error: could not save file " +view->file_path.string()+"\n"); + Singleton::terminal->print("Error: could not save file " +view->file_path.string()+"\n", true); } JDEBUG("end false"); return false; @@ -260,6 +288,17 @@ bool Notebook::close_current_page() { return true; } +boost::filesystem::path Notebook::get_current_folder() { + boost::filesystem::path current_path; + + if(get_current_page()!=-1) + current_path=get_current_view()->project_path; + else + current_path=Singleton::directories->current_path; + + return current_path; +} + bool Notebook::save_modified_dialog() { Gtk::MessageDialog dialog((Gtk::Window&)(*get_toplevel()), "Save file!", false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_YES_NO); dialog.set_default_response(Gtk::RESPONSE_YES); diff --git a/src/notebook.h b/src/notebook.h index abb70c7..15e9cd1 100644 --- a/src/notebook.h +++ b/src/notebook.h @@ -21,6 +21,7 @@ public: bool save(int page, bool reparse_needed=false); bool save_current(); void configure(int view_nr); + boost::filesystem::path get_current_folder(); private: bool save_modified_dialog(); diff --git a/src/source.cc b/src/source.cc index 2f196d8..2688854 100644 --- a/src/source.cc +++ b/src/source.cc @@ -91,7 +91,7 @@ Source::View::View(const boost::filesystem::path &file_path, const boost::filesy } else { if(filesystem::read(file_path, get_buffer())==-1) - Singleton::terminal->print("Error: "+file_path.string()+" is not a valid UTF-8 file.\n"); + Singleton::terminal->print("Error: "+file_path.string()+" is not a valid UTF-8 file.\n", true); } get_source_buffer()->end_not_undoable_action(); @@ -304,7 +304,7 @@ void Source::View::configure() { if(scheme) get_source_buffer()->set_style_scheme(scheme); else - Singleton::terminal->print("Error: Could not find gtksourceview style: "+Singleton::config->source.style+'\n'); + Singleton::terminal->print("Error: Could not find gtksourceview style: "+Singleton::config->source.style+'\n', true); } if(Singleton::config->source.wrap_lines) @@ -1306,7 +1306,7 @@ Source::GenericView::GenericView(const boost::filesystem::path &file_path, const boost::property_tree::xml_parser::read_xml(language_file.string(), pt); } catch(const std::exception &e) { - Singleton::terminal->print("Error: error parsing language file "+language_file.string()+": "+e.what()+'\n'); + Singleton::terminal->print("Error: error parsing language file "+language_file.string()+": "+e.what()+'\n', true); } bool has_context_class=false; parse_language_file(completion_buffer_keywords, has_context_class, pt); diff --git a/src/source_clang.cc b/src/source_clang.cc index 4fe441d..bc35142 100644 --- a/src/source_clang.cc +++ b/src/source_clang.cc @@ -59,7 +59,7 @@ Source::View(file_path, project_path, language), parse_error(false) { } }); parse_fail_connection=parse_fail.connect([this](){ - Singleton::terminal->print("Error: failed to reparse "+this->file_path.string()+".\n"); + Singleton::terminal->print("Error: failed to reparse "+this->file_path.string()+".\n", true); set_status(""); set_info(""); parsing_in_progress->cancel("failed"); @@ -145,7 +145,7 @@ void Source::ClangViewParse::init_parse() { parse_start(); } else if (parse_thread_mapped && parsing_mutex.try_lock() && parse_thread_buffer_map_mutex.try_lock()) { - int status=clang_tu->ReparseTranslationUnit(parse_thread_buffer_map); + auto status=clang_tu->ReparseTranslationUnit(parse_thread_buffer_map); if(status==0) clang_tokens=clang_tu->get_tokens(0, parse_thread_buffer_map.find(file_path.string())->second.size()-1); else @@ -649,7 +649,7 @@ Source::ClangViewParse(file_path, project_path, language), autocomplete_cancel_s }); autocomplete_fail_connection=autocomplete_fail.connect([this]() { - Singleton::terminal->print("Error: autocomplete failed, reparsing "+this->file_path.string()+"\n"); + Singleton::terminal->print("Error: autocomplete failed, reparsing "+this->file_path.string()+"\n", true); restart_parse(); autocomplete_starting=false; autocomplete_cancel_starting=false; @@ -963,8 +963,8 @@ Source::ClangViewAutocomplete(file_path, project_path, language) { iter.forward_char(); } get_buffer()->place_cursor(iter); - while(gtk_events_pending()) - gtk_main_iteration(); + while(g_main_context_pending(NULL)) + g_main_context_iteration(NULL, false); scroll_to(get_buffer()->get_insert(), 0.0, 1.0, 0.5); } get_source_buffer()->end_user_action(); diff --git a/src/terminal.cc b/src/terminal_unix.cc similarity index 99% rename from src/terminal.cc rename to src/terminal_unix.cc index 772f8ef..2a1ee90 100644 --- a/src/terminal.cc +++ b/src/terminal_unix.cc @@ -155,7 +155,7 @@ int Terminal::execute(const std::string &command, const boost::filesystem::path pid=popen3(command, path.string(), nullptr, nullptr, nullptr); if (pid<=0) { - async_print("Error: Failed to run command: " + command + "\n"); + async_print("Error: Failed to run command: " + command + "\n", true); return -1; } else { @@ -203,7 +203,7 @@ int Terminal::execute(std::istream &stdin_stream, std::ostream &stdout_stream, c auto pid=popen3(command, path.string(), &stdin_fd, &stdout_fd, &stderr_fd); if (pid<=0) { - async_print("Error: Failed to run command: " + command + "\n"); + async_print("Error: Failed to run command: " + command + "\n", true); return -1; } else { @@ -269,7 +269,7 @@ void Terminal::async_execute(const std::string &command, const boost::filesystem async_executes_mutex.unlock(); if (pid<=0) { - async_print("Error: Failed to run command: " + command + "\n"); + async_print("Error: Failed to run command: " + command + "\n", true); if(callback) callback(-1); } diff --git a/src/terminal_win.cc b/src/terminal_win.cc index b3c57ec..962a55d 100644 --- a/src/terminal_win.cc +++ b/src/terminal_win.cc @@ -200,7 +200,7 @@ int Terminal::execute(const std::string &command, const boost::filesystem::path else process=popen3(command, path.string(), nullptr, nullptr, nullptr); if(process==NULL) { - async_print("Error: Failed to run command: " + command + "\n"); + async_print("Error: Failed to run command: " + command + "\n", true); return -1; } if(use_pipes) { @@ -257,7 +257,7 @@ int Terminal::execute(std::istream &stdin_stream, std::ostream &stdout_stream, c auto process=popen3(command, path.string(), &stdin_h, &stdout_h, &stderr_h); if(process==NULL) { - async_print("Error: Failed to run command: " + command + "\n"); + async_print("Error: Failed to run command: " + command + "\n", true); return -1; } std::thread stderr_thread([this, stderr_h](){ @@ -331,7 +331,7 @@ void Terminal::async_execute(const std::string &command, const boost::filesystem auto process=popen3(command, path.string(), &stdin_h, &stdout_h, &stderr_h); if(process==NULL) { async_executes_mutex.unlock(); - async_print("Error: Failed to run command: " + command + "\n"); + async_print("Error: Failed to run command: " + command + "\n", true); if(callback) callback(-1); return; diff --git a/src/window.cc b/src/window.cc index 388c94d..e61cba7 100644 --- a/src/window.cc +++ b/src/window.cc @@ -154,7 +154,7 @@ void Window::set_menu_actions() { boost::filesystem::path path = Dialog::new_file(); if(path!="") { if(boost::filesystem::exists(path)) { - Singleton::terminal->print("Error: "+path.string()+" already exists.\n"); + Singleton::terminal->print("Error: "+path.string()+" already exists.\n", true); } else { if(filesystem::write(path)) { @@ -164,7 +164,7 @@ void Window::set_menu_actions() { Singleton::terminal->print("New file "+path.string()+" created.\n"); } else - Singleton::terminal->print("Error: could not create new file "+path.string()+".\n"); + Singleton::terminal->print("Error: could not create new file "+path.string()+".\n", true); } } }); @@ -178,7 +178,7 @@ void Window::set_menu_actions() { Singleton::terminal->print("New folder "+path.string()+" created.\n"); } else - Singleton::terminal->print("Error: "+path.string()+" already exists.\n"); + Singleton::terminal->print("Error: "+path.string()+" already exists.\n", true); Singleton::directories->select(path); } }); @@ -195,11 +195,11 @@ void Window::set_menu_actions() { auto cpp_main_path=project_path; cpp_main_path+="/main.cpp"; if(boost::filesystem::exists(cmakelists_path)) { - Singleton::terminal->print("Error: "+cmakelists_path.string()+" already exists.\n"); + Singleton::terminal->print("Error: "+cmakelists_path.string()+" already exists.\n", true); return; } if(boost::filesystem::exists(cpp_main_path)) { - Singleton::terminal->print("Error: "+cpp_main_path.string()+" already exists.\n"); + Singleton::terminal->print("Error: "+cpp_main_path.string()+" already exists.\n", true); return; } std::string cmakelists="cmake_minimum_required(VERSION 2.8)\n\nproject("+project_name+")\n\nset(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -std=c++1y -Wall\")\n\nadd_executable("+project_name+" main.cpp)\n"; @@ -210,7 +210,7 @@ void Window::set_menu_actions() { Singleton::terminal->print("C++ project "+project_name+" created.\n"); } else - Singleton::terminal->print("Error: Could not create project "+project_path.string()+"\n"); + Singleton::terminal->print("Error: Could not create project "+project_path.string()+"\n", true); } }); @@ -330,8 +330,8 @@ void Window::set_menu_actions() { }); menu->add_action("source_center_cursor", [this]() { if(notebook.get_current_page()!=-1) { - while(gtk_events_pending()) - gtk_main_iteration(); + while(g_main_context_pending(NULL)) + g_main_context_iteration(NULL, false); if(notebook.get_current_page()!=-1) notebook.get_current_view()->scroll_to(notebook.get_current_view()->get_buffer()->get_insert(), 0.0, 1.0, 0.5); } @@ -396,8 +396,8 @@ void Window::set_menu_actions() { index=std::min(index, end_line_index); buffer->place_cursor(buffer->get_iter_at_line_index(line, index)); - while(gtk_events_pending()) - gtk_main_iteration(); + while(g_main_context_pending(NULL)) + g_main_context_iteration(NULL, false); if(notebook.get_current_page()!=-1) notebook.get_current_view()->scroll_to(notebook.get_current_view()->get_buffer()->get_insert(), 0.0, 1.0, 0.5); } @@ -432,9 +432,16 @@ void Window::set_menu_actions() { }); menu->add_action("compile_and_run", [this]() { - if(notebook.get_current_page()==-1 || compiling) + if(compiling) return; - CMake cmake(notebook.get_current_view()->file_path); + boost::filesystem::path cmake_path; + if(notebook.get_current_page()!=-1) + cmake_path=notebook.get_current_view()->file_path.parent_path(); + else + cmake_path=Singleton::directories->current_path; + if(cmake_path.empty()) + return; + CMake cmake(cmake_path); auto executables = cmake.get_functions_parameters("add_executable"); boost::filesystem::path executable_path; if(executables.size()>0 && executables[0].second.size()>0) { @@ -472,9 +479,16 @@ void Window::set_menu_actions() { } }); menu->add_action("compile", [this]() { - if(notebook.get_current_page()==-1 || compiling) + if(compiling) + return; + boost::filesystem::path cmake_path; + if(notebook.get_current_page()!=-1) + cmake_path=notebook.get_current_view()->file_path.parent_path(); + else + cmake_path=Singleton::directories->current_path; + if(cmake_path.empty()) return; - CMake cmake(notebook.get_current_view()->file_path); + CMake cmake(cmake_path); if(cmake.project_path!="") { compiling=true; Singleton::terminal->print("Compiling project "+cmake.project_path.string()+"\n"); @@ -489,21 +503,13 @@ void Window::set_menu_actions() { entry_box.labels.emplace_back(); auto label_it=entry_box.labels.begin(); label_it->update=[label_it](int state, const std::string& message){ - label_it->set_text("Run Command directory order: file project path, file directory, opened directory, current directory"); + label_it->set_text("Run Command directory order: file project path, opened directory, current directory"); }; label_it->update(0, ""); entry_box.entries.emplace_back(last_run_command, [this](const std::string& content){ if(content!="") { last_run_command=content; - boost::filesystem::path run_path; - if(notebook.get_current_page()!=-1) { - if(notebook.get_current_view()->project_path!="") - run_path=notebook.get_current_view()->project_path; - else - run_path=notebook.get_current_view()->file_path.parent_path(); - } - else - run_path=Singleton::directories->current_path; + auto run_path=notebook.get_current_folder(); Singleton::terminal->async_print("Running: "+content+'\n'); Singleton::terminal->async_execute(content, run_path, [this, content](int exit_code){ @@ -776,8 +782,8 @@ void Window::goto_line_entry() { if(line>0 && line<=buffer->get_line_count()) { line--; buffer->place_cursor(buffer->get_iter_at_line(line)); - while(gtk_events_pending()) - gtk_main_iteration(); + while(g_main_context_pending(NULL)) + g_main_context_iteration(NULL, false); if(notebook.get_current_page()!=-1) notebook.get_current_view()->scroll_to(buffer->get_insert(), 0.0, 1.0, 0.5); }