diff --git a/CMakeLists.txt b/CMakeLists.txt index 319e931..6ddac4f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required (VERSION 2.8.8) project(juci) -set(JUCI_VERSION "1.4.1.2") +set(JUCI_VERSION "1.4.1.3") set(CPACK_PACKAGE_NAME "jucipp") set(CPACK_PACKAGE_CONTACT "Ole Christian Eidheim ") diff --git a/src/config.cc b/src/config.cc index ff44d64..934b438 100644 --- a/src/config.cc +++ b/src/config.cc @@ -172,6 +172,7 @@ void Config::read(const boost::property_tree::ptree &cfg) { source.highlight_current_line = source_json.get("highlight_current_line"); source.show_line_numbers = source_json.get("show_line_numbers"); source.enable_multiple_cursors = source_json.get("enable_multiple_cursors"); + source.auto_reload_changed_files = source_json.get("auto_reload_changed_files"); source.clang_format_style = source_json.get("clang_format_style"); source.clang_usages_threads = static_cast(source_json.get("clang_usages_threads")); auto pt_doc_search=cfg.get_child("documentation_searches"); diff --git a/src/config.h b/src/config.h index 6744245..1c1000b 100644 --- a/src/config.h +++ b/src/config.h @@ -86,6 +86,7 @@ public: bool highlight_current_line; bool show_line_numbers; bool enable_multiple_cursors; + bool auto_reload_changed_files; std::string clang_format_style; unsigned clang_usages_threads; diff --git a/src/directories.cc b/src/directories.cc index ac4d186..2f6a55f 100644 --- a/src/directories.cc +++ b/src/directories.cc @@ -507,7 +507,7 @@ void Directories::add_or_update_path(const boost::filesystem::path &dir_path, co } if(path_it==directories.end()) { - auto g_file=Glib::wrap(g_file_new_for_path(dir_path.string().c_str())); //TODO: report missing constructor in giomm + auto g_file=Gio::File::create_for_path(dir_path.string()); auto monitor=g_file->monitor_directory(Gio::FileMonitorFlags::FILE_MONITOR_WATCH_MOVES); auto path_and_row=std::make_shared >(dir_path, row); auto connection=std::make_shared(); diff --git a/src/files.h b/src/files.h index 0040792..a98215f 100644 --- a/src/files.h +++ b/src/files.h @@ -59,6 +59,7 @@ R"RAW( "highlight_current_line": true, "show_line_numbers": true, "enable_multiple_cursors": false, + "auto_reload_changed_files": false, "clang_format_style_comment": "IndentWidth, AccessModifierOffset and UseTab are set automatically. See http://clang.llvm.org/docs/ClangFormatStyleOptions.html", "clang_format_style": "ColumnLimit: 0, MaxEmptyLinesToKeep: 2, SpaceBeforeParens: Never, NamespaceIndentation: All, BreakBeforeBraces: Custom, BraceWrapping: {BeforeElse: true, BeforeCatch: true}", "clang_usages_threads_comment": "The number of threads used in finding usages in unparsed files. -1 corresponds to the number of cores available, and 0 disables the search", diff --git a/src/git.cc b/src/git.cc index 03f3ab6..0a1d119 100644 --- a/src/git.cc +++ b/src/git.cc @@ -111,8 +111,7 @@ Git::Repository::Repository(const boost::filesystem::path &path) { if(work_path.empty()) throw std::runtime_error("Could not find work path"); - auto git_path_str=get_path().string(); - auto git_directory=Glib::wrap(g_file_new_for_path(git_path_str.c_str())); //TODO: report missing constructor in giomm + auto git_directory=Gio::File::create_for_path(get_path().string()); monitor=git_directory->monitor_directory(Gio::FileMonitorFlags::FILE_MONITOR_WATCH_MOVES); monitor_changed_connection=monitor->signal_changed().connect([this](const Glib::RefPtr &file, const Glib::RefPtr&, diff --git a/src/source.cc b/src/source.cc index 8a4b6df..fbe030a 100644 --- a/src/source.cc +++ b/src/source.cc @@ -55,7 +55,7 @@ Glib::RefPtr Source::guess_language(const boost::filesystem::path language=language_manager->get_language("makefile"); else if(file_path.extension()==".tcc") language=language_manager->get_language("cpphdr"); - else if(file_path.extension()==".ts") + else if(file_path.extension()==".ts" || file_path.extension()==".jsx") language=language_manager->get_language("js"); else if(!file_path.has_extension()) { for(auto &part: file_path) { @@ -125,10 +125,6 @@ Source::View::View(const boost::filesystem::path &file_path, Glib::RefPtrplace_cursor(get_buffer()->get_iter_at_offset(0)); - search_settings = gtk_source_search_settings_new(); gtk_source_search_settings_set_wrap_around(search_settings, true); search_context = gtk_source_search_context_new(get_source_buffer()->gobj(), search_settings); @@ -190,7 +186,96 @@ Source::View::View(const boost::filesystem::path &file_path, Glib::RefPtrget_id()=="chdr" || language->get_id()=="cpphdr" || language->get_id()=="c" || + static auto prettier = filesystem::find_executable("prettier"); + if(!prettier.empty() && language && + (language->get_id()=="js" || language->get_id()=="json" || language->get_id()=="css")) { + format_style=[this](bool continue_without_style_file) { + auto command=prettier.string()+" --cursor-offset "+std::to_string(get_buffer()->get_insert()->get_iter().get_offset()); + command+=" --stdin-filepath "+this->file_path.string(); + + if(get_buffer()->get_has_selection()) { + Gtk::TextIter start, end; + get_buffer()->get_selection_bounds(start, end); + command+=" --range-start "+std::to_string(start.get_offset()); + command+=" --range-end "+std::to_string(end.get_offset()); + } + + if(!continue_without_style_file) { + bool has_style_file=false; + auto style_file_search_path=this->file_path.parent_path(); + + while(true) { + if(boost::filesystem::exists(style_file_search_path/".prettierrc") || + boost::filesystem::exists(style_file_search_path/"prettier.config")) { + has_style_file=true; + break; + } + if(style_file_search_path==style_file_search_path.root_directory()) + break; + style_file_search_path=style_file_search_path.parent_path(); + } + + if(!has_style_file && !continue_without_style_file) + return; + } + + std::stringstream stdin_stream(get_buffer()->get_text()), stdout_stream, stderr_stream; + + auto exit_status=Terminal::get().process(stdin_stream, stdout_stream, command, this->file_path.parent_path(), &stderr_stream); + if(exit_status==0) { + replace_text(stdout_stream.str()); + std::string line; + std::getline(stderr_stream, line); + if(line!="NaN") { + try { + auto offset=atoi(line.c_str()); + if(offsetsize()) { + get_buffer()->place_cursor(get_buffer()->get_iter_at_offset(offset)); + hide_tooltips(); + } + } + catch(...) {} + } + } + else { + // static std::regex regex("^\\[error\\] stdin: (.*) \\(([0-9]*):([0-9]*)\\)$"); + // std::string line; + // std::getline(stderr_stream, line); + // std::smatch sm; + // if(std::regex_match(line, sm, regex)) { + // auto line=std::min(atoi(sm[1].str().c_str()), get_buffer()->get_line_count()-1); // TODO: add try + // if(line<0) + // line=0; + // auto iter=get_iter_at_line_end(line); + // auto pos=std::min(atoi(sm[2].str().c_str()), iter.get_line_offset()); // TODO: add try + // if(pos<0) + // pos=0; + // auto start=get_buffer()->get_iter_at_line_offset(line, pos); + // auto end=start; + // end.forward_char(); + // if(start==end) + // start.forward_char(); + + // std::string diagnostic_tag_name="def:error"; + // std::string severity_spelling="Error"; + + // auto spelling=sm[1].str(); + + // auto create_tooltip_buffer=[this, spelling, severity_spelling, diagnostic_tag_name]() { + // auto tooltip_buffer=Gtk::TextBuffer::create(get_buffer()->get_tag_table()); + // tooltip_buffer->insert_with_tag(tooltip_buffer->get_insert()->get_iter(), severity_spelling, diagnostic_tag_name); + // tooltip_buffer->insert_with_tag(tooltip_buffer->get_insert()->get_iter(), ":\n"+spelling, "def:note"); + // return tooltip_buffer; + // }; + // diagnostic_tooltips.emplace_back(create_tooltip_buffer, this, get_buffer()->create_mark(start), get_buffer()->create_mark(end)); + + // get_buffer()->apply_tag_by_name(diagnostic_tag_name+"_underline", start, end); + // } + Terminal::get().print("Prettier:\n"+stderr_stream.str()+'\n', true); // TODO: consider using the above WiP code instead + } + }; + } + else if(language && (language->get_id()=="chdr" || language->get_id()=="cpphdr" || language->get_id()=="c" || language->get_id()=="cpp" || language->get_id()=="objc" || language->get_id()=="java" || language->get_id()=="js" || language->get_id()=="ts" || language->get_id()=="proto" || language->get_id()=="c-sharp" || language->get_id()=="html" || language->get_id()=="cuda" || diff --git a/src/source.h b/src/source.h index b4228b6..b694d05 100644 --- a/src/source.h +++ b/src/source.h @@ -94,7 +94,7 @@ namespace Source { Tooltips diagnostic_tooltips; Tooltips type_tooltips; sigc::connection delayed_tooltips_connection; - virtual void show_diagnostic_tooltips(const Gdk::Rectangle &rectangle) {} + virtual void show_diagnostic_tooltips(const Gdk::Rectangle &rectangle) { diagnostic_tooltips.show(rectangle); } virtual void show_type_tooltips(const Gdk::Rectangle &rectangle) {} gdouble on_motion_last_x=0.0; gdouble on_motion_last_y=0.0; diff --git a/src/source_base.cc b/src/source_base.cc index 8b4a083..9e64c01 100644 --- a/src/source_base.cc +++ b/src/source_base.cc @@ -2,28 +2,78 @@ #include "info.h" #include "terminal.h" #include "git.h" +#include "config.h" #include -Source::BaseView::BaseView(const boost::filesystem::path &file_path, Glib::RefPtr language): file_path(file_path), language(language), status_diagnostics(0, 0, 0) { - boost::system::error_code ec; - canonical_file_path=boost::filesystem::canonical(file_path, ec); - if(ec) - canonical_file_path=file_path; - - last_write_time=boost::filesystem::last_write_time(file_path, ec); - if(ec) - last_write_time=static_cast(-1); +Source::BaseView::BaseView(const boost::filesystem::path &file_path, Glib::RefPtr language): Gsv::View(), file_path(file_path), language(language), status_diagnostics(0, 0, 0) { + load(); + get_buffer()->place_cursor(get_buffer()->get_iter_at_offset(0)); signal_focus_in_event().connect([this](GdkEventFocus *event) { - check_last_write_time(); + if(this->last_write_time!=static_cast(-1)) + check_last_write_time(); return false; }); + +#ifdef __APPLE__ // TODO: Gio file monitor is bugged on MacOS + class Recursive { + public: + static void f(BaseView *view, std::time_t last_write_time_) { + view->delayed_monitor_changed_connection.disconnect(); + view->delayed_monitor_changed_connection=Glib::signal_timeout().connect([view, last_write_time_]() { + boost::system::error_code ec; + auto last_write_time=boost::filesystem::last_write_time(view->file_path, ec); + if(last_write_time!=last_write_time_) + view->check_last_write_time(last_write_time); + Recursive::f(view, last_write_time); + return false; + }, 1000); + } + }; + if(this->last_write_time!=static_cast(-1)) + Recursive::f(this, last_write_time); +#else + if(this->last_write_time!=static_cast(-1)) { + monitor=Gio::File::create_for_path(file_path.string())->monitor_file(Gio::FileMonitorFlags::FILE_MONITOR_NONE); + monitor_changed_connection=monitor->signal_changed().connect([this](const Glib::RefPtr &file, + const Glib::RefPtr&, + Gio::FileMonitorEvent monitor_event) { + if(monitor_event!=Gio::FileMonitorEvent::FILE_MONITOR_EVENT_CHANGES_DONE_HINT) { + delayed_monitor_changed_connection.disconnect(); + delayed_monitor_changed_connection=Glib::signal_timeout().connect([this]() { + check_last_write_time(); + return false; + }, 500); + } + }); + } +#endif +} + +Source::BaseView::~BaseView() { + monitor_changed_connection.disconnect(); + delayed_monitor_changed_connection.disconnect(); } bool Source::BaseView::load() { + boost::system::error_code ec; + last_write_time=boost::filesystem::last_write_time(file_path, ec); + if(ec) + last_write_time=static_cast(-1); + disable_spellcheck=true; get_source_buffer()->begin_not_undoable_action(); - bool status=true; + + class Guard { + public: + Source::BaseView *view; + ~Guard() { + view->get_source_buffer()->end_not_undoable_action(); + view->disable_spellcheck=false; + } + }; + Guard guard{this}; + if(language) { std::ifstream input(file_path.string(), std::ofstream::binary); if(input) { @@ -39,13 +89,17 @@ bool Source::BaseView::load() { ustr.replace(iter, next_char_iter, "?"); valid=false; } + + if(!valid) + Terminal::get().print("Warning: "+file_path.string()+" is not a valid UTF-8 file. Saving might corrupt the file.\n"); + if(get_buffer()->size()==0) get_buffer()->insert_at_cursor(ustr); else replace_text(ustr.raw()); - - if(!valid) - Terminal::get().print("Warning: "+file_path.string()+" is not a valid UTF-8 file. Saving might corrupt the file.\n"); + } + else { + return false; } } else { @@ -55,30 +109,23 @@ bool Source::BaseView::load() { ss << input.rdbuf(); Glib::ustring ustr=ss.str(); - bool valid=true; if(ustr.validate()) { if(get_buffer()->size()==0) get_buffer()->insert_at_cursor(ustr); else replace_text(ustr.raw()); } - else - valid=false; - - if(!valid) + else { Terminal::get().print("Error: "+file_path.string()+" is not a valid UTF-8 file.\n", true); - status=false; + return false; + } + } + else { + return false; } } - get_source_buffer()->end_not_undoable_action(); - disable_spellcheck=false; - boost::system::error_code ec; - last_write_time=boost::filesystem::last_write_time(file_path, ec); - if(ec) - last_write_time=static_cast(-1); - - return status; + return true; } void Source::BaseView::replace_text(const std::string &new_text) { @@ -149,15 +196,8 @@ void Source::BaseView::replace_text(const std::string &new_text) { } void Source::BaseView::rename(const boost::filesystem::path &path) { - { - std::unique_lock lock(file_path_mutex); - file_path=path; - - boost::system::error_code ec; - canonical_file_path=boost::filesystem::canonical(file_path, ec); - if(ec) - canonical_file_path=file_path; - } + file_path=path; + if(update_status_file_path) update_status_file_path(this); if(update_tab_label) @@ -284,11 +324,24 @@ Gtk::TextIter Source::BaseView::get_tabs_end_iter() { return get_tabs_end_iter(get_buffer()->get_insert()); } -void Source::BaseView::check_last_write_time() { - if(has_focus()) { +void Source::BaseView::check_last_write_time(std::time_t last_write_time_) { + if(this->last_write_time==static_cast(-1)) + return; + + if(Config::get().source.auto_reload_changed_files && !get_buffer()->get_modified()) { + boost::system::error_code ec; + auto last_write_time=last_write_time_!=static_cast(-1) ? last_write_time_ : boost::filesystem::last_write_time(file_path, ec); + if(!ec && last_write_time!=this->last_write_time) { + if(load()) { + get_buffer()->set_modified(false); + return; + } + } + } + else if(has_focus()) { boost::system::error_code ec; - auto last_write_time=boost::filesystem::last_write_time(file_path, ec); - if(!ec && this->last_write_time!=static_cast(-1) && last_write_time!=this->last_write_time) + auto last_write_time=last_write_time_!=static_cast(-1) ? last_write_time_ : boost::filesystem::last_write_time(file_path, ec); + if(!ec && last_write_time!=this->last_write_time) Info::get().print("Caution: " + file_path.filename().string() + " was changed outside of juCi++"); } } diff --git a/src/source_base.h b/src/source_base.h index e0227fa..2adf87d 100644 --- a/src/source_base.h +++ b/src/source_base.h @@ -8,17 +8,21 @@ namespace Source { class BaseView : public Gsv::View { public: BaseView(const boost::filesystem::path &file_path, Glib::RefPtr language); + ~BaseView(); boost::filesystem::path file_path; - boost::filesystem::path canonical_file_path; Glib::RefPtr language; bool load(); /// Set new text more optimally and without unnecessary scrolling void replace_text(const std::string &new_text); - void rename(const boost::filesystem::path &path); + virtual void rename(const boost::filesystem::path &path); virtual bool save() = 0; + Glib::RefPtr monitor; + sigc::connection monitor_changed_connection; + sigc::connection delayed_monitor_changed_connection; + virtual void configure() = 0; virtual void hide_tooltips() = 0; virtual void hide_dialogs() = 0; @@ -69,8 +73,7 @@ namespace Source { bool disable_spellcheck=false; protected: - std::mutex file_path_mutex; std::time_t last_write_time; - void check_last_write_time(); + void check_last_write_time(std::time_t last_write_time_=static_cast(-1)); }; } diff --git a/src/source_clang.cc b/src/source_clang.cc index 9baa38f..ced01ae 100644 --- a/src/source_clang.cc +++ b/src/source_clang.cc @@ -358,10 +358,6 @@ void Source::ClangViewParse::update_diagnostics() { update_status_diagnostics(this); } -void Source::ClangViewParse::show_diagnostic_tooltips(const Gdk::Rectangle &rectangle) { - diagnostic_tooltips.show(rectangle); -} - void Source::ClangViewParse::show_type_tooltips(const Gdk::Rectangle &rectangle) { if(parsed) { Gtk::TextIter iter; diff --git a/src/source_clang.h b/src/source_clang.h index 5df0e04..bea1eda 100644 --- a/src/source_clang.h +++ b/src/source_clang.h @@ -30,7 +30,6 @@ namespace Source { std::vector> clang_tokens_offsets; sigc::connection delayed_reparse_connection; - void show_diagnostic_tooltips(const Gdk::Rectangle &rectangle) override; void show_type_tooltips(const Gdk::Rectangle &rectangle) override; std::set diagnostic_offsets; diff --git a/src/source_diff.cc b/src/source_diff.cc index 9c70a1d..2ed28dc 100644 --- a/src/source_diff.cc +++ b/src/source_diff.cc @@ -35,6 +35,11 @@ void Source::DiffView::Renderer::draw_vfunc(const Cairo::RefPtr } Source::DiffView::DiffView(const boost::filesystem::path &file_path, Glib::RefPtr language) : BaseView(file_path, language), renderer(new Renderer()) { + boost::system::error_code ec; + canonical_file_path=boost::filesystem::canonical(file_path, ec); + if(ec) + canonical_file_path=file_path; + renderer->tag_added=get_buffer()->create_tag("git_added"); renderer->tag_modified=get_buffer()->create_tag("git_modified"); renderer->tag_removed=get_buffer()->create_tag("git_removed"); @@ -144,7 +149,6 @@ void Source::DiffView::configure() { if(monitor_event!=Gio::FileMonitorEvent::FILE_MONITOR_EVENT_CHANGES_DONE_HINT) { delayed_monitor_changed_connection.disconnect(); delayed_monitor_changed_connection=Glib::signal_timeout().connect([this]() { - check_last_write_time(); monitor_changed=true; parse_state=ParseState::STARTING; std::unique_lock lock(parse_mutex); @@ -251,6 +255,16 @@ void Source::DiffView::configure() { }); } +void Source::DiffView::rename(const boost::filesystem::path &path) { + Source::BaseView::rename(path); + + std::lock_guard lock(canonical_file_path_mutex); + boost::system::error_code ec; + canonical_file_path=boost::filesystem::canonical(path, ec); + if(ec) + canonical_file_path=path; +} + void Source::DiffView::git_goto_next_diff() { auto iter=get_buffer()->get_insert()->get_iter(); auto insert_iter=iter; @@ -300,7 +314,7 @@ std::unique_ptr Source::DiffView::get_diff() { auto work_path=filesystem::get_normal_path(repository->get_work_path()); boost::filesystem::path relative_path; { - std::unique_lock lock(file_path_mutex); + std::unique_lock lock(canonical_file_path_mutex); relative_path=filesystem::get_relative_path(canonical_file_path, work_path); if(relative_path.empty()) throw std::runtime_error("not a relative path"); diff --git a/src/source_diff.h b/src/source_diff.h index 5e7c9e4..a078a84 100644 --- a/src/source_diff.h +++ b/src/source_diff.h @@ -32,13 +32,17 @@ namespace Source { DiffView(const boost::filesystem::path &file_path, Glib::RefPtr language); ~DiffView(); - public: void configure() override; + void rename(const boost::filesystem::path &path) override; + void git_goto_next_diff(); std::string git_get_diff_details(); + boost::filesystem::path canonical_file_path; private: + std::mutex canonical_file_path_mutex; + std::unique_ptr renderer; Dispatcher dispatcher; diff --git a/src/source_language_protocol.cc b/src/source_language_protocol.cc index a2477a5..926a41e 100644 --- a/src/source_language_protocol.cc +++ b/src/source_language_protocol.cc @@ -417,20 +417,24 @@ Source::LanguageProtocolView::~LanguageProtocolView() { void Source::LanguageProtocolView::setup_navigation_and_refactoring() { if(capabilities.document_formatting) { format_style=[this](bool continue_without_style_file) { - bool has_style_file=false; - auto style_file_search_path=this->file_path.parent_path(); - auto style_file='.'+language_id+"-format"; - while(true) { - if(boost::filesystem::exists(style_file_search_path/style_file)) { - has_style_file=true; - break; + if(!continue_without_style_file) { + bool has_style_file=false; + auto style_file_search_path=this->file_path.parent_path(); + auto style_file='.'+language_id+"-format"; + + while(true) { + if(boost::filesystem::exists(style_file_search_path/style_file)) { + has_style_file=true; + break; + } + if(style_file_search_path==style_file_search_path.root_directory()) + break; + style_file_search_path=style_file_search_path.parent_path(); } - if(style_file_search_path==style_file_search_path.root_directory()) - break; - style_file_search_path=style_file_search_path.parent_path(); + + if(!has_style_file && !continue_without_style_file) + return; } - if(!has_style_file && !continue_without_style_file) - return; class Replace { public: @@ -945,10 +949,6 @@ Gtk::TextIter Source::LanguageProtocolView::get_iter_at_line_pos(int line, int p return get_buffer()->get_iter_at_line_offset(line, pos); } -void Source::LanguageProtocolView::show_diagnostic_tooltips(const Gdk::Rectangle &rectangle) { - diagnostic_tooltips.show(rectangle); -} - void Source::LanguageProtocolView::show_type_tooltips(const Gdk::Rectangle &rectangle) { if(!capabilities.hover) return; diff --git a/src/source_language_protocol.h b/src/source_language_protocol.h index f3389d2..0a9a172 100644 --- a/src/source_language_protocol.h +++ b/src/source_language_protocol.h @@ -93,7 +93,6 @@ namespace Source { Gtk::TextIter get_iter_at_line_pos(int line, int pos) override; protected: - void show_diagnostic_tooltips(const Gdk::Rectangle &rectangle) override; void show_type_tooltips(const Gdk::Rectangle &rectangle) override; private: diff --git a/src/terminal.cc b/src/terminal.cc index a46d023..216e19f 100644 --- a/src/terminal.cc +++ b/src/terminal.cc @@ -38,7 +38,7 @@ int Terminal::process(const std::string &command, const boost::filesystem::path return process->get_exit_status(); } -int Terminal::process(std::istream &stdin_stream, std::ostream &stdout_stream, const std::string &command, const boost::filesystem::path &path) { +int Terminal::process(std::istream &stdin_stream, std::ostream &stdout_stream, const std::string &command, const boost::filesystem::path &path, std::ostream *stderr_stream) { TinyProcessLib::Process process(command, path.string(), [&stdout_stream](const char* bytes, size_t n) { Glib::ustring umessage(std::string(bytes, n)); Glib::ustring::iterator iter; @@ -48,8 +48,11 @@ int Terminal::process(std::istream &stdin_stream, std::ostream &stdout_stream, c umessage.replace(iter, next_char_iter, "?"); } stdout_stream.write(umessage.data(), n); - }, [this](const char* bytes, size_t n) { - async_print(std::string(bytes, n), true); + }, [this, stderr_stream](const char* bytes, size_t n) { + if(stderr_stream) + stderr_stream->write(bytes, n); + else + async_print(std::string(bytes, n), true); }, true); if(process.get_id()<=0) { diff --git a/src/terminal.h b/src/terminal.h index af7ebcb..8499cbd 100644 --- a/src/terminal.h +++ b/src/terminal.h @@ -17,7 +17,7 @@ public: } int process(const std::string &command, const boost::filesystem::path &path="", bool use_pipes=true); - int process(std::istream &stdin_stream, std::ostream &stdout_stream, const std::string &command, const boost::filesystem::path &path=""); + int process(std::istream &stdin_stream, std::ostream &stdout_stream, const std::string &command, const boost::filesystem::path &path="", std::ostream *stderr_stream=nullptr); void async_process(const std::string &command, const boost::filesystem::path &path="", std::function callback=nullptr, bool quiet=false); void kill_last_async_process(bool force=false); void kill_async_processes(bool force=false); diff --git a/src/window.cc b/src/window.cc index 00a9deb..97478a6 100644 --- a/src/window.cc +++ b/src/window.cc @@ -285,12 +285,10 @@ void Window::set_menu_actions() { return; } - view->load(); - while(Gtk::Main::events_pending()) - Gtk::Main::iteration(false); - Notebook::get().delete_cursor_locations(view); - view->get_buffer()->set_modified(false); - view->full_reparse(); + if(view->load()) { + view->get_buffer()->set_modified(false); + view->full_reparse(); + } } } });