Browse Source

Added autocomplete in current namespace for clangview. Autocomplete currently starts after 3 characters. Will try to clean up this code soon.

merge-requests/365/head
eidheim 11 years ago
parent
commit
4e38ef8760
  1. 127
      juci/source.cc
  2. 15
      juci/source.h

127
juci/source.cc

@ -234,10 +234,7 @@ parse_thread_go(true), parse_thread_mapped(false), parse_thread_stop(false) {
diagnostic_tooltips.hide(); diagnostic_tooltips.hide();
}); });
signal_motion_notify_event().connect(sigc::mem_fun(*this, &Source::ClangView::clangview_on_motion_notify_event), false); get_buffer()->signal_mark_set().connect(sigc::mem_fun(*this, &Source::ClangView::on_mark_set), false);
signal_focus_out_event().connect(sigc::mem_fun(*this, &Source::ClangView::clangview_on_focus_out_event), false);
signal_scroll_event().connect(sigc::mem_fun(*this, &Source::ClangView::clangview_on_scroll_event), false);
get_buffer()->signal_mark_set().connect(sigc::mem_fun(*this, &Source::ClangView::clangview_on_mark_set), false);
} }
Source::ClangView::~ClangView() { Source::ClangView::~ClangView() {
@ -406,7 +403,7 @@ void Source::ClangView::update_types() {
} }
} }
bool Source::ClangView::clangview_on_motion_notify_event(GdkEventMotion* event) { bool Source::ClangView::on_motion_notify_event(GdkEventMotion* event) {
delayed_tooltips_connection.disconnect(); delayed_tooltips_connection.disconnect();
if(clang_readable) { if(clang_readable) {
Gdk::Rectangle rectangle(event->x, event->y, 1, 1); Gdk::Rectangle rectangle(event->x, event->y, 1, 1);
@ -419,10 +416,10 @@ bool Source::ClangView::clangview_on_motion_notify_event(GdkEventMotion* event)
diagnostic_tooltips.hide(); diagnostic_tooltips.hide();
} }
return false; return Source::View::on_motion_notify_event(event);
} }
void Source::ClangView::clangview_on_mark_set(const Gtk::TextBuffer::iterator& iterator, const Glib::RefPtr<Gtk::TextBuffer::Mark>& mark) { void Source::ClangView::on_mark_set(const Gtk::TextBuffer::iterator& iterator, const Glib::RefPtr<Gtk::TextBuffer::Mark>& mark) {
if(get_buffer()->get_has_selection() && mark->get_name()=="selection_bound") if(get_buffer()->get_has_selection() && mark->get_name()=="selection_bound")
delayed_tooltips_connection.disconnect(); delayed_tooltips_connection.disconnect();
@ -448,18 +445,18 @@ void Source::ClangView::clangview_on_mark_set(const Gtk::TextBuffer::iterator& i
} }
} }
bool Source::ClangView::clangview_on_focus_out_event(GdkEventFocus* event) { bool Source::ClangView::on_focus_out_event(GdkEventFocus* event) {
delayed_tooltips_connection.disconnect(); delayed_tooltips_connection.disconnect();
type_tooltips.hide(); type_tooltips.hide();
diagnostic_tooltips.hide(); diagnostic_tooltips.hide();
return false; return Source::View::on_focus_out_event(event);
} }
bool Source::ClangView::clangview_on_scroll_event(GdkEventScroll* event) { bool Source::ClangView::on_scroll_event(GdkEventScroll* event) {
delayed_tooltips_connection.disconnect(); delayed_tooltips_connection.disconnect();
type_tooltips.hide(); type_tooltips.hide();
diagnostic_tooltips.hide(); diagnostic_tooltips.hide();
return false; return Source::View::on_scroll_event(event);
} }
void Source::ClangView:: void Source::ClangView::
@ -587,33 +584,46 @@ 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::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) { Source::ClangView(file_path, project_path, terminal), selection_dialog(*this) {
get_buffer()->signal_changed().connect([this](){ get_buffer()->signal_changed().connect([this](){
if(!selection_dialog.shown) { std::string line=" "+get_line_before_insert();
auto insert=get_buffer()->get_insert(); if((std::count(line.begin(), line.end(), '\"')%2)!=1 && line.find("//")==std::string::npos) {
auto iter=insert->get_iter(); const std::regex in_specified_namespace("^(.*)(->|\\.|::)([a-zA-Z0-9_]*)$");
int line_nr=iter.get_line(); const std::regex within_namespace("^(.*)([^a-zA-Z0-9_]+)([a-zA-Z_][a-zA-Z0-9_]{2,})$");
auto line_iter=get_buffer()->get_iter_at_line(line_nr);
std::string line=get_buffer()->get_text(line_iter, iter);
const std::regex method("^(.*)(->|\\.|::)([a-zA-Z0-9_]*)$");
std::smatch sm; std::smatch sm;
if(std::regex_match(line, sm, method)) { if(std::regex_match(line, sm, in_specified_namespace)) {
if(sm[1].str().find("//")==std::string::npos) { if(last_keyval=='.' || last_keyval=='>' || last_keyval==':') {
if(last_keyval=='.' || last_keyval=='>' || last_keyval==':') { if(sm[3]=="" && !autocomplete_starting && !selection_dialog.shown) {
if(sm[3]=="" && !autocomplete_running) { prefix="";
start_autocomplete(); autocomplete();
}
} }
else if(autocomplete_starting)
autocomplete_cancel_starting=true;
}
}
else if(std::regex_match(line, sm, within_namespace)) {
prefix=sm[3].str();
if((last_keyval>='a' && last_keyval<='z') || (last_keyval>='A' && last_keyval<='Z') || (last_keyval>='0' && last_keyval<='9') || last_keyval=='_') {
if(!autocomplete_starting && !selection_dialog.shown) {
autocomplete();
}
}
else if(last_keyval!=0) {
autocomplete_cancel_starting=true;
if(selection_dialog.shown)
selection_dialog.hide();
} }
} }
else if(autocomplete_running) else if(last_keyval!=0) {
cancel_show_autocomplete=true; autocomplete_cancel_starting=true;
if(selection_dialog.shown)
selection_dialog.hide();
}
if(autocomplete_starting || selection_dialog.shown)
delayed_reparse_connection.disconnect();
} }
if(autocomplete_running || selection_dialog.shown)
delayed_reparse_connection.disconnect();
}); });
get_buffer()->signal_mark_set().connect([this](const Gtk::TextBuffer::iterator& iterator, const Glib::RefPtr<Gtk::TextBuffer::Mark>& mark){ get_buffer()->signal_mark_set().connect([this](const Gtk::TextBuffer::iterator& iterator, const Glib::RefPtr<Gtk::TextBuffer::Mark>& mark){
if(mark->get_name()=="insert") { if(mark->get_name()=="insert") {
cancel_show_autocomplete=true; autocomplete_cancel_starting=true;
if(selection_dialog.shown) { if(selection_dialog.shown) {
selection_dialog.hide(); selection_dialog.hide();
} }
@ -635,6 +645,7 @@ Source::ClangView(file_path, project_path, terminal), selection_dialog(*this) {
} }
bool Source::ClangViewAutocomplete::on_key_press_event(GdkEventKey *key) { bool Source::ClangViewAutocomplete::on_key_press_event(GdkEventKey *key) {
last_keyval=0;
if(selection_dialog.shown) { if(selection_dialog.shown) {
delayed_reparse_connection.disconnect(); delayed_reparse_connection.disconnect();
if(selection_dialog.on_key_press(key)) if(selection_dialog.on_key_press(key))
@ -643,18 +654,30 @@ bool Source::ClangViewAutocomplete::on_key_press_event(GdkEventKey *key) {
last_keyval=key->keyval; last_keyval=key->keyval;
return ClangView::on_key_press_event(key); return ClangView::on_key_press_event(key);
} }
void Source::ClangViewAutocomplete::start_autocomplete() { void Source::ClangViewAutocomplete::autocomplete() {
if(!autocomplete_running) { if(!autocomplete_starting) {
autocomplete_running=true; autocomplete_starting=true;
cancel_show_autocomplete=false; autocomplete_cancel_starting=false;
if(prefix.size()==0) {
if(selection_dialog.start_mark)
get_buffer()->delete_mark(selection_dialog.start_mark);
auto start_iter=get_buffer()->get_insert()->get_iter();
selection_dialog.start_mark=get_buffer()->create_mark(start_iter);
}
INFO("Source::ClangView::on_key_release getting autocompletions"); INFO("Source::ClangView::on_key_release getting autocompletions");
std::shared_ptr<std::vector<Source::AutoCompleteData> > ac_data=std::make_shared<std::vector<Source::AutoCompleteData> >(); std::shared_ptr<std::vector<Source::AutoCompleteData> > ac_data=std::make_shared<std::vector<Source::AutoCompleteData> >();
if(selection_dialog.start_mark)
get_buffer()->delete_mark(selection_dialog.start_mark);
selection_dialog.start_mark=get_buffer()->create_mark(get_buffer()->get_insert()->get_iter());
autocomplete_done_connection.disconnect(); autocomplete_done_connection.disconnect();
autocomplete_done_connection=autocomplete_done.connect([this, ac_data](){ autocomplete_done_connection=autocomplete_done.connect([this, ac_data](){
if(!cancel_show_autocomplete) { if(!autocomplete_cancel_starting) {
if(prefix.size()>0) {
if(selection_dialog.start_mark)
get_buffer()->delete_mark(selection_dialog.start_mark);
auto start_iter=get_buffer()->get_insert()->get_iter();
for(size_t c=0;c<prefix.size();c++)
start_iter--;
selection_dialog.start_mark=get_buffer()->create_mark(start_iter);
}
std::map<std::string, std::pair<std::string, std::string> > rows; std::map<std::string, std::pair<std::string, std::string> > rows;
for (auto &data : *ac_data) { for (auto &data : *ac_data) {
std::stringstream ss; std::stringstream ss;
@ -669,8 +692,10 @@ void Source::ClangViewAutocomplete::start_autocomplete() {
} }
} }
if (ss.str().length() > 0) { // if length is 0 the result is empty if (ss.str().length() > 0) { // if length is 0 the result is empty
auto pair=std::pair<std::string, std::string>(ss.str(), data.brief_comments); if(prefix.size()==0 || ss.str().find(prefix)==0) {
rows[ss.str() + " --> " + return_value] = pair; auto pair=std::pair<std::string, std::string>(ss.str(), data.brief_comments);
rows[ss.str() + " --> " + return_value] = pair;
}
} }
} }
if (rows.empty()) { if (rows.empty()) {
@ -679,18 +704,24 @@ void Source::ClangViewAutocomplete::start_autocomplete() {
selection_dialog.rows=std::move(rows); selection_dialog.rows=std::move(rows);
selection_dialog.show(); selection_dialog.show();
} }
autocomplete_running=false; autocomplete_starting=false;
}); });
std::shared_ptr<std::map<std::string, std::string> > buffer_map=std::make_shared<std::map<std::string, std::string> >(); std::shared_ptr<std::map<std::string, std::string> > buffer_map=std::make_shared<std::map<std::string, std::string> >();
(*buffer_map)[this->file_path]=get_buffer()->get_text(get_buffer()->begin(), get_buffer()->get_insert()->get_iter()); auto& buffer=(*buffer_map)[this->file_path];
(*buffer_map)[this->file_path]+="\n"; buffer=get_buffer()->get_text(get_buffer()->begin(), get_buffer()->get_insert()->get_iter());
auto iter = get_source_buffer()->get_insert()->get_iter(); auto iter = get_source_buffer()->get_insert()->get_iter();
auto line_nr=iter.get_line()+1; auto line_nr=iter.get_line()+1;
auto column_nr=iter.get_line_offset()+2; auto column_nr=iter.get_line_offset()+1;
while((buffer.back()>='a' && buffer.back()<='z') || (buffer.back()>='A' && buffer.back()<='Z') || (buffer.back()>='0' && buffer.back()<='9') || buffer.back()=='_') {
buffer.pop_back();
column_nr--;
}
buffer+="\n";
std::thread autocomplete_thread([this, ac_data, line_nr, column_nr, buffer_map](){ std::thread autocomplete_thread([this, ac_data, line_nr, column_nr, buffer_map](){
parsing_mutex.lock(); parsing_mutex.lock();
*ac_data=move(get_autocomplete_suggestions(line_nr, column_nr, *buffer_map)); *ac_data=move(get_autocomplete_suggestions(line_nr, column_nr, *buffer_map));
cout << "selection size: " << ac_data->size() << endl;
autocomplete_done(); autocomplete_done();
parsing_mutex.unlock(); parsing_mutex.unlock();
}); });
@ -707,11 +738,13 @@ get_autocomplete_suggestions(int line_number, int column, std::map<std::string,
file_path, file_path,
buffer_map, buffer_map,
line_number, line_number,
column-1); column);
for (int i = 0; i < results.size(); i++) { for (int i = 0; i < results.size(); i++) {
auto result=results.get(i); auto result=results.get(i);
suggestions.emplace_back(result.get_chunks()); if(result.available()) {
suggestions.back().brief_comments=result.get_brief_comments(); suggestions.emplace_back(result.get_chunks());
suggestions.back().brief_comments=result.get_brief_comments();
}
} }
DEBUG("Number of suggestions"); DEBUG("Number of suggestions");
DEBUG_VAR(suggestions.size()); DEBUG_VAR(suggestions.size());

15
juci/source.h

@ -96,11 +96,11 @@ namespace Source {
void update_types(); void update_types();
Tooltips diagnostic_tooltips; Tooltips diagnostic_tooltips;
Tooltips type_tooltips; Tooltips type_tooltips;
bool clangview_on_motion_notify_event(GdkEventMotion* event); bool on_motion_notify_event(GdkEventMotion* event);
void clangview_on_mark_set(const Gtk::TextBuffer::iterator& iterator, const Glib::RefPtr<Gtk::TextBuffer::Mark>& mark); void on_mark_set(const Gtk::TextBuffer::iterator& iterator, const Glib::RefPtr<Gtk::TextBuffer::Mark>& mark);
sigc::connection delayed_tooltips_connection; sigc::connection delayed_tooltips_connection;
bool clangview_on_focus_out_event(GdkEventFocus* event); bool on_focus_out_event(GdkEventFocus* event);
bool clangview_on_scroll_event(GdkEventScroll* event); bool on_scroll_event(GdkEventScroll* event);
static clang::Index clang_index; static clang::Index clang_index;
std::unique_ptr<clang::Tokens> clang_tokens; std::unique_ptr<clang::Tokens> clang_tokens;
bool clang_readable=false; bool clang_readable=false;
@ -129,14 +129,15 @@ namespace Source {
protected: protected:
bool on_key_press_event(GdkEventKey* key); bool on_key_press_event(GdkEventKey* key);
private: private:
void start_autocomplete(); void autocomplete();
SelectionDialog selection_dialog; SelectionDialog selection_dialog;
std::vector<Source::AutoCompleteData> get_autocomplete_suggestions(int line_number, int column, std::map<std::string, std::string>& buffer_map); std::vector<Source::AutoCompleteData> get_autocomplete_suggestions(int line_number, int column, std::map<std::string, std::string>& buffer_map);
Glib::Dispatcher autocomplete_done; Glib::Dispatcher autocomplete_done;
sigc::connection autocomplete_done_connection; sigc::connection autocomplete_done_connection;
bool autocomplete_running=false; bool autocomplete_starting=false;
bool cancel_show_autocomplete=false; bool autocomplete_cancel_starting=false;
char last_keyval=0; char last_keyval=0;
std::string prefix;
}; };
class Controller { class Controller {

Loading…
Cancel
Save