From d5eef33fd7beeeecb4d1497b2b6d09afe7c73e0b Mon Sep 17 00:00:00 2001 From: eidheim Date: Thu, 16 Jul 2015 11:22:53 +0200 Subject: [PATCH 1/3] Hopefully fixed the strange behaviour with the bold feature, among other smaller things. --- juci/selectiondialog.cc | 2 ++ juci/selectiondialog.h | 1 + juci/source.cc | 46 +++++++++++++++++++++++++++++------------ juci/source.h | 3 ++- 4 files changed, 38 insertions(+), 14 deletions(-) diff --git a/juci/selectiondialog.cc b/juci/selectiondialog.cc index be51467..18e9f1a 100644 --- a/juci/selectiondialog.cc +++ b/juci/selectiondialog.cc @@ -65,6 +65,8 @@ void SelectionDialog::hide() { window->hide(); if(tooltips) tooltips->hide(); + if(on_hide) + on_hide(); } void SelectionDialog::select(bool hide_window) { diff --git a/juci/selectiondialog.h b/juci/selectiondialog.h index f93274f..b497d6c 100644 --- a/juci/selectiondialog.h +++ b/juci/selectiondialog.h @@ -14,6 +14,7 @@ public: void move(); bool on_key_release(GdkEventKey* key); bool on_key_press(GdkEventKey* key); + std::function on_hide; std::map > rows; bool shown=false; diff --git a/juci/source.cc b/juci/source.cc index cfeeef5..d424fb6 100644 --- a/juci/source.cc +++ b/juci/source.cc @@ -150,8 +150,8 @@ clang::Index Source::ClangView::clang_index(0, 0); Source::ClangView::ClangView(const std::string& file_path, const std::string& project_path, Terminal::Controller& terminal): Source::View(file_path, project_path), terminal(terminal), parse_thread_go(true), parse_thread_mapped(false), parse_thread_stop(false) { - similar_token_tag=get_buffer()->create_tag(); - similar_token_tag->property_weight()=Pango::WEIGHT_BOLD; + similar_tokens_tag=get_buffer()->create_tag(); + similar_tokens_tag->property_weight()=Pango::WEIGHT_BOLD; int start_offset = get_source_buffer()->begin().get_offset(); int end_offset = get_source_buffer()->end().get_offset(); @@ -223,17 +223,21 @@ parse_thread_go(true), parse_thread_mapped(false), parse_thread_stop(false) { } } }); - + get_buffer()->signal_changed().connect([this]() { parse_thread_mapped=false; + clang_readable=false; delayed_reparse_connection.disconnect(); delayed_reparse_connection=Glib::signal_timeout().connect([this]() { - clang_readable=false; parse_thread_go=true; return false; }, 1000); type_tooltips.hide(); diagnostic_tooltips.hide(); + if(last_similar_token_marked!="") { + get_buffer()->remove_tag(similar_tokens_tag, get_buffer()->begin(), get_buffer()->end()); + last_similar_token_marked=""; + } }); get_buffer()->signal_mark_set().connect(sigc::mem_fun(*this, &Source::ClangView::on_mark_set), false); @@ -429,21 +433,32 @@ void Source::ClangView::on_mark_set(const Gtk::TextBuffer::iterator& iterator, c type_tooltips.hide(); diagnostic_tooltips.hide(); - get_buffer()->remove_tag(similar_token_tag, get_buffer()->begin(), get_buffer()->end()); + bool found=false; if(clang_readable) { for(auto &token: *clang_tokens) { if(token.has_type()) { auto range_data=token.source_range.get_range_data(); auto insert_offset=(unsigned)get_buffer()->get_insert()->get_iter().get_offset(); if(range_data.path==file_path && insert_offset>=range_data.start_offset && insert_offset<=range_data.end_offset) { - auto offsets=clang_tokens->get_similar_token_offsets(token); - for(auto &offset: offsets) { - get_buffer()->apply_tag(similar_token_tag, get_buffer()->get_iter_at_offset(offset.first), get_buffer()->get_iter_at_offset(offset.second)); + found=true; + auto referenced_usr_and_token_spelling=token.get_cursor().get_referenced_usr()+token.get_token_spelling(); + if(last_similar_token_marked!=referenced_usr_and_token_spelling) { + get_buffer()->remove_tag(similar_tokens_tag, get_buffer()->begin(), get_buffer()->end()); + auto offsets=clang_tokens->get_similar_token_offsets(token); + for(auto &offset: offsets) { + get_buffer()->apply_tag(similar_tokens_tag, get_buffer()->get_iter_at_offset(offset.first), get_buffer()->get_iter_at_offset(offset.second)); + } + last_similar_token_marked=referenced_usr_and_token_spelling; + break; } } } } } + if(!found && last_similar_token_marked!="") { + get_buffer()->remove_tag(similar_tokens_tag, get_buffer()->begin(), get_buffer()->end()); + last_similar_token_marked=""; + } } } @@ -552,15 +567,22 @@ bool Source::ClangView::on_key_press_event(GdkEventKey* key) { //// ClangViewAutocomplete /// ////////////////////////////// Source::ClangViewAutocomplete::ClangViewAutocomplete(const std::string& file_path, const std::string& project_path, Terminal::Controller& terminal): -Source::ClangView(file_path, project_path, terminal), selection_dialog(*this), autocomplete_cancel_starting(false) { +Source::ClangView(file_path, project_path, terminal), selection_dialog(*this), autocomplete_cancel_starting(false) { + selection_dialog.on_hide=[this](){ + + }; + get_buffer()->signal_changed().connect([this](){ - if(last_keyval==GDK_KEY_BackSpace) + if(selection_dialog.shown) + delayed_reparse_connection.disconnect(); + const std::regex autocomplete_keys("[a-zA-Z0-9_>\\.:]"); + std::smatch sm; + if(!std::regex_match(std::string()+(char)last_keyval, sm, autocomplete_keys)) return; std::string line=" "+get_line_before_insert(); if((std::count(line.begin(), line.end(), '\"')%2)!=1 && line.find("//")==std::string::npos) { const std::regex in_specified_namespace("^(.*[a-zA-Z0-9_\\)])(->|\\.|::)([a-zA-Z0-9_]*)$"); const std::regex within_namespace("^(.*)([^a-zA-Z0-9_]+)([a-zA-Z0-9_]{3,})$"); - std::smatch sm; if(std::regex_match(line, sm, in_specified_namespace)) { prefix_mutex.lock(); prefix=sm[3].str(); @@ -600,7 +622,6 @@ Source::ClangView(file_path, project_path, terminal), selection_dialog(*this), a }, false); signal_key_release_event().connect([this](GdkEventKey* key){ if(selection_dialog.shown) { - delayed_reparse_connection.disconnect(); //TODO: place this somewhere better (buffer_changed maybe) if(selection_dialog.on_key_release(key)) return true; } @@ -612,7 +633,6 @@ Source::ClangView(file_path, project_path, terminal), selection_dialog(*this), a bool Source::ClangViewAutocomplete::on_key_press_event(GdkEventKey *key) { last_keyval=key->keyval; if(selection_dialog.shown) { - delayed_reparse_connection.disconnect(); //TODO: place this somewhere better (buffer_changed maybe) if(selection_dialog.on_key_press(key)) return true; } diff --git a/juci/source.h b/juci/source.h index 8c5a9e2..12f9569 100644 --- a/juci/source.h +++ b/juci/source.h @@ -91,7 +91,8 @@ namespace Source { bool on_motion_notify_event(GdkEventMotion* event); void on_mark_set(const Gtk::TextBuffer::iterator& iterator, const Glib::RefPtr& mark); sigc::connection delayed_tooltips_connection; - Glib::RefPtr similar_token_tag; + Glib::RefPtr similar_tokens_tag; + std::string last_similar_token_marked; bool on_scroll_event(GdkEventScroll* event); static clang::Index clang_index; From a464cb3a42f32f2f4890c3fb7579252ca0f81676 Mon Sep 17 00:00:00 2001 From: eidheim Date: Thu, 16 Jul 2015 12:01:12 +0200 Subject: [PATCH 2/3] Fixed issue with autocomplete not starting. Autocomplete is now trying to start again if canceled. --- juci/source.cc | 86 +++++++++++++++++++++++++++----------------------- juci/source.h | 3 +- 2 files changed, 49 insertions(+), 40 deletions(-) diff --git a/juci/source.cc b/juci/source.cc index d424fb6..d7d7ab2 100644 --- a/juci/source.cc +++ b/juci/source.cc @@ -234,9 +234,9 @@ parse_thread_go(true), parse_thread_mapped(false), parse_thread_stop(false) { }, 1000); type_tooltips.hide(); diagnostic_tooltips.hide(); - if(last_similar_token_marked!="") { + if(last_similar_tokens_tagged!="") { get_buffer()->remove_tag(similar_tokens_tag, get_buffer()->begin(), get_buffer()->end()); - last_similar_token_marked=""; + last_similar_tokens_tagged=""; } }); @@ -442,22 +442,22 @@ void Source::ClangView::on_mark_set(const Gtk::TextBuffer::iterator& iterator, c if(range_data.path==file_path && insert_offset>=range_data.start_offset && insert_offset<=range_data.end_offset) { found=true; auto referenced_usr_and_token_spelling=token.get_cursor().get_referenced_usr()+token.get_token_spelling(); - if(last_similar_token_marked!=referenced_usr_and_token_spelling) { + if(last_similar_tokens_tagged!=referenced_usr_and_token_spelling) { get_buffer()->remove_tag(similar_tokens_tag, get_buffer()->begin(), get_buffer()->end()); auto offsets=clang_tokens->get_similar_token_offsets(token); for(auto &offset: offsets) { get_buffer()->apply_tag(similar_tokens_tag, get_buffer()->get_iter_at_offset(offset.first), get_buffer()->get_iter_at_offset(offset.second)); } - last_similar_token_marked=referenced_usr_and_token_spelling; + last_similar_tokens_tagged=referenced_usr_and_token_spelling; break; } } } } } - if(!found && last_similar_token_marked!="") { + if(!found && last_similar_tokens_tagged!="") { get_buffer()->remove_tag(similar_tokens_tag, get_buffer()->begin(), get_buffer()->end()); - last_similar_token_marked=""; + last_similar_tokens_tagged=""; } } } @@ -569,43 +569,13 @@ bool Source::ClangView::on_key_press_event(GdkEventKey* key) { Source::ClangViewAutocomplete::ClangViewAutocomplete(const std::string& file_path, const std::string& project_path, Terminal::Controller& terminal): Source::ClangView(file_path, project_path, terminal), selection_dialog(*this), autocomplete_cancel_starting(false) { selection_dialog.on_hide=[this](){ - + //TODO: start parsing again? }; get_buffer()->signal_changed().connect([this](){ if(selection_dialog.shown) delayed_reparse_connection.disconnect(); - const std::regex autocomplete_keys("[a-zA-Z0-9_>\\.:]"); - std::smatch sm; - if(!std::regex_match(std::string()+(char)last_keyval, sm, autocomplete_keys)) - return; - std::string line=" "+get_line_before_insert(); - if((std::count(line.begin(), line.end(), '\"')%2)!=1 && line.find("//")==std::string::npos) { - const std::regex in_specified_namespace("^(.*[a-zA-Z0-9_\\)])(->|\\.|::)([a-zA-Z0-9_]*)$"); - const std::regex within_namespace("^(.*)([^a-zA-Z0-9_]+)([a-zA-Z0-9_]{3,})$"); - if(std::regex_match(line, sm, in_specified_namespace)) { - prefix_mutex.lock(); - prefix=sm[3].str(); - prefix_mutex.unlock(); - if((prefix.size()==0 || prefix[0]<'0' || prefix[0]>'9') && !autocomplete_starting && !selection_dialog.shown) { - autocomplete(); - } - else if(last_keyval=='.' && autocomplete_starting) - autocomplete_cancel_starting=true; - } - else if(std::regex_match(line, sm, within_namespace)) { - prefix_mutex.lock(); - prefix=sm[3].str(); - prefix_mutex.unlock(); - if((prefix.size()==0 || prefix[0]<'0' || prefix[0]>'9') && !autocomplete_starting && !selection_dialog.shown) { - autocomplete(); - } - } - else - autocomplete_cancel_starting=true; - if(autocomplete_starting || selection_dialog.shown) - delayed_reparse_connection.disconnect(); - } + start_autocomplete(); }); get_buffer()->signal_mark_set().connect([this](const Gtk::TextBuffer::iterator& iterator, const Glib::RefPtr& mark){ if(mark->get_name()=="insert") { @@ -647,6 +617,42 @@ bool Source::ClangViewAutocomplete::on_focus_out_event(GdkEventFocus* event) { return Source::ClangView::on_focus_out_event(event); } +void Source::ClangViewAutocomplete::start_autocomplete() { + const std::regex autocomplete_keys("[a-zA-Z0-9_>\\.:]"); + std::smatch sm; + if(!std::regex_match(std::string()+(char)last_keyval, sm, autocomplete_keys)) { + autocomplete_cancel_starting=true; + return; + } + std::string line=" "+get_line_before_insert(); + if((std::count(line.begin(), line.end(), '\"')%2)!=1 && line.find("//")==std::string::npos) { + const std::regex in_specified_namespace("^(.*[a-zA-Z0-9_\\)])(->|\\.|::)([a-zA-Z0-9_]*)$"); + const std::regex within_namespace("^(.*)([^a-zA-Z0-9_]+)([a-zA-Z0-9_]{3,})$"); + if(std::regex_match(line, sm, in_specified_namespace)) { + prefix_mutex.lock(); + prefix=sm[3].str(); + prefix_mutex.unlock(); + if((prefix.size()==0 || prefix[0]<'0' || prefix[0]>'9') && !autocomplete_starting && !selection_dialog.shown) { + autocomplete(); + } + else if(last_keyval=='.' && autocomplete_starting) + autocomplete_cancel_starting=true; + } + else if(std::regex_match(line, sm, within_namespace)) { + prefix_mutex.lock(); + prefix=sm[3].str(); + prefix_mutex.unlock(); + if((prefix.size()==0 || prefix[0]<'0' || prefix[0]>'9') && !autocomplete_starting && !selection_dialog.shown) { + autocomplete(); + } + } + else + autocomplete_cancel_starting=true; + if(autocomplete_starting || selection_dialog.shown) + delayed_reparse_connection.disconnect(); + } +} + void Source::ClangViewAutocomplete::autocomplete() { if(!autocomplete_starting) { autocomplete_starting=true; @@ -655,6 +661,7 @@ void Source::ClangViewAutocomplete::autocomplete() { std::shared_ptr > ac_data=std::make_shared >(); autocomplete_done_connection.disconnect(); autocomplete_done_connection=autocomplete_done.connect([this, ac_data](){ + autocomplete_starting=false; if(!autocomplete_cancel_starting) { if(selection_dialog.start_mark) get_buffer()->delete_mark(selection_dialog.start_mark); @@ -688,7 +695,8 @@ void Source::ClangViewAutocomplete::autocomplete() { selection_dialog.rows=std::move(rows); selection_dialog.show(); } - autocomplete_starting=false; + else + start_autocomplete(); }); std::shared_ptr > buffer_map=std::make_shared >(); diff --git a/juci/source.h b/juci/source.h index 12f9569..2131831 100644 --- a/juci/source.h +++ b/juci/source.h @@ -92,7 +92,7 @@ namespace Source { void on_mark_set(const Gtk::TextBuffer::iterator& iterator, const Glib::RefPtr& mark); sigc::connection delayed_tooltips_connection; Glib::RefPtr similar_tokens_tag; - std::string last_similar_token_marked; + std::string last_similar_tokens_tagged; bool on_scroll_event(GdkEventScroll* event); static clang::Index clang_index; @@ -119,6 +119,7 @@ namespace Source { bool on_key_press_event(GdkEventKey* key); bool on_focus_out_event(GdkEventFocus* event); private: + void start_autocomplete(); void autocomplete(); SelectionDialog selection_dialog; std::vector get_autocomplete_suggestions(int line_number, int column, std::map& buffer_map); From 460f80a22ab5b3ae2549afa7145c004ec75a520c Mon Sep 17 00:00:00 2001 From: eidheim Date: Thu, 16 Jul 2015 12:27:37 +0200 Subject: [PATCH 3/3] Autocomplete and reparse should now live in perfect symbiosis. --- juci/source.cc | 26 ++++++++++++++------------ juci/source.h | 5 +++-- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/juci/source.cc b/juci/source.cc index d7d7ab2..17e1378 100644 --- a/juci/source.cc +++ b/juci/source.cc @@ -225,13 +225,7 @@ parse_thread_go(true), parse_thread_mapped(false), parse_thread_stop(false) { }); get_buffer()->signal_changed().connect([this]() { - parse_thread_mapped=false; - clang_readable=false; - delayed_reparse_connection.disconnect(); - delayed_reparse_connection=Glib::signal_timeout().connect([this]() { - parse_thread_go=true; - return false; - }, 1000); + start_reparse(); type_tooltips.hide(); diagnostic_tooltips.hide(); if(last_similar_tokens_tagged!="") { @@ -266,15 +260,23 @@ init_syntax_highlighting(const std::map clang_tokens=clang_tu->get_tokens(0, buffers.find(file_path)->second.size()-1); } -std::map Source::ClangView:: -get_buffer_map() const { +std::map Source::ClangView::get_buffer_map() const { std::map buffer_map; buffer_map[file_path]=get_source_buffer()->get_text().raw(); return buffer_map; } -int Source::ClangView:: -reparse(const std::map &buffer) { +void Source::ClangView::start_reparse() { + parse_thread_mapped=false; + clang_readable=false; + delayed_reparse_connection.disconnect(); + delayed_reparse_connection=Glib::signal_timeout().connect([this]() { + parse_thread_go=true; + return false; + }, 1000); +} + +int Source::ClangView::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); return status; @@ -569,7 +571,7 @@ bool Source::ClangView::on_key_press_event(GdkEventKey* key) { Source::ClangViewAutocomplete::ClangViewAutocomplete(const std::string& file_path, const std::string& project_path, Terminal::Controller& terminal): Source::ClangView(file_path, project_path, terminal), selection_dialog(*this), autocomplete_cancel_starting(false) { selection_dialog.on_hide=[this](){ - //TODO: start parsing again? + start_reparse(); }; get_buffer()->signal_changed().connect([this](){ diff --git a/juci/source.h b/juci/source.h index 2131831..7a2a05a 100644 --- a/juci/source.h +++ b/juci/source.h @@ -70,12 +70,13 @@ namespace Source { ClangView(const std::string& file_path, const std::string& project_path, Terminal::Controller& terminal); ~ClangView(); protected: + void start_reparse(); + bool on_key_press_event(GdkEventKey* key); + bool on_focus_out_event(GdkEventFocus* event); std::unique_ptr clang_tu; std::map get_buffer_map() const; std::mutex parsing_mutex; sigc::connection delayed_reparse_connection; - bool on_key_press_event(GdkEventKey* key); - bool on_focus_out_event(GdkEventFocus* event); private: // inits the syntax highligthing on file open void init_syntax_highlighting(const std::map