From d88c40fdcfb1509850aa7ec1f230eee76bfe9bdf Mon Sep 17 00:00:00 2001 From: eidheim Date: Thu, 18 Jun 2020 14:38:11 +0200 Subject: [PATCH] Slightly improved snippet cursor behaviour, and multiple snippet parameter selections are now shown --- src/source.cpp | 10 +++++ src/source_base.cpp | 99 ++++++++++++++++++++++++++++----------------- src/source_base.hpp | 9 +++-- 3 files changed, 78 insertions(+), 40 deletions(-) diff --git a/src/source.cpp b/src/source.cpp index f9560da..253c846 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -499,6 +499,16 @@ void Source::View::configure() { } //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()) { get_completion()->unblock_interactive(); interactive_completion = true; diff --git a/src/source_base.cpp b/src/source_base.cpp index f97818c..299e287 100644 --- a/src/source_base.cpp +++ b/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_set() = true; + extra_cursor_selection = get_buffer()->create_tag(); + get_buffer()->signal_mark_set().connect([this](const Gtk::TextBuffer::iterator &iter, const Glib::RefPtr &mark) { if(mark->get_name() == "insert") { keep_clipboard = false; @@ -997,7 +999,7 @@ bool Source::BaseView::on_key_press_event(GdkEventKey *key) { for(auto &extra_cursor : extra_cursors) { auto iter = extra_cursor.mark->get_iter(); 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); } 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) { auto iter = extra_cursor.mark->get_iter(); 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); } auto insert = get_buffer()->get_insert(); @@ -1070,7 +1072,7 @@ bool Source::BaseView::on_key_press_event_extra_cursors(GdkEventKey *key) { return false; auto &extra_cursor = extra_cursors.back(); auto iter = extra_cursor.mark->get_iter(); - auto line_offset = extra_cursor.offset; + auto line_offset = extra_cursor.line_offset; if(iter.backward_line()) { auto end_line_iter = iter; if(!end_line_iter.ends_line()) @@ -1085,7 +1087,7 @@ bool Source::BaseView::on_key_press_event_extra_cursors(GdkEventKey *key) { return false; auto &extra_cursor = extra_cursors.back(); auto iter = extra_cursor.mark->get_iter(); - auto line_offset = extra_cursor.offset; + auto line_offset = extra_cursor.line_offset; if(iter.forward_line()) { auto end_line_iter = iter; 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; for(auto &extra_cursor : extra_cursors) { auto iter = extra_cursor.mark->get_iter(); - auto line_offset = extra_cursor.offset; + auto line_offset = extra_cursor.line_offset; if(iter.backward_line()) { auto end_line_iter = iter; 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; for(auto &extra_cursor : extra_cursors) { auto iter = extra_cursor.mark->get_iter(); - auto line_offset = extra_cursor.offset; + auto line_offset = extra_cursor.line_offset; if(iter.forward_line()) { auto end_line_iter = iter; 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 &mark) mutable { for(auto &extra_cursor : extra_cursors) { 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; } } @@ -1207,9 +1209,9 @@ void Source::BaseView::setup_extra_cursor_signals() { get_buffer()->move_mark(extra_cursor.mark, iter); } 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); - get_buffer()->move_mark(extra_cursor.mark, iter); + get_buffer()->move_mark(extra_cursor.insert, iter); } } enable_multiple_cursors = true; @@ -1230,11 +1232,15 @@ void Source::BaseView::setup_extra_cursor_signals() { get_buffer()->insert(iter, text); auto extra_cursor_iter = extra_cursor.mark->get_iter(); 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) { - extra_cursor.initial_forward_erase_size.reset(); - auto iter = extra_cursor.mark->get_iter(); + auto start_iter = extra_cursor.insert->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); get_buffer()->insert(iter, text); } @@ -1244,14 +1250,22 @@ void Source::BaseView::setup_extra_cursor_signals() { auto erase_backward_length = std::make_shared(0); auto erase_forward_length = std::make_shared(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(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())) { auto insert_offset = get_buffer()->get_insert()->get_iter().get_offset(); *erase_backward_length = insert_offset - iter_start.get_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); - 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)) { enable_multiple_cursors = false; for(auto &extra_cursor : extra_cursors) { @@ -1262,23 +1276,28 @@ void Source::BaseView::setup_extra_cursor_signals() { get_buffer()->erase(start_iter, end_iter); auto extra_cursor_iter = extra_cursor.mark->get_iter(); 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) { - auto start_iter = extra_cursor.mark->get_iter(); - auto end_iter = start_iter; - start_iter.backward_chars(*erase_backward_length); - if(extra_cursor.initial_forward_erase_size) { // In case of different sized placeholders - end_iter.forward_chars(*extra_cursor.initial_forward_erase_size); - extra_cursor.initial_forward_erase_size.reset(); - } - else + if(*erase_selection) + get_buffer()->erase(extra_cursor.insert->get_iter(), extra_cursor.selection_bound->get_iter()); + else { + auto start_iter = extra_cursor.insert->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); + + start_iter = extra_cursor.insert->get_iter(); + end_iter = start_iter; 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; *erase_backward_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 auto it = parameter_offsets_and_sizes_map.find(0); if(it != parameter_offsets_and_sizes_map.end()) { - auto rit = parameter_offsets_and_sizes_map.rbegin(); - parameter_offsets_and_sizes_map.emplace(rit->first + 1, std::move(it->second)); + parameter_offsets_and_sizes_map.emplace(parameter_offsets_and_sizes_map.rbegin()->first + 1, std::move(it->second)); 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(); get_buffer()->delete_mark(mark); - for(auto it = parameter_offsets_and_sizes_map.rbegin(); it != parameter_offsets_and_sizes_map.rend(); ++it) { - snippet_parameters_list.emplace_front(); - for(auto &offsets : it->second) { + for(auto ¶meter_offsets_and_sized : parameter_offsets_and_sizes_map) { + snippet_parameters_list.emplace_back(); + for(auto &offsets : parameter_offsets_and_sized.second) { auto start = iter; start.forward_chars(offsets.first); auto end = start; 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() { if(!extra_snippet_cursors.empty()) { for(auto &extra_cursor : extra_snippet_cursors) { - extra_cursor.mark->set_visible(false); - get_buffer()->delete_mark(extra_cursor.mark); + extra_cursor.insert->set_visible(false); + get_buffer()->delete_mark(extra_cursor.insert); + get_buffer()->delete_mark(extra_cursor.selection_bound); } extra_snippet_cursors.clear(); } 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 ¶meters : snippet_parameters_list) { for(auto ¶meter : 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()) { @@ -1539,8 +1562,8 @@ bool Source::BaseView::select_snippet_parameter() { first = false; } else { - extra_snippet_cursors.emplace_back(ExtraSnippetCursor{get_buffer()->create_mark(start, false), end.get_offset() - start.get_offset()}); - extra_snippet_cursors.back().mark->set_visible(true); + extra_snippet_cursors.emplace_back(ExtraSnippetCursor{get_buffer()->create_mark(start, false), get_buffer()->create_mark(end, false)}); + extra_snippet_cursors.back().insert->set_visible(true); setup_extra_cursor_signals(); } @@ -1569,14 +1592,16 @@ bool Source::BaseView::clear_snippet_marks() { if(!extra_snippet_cursors.empty()) { for(auto &extra_cursor : extra_snippet_cursors) { - extra_cursor.mark->set_visible(false); - get_buffer()->delete_mark(extra_cursor.mark); + extra_cursor.insert->set_visible(false); + get_buffer()->delete_mark(extra_cursor.insert); + get_buffer()->delete_mark(extra_cursor.selection_bound); } extra_snippet_cursors.clear(); cleared = true; } 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; } diff --git a/src/source_base.hpp b/src/source_base.hpp index 214297a..12d8e42 100644 --- a/src/source_base.hpp +++ b/src/source_base.hpp @@ -141,19 +141,21 @@ namespace Source { void cleanup_whitespace_characters(const Gtk::TextIter &iter); bool enable_multiple_cursors = false; + Glib::RefPtr extra_cursor_selection; bool on_key_press_event(GdkEventKey *key) override; bool on_key_press_event_extra_cursors(GdkEventKey *key); struct ExtraCursor { Glib::RefPtr mark; - int offset; + /// Used when moving cursor up/down lines + int line_offset; }; std::vector extra_cursors; struct ExtraSnippetCursor { - Glib::RefPtr mark; - boost::optional initial_forward_erase_size; + Glib::RefPtr insert; + Glib::RefPtr selection_bound; }; std::vector extra_snippet_cursors; @@ -166,6 +168,7 @@ namespace Source { std::vector *snippets GUARDED_BY(snippets_mutex) = nullptr; struct SnippetParameter { Glib::RefPtr start, end; + /// Used to check if the parameter has been deleted, and should be passed on next tab int size; }; std::list> snippet_parameters_list;