From 64ce7473ed20c2adc144d64a80b6300dfce38d4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lien=20Sell=C3=A6g?= Date: Fri, 17 Apr 2015 13:01:12 +0200 Subject: [PATCH] juci working auto complete --- juci/notebook.cc | 193 +++++++++++++++++++++++++++++------------------ juci/notebook.h | 25 +++--- juci/source.cc | 16 ++-- juci/source.h | 25 +++++- 4 files changed, 166 insertions(+), 93 deletions(-) diff --git a/juci/notebook.cc b/juci/notebook.cc index b5f437b..bf3ef2b 100644 --- a/juci/notebook.cc +++ b/juci/notebook.cc @@ -1,6 +1,5 @@ #include "notebook.h" #include -#include "clangmm.h" Notebook::Model::Model() { cc_extension_ = ".cc"; @@ -13,7 +12,8 @@ Notebook::View::View() { view_.set_position(120); } -Notebook::Controller::Controller(Gtk::Window& window, Keybindings::Controller& keybindings, +Notebook::Controller::Controller(Gtk::Window& window, + Keybindings::Controller& keybindings, Source::Config& source_cfg, Directories::Config& dir_cfg) : source_config_(source_cfg), @@ -23,8 +23,8 @@ Notebook::Controller::Controller(Gtk::Window& window, Keybindings::Controller& k refClipboard_ = Gtk::Clipboard::get(); ispopup = false; view().pack1(directories_.widget(), true, true); - CreateKeybindings(keybindings); -} // Constructor + CreateKeybindings(keybindings); + } // Constructor void Notebook::Controller::CreateKeybindings(Keybindings::Controller @@ -98,7 +98,7 @@ void Notebook::Controller::CreateKeybindings(Keybindings::Controller [this]() { OnEditPaste(); }); - entry_.view_.entry().signal_activate(). + entry_.view_.entry().signal_activate(). connect( [this]() { if (is_new_file_) { @@ -131,54 +131,103 @@ void Notebook::Controller::CreateKeybindings(Keybindings::Controller }); } -bool Notebook::Controller:: OnMouseRelease(GdkEventButton* button){ - if(button->button == 1 && ispopup){ - popup_.response(Gtk::RESPONSE_DELETE_EVENT); - return true; +bool Notebook::Controller:: OnMouseRelease(GdkEventButton* button) { + if (button->button == 1 && ispopup) { + popup_.response(Gtk::RESPONSE_DELETE_EVENT); + return true; } return false; } -bool Notebook::Controller::OnKeyRelease(GdkEventKey* key){ - if(key->keyval==46){ - return GeneratePopup(); - } - return false; +bool Notebook::Controller::OnKeyRelease(GdkEventKey* key) { + return GeneratePopup(key->keyval); } -bool Notebook::Controller::GeneratePopup(){ +bool Notebook::Controller::GeneratePopup(int key_id) { // Get function to fill popup with suggests item vector under is for testing - std::vector items; - Gtk::TextIter start = CurrentTextView().get_buffer()->get_insert()->get_iter(); - text_vec_.at(CurrentPage())->GetAutoCompleteSuggestions(start.get_line()+1, - start.get_line_offset()+2, - &items); - std::cout << items.size()<< std::endl; - + Gtk::TextIter beg = CurrentTextView().get_buffer()->get_insert()->get_iter(); + Gtk::TextIter end = CurrentTextView().get_buffer()->get_insert()->get_iter(); + Gtk::TextIter tmp = CurrentTextView().get_buffer()->get_insert()->get_iter(); + Gtk::TextIter tmp1 = CurrentTextView().get_buffer()->get_insert()->get_iter(); + Gtk::TextIter line = + CurrentTextView().get_buffer()->get_iter_at_line(tmp.get_line()); + if (end.backward_char() && end.backward_char()) { + bool illegal_chars = + end.backward_search("\"", Gtk::TEXT_SEARCH_VISIBLE_ONLY, tmp, tmp1, line) + || + end.backward_search("//", Gtk::TEXT_SEARCH_VISIBLE_ONLY, tmp, tmp1, line); + if (illegal_chars) { + return false; + } + std::string c = text_vec_[CurrentPage()]->buffer()->get_text(end, beg); + switch (key_id) { + case 46: + break; + case 58: + if (c != "::") return false; + break; + case 60: + if (c != "->") return false; + break; + case 62: + if (c != "->") return false; + break; + default: + return false; + } + } else { + return false; + } + std::vector acdata; + text_vec_.at(CurrentPage())-> + GetAutoCompleteSuggestions(beg.get_line()+1, + beg.get_line_offset()+2, + &acdata); + std::map items; + for (auto &data : acdata) { + std::stringstream ss; + std::string return_value; + for (auto &chunk : data.chunks_) { + switch (chunk.kind()) { + case clang::CompletionChunk_ResultType: + return_value = chunk.chunk(); + break; + case clang::CompletionChunk_Informative: + break; + default: + ss << chunk.chunk(); + break; + } + } + items[ss.str() + " --> " + return_value] = ss.str(); + } // Replace over with get suggestions from zalox! OVER IS JUST FOR TESTING - Gtk::ScrolledWindow popup_scroll_; - Gtk::ListViewText listview_(1,false,Gtk::SelectionMode::SELECTION_SINGLE); - + Gtk::ListViewText listview_(1, false, Gtk::SelectionMode::SELECTION_SINGLE); popup_scroll_.set_policy(Gtk::PolicyType::POLICY_NEVER, - Gtk::PolicyType::POLICY_NEVER); - listview_.set_enable_search(false); + Gtk::PolicyType::POLICY_NEVER); + listview_.set_enable_search(true); listview_.set_headers_visible(false); listview_.set_hscroll_policy(Gtk::ScrollablePolicy::SCROLL_NATURAL); listview_.set_activate_on_single_click(true); - for (auto &i : items) listview_.append(i); - popup_scroll_.add(listview_); + if (items.empty()) { + items["No suggestions found..."] = ""; + } + for (auto &i : items) { + listview_.append(i.first); + } + popup_scroll_.add(listview_); popup_.get_vbox()->pack_start(popup_scroll_); popup_.set_transient_for(*window_); popup_.show_all(); int popup_x = popup_.get_width(); - int popup_y = items.size()*20; - PopupSetSize(popup_scroll_,popup_x,popup_y); - int x,y; - FindPopupPosition(CurrentTextView(),popup_x,popup_y,x,y); + int popup_y = items.size() * 20; + PopupSetSize(popup_scroll_, popup_x, popup_y); + int x, y; + FindPopupPosition(CurrentTextView(), popup_x, popup_y, x, y); popup_.move(x, y+15); - PopupSelectHandler(popup_, listview_); + PopupSelectHandler(popup_, listview_, &items); ispopup = true; popup_.run(); popup_.hide(); @@ -232,9 +281,7 @@ void Notebook::Controller::OnOpenFile(std::string path) { unsigned pos = path.find_last_of("/\\"); Notebook().append_page(*editor_vec_.back(), path.substr(pos+1)); Notebook().show_all_children(); - std::cout << "setting current page"<< std::endl; Notebook().set_current_page(Pages()-1); - std::cout << "current page set" << std::endl; Notebook().set_focus_child(text_vec_.back()->view()); OnBufferChange(); } @@ -431,37 +478,37 @@ Gtk::Notebook& Notebook::Controller::Notebook() { void Notebook::Controller::TextViewHandlers(Gtk::TextView& textview) { textview.get_buffer()->signal_changed().connect( - [this]() { - OnBufferChange(); - }); + [this]() { + OnBufferChange(); + }); textview.signal_button_release_event(). - connect(sigc::mem_fun(*this,&Notebook::Controller::OnMouseRelease),false); + connect(sigc::mem_fun(*this, &Notebook::Controller::OnMouseRelease), false); textview.signal_key_release_event(). - connect(sigc::mem_fun(*this,&Notebook::Controller::OnKeyRelease),false); - - + connect(sigc::mem_fun(*this, &Notebook::Controller::OnKeyRelease), false); } + void Notebook::Controller::PopupSelectHandler(Gtk::Dialog &popup, - Gtk::ListViewText &listview){ + Gtk::ListViewText &listview, + std::map + *items) { listview.signal_row_activated(). - connect([this, &listview, &popup](const Gtk::TreeModel::Path& path, - Gtk::TreeViewColumn*) { - std::string selected = - listview.get_text(listview.get_selected()[0]); - CurrentTextView().get_buffer()->insert_at_cursor(selected); - popup.response(Gtk::RESPONSE_DELETE_EVENT); - }); + connect([this, &listview, &popup, items](const Gtk::TreeModel::Path& path, + Gtk::TreeViewColumn*) { + std::string selected = items-> + at(listview.get_text(listview.get_selected()[0])); + CurrentTextView().get_buffer()->insert_at_cursor(selected); + popup.response(Gtk::RESPONSE_DELETE_EVENT); + }); } void Notebook::Controller::PopupSetSize(Gtk::ScrolledWindow &scroll, - int ¤t_x, - int ¤t_y) { + int ¤t_x, + int ¤t_y) { int textview_x = CurrentTextView().get_width(); int textview_y = 150; bool is_never_scroll_x = true; bool is_never_scroll_y = true; - std::cout << textview_x << std::endl; if (current_x > textview_x) { current_x = textview_x; is_never_scroll_x = false; @@ -470,36 +517,36 @@ void Notebook::Controller::PopupSetSize(Gtk::ScrolledWindow &scroll, current_y = textview_y; is_never_scroll_y = false; } - scroll.set_size_request(current_x,current_y); + scroll.set_size_request(current_x, current_y); if (!is_never_scroll_x && !is_never_scroll_y) { scroll.set_policy(Gtk::PolicyType::POLICY_AUTOMATIC, - Gtk::PolicyType::POLICY_AUTOMATIC); + Gtk::PolicyType::POLICY_AUTOMATIC); } else if (!is_never_scroll_x && is_never_scroll_y) { scroll.set_policy(Gtk::PolicyType::POLICY_AUTOMATIC, - Gtk::PolicyType::POLICY_NEVER); + Gtk::PolicyType::POLICY_NEVER); } else if (is_never_scroll_x && !is_never_scroll_y) { scroll.set_policy(Gtk::PolicyType::POLICY_NEVER, - Gtk::PolicyType::POLICY_AUTOMATIC); + Gtk::PolicyType::POLICY_AUTOMATIC); } } void Notebook::Controller::FindPopupPosition(Gtk::TextView& textview, - int popup_x, - int popup_y, - int &x, - int &y){ + int popup_x, + int popup_y, + int &x, + int &y) { Gdk::Rectangle temp1, temp2; textview.get_cursor_locations( - CurrentTextView(). - get_buffer()->get_insert()-> - get_iter(), temp1,temp2); + CurrentTextView(). + get_buffer()->get_insert()-> + get_iter(), temp1, temp2); int textview_edge_x = 0; int textview_edge_y = 0; textview.buffer_to_window_coords( - Gtk::TextWindowType::TEXT_WINDOW_WIDGET, - temp1.get_x(), - temp1.get_y(), - x, y); + Gtk::TextWindowType::TEXT_WINDOW_WIDGET, + temp1.get_x(), + temp1.get_y(), + x, y); Glib::RefPtr gdkw = CurrentTextView().get_window(Gtk::TextWindowType::TEXT_WINDOW_WIDGET); gdkw->get_origin(textview_edge_x, textview_edge_y); @@ -508,17 +555,17 @@ void Notebook::Controller::FindPopupPosition(Gtk::TextView& textview, y+=textview_edge_y; if ((textview_edge_x-x)*-1 > textview.get_width()-popup_x) { x -= popup_x; - if(x textview.get_height()-popup_y) { y -= (popup_y+14) + 15; - if(xget_text(); file.close(); } diff --git a/juci/notebook.h b/juci/notebook.h index 5eac6b0..ccab51b 100644 --- a/juci/notebook.h +++ b/juci/notebook.h @@ -8,6 +8,7 @@ #include "directories.h" #include #include +#include #include namespace Notebook { @@ -57,27 +58,31 @@ namespace Notebook { void OnCreatePage(); bool ScrollEventCallback(GdkEventScroll* scroll_event); int Pages(); - Directories::Controller& directories() { return directories_; } + Directories::Controller& directories() { return directories_; } Gtk::Paned& view(); - bool GeneratePopup(); + bool GeneratePopup(int key); void Search(bool forward); const Source::Config& source_config() { return source_config_; } bool OnMouseRelease(GdkEventButton* button); bool OnKeyRelease(GdkEventKey* key); + protected: void TextViewHandlers(Gtk::TextView& textview); void PopupSelectHandler(Gtk::Dialog &popup, - Gtk::ListViewText &listview); - private: + Gtk::ListViewText &listview, + std::map + *items); + + private: void CreateKeybindings(Keybindings::Controller& keybindings); void FindPopupPosition(Gtk::TextView& textview, - int popup_x, - int popup_y, - int &x, - int &y); + int popup_x, + int popup_y, + int &x, + int &y); void PopupSetSize(Gtk::ScrolledWindow& scroll, - int ¤t_x, - int ¤t_y); + int ¤t_x, + int ¤t_y); Glib::RefPtr m_refBuilder; Glib::RefPtr refActionGroup; Source::Config source_config_; diff --git a/juci/source.cc b/juci/source.cc index baec800..5210541 100644 --- a/juci/source.cc +++ b/juci/source.cc @@ -135,7 +135,8 @@ void Source::Controller::OnLineEdit() { } void Source::Controller:: GetAutoCompleteSuggestions(int line_number, int column, - std::vector *suggestions) { + std::vector + *suggestions) { parsing.lock(); model().GetAutoCompleteSuggestions(view().get_buffer() ->get_text().raw(), @@ -149,19 +150,20 @@ void Source::Model:: GetAutoCompleteSuggestions(const std::string& buffer, int line_number, int column, - std::vector *suggestions) { + std::vector + *suggestions) { clang::CodeCompleteResults results(&tu_, file_path(), buffer, line_number, column); for (int i = 0; i < results.size(); i++) { - std::stringstream ss; - const vector c = results.get(i).get_chunks(); - for (auto &stringchunk : c) { - ss << stringchunk.chunk(); + const vector chunks_ = results.get(i).get_chunks(); + std::vector chunks; + for (auto &chunk : chunks_) { + chunks.emplace_back(chunk); } - suggestions->emplace_back(ss.str()); + suggestions->emplace_back(chunks); } } diff --git a/juci/source.h b/juci/source.h index 8450807..cf8789a 100644 --- a/juci/source.h +++ b/juci/source.h @@ -74,6 +74,24 @@ namespace Source { string GetLine(const Gtk::TextIter &begin); }; // class View + class AutoCompleteChunk { + public: + explicit AutoCompleteChunk(const clang::CompletionChunk &chunk) : + chunk_(chunk.chunk()), kind_(chunk.kind()) { } + const std::string& chunk() const { return chunk_; } + const clang::CompletionChunkKind& kind() const { return kind_; } + private: + std::string chunk_; + enum clang::CompletionChunkKind kind_; + }; + + class AutoCompleteData { + public: + explicit AutoCompleteData(const std::vector &chunks) : + chunks_(chunks) { } + std::vector chunks_; + }; + class Model{ public: // constructor for Source::Model @@ -98,7 +116,8 @@ namespace Source { void GetAutoCompleteSuggestions(const std::string& buffer, int line_number, int column, - std::vector *suggestions); + std::vector + *suggestions); ~Model() { } int ReParse(const std::string &buffer); std::vector ExtractTokens(int, int); @@ -113,7 +132,6 @@ namespace Source { int token_kind); void HighlightCursor(clang::Token *token, std::vector *source_ranges); - std::vector get_compilation_commands(); }; @@ -127,7 +145,8 @@ namespace Source { void OnOpenFile(const string &filename); void GetAutoCompleteSuggestions(int line_number, int column, - std::vector *suggestions); + std::vector + *suggestions); Glib::RefPtr buffer(); private: