diff --git a/juci/selectiondialog.cc b/juci/selectiondialog.cc index 7d333ca..c96d7c7 100644 --- a/juci/selectiondialog.cc +++ b/juci/selectiondialog.cc @@ -11,7 +11,7 @@ void SelectionDialog::show() { window=std::unique_ptr(new Gtk::Window(Gtk::WindowType::WINDOW_POPUP)); scrolled_window=std::unique_ptr(new Gtk::ScrolledWindow()); - list_view_text=std::unique_ptr(new Gtk::ListViewText(1, false, Gtk::SelectionMode::SELECTION_SINGLE)); + list_view_text=std::unique_ptr(new Gtk::ListViewText(1, false, Gtk::SelectionMode::SELECTION_BROWSE)); window->set_default_size(0, 0); window->property_decorated()=false; @@ -22,7 +22,7 @@ void SelectionDialog::show() { list_view_text->set_hscroll_policy(Gtk::ScrollablePolicy::SCROLL_NATURAL); list_view_text->set_activate_on_single_click(true); list_view_text->set_search_entry(search_entry); - list_view_text->set_hover_selection(true); + list_view_text->set_hover_selection(false); list_view_text->set_rules_hint(true); //list_view_text->set_fixed_height_mode(true); //TODO: This is buggy on OS X, remember to post an issue on GTK+ 3 @@ -108,7 +108,6 @@ bool SelectionDialog::on_key_release(GdkEventKey* key) { auto text=text_view.get_buffer()->get_text(start_mark->get_iter(), text_view.get_buffer()->get_insert()->get_iter()); if(text.size()>0) { search_entry.set_text(text); - list_view_text->set_search_entry(search_entry); } } @@ -173,7 +172,7 @@ void SelectionDialog::cursor_changed() { if(select.second.size()>0) { tooltips=std::unique_ptr(new Tooltips()); auto tooltip_text=select.second; - auto get_tooltip_buffer=[this, tooltip_text]() { + auto get_tooltip_buffer=[this, tooltip_text]() { auto tooltip_buffer=Gtk::TextBuffer::create(text_view.get_buffer()->get_tag_table()); //TODO: Insert newlines to tooltip_text (use 80 chars, then newline?) tooltip_buffer->insert_at_cursor(tooltip_text); diff --git a/juci/source.cc b/juci/source.cc index 9ff1a95..c44c44c 100644 --- a/juci/source.cc +++ b/juci/source.cc @@ -170,7 +170,7 @@ parse_thread_go(true), parse_thread_mapped(false), parse_thread_stop(false) { start_offset, end_offset, &ClangView::clang_index); - update_syntax(extract_tokens(0, get_source_buffer()->get_text().size())); //TODO: replace get_source_buffer()->get_text().size() + update_syntax(); //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: @@ -188,10 +188,10 @@ parse_thread_go(true), parse_thread_mapped(false), parse_thread_stop(false) { if(parse_thread_mapped) { if(parsing_mutex.try_lock()) { INFO("Updating syntax"); - update_syntax(extract_tokens(0, get_source_buffer()->get_text().size())); + update_syntax(); update_diagnostics(); update_types(); - clang_updated=true; + clang_readable=true; parsing_mutex.unlock(); INFO("Syntax updated"); } @@ -221,17 +221,20 @@ parse_thread_go(true), parse_thread_mapped(false), parse_thread_stop(false) { } } }); - - autocomplete_done.connect([this](){ - if(autocomplete_done_function) - autocomplete_done_function(); - }); - + get_source_buffer()->signal_changed().connect([this]() { - autocomplete_cancel=true; + cancel_show_autocomplete=true; parse_thread_mapped=false; - clang_updated=false; - parse_thread_go=true; + delayed_reparse_connection.disconnect(); + if(!selection_dialog.shown) { + delayed_reparse_connection=Glib::signal_timeout().connect([this]() { + clang_readable=false; + parse_thread_go=true; + return false; + }, 1000); + } + type_tooltips.hide(); + diagnostic_tooltips.hide(); }); signal_key_press_event().connect(sigc::mem_fun(*this, &Source::ClangView::on_key_press), false); @@ -263,6 +266,10 @@ init_syntax_highlighting(const std::map file_path, arguments, buffers)); + clang::SourceLocation start(clang_tu.get(), file_path, 0); + clang::SourceLocation end(clang_tu.get(), file_path, buffers.find(file_path)->second.size()-1); + clang::SourceRange range(&start, &end); + clang_tokens=std::unique_ptr(new clang::Tokens(clang_tu.get(), &range)); } std::map Source::ClangView:: @@ -274,7 +281,12 @@ get_buffer_map() const { int Source::ClangView:: reparse(const std::map &buffer) { - return clang_tu->ReparseTranslationUnit(file_path, buffer); + int status = clang_tu->ReparseTranslationUnit(file_path, buffer); + clang::SourceLocation start(clang_tu.get(), file_path, 0); + clang::SourceLocation end(clang_tu.get(), file_path, parse_thread_buffer_map.find(file_path)->second.size()-1); + clang::SourceRange range(&start, &end); + clang_tokens=std::unique_ptr(new clang::Tokens(clang_tu.get(), &range)); + return status; } std::vector Source::ClangView:: @@ -320,13 +332,8 @@ get_compilation_commands() { return arguments; } -std::vector Source::ClangView:: -extract_tokens(int start_offset, int end_offset) { +void Source::ClangView::update_syntax() { std::vector ranges; - clang::SourceLocation start(clang_tu.get(), file_path, start_offset); - clang::SourceLocation end(clang_tu.get(), file_path, end_offset); - clang::SourceRange range(&start, &end); - clang_tokens=std::unique_ptr(new clang::Tokens(clang_tu.get(), &range)); for (auto &token : *clang_tokens) { switch (token.kind()) { case 0: highlight_cursor(&token, &ranges); break; // PunctuationToken @@ -336,10 +343,6 @@ extract_tokens(int start_offset, int end_offset) { case 4: highlight_token(&token, &ranges, 705); break; // CommentToken } } - return ranges; -} - -void Source::ClangView::update_syntax(const std::vector &ranges) { if (ranges.empty() || ranges.size() == 0) { return; } @@ -424,7 +427,7 @@ void Source::ClangView::update_types() { tooltip_buffer->insert_at_cursor("Type: "+(*clang_tokens)[c].type); auto brief_comment=clang_tokens->get_brief_comments(c); if(brief_comment!="") - tooltip_buffer->insert_at_cursor("\n\n"+brief_comment); + tooltip_buffer->insert_at_cursor("\n\n"+brief_comment+"."); return tooltip_buffer; }; @@ -435,8 +438,8 @@ void Source::ClangView::update_types() { } bool Source::ClangView::clangview_on_motion_notify_event(GdkEventMotion* event) { - on_mark_set_timeout_connection.disconnect(); - if(clang_updated) { + delayed_tooltips_connection.disconnect(); + if(clang_readable) { Gdk::Rectangle rectangle(event->x, event->y, 1, 1); diagnostic_tooltips.init(); type_tooltips.show(rectangle); @@ -452,16 +455,16 @@ bool Source::ClangView::clangview_on_motion_notify_event(GdkEventMotion* event) void Source::ClangView::clangview_on_mark_set(const Gtk::TextBuffer::iterator& iterator, const Glib::RefPtr& mark) { if(get_buffer()->get_has_selection() && mark->get_name()=="selection_bound") - on_mark_set_timeout_connection.disconnect(); + delayed_tooltips_connection.disconnect(); if(mark->get_name()=="insert") { - autocomplete_cancel=true; + cancel_show_autocomplete=true; if(selection_dialog.shown) { selection_dialog.hide(); } - on_mark_set_timeout_connection.disconnect(); - on_mark_set_timeout_connection=Glib::signal_timeout().connect([this]() { - if(clang_updated) { + delayed_tooltips_connection.disconnect(); + delayed_tooltips_connection=Glib::signal_timeout().connect([this]() { + if(clang_readable) { Gdk::Rectangle rectangle; get_iter_location(get_buffer()->get_insert()->get_iter(), rectangle); int location_window_x, location_window_y; @@ -481,7 +484,7 @@ void Source::ClangView::clangview_on_mark_set(const Gtk::TextBuffer::iterator& i } bool Source::ClangView::clangview_on_focus_out_event(GdkEventFocus* event) { - on_mark_set_timeout_connection.disconnect(); + delayed_tooltips_connection.disconnect(); type_tooltips.hide(); diagnostic_tooltips.hide(); return false; @@ -491,7 +494,7 @@ bool Source::ClangView::clangview_on_scroll_event(GdkEventScroll* event) { if(selection_dialog.shown) selection_dialog.move(); - on_mark_set_timeout_connection.disconnect(); + delayed_tooltips_connection.disconnect(); type_tooltips.hide(); diagnostic_tooltips.hide(); return false; @@ -570,13 +573,15 @@ bool Source::ClangView::on_key_release(GdkEventKey* key) { } else { return false; } + delayed_reparse_connection.disconnect(); if(!autocomplete_running) { autocomplete_running=true; - autocomplete_cancel=false; + cancel_show_autocomplete=false; INFO("Source::ClangView::on_key_release getting autocompletions"); std::shared_ptr > ac_data=std::make_shared >(); - autocomplete_done_function=[this, ac_data](){ - if(!autocomplete_cancel) { + autocomplete_done_connection.disconnect(); + autocomplete_done_connection=autocomplete_done.connect([this, ac_data](){ + if(!cancel_show_autocomplete) { std::map > rows; for (auto &data : *ac_data) { std::stringstream ss; @@ -602,7 +607,7 @@ bool Source::ClangView::on_key_release(GdkEventKey* key) { selection_dialog.show(); } autocomplete_running=false; - }; + }); std::shared_ptr > buffer_map=std::make_shared >(); (*buffer_map)[file_path]=get_buffer()->get_text(get_buffer()->begin(), get_buffer()->get_insert()->get_iter()); diff --git a/juci/source.h b/juci/source.h index 1cc82de..f9aab45 100644 --- a/juci/source.h +++ b/juci/source.h @@ -96,16 +96,16 @@ namespace Source { clang::Index *index); std::vector get_autocomplete_suggestions(int line_number, int column, std::map& buffer_map); SelectionDialog selection_dialog; + int reparse(const std::map &buffers); - std::vector extract_tokens(int, int); - void update_syntax(const std::vector &locations); + void update_syntax(); void update_diagnostics(); void update_types(); Tooltips diagnostic_tooltips; Tooltips type_tooltips; bool clangview_on_motion_notify_event(GdkEventMotion* event); void clangview_on_mark_set(const Gtk::TextBuffer::iterator& iterator, const Glib::RefPtr& mark); - sigc::connection on_mark_set_timeout_connection; + sigc::connection delayed_tooltips_connection; bool clangview_on_focus_out_event(GdkEventFocus* event); bool clangview_on_scroll_event(GdkEventScroll* event); @@ -115,7 +115,7 @@ namespace Source { std::unique_ptr clang_tu; std::unique_ptr clang_tokens; - bool clang_updated=false; + bool clang_readable=false; void highlight_token(clang::Token *token, std::vector *source_ranges, int token_kind); @@ -125,12 +125,14 @@ namespace Source { bool on_key_press(GdkEventKey* key); bool on_key_release(GdkEventKey* key); Terminal::Controller& terminal; - std::shared_ptr parsing_in_progress; Glib::Dispatcher autocomplete_done; - std::function autocomplete_done_function; + sigc::connection autocomplete_done_connection; + + sigc::connection delayed_reparse_connection; + std::shared_ptr parsing_in_progress; bool autocomplete_running=false; - bool autocomplete_cancel=false; + bool cancel_show_autocomplete=false; Glib::Dispatcher parse_done; Glib::Dispatcher parse_start; std::thread parse_thread;