diff --git a/src/notebook.cc b/src/notebook.cc index 6fd29d9..a6c04ae 100644 --- a/src/notebook.cc +++ b/src/notebook.cc @@ -205,7 +205,7 @@ bool Notebook::save(int page, bool reparse_needed) { for(auto a_view: source_views) { if(auto a_clang_view=dynamic_cast(a_view)) { if(clang_view!=a_clang_view) - a_clang_view->reparse_needed=true; + a_clang_view->soft_reparse_needed=true; } } } @@ -230,12 +230,8 @@ bool Notebook::save(int page, bool reparse_needed) { if(project_path!="") { for(auto source_view: source_views) { if(auto source_clang_view=dynamic_cast(source_view)) { - if(project_path==source_clang_view->project_path) { - 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", true); - } + if(project_path==source_clang_view->project_path) + source_clang_view->full_reparse_needed=true; } } } diff --git a/src/selectiondialog.h b/src/selectiondialog.h index b13fffb..5673f1a 100644 --- a/src/selectiondialog.h +++ b/src/selectiondialog.h @@ -58,13 +58,13 @@ class SelectionDialog : public SelectionDialogBase { public: SelectionDialog(Gtk::TextView& text_view, Glib::RefPtr start_mark, bool show_search_entry=true, bool use_markup=false); bool on_key_press(GdkEventKey* key); - void show(); + void show() override; }; class CompletionDialog : public SelectionDialogBase { public: CompletionDialog(Gtk::TextView& text_view, Glib::RefPtr start_mark); - void show(); + void show() override; bool on_key_release(GdkEventKey* key); bool on_key_press(GdkEventKey* key); diff --git a/src/source.cc b/src/source.cc index c31c828..839958b 100644 --- a/src/source.cc +++ b/src/source.cc @@ -396,7 +396,7 @@ void Source::View::set_tooltip_events() { delayed_tooltips_connection=Glib::signal_timeout().connect([this, x, y]() { Tooltips::init(); Gdk::Rectangle rectangle(x, y, 1, 1); - if(source_readable) { + if(parsed) { show_type_tooltips(rectangle); show_diagnostic_tooltips(rectangle); } @@ -426,7 +426,7 @@ void Source::View::set_tooltip_events() { rectangle.set_x(location_window_x-2); rectangle.set_y(location_window_y); rectangle.set_width(5); - if(source_readable) { + if(parsed) { show_type_tooltips(rectangle); show_diagnostic_tooltips(rectangle); } @@ -1245,7 +1245,18 @@ std::pair Source::View::spellcheck_get_word(Gtk::T } void Source::View::spellcheck_word(const Gtk::TextIter& start, const Gtk::TextIter& end) { - auto word=get_buffer()->get_text(start, end); + auto spellcheck_start=start; + auto spellcheck_end=end; + if((spellcheck_end.get_offset()-spellcheck_start.get_offset())>=2) { + auto last_char=spellcheck_end; + last_char.backward_char(); + if(*spellcheck_start=='\'' && *last_char=='\'') { + spellcheck_start.forward_char(); + spellcheck_end.backward_char(); + } + } + + auto word=get_buffer()->get_text(spellcheck_start, spellcheck_end); if(word.size()>0) { auto correct = aspell_speller_check(spellcheck_checker, word.data(), word.bytes()); if(correct==0) diff --git a/src/source.h b/src/source.h index d5e28f5..d2046a0 100644 --- a/src/source.h +++ b/src/source.h @@ -101,8 +101,13 @@ namespace Source { void set_tab_char_and_size(char tab_char, unsigned tab_size); std::pair get_tab_char_and_size() {return {tab_char, tab_size};} + + bool soft_reparse_needed=false; + bool full_reparse_needed=false; + virtual void soft_reparse() {} + virtual bool full_reparse() {return true;} protected: - bool source_readable; + bool parsed=false; Tooltips diagnostic_tooltips; Tooltips type_tooltips; virtual void show_diagnostic_tooltips(const Gdk::Rectangle &rectangle) {} diff --git a/src/source_clang.cc b/src/source_clang.cc index 8fb5ed0..ad5e596 100644 --- a/src/source_clang.cc +++ b/src/source_clang.cc @@ -48,7 +48,7 @@ Source::View(file_path, project_path, language), parse_error(false) { if(parsing_mutex.try_lock()) { update_syntax(); update_diagnostics(); - source_readable=true; + parsed=true; set_status(""); parsing_mutex.unlock(); } @@ -67,7 +67,7 @@ Source::View(file_path, project_path, language), parse_error(false) { init_parse(); get_buffer()->signal_changed().connect([this]() { - start_reparse(); + soft_reparse(); type_tooltips.hide(); diagnostic_tooltips.hide(); }); @@ -108,7 +108,7 @@ void Source::ClangViewParse::configure() { void Source::ClangViewParse::init_parse() { type_tooltips.hide(); diagnostic_tooltips.hide(); - source_readable=false; + parsed=false; parse_thread_go=true; parse_thread_mapped=false; parse_thread_stop=false; @@ -170,12 +170,12 @@ std::map Source::ClangViewParse::get_buffer_map() cons return buffer_map; } -void Source::ClangViewParse::start_reparse() { +void Source::ClangViewParse::soft_reparse() { parse_thread_mapped=false; - source_readable=false; + parsed=false; delayed_reparse_connection.disconnect(); delayed_reparse_connection=Glib::signal_timeout().connect([this]() { - source_readable=false; + parsed=false; parse_thread_go=true; set_status("parsing..."); return false; @@ -367,7 +367,7 @@ void Source::ClangViewParse::show_diagnostic_tooltips(const Gdk::Rectangle &rect } void Source::ClangViewParse::show_type_tooltips(const Gdk::Rectangle &rectangle) { - if(source_readable) { + if(parsed) { Gtk::TextIter iter; int location_x, location_y; window_to_buffer_coords(Gtk::TextWindowType::TEXT_WINDOW_TEXT, rectangle.get_x(), rectangle.get_y(), location_x, location_y); @@ -650,7 +650,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", true); - restart_parse(); + full_reparse(); autocomplete_starting=false; autocomplete_cancel_starting=false; }); @@ -661,9 +661,9 @@ Source::ClangViewParse(file_path, project_path, language), autocomplete_cancel_s do_delete_object_connection.disconnect(); delete this; }); - do_restart_parse.connect([this](){ + do_full_reparse.connect([this](){ init_parse(); - restart_parse_running=false; + full_reparse_running=false; }); } @@ -738,8 +738,8 @@ void Source::ClangViewAutocomplete::autocomplete() { completion_dialog->on_hide=[this](){ get_source_buffer()->end_user_action(); completion_dialog_shown=false; - source_readable=false; - start_reparse(); + parsed=false; + soft_reparse(); }; completion_dialog->on_select=[this, rows](const std::string& selected, bool hide_window) { auto row = rows->at(selected); @@ -798,11 +798,11 @@ void Source::ClangViewAutocomplete::autocomplete() { completion_dialog->show(); } else - start_reparse(); + soft_reparse(); } else { set_status(""); - start_reparse(); + soft_reparse(); start_autocomplete(); } }); @@ -874,8 +874,8 @@ void Source::ClangViewAutocomplete::async_delete() { 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(full_reparse_thread.joinable()) + full_reparse_thread.join(); if(parse_thread.joinable()) parse_thread.join(); if(autocomplete_thread.joinable()) @@ -884,19 +884,19 @@ void Source::ClangViewAutocomplete::async_delete() { }); } -bool Source::ClangViewAutocomplete::restart_parse() { - if(!restart_parse_running && !parse_error) { - reparse_needed=false; - restart_parse_running=true; +bool Source::ClangViewAutocomplete::full_reparse() { + if(!full_reparse_running && !parse_error) { + soft_reparse_needed=false; + full_reparse_running=true; parse_thread_stop=true; - if(restart_parse_thread.joinable()) - restart_parse_thread.join(); - restart_parse_thread=std::thread([this](){ + if(full_reparse_thread.joinable()) + full_reparse_thread.join(); + full_reparse_thread=std::thread([this](){ if(parse_thread.joinable()) parse_thread.join(); if(autocomplete_thread.joinable()) autocomplete_thread.join(); - do_restart_parse(); + do_full_reparse(); }); return true; } @@ -972,7 +972,7 @@ Source::ClangViewAutocomplete(file_path, project_path, language) { }; get_token=[this]() -> Token { - if(source_readable) { + if(parsed) { auto iter=get_buffer()->get_insert()->get_iter(); auto line=(unsigned)iter.get_line(); auto index=(unsigned)iter.get_line_index(); @@ -994,7 +994,7 @@ Source::ClangViewAutocomplete(file_path, project_path, language) { rename_similar_tokens=[this](const Token &token, const std::string &text) { size_t number=0; - if(source_readable && token.language && + if(parsed && token.language && (token.language->get_id()=="chdr" || token.language->get_id()=="cpphdr" || token.language->get_id()=="c" || token.language->get_id()=="cpp" || token.language->get_id()=="objc")) { auto offsets=clang_tokens->get_similar_token_offsets(static_cast(token.type), token.spelling, token.usr); std::vector, Glib::RefPtr > > marks; @@ -1029,7 +1029,7 @@ Source::ClangViewAutocomplete(file_path, project_path, language) { get_declaration_location=[this](){ Offset location; - if(source_readable) { + if(parsed) { auto iter=get_buffer()->get_insert()->get_iter(); auto line=(unsigned)iter.get_line(); auto index=(unsigned)iter.get_line_index(); @@ -1055,7 +1055,7 @@ Source::ClangViewAutocomplete(file_path, project_path, language) { get_usages=[this](const Token &token) { std::vector > usages; - if(source_readable && token.language && + if(parsed && token.language && (token.language->get_id()=="chdr" || token.language->get_id()=="cpphdr" || token.language->get_id()=="c" || token.language->get_id()=="cpp" || token.language->get_id()=="objc")) { auto offsets=clang_tokens->get_similar_token_offsets(static_cast(token.type), token.spelling, token.usr); for(auto &offset: offsets) { @@ -1096,7 +1096,7 @@ Source::ClangViewAutocomplete(file_path, project_path, language) { }; goto_method=[this](){ - if(source_readable) { + if(parsed) { auto iter=get_buffer()->get_insert()->get_iter(); Gdk::Rectangle visible_rect; get_visible_rect(visible_rect); @@ -1167,7 +1167,7 @@ Source::ClangViewAutocomplete(file_path, project_path, language) { }; std::vector data; - if(source_readable) { + if(parsed) { auto iter=get_buffer()->get_insert()->get_iter(); auto line=(unsigned)iter.get_line(); auto index=(unsigned)iter.get_line_index(); @@ -1261,7 +1261,7 @@ Source::ClangViewAutocomplete(file_path, project_path, language) { }; goto_next_diagnostic=[this]() { - if(source_readable) { + if(parsed) { auto insert_offset=get_buffer()->get_insert()->get_iter().get_offset(); for(auto offset: diagnostic_offsets) { if(offset>insert_offset) { @@ -1280,7 +1280,7 @@ Source::ClangViewAutocomplete(file_path, project_path, language) { apply_fix_its=[this]() { std::vector, Glib::RefPtr > > fix_it_marks; - if(source_readable) { + if(parsed) { for(auto &fix_it: fix_its) { auto start_iter=get_buffer()->get_iter_at_line_index(fix_it.offsets.first.line-1, fix_it.offsets.first.index-1); auto end_iter=get_buffer()->get_iter_at_line_index(fix_it.offsets.second.line-1, fix_it.offsets.second.index-1); @@ -1311,7 +1311,7 @@ Source::ClangViewAutocomplete(file_path, project_path, language) { } void Source::ClangViewRefactor::tag_similar_tokens(const Token &token) { - if(source_readable) { + if(parsed) { if(token && last_tagged_token!=token) { for(auto &mark: similar_token_marks) { get_buffer()->remove_tag(similar_tokens_tag, mark.first->get_iter(), mark.second->get_iter()); diff --git a/src/source_clang.h b/src/source_clang.h index 7cb7fdb..8ed8157 100644 --- a/src/source_clang.h +++ b/src/source_clang.h @@ -22,13 +22,13 @@ namespace Source { }; ClangViewParse(const boost::filesystem::path &file_path, const boost::filesystem::path& project_path, Glib::RefPtr language); - virtual void configure(); + bool on_key_press_event(GdkEventKey* key) override; - void start_reparse(); - bool reparse_needed=false; + void configure() override; + + void soft_reparse() override; protected: void init_parse(); - bool on_key_press_event(GdkEventKey* key); std::unique_ptr clang_tu; std::mutex parsing_mutex; std::unique_ptr clang_tokens; @@ -39,8 +39,8 @@ namespace Source { std::atomic parse_thread_stop; std::atomic parse_error; - virtual void show_diagnostic_tooltips(const Gdk::Rectangle &rectangle); - virtual void show_type_tooltips(const Gdk::Rectangle &rectangle); + void show_diagnostic_tooltips(const Gdk::Rectangle &rectangle) override; + void show_type_tooltips(const Gdk::Rectangle &rectangle) override; boost::regex bracket_regex; boost::regex no_bracket_statement_regex; @@ -81,10 +81,11 @@ namespace Source { }; ClangViewAutocomplete(const boost::filesystem::path &file_path, const boost::filesystem::path& project_path, Glib::RefPtr language); + bool on_key_press_event(GdkEventKey* key) override; + virtual void async_delete(); - bool restart_parse(); + bool full_reparse() override; protected: - bool on_key_press_event(GdkEventKey* key); std::thread autocomplete_thread; sigc::connection autocomplete_done_connection; sigc::connection autocomplete_fail_connection; @@ -105,10 +106,10 @@ namespace Source { std::mutex prefix_mutex; Glib::Dispatcher do_delete_object; - Glib::Dispatcher do_restart_parse; + Glib::Dispatcher do_full_reparse; std::thread delete_thread; - std::thread restart_parse_thread; - bool restart_parse_running=false; + std::thread full_reparse_thread; + bool full_reparse_running=false; }; class ClangViewRefactor : public ClangViewAutocomplete { @@ -127,7 +128,7 @@ namespace Source { class ClangView : public ClangViewRefactor { public: ClangView(const boost::filesystem::path &file_path, const boost::filesystem::path& project_path, Glib::RefPtr language); - virtual void async_delete(); + void async_delete() override; }; } diff --git a/src/window.cc b/src/window.cc index 559e853..7b812bd 100644 --- a/src/window.cc +++ b/src/window.cc @@ -81,26 +81,30 @@ Window::Window() : compiling(false) { notebook.signal_switch_page().connect([this](Gtk::Widget* page, guint page_num) { if(notebook.get_current_page()!=-1) { + auto view=notebook.get_current_view(); if(search_entry_shown && entry_box.labels.size()>0) { - notebook.get_current_view()->update_search_occurrences=[this](int number){ + view->update_search_occurrences=[this](int number){ entry_box.labels.begin()->update(0, std::to_string(number)); }; - notebook.get_current_view()->search_highlight(last_search, case_sensitive_search, regex_search); + view->search_highlight(last_search, case_sensitive_search, regex_search); } activate_menu_items(); - Singleton::directories->select(notebook.get_current_view()->file_path); + Singleton::directories->select(view->file_path); - if(auto source_view=dynamic_cast(notebook.get_current_view())) { - if(source_view->reparse_needed) { - source_view->start_reparse(); - source_view->reparse_needed=false; - } + if(view->full_reparse_needed) { + if(!view->full_reparse()) + Singleton::terminal->async_print("Error: failed to reparse "+view->file_path.string()+". Please reopen the file manually.\n", true); + view->full_reparse_needed=false; + } + else if(view->soft_reparse_needed) { + view->soft_reparse(); + view->soft_reparse_needed=false; } - notebook.get_current_view()->set_status(notebook.get_current_view()->status); - notebook.get_current_view()->set_info(notebook.get_current_view()->info); + view->set_status(view->status); + view->set_info(view->info); } }); notebook.signal_page_removed().connect([this](Gtk::Widget* page, guint page_num) { @@ -674,7 +678,7 @@ bool Window::on_key_press_event(GdkEventKey *event) { } #endif - return Gtk::Window::on_key_press_event(event); + return Gtk::ApplicationWindow::on_key_press_event(event); } bool Window::on_delete_event(GdkEventAny *event) {