From eb13a7e81fc1c2084ea5c580d7ffcd2b62077697 Mon Sep 17 00:00:00 2001 From: eidheim Date: Sun, 15 Nov 2015 13:30:20 +0100 Subject: [PATCH] Added Go to Usage, and fixed #82 by removing the directory ignore option. This also makes implementing git integration easier. --- src/config.cc | 13 -------- src/config.h | 8 ----- src/directories.cc | 71 ++++++++++++++++------------------------- src/directories.h | 1 - src/files.h | 9 ++---- src/menu.cc | 5 +++ src/source.h | 12 +++++-- src/source_clang.cc | 28 +++++++++++++--- src/source_clang.h | 1 - src/window.cc | 78 ++++++++++++++++++++++++++++++++++++++++++--- 10 files changed, 142 insertions(+), 84 deletions(-) diff --git a/src/config.cc b/src/config.cc index 094d57e..2f7ea47 100644 --- a/src/config.cc +++ b/src/config.cc @@ -81,7 +81,6 @@ void Config::retrieve_config() { menu.keys[i.first] = i.second.get_value(); } get_source(); - get_directory_filter(); window.theme_name=cfg.get("gtk_theme.name"); window.theme_variant=cfg.get("gtk_theme.variant"); @@ -188,15 +187,3 @@ void Config::get_source() { } } } - -void Config::get_directory_filter() { - boost::property_tree::ptree dir_json = cfg.get_child("directoryfilter"); - boost::property_tree::ptree ignore_json = dir_json.get_child("ignore"); - boost::property_tree::ptree except_json = dir_json.get_child("exceptions"); - directories.exceptions.clear(); - directories.ignored.clear(); - for ( auto &i : except_json ) - directories.exceptions.emplace_back(i.second.get_value()); - for ( auto &i : ignore_json ) - directories.ignored.emplace_back(i.second.get_value()); -} diff --git a/src/config.h b/src/config.h index 0bfb91d..99e398e 100644 --- a/src/config.h +++ b/src/config.h @@ -31,12 +31,6 @@ public: int history_size; }; - class Directories { - public: - std::vector ignored; - std::vector exceptions; - }; - class Source { public: class DocumentationSearch { @@ -72,7 +66,6 @@ public: Menu menu; Window window; Terminal terminal; - Directories directories; Source source; const boost::filesystem::path& juci_home_path() const { return home; } @@ -83,7 +76,6 @@ private: bool check_config_file(const boost::property_tree::ptree &default_cfg, std::string parent_path=""); void update_config_file(); void get_source(); - void get_directory_filter(); boost::property_tree::ptree cfg; boost::filesystem::path home; diff --git a/src/directories.cc b/src/directories.cc index 14d774f..6075578 100644 --- a/src/directories.cc +++ b/src/directories.cc @@ -197,21 +197,6 @@ void Directories::select(const boost::filesystem::path &path) { JDEBUG("end"); } -bool Directories::ignored(std::string path) { - std::transform(path.begin(), path.end(), path.begin(), ::tolower); - - for(std::string &i : Singleton::config->directories.exceptions) { - if(i == path) - return false; - } - for(auto &i : Singleton::config->directories.ignored) { - if(path.find(i, 0) != std::string::npos) - return true; - } - - return false; -} - void Directories::add_path(const boost::filesystem::path& dir_path, const Gtk::TreeModel::Row &parent) { last_write_times[dir_path.string()]={parent, boost::filesystem::last_write_time(dir_path)}; std::unique_ptr children; //Gtk::TreeNodeChildren is missing default constructor... @@ -227,39 +212,37 @@ void Directories::add_path(const boost::filesystem::path& dir_path, const Gtk::T boost::filesystem::directory_iterator end_it; for(boost::filesystem::directory_iterator it(dir_path);it!=end_it;it++) { auto filename=it->path().filename().string(); - if (!ignored(filename)) { - bool already_added=false; - if(*children) { - for(auto &child: *children) { - if(child.get_value(column_record.name)==filename) { - not_deleted.emplace(filename); - already_added=true; - break; - } + bool already_added=false; + if(*children) { + for(auto &child: *children) { + if(child.get_value(column_record.name)==filename) { + not_deleted.emplace(filename); + already_added=true; + break; } } - if(!already_added) { - auto child = tree_store->append(*children); - not_deleted.emplace(filename); - child->set_value(column_record.name, filename); - child->set_value(column_record.path, it->path().string()); - if (boost::filesystem::is_directory(*it)) { - child->set_value(column_record.id, "a"+filename); - auto grandchild=tree_store->append(child->children()); - grandchild->set_value(column_record.name, std::string("(empty)")); + } + if(!already_added) { + auto child = tree_store->append(*children); + not_deleted.emplace(filename); + child->set_value(column_record.name, filename); + child->set_value(column_record.path, it->path().string()); + if (boost::filesystem::is_directory(*it)) { + child->set_value(column_record.id, "a"+filename); + auto grandchild=tree_store->append(child->children()); + grandchild->set_value(column_record.name, std::string("(empty)")); + Gdk::RGBA rgba; + rgba.set_rgba(0.5, 0.5, 0.5); + grandchild->set_value(column_record.color, rgba); + } + else { + child->set_value(column_record.id, "b"+filename); + + auto language=Source::guess_language(it->path().filename()); + if(!language) { Gdk::RGBA rgba; rgba.set_rgba(0.5, 0.5, 0.5); - grandchild->set_value(column_record.color, rgba); - } - else { - child->set_value(column_record.id, "b"+filename); - - auto language=Source::guess_language(it->path().filename()); - if(!language) { - Gdk::RGBA rgba; - rgba.set_rgba(0.5, 0.5, 0.5); - child->set_value(column_record.color, rgba); - } + child->set_value(column_record.color, rgba); } } } diff --git a/src/directories.h b/src/directories.h index 62ef8cd..9435504 100644 --- a/src/directories.h +++ b/src/directories.h @@ -38,7 +38,6 @@ public: private: void add_path(const boost::filesystem::path& dir_path, const Gtk::TreeModel::Row &row); - bool ignored(std::string path); Gtk::TreeView tree_view; Glib::RefPtr tree_store; ColumnRecord column_record; diff --git a/src/files.h b/src/files.h index a14f680..dc6e635 100644 --- a/src/files.h +++ b/src/files.h @@ -1,6 +1,6 @@ #include -#define JUCI_VERSION "0.9.5" +#define JUCI_VERSION "0.9.6" const std::string configjson = "{\n" @@ -85,6 +85,7 @@ const std::string configjson = " \"source_center_cursor\": \"l\",\n" " \"source_find_documentation\": \"d\",\n" " \"source_goto_declaration\": \"d\",\n" +" \"source_goto_usage\": \"u\",\n" " \"source_goto_method\": \"m\",\n" " \"source_rename\": \"r\",\n" " \"source_goto_next_diagnostic\": \"e\",\n" @@ -117,12 +118,6 @@ const std::string configjson = " \"@any\": \"https://www.google.com/search?btnI&q=\"\n" " }\n" " }\n" -" },\n" -" \"directoryfilter\": {\n" -" \"ignore\": [\n" -" ],\n" -" \"exceptions\": [\n" -" ]\n" " }\n" "}\n"; diff --git a/src/menu.cc b/src/menu.cc index 735882a..60b8e9c 100644 --- a/src/menu.cc +++ b/src/menu.cc @@ -211,6 +211,11 @@ void Menu::init() { +accels["source_goto_declaration"]+ //For Ubuntu... " " " " + " _Go to Usage" + " app.source_goto_usage" + +accels["source_goto_usage"]+ //For Ubuntu... + " " + " " " _Go to Method" " app.source_goto_method" +accels["source_goto_method"]+ //For Ubuntu... diff --git a/src/source.h b/src/source.h index 9de045a..9553ae0 100644 --- a/src/source.h +++ b/src/source.h @@ -19,6 +19,10 @@ namespace Source { Token(Glib::RefPtr language, int type, const std::string &spelling, const std::string &usr): language(language), type(type), spelling(spelling), usr(usr) {} operator bool() const {return (type>=0 && spelling.size()>0 && usr.size()>0);} + bool operator==(const Token &o) const {return (type==o.type && + spelling==o.spelling && + usr==o.usr);} + bool operator!=(const Token &o) const {return !(*this==o);} Glib::RefPtr language; int type; @@ -29,11 +33,12 @@ namespace Source { class Offset { public: Offset() {} - Offset(unsigned line, unsigned index): line(line), index(index) {} + Offset(unsigned line, unsigned index, const boost::filesystem::path &file_path=""): line(line), index(index), file_path(file_path) {} bool operator==(const Offset &o) {return (line==o.line && index==o.index);} unsigned line; unsigned index; + boost::filesystem::path file_path; }; class FixIt { @@ -71,7 +76,8 @@ namespace Source { Glib::RefPtr language; std::function auto_indent; - std::function()> get_declaration_location; + std::function get_declaration_location; + std::function >(const Token &token)> get_usages; std::function goto_method; std::function get_token; std::function()> get_token_data; @@ -79,6 +85,8 @@ namespace Source { std::function goto_next_diagnostic; std::function apply_fix_its; + std::unique_ptr selection_dialog; + std::function on_update_status; std::function on_update_info; void set_status(const std::string &status); diff --git a/src/source_clang.cc b/src/source_clang.cc index fdf1d9c..e7eb612 100644 --- a/src/source_clang.cc +++ b/src/source_clang.cc @@ -1028,7 +1028,7 @@ Source::ClangViewAutocomplete(file_path, project_path, language) { }); get_declaration_location=[this](){ - std::pair location; + Offset location; if(source_readable) { auto iter=get_buffer()->get_insert()->get_iter(); auto line=(unsigned)iter.get_line(); @@ -1039,10 +1039,10 @@ Source::ClangViewAutocomplete(file_path, project_path, language) { if(line==token.offsets.first.line-1 && index>=token.offsets.first.index-1 && index <=token.offsets.second.index-1) { auto referenced=cursor.get_referenced(); if(referenced) { - location.first=referenced.get_source_location().get_path(); + location.file_path=referenced.get_source_location().get_path(); auto clang_offset=referenced.get_source_location().get_offset(); - location.second.line=clang_offset.line; - location.second.index=clang_offset.index; + location.line=clang_offset.line; + location.index=clang_offset.index; break; } } @@ -1052,6 +1052,26 @@ Source::ClangViewAutocomplete(file_path, project_path, language) { return location; }; + get_usages=[this](const Token &token) { + std::vector > usages; + + if(source_readable && 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) { + auto start_iter=get_buffer()->get_iter_at_line(offset.first.line-1); + while(!start_iter.ends_line() && (*start_iter==' ' || *start_iter=='\t')) + start_iter.forward_char(); + auto end_iter=start_iter; + while(!end_iter.ends_line()) + end_iter.forward_char(); + usages.emplace_back(Offset(offset.first.line-1, offset.first.index-1, this->file_path), get_buffer()->get_text(start_iter, end_iter)); + } + } + + return usages; + }; + goto_method=[this](){ if(source_readable) { auto iter=get_buffer()->get_insert()->get_iter(); diff --git a/src/source_clang.h b/src/source_clang.h index 20c8214..9af7a01 100644 --- a/src/source_clang.h +++ b/src/source_clang.h @@ -121,7 +121,6 @@ namespace Source { void tag_similar_tokens(const Token &token); Glib::RefPtr similar_tokens_tag; Token last_tagged_token; - std::unique_ptr selection_dialog; bool renaming=false; }; diff --git a/src/window.cc b/src/window.cc index e61cba7..4e09a74 100644 --- a/src/window.cc +++ b/src/window.cc @@ -382,10 +382,15 @@ void Window::set_menu_actions() { if(notebook.get_current_page()!=-1) { if(notebook.get_current_view()->get_declaration_location) { auto location=notebook.get_current_view()->get_declaration_location(); - if(location.first.size()>0) { - notebook.open(location.first); - auto line=static_cast(location.second.line)-1; - auto index=static_cast(location.second.index)-1; + if(!location.file_path.empty()) { + boost::filesystem::path declaration_file; + boost::system::error_code ec; + declaration_file=boost::filesystem::canonical(location.file_path, ec); + if(ec) + declaration_file=location.file_path; + notebook.open(declaration_file); + auto line=static_cast(location.line)-1; + auto index=static_cast(location.index)-1; auto buffer=notebook.get_current_view()->get_buffer(); line=std::min(line, buffer->get_line_count()-1); if(line>=0) { @@ -405,6 +410,71 @@ void Window::set_menu_actions() { } } }); + menu->add_action("source_goto_usage", [this]() { + if(notebook.get_current_page()!=-1) { + auto current_view=notebook.get_current_view(); + if(current_view->get_token && current_view->get_usages) { + auto token=current_view->get_token(); + if(token) { + auto iter=current_view->get_buffer()->get_insert()->get_iter(); + Gdk::Rectangle visible_rect; + current_view->get_visible_rect(visible_rect); + Gdk::Rectangle iter_rect; + current_view->get_iter_location(iter, iter_rect); + iter_rect.set_width(1); + if(!visible_rect.intersects(iter_rect)) { + current_view->get_iter_at_location(iter, 0, visible_rect.get_y()+visible_rect.get_height()/3); + } + current_view->selection_dialog=std::unique_ptr(new SelectionDialog(*current_view, current_view->get_buffer()->create_mark(iter))); + auto rows=std::make_shared >(); + + //First add usages in current file + auto usages=current_view->get_usages(token); + for(auto &usage: usages) { + auto iter=current_view->get_buffer()->get_iter_at_line_index(usage.first.line, usage.first.index); + auto row=std::to_string(iter.get_line()+1)+':'+std::to_string(iter.get_line_offset()+1)+' '+usage.second; + (*rows)[row]=usage.first; + current_view->selection_dialog->add_row(row); + } + //Then the remaining opened files + for(int page=0;pageget_usages) { + auto usages=view->get_usages(token); + for(auto &usage: usages) { + auto iter=view->get_buffer()->get_iter_at_line_index(usage.first.line, usage.first.index); + auto row=usage.first.file_path.filename().string()+":"+std::to_string(iter.get_line()+1)+':'+std::to_string(iter.get_line_offset()+1)+' '+usage.second; + (*rows)[row]=usage.first; + current_view->selection_dialog->add_row(row); + } + } + } + } + + if(rows->size()==0) + return; + current_view->selection_dialog->on_select=[this, rows](const std::string& selected, bool hide_window) { + auto offset=rows->at(selected); + boost::filesystem::path declaration_file; + boost::system::error_code ec; + declaration_file=boost::filesystem::canonical(offset.file_path, ec); + if(ec) + declaration_file=offset.file_path; + notebook.open(declaration_file); + auto view=notebook.get_current_view(); + view->get_buffer()->place_cursor(view->get_buffer()->get_iter_at_line_index(offset.line, offset.index)); + while(g_main_context_pending(NULL)) + g_main_context_iteration(NULL, false); + if(notebook.get_current_page()!=-1) + view->scroll_to(view->get_buffer()->get_insert(), 0.0, 1.0, 0.5); + //delayed_tooltips_connection.disconnect(); + }; + current_view->selection_dialog->show(); + } + } + } + }); menu->add_action("source_goto_method", [this]() { if(notebook.get_current_page()!=-1) { if(notebook.get_current_view()->goto_method) {