Browse Source

Slightly improved snippet cursor behaviour, and multiple snippet parameter selections are now shown

pipelines/235045657
eidheim 6 years ago
parent
commit
d88c40fdcf
  1. 10
      src/source.cpp
  2. 99
      src/source_base.cpp
  3. 9
      src/source_base.hpp

10
src/source.cpp

@ -499,6 +499,16 @@ void Source::View::configure() {
} }
//TODO: clear tag_class and param_spec? //TODO: clear tag_class and param_spec?
style = scheme->get_style("selection");
if(style && style->property_foreground_set())
extra_cursor_selection->property_foreground() = style->property_foreground().get_value();
else
extra_cursor_selection->property_foreground_rgba() = get_style_context()->get_color(Gtk::StateFlags::STATE_FLAG_SELECTED);
if(style && style->property_background_set())
extra_cursor_selection->property_background() = style->property_background().get_value();
else
extra_cursor_selection->property_background_rgba() = get_style_context()->get_background_color(Gtk::StateFlags::STATE_FLAG_SELECTED);
if(Config::get().menu.keys["source_show_completion"].empty()) { if(Config::get().menu.keys["source_show_completion"].empty()) {
get_completion()->unblock_interactive(); get_completion()->unblock_interactive();
interactive_completion = true; interactive_completion = true;

99
src/source_base.cpp

@ -179,6 +179,8 @@ Source::BaseView::BaseView(const boost::filesystem::path &file_path, const Glib:
snippet_parameter_tag->property_background_rgba() = rgba; snippet_parameter_tag->property_background_rgba() = rgba;
snippet_parameter_tag->property_background_set() = true; snippet_parameter_tag->property_background_set() = true;
extra_cursor_selection = get_buffer()->create_tag();
get_buffer()->signal_mark_set().connect([this](const Gtk::TextBuffer::iterator &iter, const Glib::RefPtr<Gtk::TextBuffer::Mark> &mark) { get_buffer()->signal_mark_set().connect([this](const Gtk::TextBuffer::iterator &iter, const Glib::RefPtr<Gtk::TextBuffer::Mark> &mark) {
if(mark->get_name() == "insert") { if(mark->get_name() == "insert") {
keep_clipboard = false; keep_clipboard = false;
@ -997,7 +999,7 @@ bool Source::BaseView::on_key_press_event(GdkEventKey *key) {
for(auto &extra_cursor : extra_cursors) { for(auto &extra_cursor : extra_cursors) {
auto iter = extra_cursor.mark->get_iter(); auto iter = extra_cursor.mark->get_iter();
iter.backward_word_start(); iter.backward_word_start();
extra_cursor.offset = iter.get_line_offset(); extra_cursor.line_offset = iter.get_line_offset();
get_buffer()->move_mark(extra_cursor.mark, iter); get_buffer()->move_mark(extra_cursor.mark, iter);
} }
auto insert = get_buffer()->get_insert(); auto insert = get_buffer()->get_insert();
@ -1015,7 +1017,7 @@ bool Source::BaseView::on_key_press_event(GdkEventKey *key) {
for(auto &extra_cursor : extra_cursors) { for(auto &extra_cursor : extra_cursors) {
auto iter = extra_cursor.mark->get_iter(); auto iter = extra_cursor.mark->get_iter();
iter.forward_visible_word_end(); iter.forward_visible_word_end();
extra_cursor.offset = iter.get_line_offset(); extra_cursor.line_offset = iter.get_line_offset();
get_buffer()->move_mark(extra_cursor.mark, iter); get_buffer()->move_mark(extra_cursor.mark, iter);
} }
auto insert = get_buffer()->get_insert(); auto insert = get_buffer()->get_insert();
@ -1070,7 +1072,7 @@ bool Source::BaseView::on_key_press_event_extra_cursors(GdkEventKey *key) {
return false; return false;
auto &extra_cursor = extra_cursors.back(); auto &extra_cursor = extra_cursors.back();
auto iter = extra_cursor.mark->get_iter(); auto iter = extra_cursor.mark->get_iter();
auto line_offset = extra_cursor.offset; auto line_offset = extra_cursor.line_offset;
if(iter.backward_line()) { if(iter.backward_line()) {
auto end_line_iter = iter; auto end_line_iter = iter;
if(!end_line_iter.ends_line()) if(!end_line_iter.ends_line())
@ -1085,7 +1087,7 @@ bool Source::BaseView::on_key_press_event_extra_cursors(GdkEventKey *key) {
return false; return false;
auto &extra_cursor = extra_cursors.back(); auto &extra_cursor = extra_cursors.back();
auto iter = extra_cursor.mark->get_iter(); auto iter = extra_cursor.mark->get_iter();
auto line_offset = extra_cursor.offset; auto line_offset = extra_cursor.line_offset;
if(iter.forward_line()) { if(iter.forward_line()) {
auto end_line_iter = iter; auto end_line_iter = iter;
if(!end_line_iter.ends_line()) if(!end_line_iter.ends_line())
@ -1137,7 +1139,7 @@ bool Source::BaseView::on_key_press_event_extra_cursors(GdkEventKey *key) {
enable_multiple_cursors = false; enable_multiple_cursors = false;
for(auto &extra_cursor : extra_cursors) { for(auto &extra_cursor : extra_cursors) {
auto iter = extra_cursor.mark->get_iter(); auto iter = extra_cursor.mark->get_iter();
auto line_offset = extra_cursor.offset; auto line_offset = extra_cursor.line_offset;
if(iter.backward_line()) { if(iter.backward_line()) {
auto end_line_iter = iter; auto end_line_iter = iter;
if(!end_line_iter.ends_line()) if(!end_line_iter.ends_line())
@ -1152,7 +1154,7 @@ bool Source::BaseView::on_key_press_event_extra_cursors(GdkEventKey *key) {
enable_multiple_cursors = false; enable_multiple_cursors = false;
for(auto &extra_cursor : extra_cursors) { for(auto &extra_cursor : extra_cursors) {
auto iter = extra_cursor.mark->get_iter(); auto iter = extra_cursor.mark->get_iter();
auto line_offset = extra_cursor.offset; auto line_offset = extra_cursor.line_offset;
if(iter.forward_line()) { if(iter.forward_line()) {
auto end_line_iter = iter; auto end_line_iter = iter;
if(!end_line_iter.ends_line()) if(!end_line_iter.ends_line())
@ -1191,7 +1193,7 @@ void Source::BaseView::setup_extra_cursor_signals() {
get_buffer()->signal_mark_set().connect([this, last_insert](const Gtk::TextBuffer::iterator &iter, const Glib::RefPtr<Gtk::TextBuffer::Mark> &mark) mutable { get_buffer()->signal_mark_set().connect([this, last_insert](const Gtk::TextBuffer::iterator &iter, const Glib::RefPtr<Gtk::TextBuffer::Mark> &mark) mutable {
for(auto &extra_cursor : extra_cursors) { for(auto &extra_cursor : extra_cursors) {
if(extra_cursor.mark == mark && !iter.ends_line()) { if(extra_cursor.mark == mark && !iter.ends_line()) {
extra_cursor.offset = std::max(extra_cursor.offset, iter.get_line_offset()); extra_cursor.line_offset = std::max(extra_cursor.line_offset, iter.get_line_offset());
break; break;
} }
} }
@ -1207,9 +1209,9 @@ void Source::BaseView::setup_extra_cursor_signals() {
get_buffer()->move_mark(extra_cursor.mark, iter); get_buffer()->move_mark(extra_cursor.mark, iter);
} }
for(auto &extra_cursor : extra_snippet_cursors) { for(auto &extra_cursor : extra_snippet_cursors) {
auto iter = extra_cursor.mark->get_iter(); auto iter = extra_cursor.insert->get_iter();
iter.forward_chars(offset_diff); iter.forward_chars(offset_diff);
get_buffer()->move_mark(extra_cursor.mark, iter); get_buffer()->move_mark(extra_cursor.insert, iter);
} }
} }
enable_multiple_cursors = true; enable_multiple_cursors = true;
@ -1230,11 +1232,15 @@ void Source::BaseView::setup_extra_cursor_signals() {
get_buffer()->insert(iter, text); get_buffer()->insert(iter, text);
auto extra_cursor_iter = extra_cursor.mark->get_iter(); auto extra_cursor_iter = extra_cursor.mark->get_iter();
if(!extra_cursor_iter.ends_line()) if(!extra_cursor_iter.ends_line())
extra_cursor.offset = extra_cursor_iter.get_line_offset(); extra_cursor.line_offset = extra_cursor_iter.get_line_offset();
} }
for(auto &extra_cursor : extra_snippet_cursors) { for(auto &extra_cursor : extra_snippet_cursors) {
extra_cursor.initial_forward_erase_size.reset(); auto start_iter = extra_cursor.insert->get_iter();
auto iter = extra_cursor.mark->get_iter(); auto end_iter = extra_cursor.selection_bound->get_iter();
if(start_iter != end_iter) // Erase selection if any
get_buffer()->erase(start_iter, end_iter);
auto iter = extra_cursor.insert->get_iter();
iter.forward_chars(offset); iter.forward_chars(offset);
get_buffer()->insert(iter, text); get_buffer()->insert(iter, text);
} }
@ -1244,14 +1250,22 @@ void Source::BaseView::setup_extra_cursor_signals() {
auto erase_backward_length = std::make_shared<int>(0); auto erase_backward_length = std::make_shared<int>(0);
auto erase_forward_length = std::make_shared<int>(0); auto erase_forward_length = std::make_shared<int>(0);
get_buffer()->signal_erase().connect([this, erase_backward_length, erase_forward_length](const Gtk::TextBuffer::iterator &iter_start, const Gtk::TextBuffer::iterator &iter_end) { auto erase_selection = std::make_shared<bool>(false);
get_buffer()->signal_erase().connect([this, erase_backward_length, erase_forward_length, erase_selection](const Gtk::TextBuffer::iterator &iter_start, const Gtk::TextBuffer::iterator &iter_end) {
if(enable_multiple_cursors && (!extra_cursors.empty() || !extra_snippet_cursors.empty())) { if(enable_multiple_cursors && (!extra_cursors.empty() || !extra_snippet_cursors.empty())) {
auto insert_offset = get_buffer()->get_insert()->get_iter().get_offset(); auto insert_offset = get_buffer()->get_insert()->get_iter().get_offset();
*erase_backward_length = insert_offset - iter_start.get_offset(); *erase_backward_length = insert_offset - iter_start.get_offset();
*erase_forward_length = iter_end.get_offset() - insert_offset; *erase_forward_length = iter_end.get_offset() - insert_offset;
if(*erase_backward_length == 0) {
auto iter = get_buffer()->get_insert()->get_iter();
iter.forward_chars(*erase_forward_length);
if(iter == get_buffer()->get_selection_bound()->get_iter())
*erase_selection = true;
}
} }
}, false); }, false);
get_buffer()->signal_erase().connect([this, erase_backward_length, erase_forward_length](const Gtk::TextBuffer::iterator &iter_start, const Gtk::TextBuffer::iterator &iter_end) { get_buffer()->signal_erase().connect([this, erase_backward_length, erase_forward_length, erase_selection](const Gtk::TextBuffer::iterator &iter_start, const Gtk::TextBuffer::iterator &iter_end) {
if(enable_multiple_cursors && (*erase_backward_length != 0 || *erase_forward_length != 0)) { if(enable_multiple_cursors && (*erase_backward_length != 0 || *erase_forward_length != 0)) {
enable_multiple_cursors = false; enable_multiple_cursors = false;
for(auto &extra_cursor : extra_cursors) { for(auto &extra_cursor : extra_cursors) {
@ -1262,23 +1276,28 @@ void Source::BaseView::setup_extra_cursor_signals() {
get_buffer()->erase(start_iter, end_iter); get_buffer()->erase(start_iter, end_iter);
auto extra_cursor_iter = extra_cursor.mark->get_iter(); auto extra_cursor_iter = extra_cursor.mark->get_iter();
if(!extra_cursor_iter.ends_line()) if(!extra_cursor_iter.ends_line())
extra_cursor.offset = extra_cursor_iter.get_line_offset(); extra_cursor.line_offset = extra_cursor_iter.get_line_offset();
} }
for(auto &extra_cursor : extra_snippet_cursors) { for(auto &extra_cursor : extra_snippet_cursors) {
auto start_iter = extra_cursor.mark->get_iter(); if(*erase_selection)
auto end_iter = start_iter; get_buffer()->erase(extra_cursor.insert->get_iter(), extra_cursor.selection_bound->get_iter());
start_iter.backward_chars(*erase_backward_length); else {
if(extra_cursor.initial_forward_erase_size) { // In case of different sized placeholders auto start_iter = extra_cursor.insert->get_iter();
end_iter.forward_chars(*extra_cursor.initial_forward_erase_size); auto end_iter = extra_cursor.selection_bound->get_iter();
extra_cursor.initial_forward_erase_size.reset(); if(start_iter != end_iter) // Erase selection if any
} get_buffer()->erase(start_iter, end_iter);
else
start_iter = extra_cursor.insert->get_iter();
end_iter = start_iter;
end_iter.forward_chars(*erase_forward_length); end_iter.forward_chars(*erase_forward_length);
get_buffer()->erase(start_iter, end_iter); start_iter.backward_chars(*erase_backward_length);
get_buffer()->erase(start_iter, end_iter);
}
} }
enable_multiple_cursors = true; enable_multiple_cursors = true;
*erase_backward_length = 0; *erase_backward_length = 0;
*erase_forward_length = 0; *erase_forward_length = 0;
*erase_selection = false;
} }
}); });
} }
@ -1463,8 +1482,7 @@ void Source::BaseView::insert_snippet(Gtk::TextIter iter, const std::string &sni
// $0 should be last parameter // $0 should be last parameter
auto it = parameter_offsets_and_sizes_map.find(0); auto it = parameter_offsets_and_sizes_map.find(0);
if(it != parameter_offsets_and_sizes_map.end()) { if(it != parameter_offsets_and_sizes_map.end()) {
auto rit = parameter_offsets_and_sizes_map.rbegin(); parameter_offsets_and_sizes_map.emplace(parameter_offsets_and_sizes_map.rbegin()->first + 1, std::move(it->second));
parameter_offsets_and_sizes_map.emplace(rit->first + 1, std::move(it->second));
parameter_offsets_and_sizes_map.erase(it); parameter_offsets_and_sizes_map.erase(it);
} }
@ -1492,14 +1510,14 @@ void Source::BaseView::insert_snippet(Gtk::TextIter iter, const std::string &sni
iter = mark->get_iter(); iter = mark->get_iter();
get_buffer()->delete_mark(mark); get_buffer()->delete_mark(mark);
for(auto it = parameter_offsets_and_sizes_map.rbegin(); it != parameter_offsets_and_sizes_map.rend(); ++it) { for(auto &parameter_offsets_and_sized : parameter_offsets_and_sizes_map) {
snippet_parameters_list.emplace_front(); snippet_parameters_list.emplace_back();
for(auto &offsets : it->second) { for(auto &offsets : parameter_offsets_and_sized.second) {
auto start = iter; auto start = iter;
start.forward_chars(offsets.first); start.forward_chars(offsets.first);
auto end = start; auto end = start;
end.forward_chars(offsets.second); end.forward_chars(offsets.second);
snippet_parameters_list.front().emplace_back(SnippetParameter{get_buffer()->create_mark(start, false), get_buffer()->create_mark(end, false), end.get_offset() - start.get_offset()}); snippet_parameters_list.back().emplace_back(SnippetParameter{get_buffer()->create_mark(start, false), get_buffer()->create_mark(end, false), end.get_offset() - start.get_offset()});
} }
} }
@ -1510,16 +1528,21 @@ void Source::BaseView::insert_snippet(Gtk::TextIter iter, const std::string &sni
bool Source::BaseView::select_snippet_parameter() { bool Source::BaseView::select_snippet_parameter() {
if(!extra_snippet_cursors.empty()) { if(!extra_snippet_cursors.empty()) {
for(auto &extra_cursor : extra_snippet_cursors) { for(auto &extra_cursor : extra_snippet_cursors) {
extra_cursor.mark->set_visible(false); extra_cursor.insert->set_visible(false);
get_buffer()->delete_mark(extra_cursor.mark); get_buffer()->delete_mark(extra_cursor.insert);
get_buffer()->delete_mark(extra_cursor.selection_bound);
} }
extra_snippet_cursors.clear(); extra_snippet_cursors.clear();
} }
get_buffer()->remove_tag(snippet_parameter_tag, get_buffer()->begin(), get_buffer()->end()); get_buffer()->remove_tag(snippet_parameter_tag, get_buffer()->begin(), get_buffer()->end());
get_buffer()->remove_tag(extra_cursor_selection, get_buffer()->begin(), get_buffer()->end());
bool first = true;
for(auto &parameters : snippet_parameters_list) { for(auto &parameters : snippet_parameters_list) {
for(auto &parameter : parameters) for(auto &parameter : parameters)
get_buffer()->apply_tag(snippet_parameter_tag, parameter.start->get_iter(), parameter.end->get_iter()); get_buffer()->apply_tag(first ? extra_cursor_selection : snippet_parameter_tag, parameter.start->get_iter(), parameter.end->get_iter());
first = false;
} }
if(!snippet_parameters_list.empty()) { if(!snippet_parameters_list.empty()) {
@ -1539,8 +1562,8 @@ bool Source::BaseView::select_snippet_parameter() {
first = false; first = false;
} }
else { else {
extra_snippet_cursors.emplace_back(ExtraSnippetCursor{get_buffer()->create_mark(start, false), end.get_offset() - start.get_offset()}); extra_snippet_cursors.emplace_back(ExtraSnippetCursor{get_buffer()->create_mark(start, false), get_buffer()->create_mark(end, false)});
extra_snippet_cursors.back().mark->set_visible(true); extra_snippet_cursors.back().insert->set_visible(true);
setup_extra_cursor_signals(); setup_extra_cursor_signals();
} }
@ -1569,14 +1592,16 @@ bool Source::BaseView::clear_snippet_marks() {
if(!extra_snippet_cursors.empty()) { if(!extra_snippet_cursors.empty()) {
for(auto &extra_cursor : extra_snippet_cursors) { for(auto &extra_cursor : extra_snippet_cursors) {
extra_cursor.mark->set_visible(false); extra_cursor.insert->set_visible(false);
get_buffer()->delete_mark(extra_cursor.mark); get_buffer()->delete_mark(extra_cursor.insert);
get_buffer()->delete_mark(extra_cursor.selection_bound);
} }
extra_snippet_cursors.clear(); extra_snippet_cursors.clear();
cleared = true; cleared = true;
} }
get_buffer()->remove_tag(snippet_parameter_tag, get_buffer()->begin(), get_buffer()->end()); get_buffer()->remove_tag(snippet_parameter_tag, get_buffer()->begin(), get_buffer()->end());
get_buffer()->remove_tag(extra_cursor_selection, get_buffer()->begin(), get_buffer()->end());
return cleared; return cleared;
} }

9
src/source_base.hpp

@ -141,19 +141,21 @@ namespace Source {
void cleanup_whitespace_characters(const Gtk::TextIter &iter); void cleanup_whitespace_characters(const Gtk::TextIter &iter);
bool enable_multiple_cursors = false; bool enable_multiple_cursors = false;
Glib::RefPtr<Gtk::TextTag> extra_cursor_selection;
bool on_key_press_event(GdkEventKey *key) override; bool on_key_press_event(GdkEventKey *key) override;
bool on_key_press_event_extra_cursors(GdkEventKey *key); bool on_key_press_event_extra_cursors(GdkEventKey *key);
struct ExtraCursor { struct ExtraCursor {
Glib::RefPtr<Gtk::TextBuffer::Mark> mark; Glib::RefPtr<Gtk::TextBuffer::Mark> mark;
int offset; /// Used when moving cursor up/down lines
int line_offset;
}; };
std::vector<ExtraCursor> extra_cursors; std::vector<ExtraCursor> extra_cursors;
struct ExtraSnippetCursor { struct ExtraSnippetCursor {
Glib::RefPtr<Gtk::TextBuffer::Mark> mark; Glib::RefPtr<Gtk::TextBuffer::Mark> insert;
boost::optional<int> initial_forward_erase_size; Glib::RefPtr<Gtk::TextBuffer::Mark> selection_bound;
}; };
std::vector<ExtraSnippetCursor> extra_snippet_cursors; std::vector<ExtraSnippetCursor> extra_snippet_cursors;
@ -166,6 +168,7 @@ namespace Source {
std::vector<Snippets::Snippet> *snippets GUARDED_BY(snippets_mutex) = nullptr; std::vector<Snippets::Snippet> *snippets GUARDED_BY(snippets_mutex) = nullptr;
struct SnippetParameter { struct SnippetParameter {
Glib::RefPtr<Gtk::TextBuffer::Mark> start, end; Glib::RefPtr<Gtk::TextBuffer::Mark> start, end;
/// Used to check if the parameter has been deleted, and should be passed on next tab
int size; int size;
}; };
std::list<std::vector<SnippetParameter>> snippet_parameters_list; std::list<std::vector<SnippetParameter>> snippet_parameters_list;

Loading…
Cancel
Save