Browse Source

More flexible autocomplete, now pops up selectiondialog even after entering chars after ., -> and ::. Also some cleanup. Placed autocompletion in seperate class ClangViewAutocomplete.

merge-requests/365/head
eidheim 11 years ago
parent
commit
6a672c1086
  1. 51
      juci/selectiondialog.cc
  2. 6
      juci/selectiondialog.h
  3. 284
      juci/source.cc
  4. 50
      juci/source.h

51
juci/selectiondialog.cc

@ -18,26 +18,22 @@ void SelectionDialog::show() {
list_view_text->set_headers_visible(false); list_view_text->set_headers_visible(false);
list_view_text->set_hscroll_policy(Gtk::ScrollablePolicy::SCROLL_NATURAL); list_view_text->set_hscroll_policy(Gtk::ScrollablePolicy::SCROLL_NATURAL);
list_view_text->set_activate_on_single_click(true); list_view_text->set_activate_on_single_click(true);
list_view_text->set_search_entry(search_entry);
list_view_text->set_hover_selection(false); list_view_text->set_hover_selection(false);
list_view_text->set_rules_hint(true); 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 //list_view_text->set_fixed_height_mode(true); //TODO: This is buggy on OS X, remember to post an issue on GTK+ 3
last_selected=-1;
list_view_text->signal_row_activated().connect([this](const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn*) { list_view_text->signal_row_activated().connect([this](const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn*) {
if(shown) { if(shown) {
select(); select();
} }
}); });
list_view_text->signal_cursor_changed().connect([this](){ list_view_text->signal_cursor_changed().connect(sigc::mem_fun(*this, &SelectionDialog::cursor_changed), true);
cursor_changed();
});
list_view_text->signal_realize().connect([this](){ list_view_text->signal_realize().connect([this](){
resize(); resize();
}); });
if(start_mark)
text_view.get_buffer()->delete_mark(start_mark);
start_mark=text_view.get_buffer()->create_mark(text_view.get_buffer()->get_insert()->get_iter());
start_offset=start_mark->get_iter().get_offset(); start_offset=start_mark->get_iter().get_offset();
list_view_text->clear_items(); list_view_text->clear_items();
for (auto &i : rows) { for (auto &i : rows) {
@ -56,16 +52,23 @@ void SelectionDialog::show() {
window->show_all(); window->show_all();
shown=true; shown=true;
selected=false; row_in_entry=false;
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);
}
} }
void SelectionDialog::hide() { void SelectionDialog::hide() {
window->hide(); window->hide();
shown=false; shown=false;
if(tooltips)
tooltips->hide();
} }
void SelectionDialog::select(bool hide_window) { void SelectionDialog::select(bool hide_window) {
selected=true; row_in_entry=true;
auto selected=list_view_text->get_selected(); auto selected=list_view_text->get_selected();
std::pair<std::string, std::string> select; std::pair<std::string, std::string> select;
if(selected.size()>0) { if(selected.size()>0) {
@ -74,8 +77,6 @@ void SelectionDialog::select(bool hide_window) {
text_view.get_buffer()->insert(start_mark->get_iter(), select.first); text_view.get_buffer()->insert(start_mark->get_iter(), select.first);
} }
if(hide_window) { if(hide_window) {
if(tooltips)
tooltips->hide();
hide(); hide();
char find_char=select.first.back(); char find_char=select.first.back();
if(find_char==')' || find_char=='>') { if(find_char==')' || find_char=='>') {
@ -105,9 +106,10 @@ 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()); auto text=text_view.get_buffer()->get_text(start_mark->get_iter(), text_view.get_buffer()->get_insert()->get_iter());
if(text.size()>0) { if(text.size()>0) {
search_entry.set_text(text); search_entry.set_text(text);
list_view_text->set_search_entry(search_entry);
} }
cursor_changed();
} }
return false; return false;
} }
@ -116,12 +118,13 @@ bool SelectionDialog::on_key_press(GdkEventKey* key) {
(key->keyval>=GDK_KEY_A && key->keyval<=GDK_KEY_Z) || (key->keyval>=GDK_KEY_A && key->keyval<=GDK_KEY_Z) ||
(key->keyval>=GDK_KEY_a && key->keyval<=GDK_KEY_z) || (key->keyval>=GDK_KEY_a && key->keyval<=GDK_KEY_z) ||
key->keyval==GDK_KEY_underscore || key->keyval==GDK_KEY_BackSpace) { key->keyval==GDK_KEY_underscore || key->keyval==GDK_KEY_BackSpace) {
if(selected) { if(row_in_entry) {
text_view.get_buffer()->erase(start_mark->get_iter(), text_view.get_buffer()->get_insert()->get_iter()); text_view.get_buffer()->erase(start_mark->get_iter(), text_view.get_buffer()->get_insert()->get_iter());
selected=false; row_in_entry=false;
if(key->keyval==GDK_KEY_BackSpace) if(key->keyval==GDK_KEY_BackSpace) {
return true; return true;
} }
}
return false; return false;
} }
if(key->keyval==GDK_KEY_Shift_L || key->keyval==GDK_KEY_Shift_R || key->keyval==GDK_KEY_Alt_L || key->keyval==GDK_KEY_Alt_R || key->keyval==GDK_KEY_Control_L || key->keyval==GDK_KEY_Control_R || key->keyval==GDK_KEY_Meta_L || key->keyval==GDK_KEY_Meta_R) if(key->keyval==GDK_KEY_Shift_L || key->keyval==GDK_KEY_Shift_R || key->keyval==GDK_KEY_Alt_L || key->keyval==GDK_KEY_Alt_R || key->keyval==GDK_KEY_Control_L || key->keyval==GDK_KEY_Control_R || key->keyval==GDK_KEY_Meta_L || key->keyval==GDK_KEY_Meta_R)
@ -161,14 +164,15 @@ bool SelectionDialog::on_key_press(GdkEventKey* key) {
} }
void SelectionDialog::cursor_changed() { void SelectionDialog::cursor_changed() {
if(tooltips)
tooltips->hide();
auto selected=list_view_text->get_selected(); auto selected=list_view_text->get_selected();
if(selected.size()>0) { if(selected.size()>0) {
auto select = rows.at(list_view_text->get_text(selected[0])); if(selected[0]!=last_selected || last_selected==-1) {
if(select.second.size()>0) { if(tooltips)
tooltips->hide();
auto row = rows.at(list_view_text->get_text(selected[0]));
if(row.second.size()>0) {
tooltips=std::unique_ptr<Tooltips>(new Tooltips()); tooltips=std::unique_ptr<Tooltips>(new Tooltips());
auto tooltip_text=select.second; auto tooltip_text=row.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()); auto tooltip_buffer=Gtk::TextBuffer::create(text_view.get_buffer()->get_tag_table());
//TODO: Insert newlines to tooltip_text (use 80 chars, then newline?) //TODO: Insert newlines to tooltip_text (use 80 chars, then newline?)
@ -179,6 +183,13 @@ void SelectionDialog::cursor_changed() {
tooltips->show(true); tooltips->show(true);
} }
} }
}
else if(tooltips)
tooltips->hide();
if(selected.size()>0)
last_selected=selected[0];
else
last_selected=-1;
} }
void SelectionDialog::move() { void SelectionDialog::move() {

6
juci/selectiondialog.h

@ -16,23 +16,23 @@ public:
bool on_key_press(GdkEventKey* key); bool on_key_press(GdkEventKey* key);
std::map<std::string, std::pair<std::string, std::string> > rows; std::map<std::string, std::pair<std::string, std::string> > rows;
bool shown=false; bool shown=false;
Glib::RefPtr<Gtk::TextBuffer::Mark> start_mark;
private: private:
void resize(); void resize();
void select(bool hide_window=true); void select(bool hide_window=true);
void cursor_changed(); void cursor_changed();
Gtk::Entry search_entry; Gtk::Entry search_entry;
Glib::RefPtr<Gtk::TextBuffer::Mark> start_mark;
int start_offset; int start_offset;
bool selected; bool row_in_entry;
Gtk::TextView& text_view; Gtk::TextView& text_view;
std::unique_ptr<Gtk::Window> window; std::unique_ptr<Gtk::Window> window;
std::unique_ptr<Gtk::ScrolledWindow> scrolled_window; std::unique_ptr<Gtk::ScrolledWindow> scrolled_window;
std::unique_ptr<Gtk::ListViewText> list_view_text; std::unique_ptr<Gtk::ListViewText> list_view_text;
std::unique_ptr<Tooltips> tooltips; std::unique_ptr<Tooltips> tooltips;
int last_selected;
}; };
#endif // JUCI_SELECTIONDIALOG_H_ #endif // JUCI_SELECTIONDIALOG_H_

284
juci/source.cc

@ -63,7 +63,7 @@ string Source::View::get_line_before_insert() {
} }
//Basic indentation //Basic indentation
bool Source::View::on_key_press(GdkEventKey* key) { bool Source::View::on_key_press_event(GdkEventKey* key) {
auto config=Singletons::Config::source(); auto config=Singletons::Config::source();
const std::regex spaces_regex(std::string("^(")+config->tab_char+"*).*$"); const std::regex spaces_regex(std::string("^(")+config->tab_char+"*).*$");
//Indent as in next or previous line //Indent as in next or previous line
@ -139,7 +139,7 @@ bool Source::View::on_key_press(GdkEventKey* key) {
} }
} }
} }
return false; return Gsv::View::on_key_press_event(key);
} }
////////////////// //////////////////
@ -148,7 +148,7 @@ bool Source::View::on_key_press(GdkEventKey* key) {
clang::Index Source::ClangView::clang_index(0, 0); 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::ClangView::ClangView(const std::string& file_path, const std::string& project_path, Terminal::Controller& terminal):
Source::View(file_path, project_path), terminal(terminal), selection_dialog(*this), Source::View(file_path, project_path), terminal(terminal),
parse_thread_go(true), parse_thread_mapped(false), parse_thread_stop(false) { parse_thread_go(true), parse_thread_mapped(false), parse_thread_stop(false) {
int start_offset = get_source_buffer()->begin().get_offset(); int start_offset = get_source_buffer()->begin().get_offset();
int end_offset = get_source_buffer()->end().get_offset(); int end_offset = get_source_buffer()->end().get_offset();
@ -223,22 +223,17 @@ parse_thread_go(true), parse_thread_mapped(false), parse_thread_stop(false) {
}); });
get_source_buffer()->signal_changed().connect([this]() { get_source_buffer()->signal_changed().connect([this]() {
cancel_show_autocomplete=true;
parse_thread_mapped=false; parse_thread_mapped=false;
delayed_reparse_connection.disconnect(); delayed_reparse_connection.disconnect();
if(!selection_dialog.shown) {
delayed_reparse_connection=Glib::signal_timeout().connect([this]() { delayed_reparse_connection=Glib::signal_timeout().connect([this]() {
clang_readable=false; clang_readable=false;
parse_thread_go=true; parse_thread_go=true;
return false; return false;
}, 1000); }, 1000);
}
type_tooltips.hide(); type_tooltips.hide();
diagnostic_tooltips.hide(); diagnostic_tooltips.hide();
}); });
signal_key_press_event().connect(sigc::mem_fun(*this, &Source::ClangView::on_key_press), false);
signal_key_release_event().connect(sigc::mem_fun(*this, &Source::ClangView::on_key_release), false);
signal_motion_notify_event().connect(sigc::mem_fun(*this, &Source::ClangView::clangview_on_motion_notify_event), false); signal_motion_notify_event().connect(sigc::mem_fun(*this, &Source::ClangView::clangview_on_motion_notify_event), false);
signal_focus_out_event().connect(sigc::mem_fun(*this, &Source::ClangView::clangview_on_focus_out_event), 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); signal_scroll_event().connect(sigc::mem_fun(*this, &Source::ClangView::clangview_on_scroll_event), false);
@ -289,25 +284,6 @@ reparse(const std::map<std::string, std::string> &buffer) {
return status; return status;
} }
std::vector<Source::AutoCompleteData> Source::ClangView::
get_autocomplete_suggestions(int line_number, int column, std::map<std::string, std::string>& buffer_map) {
INFO("Getting auto complete suggestions");
std::vector<Source::AutoCompleteData> suggestions;
clang::CodeCompleteResults results(clang_tu.get(),
file_path,
buffer_map,
line_number,
column-1);
for (int i = 0; i < results.size(); i++) {
auto result=results.get(i);
suggestions.emplace_back(result.get_chunks());
suggestions.back().brief_comments=result.get_brief_comments();
}
DEBUG("Number of suggestions");
DEBUG_VAR(suggestions.size());
return suggestions;
}
std::vector<std::string> Source::ClangView:: std::vector<std::string> Source::ClangView::
get_compilation_commands() { get_compilation_commands() {
clang::CompilationDatabase db(project_path); clang::CompilationDatabase db(project_path);
@ -451,10 +427,6 @@ void Source::ClangView::clangview_on_mark_set(const Gtk::TextBuffer::iterator& i
delayed_tooltips_connection.disconnect(); delayed_tooltips_connection.disconnect();
if(mark->get_name()=="insert") { if(mark->get_name()=="insert") {
cancel_show_autocomplete=true;
if(selection_dialog.shown) {
selection_dialog.hide();
}
delayed_tooltips_connection.disconnect(); delayed_tooltips_connection.disconnect();
delayed_tooltips_connection=Glib::signal_timeout().connect([this]() { delayed_tooltips_connection=Glib::signal_timeout().connect([this]() {
if(clang_readable) { if(clang_readable) {
@ -484,9 +456,6 @@ bool Source::ClangView::clangview_on_focus_out_event(GdkEventFocus* event) {
} }
bool Source::ClangView::clangview_on_scroll_event(GdkEventScroll* event) { bool Source::ClangView::clangview_on_scroll_event(GdkEventScroll* event) {
if(selection_dialog.shown)
selection_dialog.move();
delayed_tooltips_connection.disconnect(); delayed_tooltips_connection.disconnect();
type_tooltips.hide(); type_tooltips.hide();
diagnostic_tooltips.hide(); diagnostic_tooltips.hide();
@ -525,114 +494,9 @@ highlight_token(clang::Token *token,
end_offset), token_kind); end_offset), token_kind);
} }
bool Source::ClangView::on_key_release(GdkEventKey* key) {
if(selection_dialog.shown) {
if(selection_dialog.on_key_release(key))
return true;
}
INFO("Source::ClangView::on_key_release getting iters");
// Get function to fill popup with suggests item vector under is for testing
Gtk::TextIter beg = get_source_buffer()->get_insert()->get_iter();
Gtk::TextIter end = get_source_buffer()->get_insert()->get_iter();
Gtk::TextIter tmp = get_source_buffer()->get_insert()->get_iter();
Gtk::TextIter tmp1 = get_source_buffer()->get_insert()->get_iter();
Gtk::TextIter line = get_source_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);
INFO("Source::ClangView::on_key_release checking key->keyval");
if (illegal_chars) {
return false;
}
std::string c = get_source_buffer()->get_text(end, beg);
switch (key->keyval) {
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;
}
delayed_reparse_connection.disconnect();
if(!autocomplete_running) {
autocomplete_running=true;
cancel_show_autocomplete=false;
INFO("Source::ClangView::on_key_release getting autocompletions");
std::shared_ptr<std::vector<Source::AutoCompleteData> > ac_data=std::make_shared<std::vector<Source::AutoCompleteData> >();
autocomplete_done_connection.disconnect();
autocomplete_done_connection=autocomplete_done.connect([this, ac_data](){
if(!cancel_show_autocomplete) {
std::map<std::string, std::pair<std::string, std::string> > rows;
for (auto &data : *ac_data) {
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;
}
}
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);
rows[ss.str() + " --> " + return_value] = pair;
}
}
if (rows.empty()) {
rows["No suggestions found..."] = std::pair<std::string, std::string>();
}
selection_dialog.rows=std::move(rows);
selection_dialog.show();
}
autocomplete_running=false;
});
std::shared_ptr<std::map<std::string, std::string> > buffer_map=std::make_shared<std::map<std::string, std::string> >();
(*buffer_map)[file_path]=get_buffer()->get_text(get_buffer()->begin(), get_buffer()->get_insert()->get_iter());
(*buffer_map)[file_path]+="\n";
auto line_nr=beg.get_line()+1;
auto column_nr=beg.get_line_offset()+2;
std::thread autocomplete_thread([this, ac_data, line_nr, column_nr, buffer_map](){
parsing_mutex.lock();
*ac_data=move(get_autocomplete_suggestions(line_nr, column_nr, *buffer_map));
autocomplete_done();
parsing_mutex.unlock();
});
autocomplete_thread.detach();
}
else {
std::map<std::string, std::pair<std::string, std::string> > rows;
rows["Autocomplete already running, try again."] = std::pair<std::string, std::string>("", "");
selection_dialog.rows=std::move(rows);
selection_dialog.show();
}
return false;
}
//Clang indentation //Clang indentation
//TODO: replace indentation methods with a better implementation or maybe use libclang //TODO: replace indentation methods with a better implementation or maybe use libclang
bool Source::ClangView::on_key_press(GdkEventKey* key) { bool Source::ClangView::on_key_press_event(GdkEventKey* key) {
if(selection_dialog.shown) {
if(selection_dialog.on_key_press(key))
return true;
}
auto config=Singletons::Config::source(); auto config=Singletons::Config::source();
const std::regex bracket_regex(std::string("^(")+config->tab_char+"*).*\\{ *$"); const std::regex bracket_regex(std::string("^(")+config->tab_char+"*).*\\{ *$");
const std::regex no_bracket_statement_regex(std::string("^(")+config->tab_char+"*)(if|for|else if|catch|while) *\\(.*[^;}] *$"); const std::regex no_bracket_statement_regex(std::string("^(")+config->tab_char+"*)(if|for|else if|catch|while) *\\(.*[^;}] *$");
@ -713,7 +577,143 @@ bool Source::ClangView::on_key_press(GdkEventKey* key) {
return false; return false;
} }
return Source::View::on_key_press(key); return Source::View::on_key_press_event(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) {
get_buffer()->signal_changed().connect([this](){
if(!selection_dialog.shown) {
auto insert=get_buffer()->get_insert();
auto iter=insert->get_iter();
int line_nr=iter.get_line();
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;
if(std::regex_match(line, sm, method)) {
if(sm[1].str().find("//")==std::string::npos) {
if(last_keyval=='.' || last_keyval=='>' || last_keyval==':') {
if(sm[3]=="" && !autocomplete_running) {
start_autocomplete();
}
}
}
}
else if(autocomplete_running)
cancel_show_autocomplete=true;
}
});
get_buffer()->signal_mark_set().connect([this](const Gtk::TextBuffer::iterator& iterator, const Glib::RefPtr<Gtk::TextBuffer::Mark>& mark){
if(mark->get_name()=="insert") {
cancel_show_autocomplete=true;
if(selection_dialog.shown) {
selection_dialog.hide();
}
}
});
signal_scroll_event().connect([this](GdkEventScroll* event){
if(selection_dialog.shown)
selection_dialog.move();
return false;
}, false);
signal_key_release_event().connect([this](GdkEventKey* key){
if(selection_dialog.shown) {
if(selection_dialog.on_key_release(key))
return true;
}
return false;
}, false);
}
bool Source::ClangViewAutocomplete::on_key_press_event(GdkEventKey *key) {
if(selection_dialog.shown) {
delayed_reparse_connection.disconnect();
if(selection_dialog.on_key_press(key))
return true;
}
last_keyval=key->keyval;
return ClangView::on_key_press_event(key);
}
void Source::ClangViewAutocomplete::start_autocomplete() {
delayed_reparse_connection.disconnect();
if(!autocomplete_running) {
autocomplete_running=true;
cancel_show_autocomplete=false;
INFO("Source::ClangView::on_key_release getting autocompletions");
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=autocomplete_done.connect([this, ac_data](){
if(!cancel_show_autocomplete) {
std::map<std::string, std::pair<std::string, std::string> > rows;
for (auto &data : *ac_data) {
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;
}
}
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);
rows[ss.str() + " --> " + return_value] = pair;
}
}
if (rows.empty()) {
rows["No suggestions found..."] = std::pair<std::string, std::string>();
}
selection_dialog.rows=std::move(rows);
selection_dialog.show();
}
autocomplete_running=false;
});
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());
(*buffer_map)[this->file_path]+="\n";
auto iter = get_source_buffer()->get_insert()->get_iter();
auto line_nr=iter.get_line()+1;
auto column_nr=iter.get_line_offset()+2;
std::thread autocomplete_thread([this, ac_data, line_nr, column_nr, buffer_map](){
parsing_mutex.lock();
*ac_data=move(get_autocomplete_suggestions(line_nr, column_nr, *buffer_map));
autocomplete_done();
parsing_mutex.unlock();
});
autocomplete_thread.detach();
}
}
std::vector<Source::AutoCompleteData> Source::ClangViewAutocomplete::
get_autocomplete_suggestions(int line_number, int column, std::map<std::string, std::string>& buffer_map) {
INFO("Getting auto complete suggestions");
std::vector<Source::AutoCompleteData> suggestions;
clang::CodeCompleteResults results(clang_tu.get(),
file_path,
buffer_map,
line_number,
column-1);
for (int i = 0; i < results.size(); i++) {
auto result=results.get(i);
suggestions.emplace_back(result.get_chunks());
suggestions.back().brief_comments=result.get_brief_comments();
}
DEBUG("Number of suggestions");
DEBUG_VAR(suggestions.size());
return suggestions;
} }
//////////////////// ////////////////////
@ -727,7 +727,7 @@ Source::Controller::Controller(const std::string& file_path, std::string project
project_path=boost::filesystem::path(file_path).parent_path().string(); project_path=boost::filesystem::path(file_path).parent_path().string();
} }
if (Singletons::Config::source()->legal_extension(file_path.substr(file_path.find_last_of(".") + 1))) if (Singletons::Config::source()->legal_extension(file_path.substr(file_path.find_last_of(".") + 1)))
view=std::unique_ptr<View>(new ClangView(file_path, project_path, terminal)); view=std::unique_ptr<View>(new ClangViewAutocomplete(file_path, project_path, terminal));
else else
view=std::unique_ptr<View>(new GenericView(file_path, project_path)); view=std::unique_ptr<View>(new GenericView(file_path, project_path));
INFO("Source Controller with childs constructed"); INFO("Source Controller with childs constructed");

50
juci/source.h

@ -60,18 +60,16 @@ namespace Source {
std::string project_path; std::string project_path;
Gtk::TextIter search_start, search_end; Gtk::TextIter search_start, search_end;
protected: protected:
bool on_key_press(GdkEventKey* key); bool on_key_press_event(GdkEventKey* key);
}; // class View }; // class View
class GenericView : public View { class GenericView : public View {
public: public:
GenericView(const std::string& file_path, const std::string& project_path): GenericView(const std::string& file_path, const std::string& project_path):
View(file_path, project_path) { View(file_path, project_path) {}
signal_key_press_event().connect(sigc::mem_fun(*this, &Source::GenericView::on_key_press), false); protected:
} bool on_key_press_event(GdkEventKey* key) {
private: return Source::View::on_key_press_event(key);
bool on_key_press(GdkEventKey* key) {
return Source::View::on_key_press(key);
} }
}; };
@ -79,6 +77,12 @@ namespace Source {
public: public:
ClangView(const std::string& file_path, const std::string& project_path, Terminal::Controller& terminal); ClangView(const std::string& file_path, const std::string& project_path, Terminal::Controller& terminal);
~ClangView(); ~ClangView();
protected:
std::unique_ptr<clang::TranslationUnit> clang_tu;
std::map<std::string, std::string> get_buffer_map() const;
std::mutex parsing_mutex;
sigc::connection delayed_reparse_connection;
bool on_key_press_event(GdkEventKey* key);
private: private:
// inits the syntax highligthing on file open // inits the syntax highligthing on file open
void init_syntax_highlighting(const std::map<std::string, std::string> void init_syntax_highlighting(const std::map<std::string, std::string>
@ -86,9 +90,6 @@ namespace Source {
int start_offset, int start_offset,
int end_offset, int end_offset,
clang::Index *index); clang::Index *index);
std::vector<Source::AutoCompleteData> get_autocomplete_suggestions(int line_number, int column, std::map<std::string, std::string>& buffer_map);
SelectionDialog selection_dialog;
int reparse(const std::map<std::string, std::string> &buffers); int reparse(const std::map<std::string, std::string> &buffers);
void update_syntax(); void update_syntax();
void update_diagnostics(); void update_diagnostics();
@ -100,12 +101,7 @@ namespace Source {
sigc::connection delayed_tooltips_connection; sigc::connection delayed_tooltips_connection;
bool clangview_on_focus_out_event(GdkEventFocus* event); bool clangview_on_focus_out_event(GdkEventFocus* event);
bool clangview_on_scroll_event(GdkEventScroll* event); bool clangview_on_scroll_event(GdkEventScroll* event);
static clang::Index clang_index; static clang::Index clang_index;
std::map<std::string, std::string> get_buffer_map() const;
std::mutex parsing_mutex;
std::unique_ptr<clang::TranslationUnit> clang_tu;
std::unique_ptr<clang::Tokens> clang_tokens; std::unique_ptr<clang::Tokens> clang_tokens;
bool clang_readable=false; bool clang_readable=false;
void highlight_token(clang::Token *token, void highlight_token(clang::Token *token,
@ -114,17 +110,9 @@ namespace Source {
void highlight_cursor(clang::Token *token, void highlight_cursor(clang::Token *token,
std::vector<Range> *source_ranges); std::vector<Range> *source_ranges);
std::vector<std::string> get_compilation_commands(); std::vector<std::string> get_compilation_commands();
bool on_key_press(GdkEventKey* key);
bool on_key_release(GdkEventKey* key);
Terminal::Controller& terminal; Terminal::Controller& terminal;
Glib::Dispatcher autocomplete_done;
sigc::connection autocomplete_done_connection;
sigc::connection delayed_reparse_connection;
std::shared_ptr<Terminal::InProgress> parsing_in_progress; std::shared_ptr<Terminal::InProgress> parsing_in_progress;
bool autocomplete_running=false;
bool cancel_show_autocomplete=false;
Glib::Dispatcher parse_done; Glib::Dispatcher parse_done;
Glib::Dispatcher parse_start; Glib::Dispatcher parse_start;
std::thread parse_thread; std::thread parse_thread;
@ -135,6 +123,22 @@ namespace Source {
std::atomic<bool> parse_thread_stop; std::atomic<bool> parse_thread_stop;
}; };
class ClangViewAutocomplete : public ClangView {
public:
ClangViewAutocomplete(const std::string& file_path, const std::string& project_path, Terminal::Controller& terminal);
protected:
bool on_key_press_event(GdkEventKey* key);
private:
void start_autocomplete();
SelectionDialog selection_dialog;
std::vector<Source::AutoCompleteData> get_autocomplete_suggestions(int line_number, int column, std::map<std::string, std::string>& buffer_map);
Glib::Dispatcher autocomplete_done;
sigc::connection autocomplete_done_connection;
bool autocomplete_running=false;
bool cancel_show_autocomplete=false;
char last_keyval=0;
};
class Controller { class Controller {
public: public:
Controller(const std::string& file_path, std::string project_path, Terminal::Controller& terminal); Controller(const std::string& file_path, std::string project_path, Terminal::Controller& terminal);

Loading…
Cancel
Save