Browse Source

Improved snippet support

pipelines/235045657
eidheim 6 years ago
parent
commit
7e17bb6f23
  1. 4
      src/notebook.cpp
  2. 62
      src/source.cpp
  3. 193
      src/source_base.cpp
  4. 24
      src/source_base.hpp
  5. 414
      tests/source_test.cpp

4
src/notebook.cpp

@ -337,7 +337,7 @@ bool Notebook::open(const boost::filesystem::path &file_path_, Position position
} }
} }
if(!mark_moved) { if(!mark_moved) {
if(current_cursor_location != static_cast<size_t>(-1)) { if(current_cursor_location != static_cast<size_t>(-1) && current_cursor_location + 1 < cursor_locations.size()) {
for(auto it = cursor_locations.begin() + current_cursor_location + 1; it != cursor_locations.end();) { for(auto it = cursor_locations.begin() + current_cursor_location + 1; it != cursor_locations.end();) {
it->view->get_buffer()->delete_mark(it->mark); it->view->get_buffer()->delete_mark(it->mark);
it = cursor_locations.erase(it); it = cursor_locations.erase(it);
@ -348,7 +348,7 @@ bool Notebook::open(const boost::filesystem::path &file_path_, Position position
} }
// Combine adjacent cursor histories that are similar // Combine adjacent cursor histories that are similar
if(!cursor_locations.empty()) { if(cursor_locations.size() > 1) {
size_t cursor_locations_index = 1; size_t cursor_locations_index = 1;
auto last_it = cursor_locations.begin(); auto last_it = cursor_locations.begin();
for(auto it = cursor_locations.begin() + 1; it != cursor_locations.end();) { for(auto it = cursor_locations.begin() + 1; it != cursor_locations.end();) {

62
src/source.cpp

@ -2008,7 +2008,7 @@ bool Source::View::on_key_press_event(GdkEventKey *key) {
previous_non_modifier_keyval = last_keyval; previous_non_modifier_keyval = last_keyval;
last_keyval = key->keyval; last_keyval = key->keyval;
if((key->keyval == GDK_KEY_Tab || key->keyval == GDK_KEY_ISO_Left_Tab) && (key->state & GDK_SHIFT_MASK) == 0 && select_snippet_argument()) if((key->keyval == GDK_KEY_Tab || key->keyval == GDK_KEY_ISO_Left_Tab) && (key->state & GDK_SHIFT_MASK) == 0 && select_snippet_parameter())
return true; return true;
else if(key->keyval == GDK_KEY_Escape && clear_snippet_marks()) else if(key->keyval == GDK_KEY_Escape && clear_snippet_marks())
return true; return true;
@ -3150,8 +3150,8 @@ bool Source::View::on_key_press_event_extra_cursors(GdkEventKey *key) {
if(key->keyval == GDK_KEY_Escape && !extra_cursors.empty()) { if(key->keyval == GDK_KEY_Escape && !extra_cursors.empty()) {
for(auto &extra_cursor : extra_cursors) { for(auto &extra_cursor : extra_cursors) {
extra_cursor.first->set_visible(false); extra_cursor.mark->set_visible(false);
get_buffer()->delete_mark(extra_cursor.first); get_buffer()->delete_mark(extra_cursor.mark);
} }
extra_cursors.clear(); extra_cursors.clear();
return true; return true;
@ -3164,7 +3164,7 @@ bool Source::View::on_key_press_event_extra_cursors(GdkEventKey *key) {
if((key->keyval == GDK_KEY_Left || key->keyval == GDK_KEY_KP_Left) && (key->state & move_last_created_cursor_mask) == move_last_created_cursor_mask) { if((key->keyval == GDK_KEY_Left || key->keyval == GDK_KEY_KP_Left) && (key->state & move_last_created_cursor_mask) == move_last_created_cursor_mask) {
if(extra_cursors.empty()) if(extra_cursors.empty())
return false; return false;
auto &cursor = extra_cursors.back().first; auto &cursor = extra_cursors.back().mark;
auto iter = cursor->get_iter(); auto iter = cursor->get_iter();
iter.backward_char(); iter.backward_char();
get_buffer()->move_mark(cursor, iter); get_buffer()->move_mark(cursor, iter);
@ -3173,7 +3173,7 @@ bool Source::View::on_key_press_event_extra_cursors(GdkEventKey *key) {
if((key->keyval == GDK_KEY_Right || key->keyval == GDK_KEY_KP_Right) && (key->state & move_last_created_cursor_mask) == move_last_created_cursor_mask) { if((key->keyval == GDK_KEY_Right || key->keyval == GDK_KEY_KP_Right) && (key->state & move_last_created_cursor_mask) == move_last_created_cursor_mask) {
if(extra_cursors.empty()) if(extra_cursors.empty())
return false; return false;
auto &cursor = extra_cursors.back().first; auto &cursor = extra_cursors.back().mark;
auto iter = cursor->get_iter(); auto iter = cursor->get_iter();
iter.forward_char(); iter.forward_char();
get_buffer()->move_mark(cursor, iter); get_buffer()->move_mark(cursor, iter);
@ -3183,14 +3183,14 @@ bool Source::View::on_key_press_event_extra_cursors(GdkEventKey *key) {
if(extra_cursors.empty()) if(extra_cursors.empty())
return false; return false;
auto &extra_cursor = extra_cursors.back(); auto &extra_cursor = extra_cursors.back();
auto iter = extra_cursor.first->get_iter(); auto iter = extra_cursor.mark->get_iter();
auto line_offset = extra_cursor.second; auto line_offset = extra_cursor.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())
end_line_iter.forward_to_line_end(); end_line_iter.forward_to_line_end();
iter.forward_chars(std::min(line_offset, end_line_iter.get_line_offset())); iter.forward_chars(std::min(line_offset, end_line_iter.get_line_offset()));
get_buffer()->move_mark(extra_cursor.first, iter); get_buffer()->move_mark(extra_cursor.mark, iter);
} }
return true; return true;
} }
@ -3198,14 +3198,14 @@ bool Source::View::on_key_press_event_extra_cursors(GdkEventKey *key) {
if(extra_cursors.empty()) if(extra_cursors.empty())
return false; return false;
auto &extra_cursor = extra_cursors.back(); auto &extra_cursor = extra_cursors.back();
auto iter = extra_cursor.first->get_iter(); auto iter = extra_cursor.mark->get_iter();
auto line_offset = extra_cursor.second; auto line_offset = extra_cursor.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())
end_line_iter.forward_to_line_end(); end_line_iter.forward_to_line_end();
iter.forward_chars(std::min(line_offset, end_line_iter.get_line_offset())); iter.forward_chars(std::min(line_offset, end_line_iter.get_line_offset()));
get_buffer()->move_mark(extra_cursor.first, iter); get_buffer()->move_mark(extra_cursor.mark, iter);
} }
return true; return true;
} }
@ -3216,15 +3216,15 @@ bool Source::View::on_key_press_event_extra_cursors(GdkEventKey *key) {
auto insert_line_offset = insert_iter.get_line_offset(); auto insert_line_offset = insert_iter.get_line_offset();
auto offset = insert_iter.get_offset(); auto offset = insert_iter.get_offset();
for(auto &extra_cursor : extra_cursors) for(auto &extra_cursor : extra_cursors)
offset = std::min(offset, extra_cursor.first->get_iter().get_offset()); offset = std::min(offset, extra_cursor.mark->get_iter().get_offset());
auto iter = get_buffer()->get_iter_at_offset(offset); auto iter = get_buffer()->get_iter_at_offset(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())
end_line_iter.forward_to_line_end(); end_line_iter.forward_to_line_end();
iter.forward_chars(std::min(insert_line_offset, end_line_iter.get_line_offset())); iter.forward_chars(std::min(insert_line_offset, end_line_iter.get_line_offset()));
extra_cursors.emplace_back(get_buffer()->create_mark(iter, false), insert_line_offset); extra_cursors.emplace_back(ExtraCursor{get_buffer()->create_mark(iter, false), insert_line_offset});
extra_cursors.back().first->set_visible(true); extra_cursors.back().mark->set_visible(true);
} }
return true; return true;
} }
@ -3233,15 +3233,15 @@ bool Source::View::on_key_press_event_extra_cursors(GdkEventKey *key) {
auto insert_line_offset = insert_iter.get_line_offset(); auto insert_line_offset = insert_iter.get_line_offset();
auto offset = insert_iter.get_offset(); auto offset = insert_iter.get_offset();
for(auto &extra_cursor : extra_cursors) for(auto &extra_cursor : extra_cursors)
offset = std::max(offset, extra_cursor.first->get_iter().get_offset()); offset = std::max(offset, extra_cursor.mark->get_iter().get_offset());
auto iter = get_buffer()->get_iter_at_offset(offset); auto iter = get_buffer()->get_iter_at_offset(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())
end_line_iter.forward_to_line_end(); end_line_iter.forward_to_line_end();
iter.forward_chars(std::min(insert_line_offset, end_line_iter.get_line_offset())); iter.forward_chars(std::min(insert_line_offset, end_line_iter.get_line_offset()));
extra_cursors.emplace_back(get_buffer()->create_mark(iter, false), insert_line_offset); extra_cursors.emplace_back(ExtraCursor{get_buffer()->create_mark(iter, false), insert_line_offset});
extra_cursors.back().first->set_visible(true); extra_cursors.back().mark->set_visible(true);
} }
return true; return true;
} }
@ -3250,10 +3250,10 @@ bool Source::View::on_key_press_event_extra_cursors(GdkEventKey *key) {
if((key->keyval == GDK_KEY_Left || key->keyval == GDK_KEY_KP_Left) && (key->state & GDK_CONTROL_MASK) > 0) { if((key->keyval == GDK_KEY_Left || key->keyval == GDK_KEY_KP_Left) && (key->state & GDK_CONTROL_MASK) > 0) {
enable_multiple_cursors = false; enable_multiple_cursors = false;
for(auto &extra_cursor : extra_cursors) { for(auto &extra_cursor : extra_cursors) {
auto iter = extra_cursor.first->get_iter(); auto iter = extra_cursor.mark->get_iter();
iter.backward_word_start(); iter.backward_word_start();
extra_cursor.second = iter.get_line_offset(); extra_cursor.offset = iter.get_line_offset();
get_buffer()->move_mark(extra_cursor.first, iter); get_buffer()->move_mark(extra_cursor.mark, iter);
} }
auto insert = get_buffer()->get_insert(); auto insert = get_buffer()->get_insert();
auto iter = insert->get_iter(); auto iter = insert->get_iter();
@ -3266,10 +3266,10 @@ bool Source::View::on_key_press_event_extra_cursors(GdkEventKey *key) {
if((key->keyval == GDK_KEY_Right || key->keyval == GDK_KEY_KP_Right) && (key->state & GDK_CONTROL_MASK) > 0) { if((key->keyval == GDK_KEY_Right || key->keyval == GDK_KEY_KP_Right) && (key->state & GDK_CONTROL_MASK) > 0) {
enable_multiple_cursors = false; enable_multiple_cursors = false;
for(auto &extra_cursor : extra_cursors) { for(auto &extra_cursor : extra_cursors) {
auto iter = extra_cursor.first->get_iter(); auto iter = extra_cursor.mark->get_iter();
iter.forward_visible_word_end(); iter.forward_visible_word_end();
extra_cursor.second = iter.get_line_offset(); extra_cursor.offset = iter.get_line_offset();
get_buffer()->move_mark(extra_cursor.first, iter); get_buffer()->move_mark(extra_cursor.mark, iter);
} }
auto insert = get_buffer()->get_insert(); auto insert = get_buffer()->get_insert();
auto iter = insert->get_iter(); auto iter = insert->get_iter();
@ -3284,14 +3284,14 @@ bool Source::View::on_key_press_event_extra_cursors(GdkEventKey *key) {
if((key->keyval == GDK_KEY_Up || key->keyval == GDK_KEY_KP_Up)) { if((key->keyval == GDK_KEY_Up || key->keyval == GDK_KEY_KP_Up)) {
enable_multiple_cursors = false; enable_multiple_cursors = false;
for(auto &extra_cursor : extra_cursors) { for(auto &extra_cursor : extra_cursors) {
auto iter = extra_cursor.first->get_iter(); auto iter = extra_cursor.mark->get_iter();
auto line_offset = extra_cursor.second; auto line_offset = extra_cursor.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())
end_line_iter.forward_to_line_end(); end_line_iter.forward_to_line_end();
iter.forward_chars(std::min(line_offset, end_line_iter.get_line_offset())); iter.forward_chars(std::min(line_offset, end_line_iter.get_line_offset()));
get_buffer()->move_mark(extra_cursor.first, iter); get_buffer()->move_mark(extra_cursor.mark, iter);
} }
} }
return false; return false;
@ -3299,14 +3299,14 @@ bool Source::View::on_key_press_event_extra_cursors(GdkEventKey *key) {
if((key->keyval == GDK_KEY_Down || key->keyval == GDK_KEY_KP_Down)) { if((key->keyval == GDK_KEY_Down || key->keyval == GDK_KEY_KP_Down)) {
enable_multiple_cursors = false; enable_multiple_cursors = false;
for(auto &extra_cursor : extra_cursors) { for(auto &extra_cursor : extra_cursors) {
auto iter = extra_cursor.first->get_iter(); auto iter = extra_cursor.mark->get_iter();
auto line_offset = extra_cursor.second; auto line_offset = extra_cursor.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())
end_line_iter.forward_to_line_end(); end_line_iter.forward_to_line_end();
iter.forward_chars(std::min(line_offset, end_line_iter.get_line_offset())); iter.forward_chars(std::min(line_offset, end_line_iter.get_line_offset()));
get_buffer()->move_mark(extra_cursor.first, iter); get_buffer()->move_mark(extra_cursor.mark, iter);
} }
} }
return false; return false;
@ -3315,14 +3315,14 @@ bool Source::View::on_key_press_event_extra_cursors(GdkEventKey *key) {
// Smart Home-key, start of line // Smart Home-key, start of line
if((key->keyval == GDK_KEY_Home || key->keyval == GDK_KEY_KP_Home) && (key->state & GDK_CONTROL_MASK) == 0) { if((key->keyval == GDK_KEY_Home || key->keyval == GDK_KEY_KP_Home) && (key->state & GDK_CONTROL_MASK) == 0) {
for(auto &extra_cursor : extra_cursors) for(auto &extra_cursor : extra_cursors)
get_buffer()->move_mark(extra_cursor.first, get_smart_home_iter(extra_cursor.first->get_iter())); get_buffer()->move_mark(extra_cursor.mark, get_smart_home_iter(extra_cursor.mark->get_iter()));
enable_multiple_cursors = false; enable_multiple_cursors = false;
return false; return false;
} }
// Smart End-key, end of line // Smart End-key, end of line
if((key->keyval == GDK_KEY_End || key->keyval == GDK_KEY_KP_End) && (key->state & GDK_CONTROL_MASK) == 0) { if((key->keyval == GDK_KEY_End || key->keyval == GDK_KEY_KP_End) && (key->state & GDK_CONTROL_MASK) == 0) {
for(auto &extra_cursor : extra_cursors) for(auto &extra_cursor : extra_cursors)
get_buffer()->move_mark(extra_cursor.first, get_smart_end_iter(extra_cursor.first->get_iter())); get_buffer()->move_mark(extra_cursor.mark, get_smart_end_iter(extra_cursor.mark->get_iter()));
enable_multiple_cursors = false; enable_multiple_cursors = false;
return false; return false;
} }

193
src/source_base.cpp

@ -173,11 +173,11 @@ Source::BaseView::BaseView(const boost::filesystem::path &file_path, const Glib:
set_snippets(); set_snippets();
snippet_argument_tag = get_buffer()->create_tag(); snippet_parameter_tag = get_buffer()->create_tag();
Gdk::RGBA rgba; Gdk::RGBA rgba;
rgba.set_rgba(0.5, 0.5, 0.5, 0.4); rgba.set_rgba(0.5, 0.5, 0.5, 0.4);
snippet_argument_tag->property_background_rgba() = rgba; snippet_parameter_tag->property_background_rgba() = rgba;
snippet_argument_tag->property_background_set() = true; snippet_parameter_tag->property_background_set() = true;
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") {
@ -949,8 +949,8 @@ void Source::BaseView::setup_extra_cursor_signals() {
auto last_insert = get_buffer()->create_mark(get_buffer()->get_insert()->get_iter(), false); auto last_insert = get_buffer()->create_mark(get_buffer()->get_insert()->get_iter(), false);
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.first == mark && !iter.ends_line()) { if(extra_cursor.mark == mark && !iter.ends_line()) {
extra_cursor.second = std::max(extra_cursor.second, iter.get_line_offset()); extra_cursor.offset = std::max(extra_cursor.offset, iter.get_line_offset());
break; break;
} }
} }
@ -961,14 +961,14 @@ void Source::BaseView::setup_extra_cursor_signals() {
auto offset_diff = mark->get_iter().get_offset() - last_insert->get_iter().get_offset(); auto offset_diff = mark->get_iter().get_offset() - last_insert->get_iter().get_offset();
if(offset_diff != 0) { if(offset_diff != 0) {
for(auto &extra_cursor : extra_cursors) { for(auto &extra_cursor : extra_cursors) {
auto iter = extra_cursor.first->get_iter(); auto iter = extra_cursor.mark->get_iter();
iter.forward_chars(offset_diff); iter.forward_chars(offset_diff);
get_buffer()->move_mark(extra_cursor.first, 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->get_iter(); auto iter = extra_cursor.mark->get_iter();
iter.forward_chars(offset_diff); iter.forward_chars(offset_diff);
get_buffer()->move_mark(extra_cursor, iter); get_buffer()->move_mark(extra_cursor.mark, iter);
} }
} }
enable_multiple_cursors = true; enable_multiple_cursors = true;
@ -984,15 +984,15 @@ void Source::BaseView::setup_extra_cursor_signals() {
if(offset > 0) if(offset > 0)
offset -= text.size(); offset -= text.size();
for(auto &extra_cursor : extra_cursors) { for(auto &extra_cursor : extra_cursors) {
auto iter = extra_cursor.first->get_iter(); auto iter = extra_cursor.mark->get_iter();
iter.forward_chars(offset); iter.forward_chars(offset);
get_buffer()->insert(iter, text); get_buffer()->insert(iter, text);
auto extra_cursor_iter = extra_cursor.first->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.second = extra_cursor_iter.get_line_offset(); extra_cursor.offset = extra_cursor_iter.get_line_offset();
} }
for(auto &extra_cursor : extra_snippet_cursors) { for(auto &extra_cursor : extra_snippet_cursors) {
auto iter = extra_cursor->get_iter(); auto iter = extra_cursor.mark->get_iter();
iter.forward_chars(offset); iter.forward_chars(offset);
get_buffer()->insert(iter, text); get_buffer()->insert(iter, text);
} }
@ -1013,20 +1013,27 @@ void Source::BaseView::setup_extra_cursor_signals() {
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) {
auto start_iter = extra_cursor.first->get_iter(); auto start_iter = extra_cursor.mark->get_iter();
auto end_iter = start_iter; auto end_iter = start_iter;
start_iter.backward_chars(*erase_backward_length); start_iter.backward_chars(*erase_backward_length);
end_iter.forward_chars(*erase_forward_length); end_iter.forward_chars(*erase_forward_length);
get_buffer()->erase(start_iter, end_iter); get_buffer()->erase(start_iter, end_iter);
auto extra_cursor_iter = extra_cursor.first->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.second = extra_cursor_iter.get_line_offset(); extra_cursor.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->get_iter(); auto start_iter = extra_cursor.mark->get_iter();
auto end_iter = start_iter; auto end_iter = start_iter;
start_iter.backward_chars(*erase_backward_length); if(extra_cursor.parameter_size != std::numeric_limits<int>::max()) { // In case of different sized placeholders
end_iter.forward_chars(*erase_forward_length); if(*erase_backward_length == 0)
end_iter.forward_chars(extra_cursor.parameter_size);
extra_cursor.parameter_size = std::numeric_limits<int>::max();
}
else {
start_iter.backward_chars(*erase_backward_length);
end_iter.forward_chars(*erase_forward_length);
}
get_buffer()->erase(start_iter, end_iter); get_buffer()->erase(start_iter, end_iter);
} }
enable_multiple_cursors = true; enable_multiple_cursors = true;
@ -1037,13 +1044,16 @@ void Source::BaseView::setup_extra_cursor_signals() {
} }
void Source::BaseView::insert_snippet(Gtk::TextIter iter, const std::string &snippet) { void Source::BaseView::insert_snippet(Gtk::TextIter iter, const std::string &snippet) {
std::map<size_t, std::vector<std::pair<size_t, size_t>>> arguments_offsets; std::map<size_t, std::vector<std::pair<size_t, size_t>>> parameter_offsets_and_sizes_map;
std::string insert; std::string insert;
insert.reserve(snippet.size()); insert.reserve(snippet.size());
bool erase_line = false, erase_word = false;
size_t i = 0; size_t i = 0;
int number;
auto parse_number = [&snippet, &i, &number]() { auto parse_number = [&](int &number) {
if(i >= snippet.size()) if(i >= snippet.size())
throw std::out_of_range("unexpected end"); throw std::out_of_range("unexpected end");
std::string str; std::string str;
@ -1059,15 +1069,14 @@ void Source::BaseView::insert_snippet(Gtk::TextIter iter, const std::string &sni
return false; return false;
} }
}; };
auto compare_variable = [&snippet, &i](const char *text) { auto compare_variable = [&](const char *text) {
if(starts_with(snippet, i, text)) { if(starts_with(snippet, i, text)) {
i += strlen(text); i += strlen(text);
return true; return true;
} }
return false; return false;
}; };
bool erase_line = false, erase_word = false; auto parse_variable = [&] {
auto parse_variable = [this, &iter, &snippet, &i, &insert, &compare_variable, &erase_line, &erase_word] {
if(i >= snippet.size()) if(i >= snippet.size())
throw std::out_of_range("unexpected end"); throw std::out_of_range("unexpected end");
if(compare_variable("TM_SELECTED_TEXT")) { if(compare_variable("TM_SELECTED_TEXT")) {
@ -1125,41 +1134,46 @@ void Source::BaseView::insert_snippet(Gtk::TextIter iter, const std::string &sni
// TODO: support other variables // TODO: support other variables
return false; return false;
}; };
try {
bool escape = false; std::function<void(bool)> parse_snippet = [&](bool stop_at_curly_end) {
while(i < snippet.size()) { int number;
if(escape) { for(; i < snippet.size() && !(stop_at_curly_end && snippet[i] == '}');) {
insert += snippet[i]; if(snippet[i] == '\\') {
escape = false; if(i + 1 < snippet.size() &&
++i; (snippet[i + 1] == '$' || snippet[i + 1] == '`' || (stop_at_curly_end && snippet[i + 1] == '}'))) {
} insert += snippet[i + 1];
else if(snippet[i] == '\\') { i += 2;
escape = true; }
++i; else {
insert += '\\';
++i;
}
} }
else if(snippet[i] == '$') { else if(snippet[i] == '$') {
++i; ++i;
if(snippet.at(i) == '{') { if(snippet.at(i) == '{') {
++i; ++i;
if(parse_number()) { int number;
if(parse_number(number)) {
std::string placeholder; std::string placeholder;
if(snippet.at(i) == ':') { if(snippet.at(i) == ':') {
++i; ++i;
for(; snippet.at(i) != '}'; ++i) auto pos = insert.size();
placeholder += snippet[i]; parse_snippet(true);
placeholder = insert.substr(pos);
} }
if(snippet.at(i) != '}') if(snippet.at(i) != '}')
throw std::logic_error("closing } not found"); throw std::logic_error("closing } not found");
++i; ++i;
auto insert_character_count = utf8_character_count(insert); auto placeholder_character_count = utf8_character_count(placeholder);
arguments_offsets[number].emplace_back(insert_character_count, insert_character_count + utf8_character_count(placeholder)); parameter_offsets_and_sizes_map[number].emplace_back(utf8_character_count(insert) - placeholder_character_count, placeholder_character_count);
insert += placeholder;
} }
else { else {
if(!parse_variable()) { if(!parse_variable()) {
if(snippet.at(i) == ':') { // Use default value if(snippet.at(i) == ':') { // Use default value
++i; ++i;
parse_variable(); if(!parse_variable())
parse_snippet(true);
} }
} }
else if(snippet.at(i) == ':') { // Skip default value else if(snippet.at(i) == ':') { // Skip default value
@ -1171,28 +1185,31 @@ void Source::BaseView::insert_snippet(Gtk::TextIter iter, const std::string &sni
++i; ++i;
} }
} }
else if(parse_number()) { else if(parse_number(number))
auto insert_character_count = utf8_character_count(insert); parameter_offsets_and_sizes_map[number].emplace_back(utf8_character_count(insert), 0);
arguments_offsets[number].emplace_back(insert_character_count, insert_character_count);
}
else else
parse_variable(); parse_variable();
} }
else else {
insert += snippet[i++]; insert += snippet[i];
++i;
}
} }
};
try {
parse_snippet(false);
} }
catch(...) { catch(...) {
Terminal::get().print("Error: could not parse snippet: " + snippet + '\n', true); Terminal::get().print("Error: could not parse snippet: " + snippet + '\n', true);
return; return;
} }
// $0 should be last argument // $0 should be last parameter
auto it = arguments_offsets.find(0); auto it = parameter_offsets_and_sizes_map.find(0);
if(it != arguments_offsets.end()) { if(it != parameter_offsets_and_sizes_map.end()) {
auto rit = arguments_offsets.rbegin(); auto rit = parameter_offsets_and_sizes_map.rbegin();
arguments_offsets.emplace(rit->first + 1, std::move(it->second)); parameter_offsets_and_sizes_map.emplace(rit->first + 1, std::move(it->second));
arguments_offsets.erase(it); parameter_offsets_and_sizes_map.erase(it);
} }
auto mark = get_buffer()->create_mark(iter); auto mark = get_buffer()->create_mark(iter);
@ -1219,53 +1236,59 @@ 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 arguments_offsets_it = arguments_offsets.rbegin(); arguments_offsets_it != arguments_offsets.rend(); ++arguments_offsets_it) { for(auto it = parameter_offsets_and_sizes_map.rbegin(); it != parameter_offsets_and_sizes_map.rend(); ++it) {
snippets_marks.emplace_front(); snippet_parameters_list.emplace_front();
for(auto &offsets : arguments_offsets_it->second) { for(auto &offsets : it->second) {
auto start = iter; auto start = iter;
auto end = start;
start.forward_chars(offsets.first); start.forward_chars(offsets.first);
auto end = start;
end.forward_chars(offsets.second); end.forward_chars(offsets.second);
snippets_marks.front().emplace_back(get_buffer()->create_mark(start, false), get_buffer()->create_mark(end, false)); 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()});
get_buffer()->apply_tag(snippet_argument_tag, start, end);
} }
} }
if(!arguments_offsets.empty()) if(!parameter_offsets_and_sizes_map.empty())
select_snippet_argument(); select_snippet_parameter();
} }
bool Source::BaseView::select_snippet_argument() { 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->set_visible(false); extra_cursor.mark->set_visible(false);
get_buffer()->delete_mark(extra_cursor); get_buffer()->delete_mark(extra_cursor.mark);
} }
extra_snippet_cursors.clear(); extra_snippet_cursors.clear();
} }
if(!snippets_marks.empty()) { get_buffer()->remove_tag(snippet_parameter_tag, get_buffer()->begin(), get_buffer()->end());
auto snippets_marks_it = snippets_marks.begin(); if(!snippet_parameters_list.empty()) {
auto snippet_parameters_it = snippet_parameters_list.begin();
bool first = true; bool first = true;
for(auto &marks : *snippets_marks_it) { for(auto &snippet_parameter : *snippet_parameters_it) {
auto start = marks.first->get_iter(); auto start = snippet_parameter.start->get_iter();
auto end = marks.second->get_iter(); auto end = snippet_parameter.end->get_iter();
if(first) { if(first) {
if(snippet_parameter.size > 0 && end.get_offset() - start.get_offset() == 0) { // If the parameter has been erased
snippet_parameters_list.erase(snippet_parameters_it);
return select_snippet_parameter();
}
keep_snippet_marks = true; keep_snippet_marks = true;
get_buffer()->select_range(start, end); get_buffer()->select_range(start, end);
keep_snippet_marks = false; keep_snippet_marks = false;
first = false; first = false;
} }
else { else {
extra_snippet_cursors.emplace_back(get_buffer()->create_mark(start, false)); extra_snippet_cursors.emplace_back(ExtraSnippetCursor{get_buffer()->create_mark(start, false), end.get_offset() - start.get_offset()});
extra_snippet_cursors.back()->set_visible(true); extra_snippet_cursors.back().mark->set_visible(true);
get_buffer()->apply_tag(snippet_parameter_tag, start, end);
setup_extra_cursor_signals(); setup_extra_cursor_signals();
} }
get_buffer()->delete_mark(marks.first); get_buffer()->delete_mark(snippet_parameter.start);
get_buffer()->delete_mark(marks.second); get_buffer()->delete_mark(snippet_parameter.end);
} }
snippets_marks.erase(snippets_marks_it); snippet_parameters_list.erase(snippet_parameters_it);
return true; return true;
} }
return false; return false;
@ -1274,27 +1297,27 @@ bool Source::BaseView::select_snippet_argument() {
bool Source::BaseView::clear_snippet_marks() { bool Source::BaseView::clear_snippet_marks() {
bool cleared = false; bool cleared = false;
if(!snippets_marks.empty()) { if(!snippet_parameters_list.empty()) {
for(auto &snippet_marks : snippets_marks) { for(auto &snippet_parameters : snippet_parameters_list) {
for(auto &pair : snippet_marks) { for(auto &snippet_parameter : snippet_parameters) {
get_buffer()->delete_mark(pair.first); get_buffer()->delete_mark(snippet_parameter.start);
get_buffer()->delete_mark(pair.second); get_buffer()->delete_mark(snippet_parameter.end);
} }
} }
snippets_marks.clear(); snippet_parameters_list.clear();
cleared = true; cleared = true;
} }
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->set_visible(false); extra_cursor.mark->set_visible(false);
get_buffer()->delete_mark(extra_cursor); get_buffer()->delete_mark(extra_cursor.mark);
} }
extra_snippet_cursors.clear(); extra_snippet_cursors.clear();
cleared = true; cleared = true;
} }
get_buffer()->remove_tag(snippet_argument_tag, get_buffer()->begin(), get_buffer()->end()); get_buffer()->remove_tag(snippet_parameter_tag, get_buffer()->begin(), get_buffer()->end());
return cleared; return cleared;
} }

24
src/source_base.hpp

@ -141,19 +141,31 @@ namespace Source {
bool enable_multiple_cursors = false; bool enable_multiple_cursors = false;
std::vector<std::pair<Glib::RefPtr<Gtk::TextBuffer::Mark>, int>> extra_cursors; struct ExtraCursor {
std::vector<Glib::RefPtr<Gtk::TextBuffer::Mark>> extra_snippet_cursors; Glib::RefPtr<Gtk::TextBuffer::Mark> mark;
int offset;
};
std::vector<ExtraCursor> extra_cursors;
struct ExtraSnippetCursor {
Glib::RefPtr<Gtk::TextBuffer::Mark> mark;
int parameter_size;
};
std::vector<ExtraSnippetCursor> extra_snippet_cursors;
void setup_extra_cursor_signals(); void setup_extra_cursor_signals();
bool extra_cursors_signals_set = false; bool extra_cursors_signals_set = false;
/// After inserting a snippet, one can use tab to select the next argument /// After inserting a snippet, one can use tab to select the next parameter
bool keep_snippet_marks = false; bool keep_snippet_marks = false;
Mutex snippets_mutex; Mutex snippets_mutex;
std::vector<Snippets::Snippet> *snippets GUARDED_BY(snippets_mutex) = nullptr; std::vector<Snippets::Snippet> *snippets GUARDED_BY(snippets_mutex) = nullptr;
std::list<std::vector<std::pair<Glib::RefPtr<Gtk::TextBuffer::Mark>, Glib::RefPtr<Gtk::TextBuffer::Mark>>>> snippets_marks; struct SnippetParameter {
Glib::RefPtr<Gtk::TextTag> snippet_argument_tag; Glib::RefPtr<Gtk::TextBuffer::Mark> start, end;
int size;
};
std::list<std::vector<SnippetParameter>> snippet_parameters_list;
Glib::RefPtr<Gtk::TextTag> snippet_parameter_tag;
void insert_snippet(Gtk::TextIter iter, const std::string &snippet); void insert_snippet(Gtk::TextIter iter, const std::string &snippet);
bool select_snippet_argument(); bool select_snippet_parameter();
bool clear_snippet_marks(); bool clear_snippet_marks();
}; };
} // namespace Source } // namespace Source

414
tests/source_test.cpp

@ -59,19 +59,19 @@ int main() {
buffer->set_text(text); buffer->set_text(text);
buffer->place_cursor(buffer->begin()); buffer->place_cursor(buffer->begin());
view.replace_text(text); view.replace_text(text);
assert(buffer->get_text() == text); g_assert(buffer->get_text() == text);
assert(buffer->get_insert()->get_iter() == buffer->begin()); g_assert(buffer->get_insert()->get_iter() == buffer->begin());
buffer->place_cursor(buffer->end()); buffer->place_cursor(buffer->end());
view.replace_text(text); view.replace_text(text);
assert(buffer->get_text() == text); g_assert(buffer->get_text() == text);
assert(buffer->get_insert()->get_iter() == buffer->end()); g_assert(buffer->get_insert()->get_iter() == buffer->end());
view.place_cursor_at_line_offset(1, 0); view.place_cursor_at_line_offset(1, 0);
view.replace_text(text); view.replace_text(text);
assert(buffer->get_text() == text); g_assert(buffer->get_text() == text);
assert(buffer->get_insert()->get_iter().get_line() == 1); g_assert(buffer->get_insert()->get_iter().get_line() == 1);
assert(buffer->get_insert()->get_iter().get_line_offset() == 0); g_assert(buffer->get_insert()->get_iter().get_line_offset() == 0);
} }
{ {
auto old_text = "line 1\nline3"; auto old_text = "line 1\nline3";
@ -79,65 +79,65 @@ int main() {
buffer->set_text(old_text); buffer->set_text(old_text);
view.place_cursor_at_line_offset(1, 0); view.place_cursor_at_line_offset(1, 0);
view.replace_text(new_text); view.replace_text(new_text);
assert(buffer->get_text() == new_text); g_assert(buffer->get_text() == new_text);
assert(buffer->get_insert()->get_iter().get_line() == 2); g_assert(buffer->get_insert()->get_iter().get_line() == 2);
assert(buffer->get_insert()->get_iter().get_line_offset() == 0); g_assert(buffer->get_insert()->get_iter().get_line_offset() == 0);
view.replace_text(old_text); view.replace_text(old_text);
assert(buffer->get_text() == old_text); g_assert(buffer->get_text() == old_text);
assert(buffer->get_insert()->get_iter().get_line() == 1); g_assert(buffer->get_insert()->get_iter().get_line() == 1);
assert(buffer->get_insert()->get_iter().get_line_offset() == 0); g_assert(buffer->get_insert()->get_iter().get_line_offset() == 0);
view.place_cursor_at_line_offset(0, 0); view.place_cursor_at_line_offset(0, 0);
view.replace_text(new_text); view.replace_text(new_text);
assert(buffer->get_text() == new_text); g_assert(buffer->get_text() == new_text);
assert(buffer->get_insert()->get_iter().get_line() == 0); g_assert(buffer->get_insert()->get_iter().get_line() == 0);
assert(buffer->get_insert()->get_iter().get_line_offset() == 0); g_assert(buffer->get_insert()->get_iter().get_line_offset() == 0);
view.replace_text(old_text); view.replace_text(old_text);
assert(buffer->get_text() == old_text); g_assert(buffer->get_text() == old_text);
assert(buffer->get_insert()->get_iter().get_line() == 0); g_assert(buffer->get_insert()->get_iter().get_line() == 0);
assert(buffer->get_insert()->get_iter().get_line_offset() == 0); g_assert(buffer->get_insert()->get_iter().get_line_offset() == 0);
view.replace_text(new_text); view.replace_text(new_text);
assert(buffer->get_text() == new_text); g_assert(buffer->get_text() == new_text);
view.place_cursor_at_line_offset(2, 0); view.place_cursor_at_line_offset(2, 0);
view.replace_text(old_text); view.replace_text(old_text);
assert(buffer->get_text() == old_text); g_assert(buffer->get_text() == old_text);
assert(buffer->get_insert()->get_iter().get_line() == 1); g_assert(buffer->get_insert()->get_iter().get_line() == 1);
assert(buffer->get_insert()->get_iter().get_line_offset() == 0); g_assert(buffer->get_insert()->get_iter().get_line_offset() == 0);
} }
{ {
auto old_text = "line 1\nline 3"; auto old_text = "line 1\nline 3";
auto new_text = ""; auto new_text = "";
buffer->set_text(old_text); buffer->set_text(old_text);
view.replace_text(new_text); view.replace_text(new_text);
assert(buffer->get_text() == new_text); g_assert(buffer->get_text() == new_text);
view.replace_text(old_text); view.replace_text(old_text);
assert(buffer->get_text() == old_text); g_assert(buffer->get_text() == old_text);
assert(buffer->get_insert()->get_iter().get_line() == 1); g_assert(buffer->get_insert()->get_iter().get_line() == 1);
assert(buffer->get_insert()->get_iter().get_line_offset() == 6); g_assert(buffer->get_insert()->get_iter().get_line_offset() == 6);
} }
{ {
auto old_text = ""; auto old_text = "";
auto new_text = ""; auto new_text = "";
buffer->set_text(old_text); buffer->set_text(old_text);
view.replace_text(new_text); view.replace_text(new_text);
assert(buffer->get_text() == new_text); g_assert(buffer->get_text() == new_text);
} }
{ {
auto old_text = "line 1\nline 3\n"; auto old_text = "line 1\nline 3\n";
auto new_text = ""; auto new_text = "";
buffer->set_text(old_text); buffer->set_text(old_text);
view.replace_text(new_text); view.replace_text(new_text);
assert(buffer->get_text() == new_text); g_assert(buffer->get_text() == new_text);
view.replace_text(old_text); view.replace_text(old_text);
assert(buffer->get_text() == old_text); g_assert(buffer->get_text() == old_text);
assert(buffer->get_insert()->get_iter().get_line() == 2); g_assert(buffer->get_insert()->get_iter().get_line() == 2);
assert(buffer->get_insert()->get_iter().get_line_offset() == 0); g_assert(buffer->get_insert()->get_iter().get_line_offset() == 0);
} }
{ {
auto old_text = "line 1\n\nline 3\nline 4\n\nline 5\n"; auto old_text = "line 1\n\nline 3\nline 4\n\nline 5\n";
@ -145,16 +145,16 @@ int main() {
buffer->set_text(old_text); buffer->set_text(old_text);
view.place_cursor_at_line_offset(2, 0); view.place_cursor_at_line_offset(2, 0);
view.replace_text(new_text); view.replace_text(new_text);
assert(buffer->get_text() == new_text); g_assert(buffer->get_text() == new_text);
assert(buffer->get_insert()->get_iter().get_line() == 2); g_assert(buffer->get_insert()->get_iter().get_line() == 2);
assert(buffer->get_insert()->get_iter().get_line_offset() == 0); g_assert(buffer->get_insert()->get_iter().get_line_offset() == 0);
buffer->set_text(old_text); buffer->set_text(old_text);
view.place_cursor_at_line_offset(3, 0); view.place_cursor_at_line_offset(3, 0);
view.replace_text(new_text); view.replace_text(new_text);
assert(buffer->get_text() == new_text); g_assert(buffer->get_text() == new_text);
assert(buffer->get_insert()->get_iter().get_line() == 3); g_assert(buffer->get_insert()->get_iter().get_line() == 3);
assert(buffer->get_insert()->get_iter().get_line_offset() == 0); g_assert(buffer->get_insert()->get_iter().get_line_offset() == 0);
} }
{ {
auto old_text = "line 1\n\nline 3\nline 4\n\nline 5\n"; auto old_text = "line 1\n\nline 3\nline 4\n\nline 5\n";
@ -162,16 +162,16 @@ int main() {
buffer->set_text(old_text); buffer->set_text(old_text);
view.place_cursor_at_line_offset(2, 0); view.place_cursor_at_line_offset(2, 0);
view.replace_text(new_text); view.replace_text(new_text);
assert(buffer->get_text() == new_text); g_assert(buffer->get_text() == new_text);
assert(buffer->get_insert()->get_iter().get_line() == 2); g_assert(buffer->get_insert()->get_iter().get_line() == 2);
assert(buffer->get_insert()->get_iter().get_line_offset() == 0); g_assert(buffer->get_insert()->get_iter().get_line_offset() == 0);
buffer->set_text(old_text); buffer->set_text(old_text);
view.place_cursor_at_line_offset(3, 0); view.place_cursor_at_line_offset(3, 0);
view.replace_text(new_text); view.replace_text(new_text);
assert(buffer->get_text() == new_text); g_assert(buffer->get_text() == new_text);
assert(buffer->get_insert()->get_iter().get_line() == 4); g_assert(buffer->get_insert()->get_iter().get_line() == 4);
assert(buffer->get_insert()->get_iter().get_line_offset() == 0); g_assert(buffer->get_insert()->get_iter().get_line_offset() == 0);
} }
} }
@ -184,61 +184,61 @@ int main() {
{ {
view.place_cursor_at_line_offset(0, 0); view.place_cursor_at_line_offset(0, 0);
view.extend_selection(); view.extend_selection();
assert(view.get_selected_text() == "test"); g_assert(view.get_selected_text() == "test");
view.extend_selection(); view.extend_selection();
assert(view.get_selected_text() == "test(1, test(10), \"100\")"); g_assert(view.get_selected_text() == "test(1, test(10), \"100\")");
view.extend_selection(); view.extend_selection();
assert(view.get_selected_text() == source); g_assert(view.get_selected_text() == source);
} }
{ {
view.place_cursor_at_line_offset(0, 5); view.place_cursor_at_line_offset(0, 5);
view.extend_selection(); view.extend_selection();
assert(view.get_selected_text() == "1"); g_assert(view.get_selected_text() == "1");
view.extend_selection(); view.extend_selection();
assert(view.get_selected_text() == "1, test(10), \"100\""); g_assert(view.get_selected_text() == "1, test(10), \"100\"");
view.extend_selection(); view.extend_selection();
assert(view.get_selected_text() == "test(1, test(10), \"100\")"); g_assert(view.get_selected_text() == "test(1, test(10), \"100\")");
} }
{ {
view.place_cursor_at_line_offset(0, 7); view.place_cursor_at_line_offset(0, 7);
view.extend_selection(); view.extend_selection();
assert(view.get_selected_text() == " test(10)"); g_assert(view.get_selected_text() == " test(10)");
} }
{ {
view.place_cursor_at_line_offset(0, 8); view.place_cursor_at_line_offset(0, 8);
view.extend_selection(); view.extend_selection();
assert(view.get_selected_text() == "test"); g_assert(view.get_selected_text() == "test");
view.extend_selection(); view.extend_selection();
assert(view.get_selected_text() == "test(10)"); g_assert(view.get_selected_text() == "test(10)");
view.extend_selection(); view.extend_selection();
assert(view.get_selected_text() == " test(10)"); g_assert(view.get_selected_text() == " test(10)");
view.extend_selection(); view.extend_selection();
assert(view.get_selected_text() == "1, test(10), \"100\""); g_assert(view.get_selected_text() == "1, test(10), \"100\"");
} }
{ {
view.place_cursor_at_line_offset(0, 18); view.place_cursor_at_line_offset(0, 18);
view.extend_selection(); view.extend_selection();
assert(view.get_selected_text() == " \"100\""); g_assert(view.get_selected_text() == " \"100\"");
view.extend_selection(); view.extend_selection();
assert(view.get_selected_text() == "1, test(10), \"100\""); g_assert(view.get_selected_text() == "1, test(10), \"100\"");
} }
{ {
view.place_cursor_at_line_offset(0, 26); view.place_cursor_at_line_offset(0, 26);
view.extend_selection(); view.extend_selection();
assert(view.get_selected_text() == source); g_assert(view.get_selected_text() == source);
} }
{ {
view.place_cursor_at_line_offset(0, 27); view.place_cursor_at_line_offset(0, 27);
view.extend_selection(); view.extend_selection();
assert(view.get_selected_text() == source); g_assert(view.get_selected_text() == source);
} }
source = "int main() {\n return 1;\n}\n"; source = "int main() {\n return 1;\n}\n";
@ -246,47 +246,47 @@ int main() {
{ {
view.place_cursor_at_line_offset(0, 0); view.place_cursor_at_line_offset(0, 0);
view.extend_selection(); view.extend_selection();
assert(view.get_selected_text() == "int"); g_assert(view.get_selected_text() == "int");
view.extend_selection(); view.extend_selection();
assert(view.get_selected_text() == source.substr(0, source.size() - 1)); g_assert(view.get_selected_text() == source.substr(0, source.size() - 1));
view.extend_selection(); view.extend_selection();
assert(view.get_selected_text() == source); g_assert(view.get_selected_text() == source);
} }
{ {
view.place_cursor_at_line_offset(0, 4); view.place_cursor_at_line_offset(0, 4);
view.extend_selection(); view.extend_selection();
assert(view.get_selected_text() == "main"); g_assert(view.get_selected_text() == "main");
view.extend_selection(); view.extend_selection();
assert(view.get_selected_text() == source.substr(4, source.size() - 1 - 4)); g_assert(view.get_selected_text() == source.substr(4, source.size() - 1 - 4));
view.extend_selection(); view.extend_selection();
assert(view.get_selected_text() == source.substr(0, source.size() - 1)); g_assert(view.get_selected_text() == source.substr(0, source.size() - 1));
view.extend_selection(); view.extend_selection();
assert(view.get_selected_text() == source); g_assert(view.get_selected_text() == source);
} }
{ {
view.place_cursor_at_line_offset(1, 2); view.place_cursor_at_line_offset(1, 2);
view.extend_selection(); view.extend_selection();
assert(view.get_selected_text() == "return"); g_assert(view.get_selected_text() == "return");
view.extend_selection(); view.extend_selection();
assert(view.get_selected_text() == "return 1;"); g_assert(view.get_selected_text() == "return 1;");
view.extend_selection(); view.extend_selection();
assert(view.get_selected_text() == source.substr(12, 13)); g_assert(view.get_selected_text() == source.substr(12, 13));
view.extend_selection(); view.extend_selection();
assert(view.get_selected_text() == source.substr(4, source.size() - 1 - 4)); g_assert(view.get_selected_text() == source.substr(4, source.size() - 1 - 4));
view.extend_selection(); view.extend_selection();
assert(view.get_selected_text() == source.substr(0, source.size() - 1)); g_assert(view.get_selected_text() == source.substr(0, source.size() - 1));
view.extend_selection(); view.extend_selection();
assert(view.get_selected_text() == source); g_assert(view.get_selected_text() == source);
} }
source = "test<int, int>(11, 22);"; source = "test<int, int>(11, 22);";
@ -294,35 +294,35 @@ int main() {
{ {
view.place_cursor_at_line_offset(0, 0); view.place_cursor_at_line_offset(0, 0);
view.extend_selection(); view.extend_selection();
assert(view.get_selected_text() == "test"); g_assert(view.get_selected_text() == "test");
view.extend_selection(); view.extend_selection();
assert(view.get_selected_text() == source.substr(0, source.size() - 1)); g_assert(view.get_selected_text() == source.substr(0, source.size() - 1));
view.extend_selection(); view.extend_selection();
assert(view.get_selected_text() == source); g_assert(view.get_selected_text() == source);
} }
{ {
view.place_cursor_at_line_offset(0, 5); view.place_cursor_at_line_offset(0, 5);
view.extend_selection(); view.extend_selection();
assert(view.get_selected_text() == "int"); g_assert(view.get_selected_text() == "int");
view.extend_selection(); view.extend_selection();
assert(view.get_selected_text() == source.substr(5, 8)); g_assert(view.get_selected_text() == source.substr(5, 8));
view.extend_selection(); view.extend_selection();
assert(view.get_selected_text() == source.substr(0, source.size() - 1)); g_assert(view.get_selected_text() == source.substr(0, source.size() - 1));
} }
{ {
view.place_cursor_at_line_offset(0, 15); view.place_cursor_at_line_offset(0, 15);
view.extend_selection(); view.extend_selection();
assert(view.get_selected_text() == "11"); g_assert(view.get_selected_text() == "11");
view.extend_selection(); view.extend_selection();
assert(view.get_selected_text() == "11, 22"); g_assert(view.get_selected_text() == "11, 22");
view.extend_selection(); view.extend_selection();
assert(view.get_selected_text() == source.substr(0, source.size() - 1)); g_assert(view.get_selected_text() == source.substr(0, source.size() - 1));
} }
source = "{\n {\n test;\n }\n}\n"; source = "{\n {\n test;\n }\n}\n";
@ -330,34 +330,34 @@ int main() {
{ {
view.place_cursor_at_line_offset(2, 4); view.place_cursor_at_line_offset(2, 4);
view.extend_selection(); view.extend_selection();
assert(view.get_selected_text() == "test"); g_assert(view.get_selected_text() == "test");
view.extend_selection(); view.extend_selection();
assert(view.get_selected_text() == "test;"); g_assert(view.get_selected_text() == "test;");
view.extend_selection(); view.extend_selection();
assert(view.get_selected_text() == "\n test;\n "); g_assert(view.get_selected_text() == "\n test;\n ");
view.extend_selection(); view.extend_selection();
assert(view.get_selected_text() == "{\n test;\n }"); g_assert(view.get_selected_text() == "{\n test;\n }");
view.extend_selection(); view.extend_selection();
assert(view.get_selected_text() == "\n {\n test;\n }\n"); g_assert(view.get_selected_text() == "\n {\n test;\n }\n");
view.extend_selection(); view.extend_selection();
assert(view.get_selected_text() == "{\n {\n test;\n }\n}"); g_assert(view.get_selected_text() == "{\n {\n test;\n }\n}");
view.extend_selection(); view.extend_selection();
assert(view.get_selected_text() == source); g_assert(view.get_selected_text() == source);
view.shrink_selection(); view.shrink_selection();
assert(view.get_selected_text() == "{\n {\n test;\n }\n}"); g_assert(view.get_selected_text() == "{\n {\n test;\n }\n}");
view.shrink_selection(); view.shrink_selection();
assert(view.get_selected_text() == "\n {\n test;\n }\n"); g_assert(view.get_selected_text() == "\n {\n test;\n }\n");
view.shrink_selection(); view.shrink_selection();
assert(view.get_selected_text() == "{\n test;\n }"); g_assert(view.get_selected_text() == "{\n test;\n }");
} }
} }
@ -369,159 +369,205 @@ int main() {
{ {
buffer->set_text(""); buffer->set_text("");
view.insert_snippet(buffer->get_insert()->get_iter(), "std::cout << ${1:content} << std::endl;"); view.insert_snippet(buffer->get_insert()->get_iter(), "std::cout << ${1:content} << std::endl;");
assert(buffer->get_text() == "std::cout << content << std::endl;"); g_assert(buffer->get_text() == "std::cout << content << std::endl;");
Gtk::TextIter start, end; Gtk::TextIter start, end;
buffer->get_selection_bounds(start, end); buffer->get_selection_bounds(start, end);
assert(start.get_offset() == 13); g_assert(start.get_offset() == 13);
assert(end.get_offset() == 20); g_assert(end.get_offset() == 20);
event.keyval = GDK_KEY_t; event.keyval = GDK_KEY_t;
view.on_key_press_event(&event); view.on_key_press_event(&event);
assert(buffer->get_text() == "std::cout << t << std::endl;"); g_assert(buffer->get_text() == "std::cout << t << std::endl;");
event.keyval = GDK_KEY_e; event.keyval = GDK_KEY_e;
view.on_key_press_event(&event); view.on_key_press_event(&event);
assert(buffer->get_text() == "std::cout << te << std::endl;"); g_assert(buffer->get_text() == "std::cout << te << std::endl;");
} }
{ {
buffer->set_text(""); buffer->set_text("");
view.insert_snippet(buffer->get_insert()->get_iter(), "std::cout << ${1:} << std::endl;"); view.insert_snippet(buffer->get_insert()->get_iter(), "std::cout << ${1:} << std::endl;");
assert(buffer->get_text() == "std::cout << << std::endl;"); g_assert(buffer->get_text() == "std::cout << << std::endl;");
Gtk::TextIter start, end; Gtk::TextIter start, end;
buffer->get_selection_bounds(start, end); buffer->get_selection_bounds(start, end);
assert(start.get_offset() == 13); g_assert(start.get_offset() == 13);
assert(end.get_offset() == 13); g_assert(end.get_offset() == 13);
event.keyval = GDK_KEY_t; event.keyval = GDK_KEY_t;
view.on_key_press_event(&event); view.on_key_press_event(&event);
assert(buffer->get_text() == "std::cout << t << std::endl;"); g_assert(buffer->get_text() == "std::cout << t << std::endl;");
event.keyval = GDK_KEY_e; event.keyval = GDK_KEY_e;
view.on_key_press_event(&event); view.on_key_press_event(&event);
assert(buffer->get_text() == "std::cout << te << std::endl;"); g_assert(buffer->get_text() == "std::cout << te << std::endl;");
} }
{ {
buffer->set_text(""); buffer->set_text("");
view.insert_snippet(buffer->get_insert()->get_iter(), "std::cout << $1 << std::endl;"); view.insert_snippet(buffer->get_insert()->get_iter(), "std::cout << $1 << std::endl;");
assert(buffer->get_text() == "std::cout << << std::endl;"); g_assert(buffer->get_text() == "std::cout << << std::endl;");
Gtk::TextIter start, end; Gtk::TextIter start, end;
buffer->get_selection_bounds(start, end); buffer->get_selection_bounds(start, end);
assert(start.get_offset() == 13); g_assert(start.get_offset() == 13);
assert(end.get_offset() == 13); g_assert(end.get_offset() == 13);
event.keyval = GDK_KEY_t; event.keyval = GDK_KEY_t;
view.on_key_press_event(&event); view.on_key_press_event(&event);
assert(buffer->get_text() == "std::cout << t << std::endl;"); g_assert(buffer->get_text() == "std::cout << t << std::endl;");
event.keyval = GDK_KEY_e; event.keyval = GDK_KEY_e;
view.on_key_press_event(&event); view.on_key_press_event(&event);
assert(buffer->get_text() == "std::cout << te << std::endl;"); g_assert(buffer->get_text() == "std::cout << te << std::endl;");
} }
{ {
buffer->set_text(""); buffer->set_text("");
view.insert_snippet(buffer->get_insert()->get_iter(), "std::cout << ${1:content} << ${1:content} << std::endl;"); view.insert_snippet(buffer->get_insert()->get_iter(), "std::cout << ${1:content} << ${1:content} << std::endl;");
assert(buffer->get_text() == "std::cout << content << content << std::endl;"); g_assert(buffer->get_text() == "std::cout << content << content << std::endl;");
Gtk::TextIter start, end; Gtk::TextIter start, end;
buffer->get_selection_bounds(start, end); buffer->get_selection_bounds(start, end);
assert(start.get_offset() == 13); g_assert(start.get_offset() == 13);
assert(end.get_offset() == 20); g_assert(end.get_offset() == 20);
event.keyval = GDK_KEY_t; event.keyval = GDK_KEY_t;
view.on_key_press_event(&event); view.on_key_press_event(&event);
assert(buffer->get_text() == "std::cout << t << t << std::endl;"); g_assert(buffer->get_text() == "std::cout << t << t << std::endl;");
event.keyval = GDK_KEY_e; event.keyval = GDK_KEY_e;
view.on_key_press_event(&event); view.on_key_press_event(&event);
assert(buffer->get_text() == "std::cout << te << te << std::endl;"); g_assert(buffer->get_text() == "std::cout << te << te << std::endl;");
event.keyval = GDK_KEY_Escape; event.keyval = GDK_KEY_Escape;
view.on_key_press_event(&event); view.on_key_press_event(&event);
assert(buffer->get_text() == "std::cout << te << te << std::endl;"); g_assert(buffer->get_text() == "std::cout << te << te << std::endl;");
event.keyval = GDK_KEY_s; event.keyval = GDK_KEY_s;
view.on_key_press_event(&event); view.on_key_press_event(&event);
assert(buffer->get_text() == "std::cout << tes << te << std::endl;"); g_assert(buffer->get_text() == "std::cout << tes << te << std::endl;");
}
{
buffer->set_text("");
view.insert_snippet(buffer->get_insert()->get_iter(), "std::cout << ${1:content} << ${1:cont} << std::endl;");
g_assert(buffer->get_text() == "std::cout << content << cont << std::endl;");
Gtk::TextIter start, end;
buffer->get_selection_bounds(start, end);
g_assert(start.get_offset() == 13);
g_assert(end.get_offset() == 20);
event.keyval = GDK_KEY_t;
view.on_key_press_event(&event);
g_assert(buffer->get_text() == "std::cout << t << t << std::endl;");
event.keyval = GDK_KEY_e;
view.on_key_press_event(&event);
g_assert(buffer->get_text() == "std::cout << te << te << std::endl;");
event.keyval = GDK_KEY_Escape;
view.on_key_press_event(&event);
g_assert(buffer->get_text() == "std::cout << te << te << std::endl;");
event.keyval = GDK_KEY_s;
view.on_key_press_event(&event);
g_assert(buffer->get_text() == "std::cout << tes << te << std::endl;");
}
{
buffer->set_text("");
view.insert_snippet(buffer->get_insert()->get_iter(), "std::cout << ${1:content} << $1 << std::endl;");
g_assert(buffer->get_text() == "std::cout << content << << std::endl;");
Gtk::TextIter start, end;
buffer->get_selection_bounds(start, end);
g_assert(start.get_offset() == 13);
g_assert(end.get_offset() == 20);
event.keyval = GDK_KEY_t;
view.on_key_press_event(&event);
g_assert(buffer->get_text() == "std::cout << t << t << std::endl;");
event.keyval = GDK_KEY_e;
view.on_key_press_event(&event);
g_assert(buffer->get_text() == "std::cout << te << te << std::endl;");
event.keyval = GDK_KEY_Escape;
view.on_key_press_event(&event);
g_assert(buffer->get_text() == "std::cout << te << te << std::endl;");
event.keyval = GDK_KEY_s;
view.on_key_press_event(&event);
g_assert(buffer->get_text() == "std::cout << tes << te << std::endl;");
} }
{ {
buffer->set_text(""); buffer->set_text("");
view.insert_snippet(buffer->get_insert()->get_iter(), "std::cout << ${1:content1} << ${2:content2} << std::endl;"); view.insert_snippet(buffer->get_insert()->get_iter(), "std::cout << ${1:content1} << ${2:content2} << std::endl;");
assert(buffer->get_text() == "std::cout << content1 << content2 << std::endl;"); g_assert(buffer->get_text() == "std::cout << content1 << content2 << std::endl;");
Gtk::TextIter start, end; Gtk::TextIter start, end;
buffer->get_selection_bounds(start, end); buffer->get_selection_bounds(start, end);
assert(start.get_offset() == 13); g_assert(start.get_offset() == 13);
assert(end.get_offset() == 21); g_assert(end.get_offset() == 21);
event.keyval = GDK_KEY_t; event.keyval = GDK_KEY_t;
view.on_key_press_event(&event); view.on_key_press_event(&event);
assert(buffer->get_text() == "std::cout << t << content2 << std::endl;"); g_assert(buffer->get_text() == "std::cout << t << content2 << std::endl;");
event.keyval = GDK_KEY_e; event.keyval = GDK_KEY_e;
view.on_key_press_event(&event); view.on_key_press_event(&event);
assert(buffer->get_text() == "std::cout << te << content2 << std::endl;"); g_assert(buffer->get_text() == "std::cout << te << content2 << std::endl;");
event.keyval = GDK_KEY_Tab; event.keyval = GDK_KEY_Tab;
view.on_key_press_event(&event); view.on_key_press_event(&event);
assert(buffer->get_text() == "std::cout << te << content2 << std::endl;"); g_assert(buffer->get_text() == "std::cout << te << content2 << std::endl;");
event.keyval = GDK_KEY_t; event.keyval = GDK_KEY_t;
view.on_key_press_event(&event); view.on_key_press_event(&event);
assert(buffer->get_text() == "std::cout << te << t << std::endl;"); g_assert(buffer->get_text() == "std::cout << te << t << std::endl;");
} }
{ {
buffer->set_text(""); buffer->set_text("");
view.insert_snippet(buffer->get_insert()->get_iter(), "std::cout << ${1:content} << $0 << std::endl;"); view.insert_snippet(buffer->get_insert()->get_iter(), "std::cout << ${1:content} << $0 << std::endl;");
assert(buffer->get_text() == "std::cout << content << << std::endl;"); g_assert(buffer->get_text() == "std::cout << content << << std::endl;");
Gtk::TextIter start, end; Gtk::TextIter start, end;
buffer->get_selection_bounds(start, end); buffer->get_selection_bounds(start, end);
assert(start.get_offset() == 13); g_assert(start.get_offset() == 13);
assert(end.get_offset() == 20); g_assert(end.get_offset() == 20);
event.keyval = GDK_KEY_t; event.keyval = GDK_KEY_t;
view.on_key_press_event(&event); view.on_key_press_event(&event);
assert(buffer->get_text() == "std::cout << t << << std::endl;"); g_assert(buffer->get_text() == "std::cout << t << << std::endl;");
event.keyval = GDK_KEY_e; event.keyval = GDK_KEY_e;
view.on_key_press_event(&event); view.on_key_press_event(&event);
assert(buffer->get_text() == "std::cout << te << << std::endl;"); g_assert(buffer->get_text() == "std::cout << te << << std::endl;");
event.keyval = GDK_KEY_Tab; event.keyval = GDK_KEY_Tab;
view.on_key_press_event(&event); view.on_key_press_event(&event);
assert(buffer->get_text() == "std::cout << te << << std::endl;"); g_assert(buffer->get_text() == "std::cout << te << << std::endl;");
event.keyval = GDK_KEY_t; event.keyval = GDK_KEY_t;
view.on_key_press_event(&event); view.on_key_press_event(&event);
assert(buffer->get_text() == "std::cout << te << t << std::endl;"); g_assert(buffer->get_text() == "std::cout << te << t << std::endl;");
} }
{ {
buffer->set_text(""); buffer->set_text("");
view.insert_snippet(buffer->get_insert()->get_iter(), "std::cout << ${2:content2} << ${1:content1} << std::endl;"); view.insert_snippet(buffer->get_insert()->get_iter(), "std::cout << ${2:content2} << ${1:content1} << std::endl;");
assert(buffer->get_text() == "std::cout << content2 << content1 << std::endl;"); g_assert(buffer->get_text() == "std::cout << content2 << content1 << std::endl;");
Gtk::TextIter start, end; Gtk::TextIter start, end;
buffer->get_selection_bounds(start, end); buffer->get_selection_bounds(start, end);
assert(start.get_offset() == 25); g_assert(start.get_offset() == 25);
assert(end.get_offset() == 33); g_assert(end.get_offset() == 33);
event.keyval = GDK_KEY_t; event.keyval = GDK_KEY_t;
view.on_key_press_event(&event); view.on_key_press_event(&event);
assert(buffer->get_text() == "std::cout << content2 << t << std::endl;"); g_assert(buffer->get_text() == "std::cout << content2 << t << std::endl;");
event.keyval = GDK_KEY_e; event.keyval = GDK_KEY_e;
view.on_key_press_event(&event); view.on_key_press_event(&event);
assert(buffer->get_text() == "std::cout << content2 << te << std::endl;"); g_assert(buffer->get_text() == "std::cout << content2 << te << std::endl;");
event.keyval = GDK_KEY_Tab; event.keyval = GDK_KEY_Tab;
view.on_key_press_event(&event); view.on_key_press_event(&event);
assert(buffer->get_text() == "std::cout << content2 << te << std::endl;"); g_assert(buffer->get_text() == "std::cout << content2 << te << std::endl;");
event.keyval = GDK_KEY_t; event.keyval = GDK_KEY_t;
view.on_key_press_event(&event); view.on_key_press_event(&event);
assert(buffer->get_text() == "std::cout << t << te << std::endl;"); g_assert(buffer->get_text() == "std::cout << t << te << std::endl;");
} }
{ {
buffer->set_text("test"); buffer->set_text("test");
buffer->select_range(buffer->begin(), buffer->end()); buffer->select_range(buffer->begin(), buffer->end());
view.insert_snippet(buffer->get_insert()->get_iter(), "<$1>${TM_SELECTED_TEXT}</$1>"); view.insert_snippet(buffer->get_insert()->get_iter(), "<$1>${TM_SELECTED_TEXT}</$1>");
assert(buffer->get_text() == "<>test</>"); g_assert(buffer->get_text() == "<>test</>");
Gtk::TextIter start, end; Gtk::TextIter start, end;
buffer->get_selection_bounds(start, end); buffer->get_selection_bounds(start, end);
assert(start.get_offset() == 1); g_assert(start.get_offset() == 1);
assert(end.get_offset() == 1); g_assert(end.get_offset() == 1);
event.keyval = GDK_KEY_t; event.keyval = GDK_KEY_t;
view.on_key_press_event(&event); view.on_key_press_event(&event);
assert(buffer->get_text() == "<t>test</t>"); g_assert(buffer->get_text() == "<t>test</t>");
event.keyval = GDK_KEY_e; event.keyval = GDK_KEY_e;
view.on_key_press_event(&event); view.on_key_press_event(&event);
assert(buffer->get_text() == "<te>test</te>"); g_assert(buffer->get_text() == "<te>test</te>");
} }
{ {
buffer->set_text("test test"); buffer->set_text("test test");
@ -531,33 +577,103 @@ int main() {
end.forward_chars(4); end.forward_chars(4);
buffer->select_range(start, end); buffer->select_range(start, end);
view.insert_snippet(buffer->get_insert()->get_iter(), "<$1>${TM_SELECTED_TEXT:TM_CURRENT_LINE}</$1>"); view.insert_snippet(buffer->get_insert()->get_iter(), "<$1>${TM_SELECTED_TEXT:TM_CURRENT_LINE}</$1>");
assert(buffer->get_text() == "<>test</> test"); g_assert(buffer->get_text() == "<>test</> test");
buffer->get_selection_bounds(start, end); buffer->get_selection_bounds(start, end);
assert(start.get_offset() == 1); g_assert(start.get_offset() == 1);
assert(end.get_offset() == 1); g_assert(end.get_offset() == 1);
event.keyval = GDK_KEY_t; event.keyval = GDK_KEY_t;
view.on_key_press_event(&event); view.on_key_press_event(&event);
assert(buffer->get_text() == "<t>test</t> test"); g_assert(buffer->get_text() == "<t>test</t> test");
event.keyval = GDK_KEY_e; event.keyval = GDK_KEY_e;
view.on_key_press_event(&event); view.on_key_press_event(&event);
assert(buffer->get_text() == "<te>test</te> test"); g_assert(buffer->get_text() == "<te>test</te> test");
} }
{ {
buffer->set_text("test test"); buffer->set_text("test test");
view.insert_snippet(buffer->get_insert()->get_iter(), "<$1>${TM_SELECTED_TEXT:TM_CURRENT_LINE}</$1>"); view.insert_snippet(buffer->get_insert()->get_iter(), "<$1>${TM_SELECTED_TEXT:TM_CURRENT_LINE}</$1>");
assert(buffer->get_text() == "<>test test</>"); g_assert(buffer->get_text() == "<>test test</>");
Gtk::TextIter start, end;
buffer->get_selection_bounds(start, end);
g_assert(start.get_offset() == 1);
g_assert(end.get_offset() == 1);
event.keyval = GDK_KEY_t;
view.on_key_press_event(&event);
g_assert(buffer->get_text() == "<t>test test</t>");
event.keyval = GDK_KEY_e;
view.on_key_press_event(&event);
g_assert(buffer->get_text() == "<te>test test</te>");
}
{
buffer->set_text("");
view.insert_snippet(buffer->get_insert()->get_iter(), "\\textbf{${TM_SELECTED_TEXT:no text was selected}}");
g_assert(buffer->get_text() == "\\textbf{no text was selected}");
g_assert(buffer->get_insert()->get_iter().get_offset() == 29);
}
{
buffer->set_text("");
view.insert_snippet(buffer->get_insert()->get_iter(), "<div${1: id=\"${2:some_id}\"}>\n $0\n</div>");
auto result = "<div id=\"some_id\">\n \n</div>";
g_assert(buffer->get_text() == result);
Gtk::TextIter start, end; Gtk::TextIter start, end;
buffer->get_selection_bounds(start, end); buffer->get_selection_bounds(start, end);
assert(start.get_offset() == 1); g_assert(start.get_offset() == 4);
assert(end.get_offset() == 1); g_assert(end.get_offset() == 17);
event.keyval = GDK_KEY_Tab;
view.on_key_press_event(&event);
g_assert(buffer->get_text() == result);
buffer->get_selection_bounds(start, end);
g_assert(start.get_offset() == 9);
g_assert(end.get_offset() == 16);
event.keyval = GDK_KEY_Tab;
view.on_key_press_event(&event);
g_assert(buffer->get_text() == result);
g_assert(buffer->get_insert()->get_iter().get_offset() == 21);
}
{
buffer->set_text("");
view.insert_snippet(buffer->get_insert()->get_iter(), "<div${1: id=\"${2:some_id}\"}>\n $0\n</div>");
g_assert(buffer->get_text() == "<div id=\"some_id\">\n \n</div>");
Gtk::TextIter start, end;
buffer->get_selection_bounds(start, end);
g_assert(start.get_offset() == 4);
g_assert(end.get_offset() == 17);
event.keyval = GDK_KEY_t; event.keyval = GDK_KEY_t;
view.on_key_press_event(&event); view.on_key_press_event(&event);
assert(buffer->get_text() == "<t>test test</t>"); g_assert(buffer->get_text() == "<divt>\n \n</div>");
buffer->get_selection_bounds(start, end);
g_assert(start.get_offset() == 5);
g_assert(end.get_offset() == 5);
event.keyval = GDK_KEY_Tab;
view.on_key_press_event(&event);
g_assert(buffer->get_text() == "<divt>\n \n</div>");
g_assert(buffer->get_insert()->get_iter().get_offset() == 9);
}
{
buffer->set_text("");
view.insert_snippet(buffer->get_insert()->get_iter(), "\\begin{${1:enumerate}}\n $0\n\\end{$1}");
g_assert(buffer->get_text() == "\\begin{enumerate}\n \n\\end{}");
Gtk::TextIter start, end;
buffer->get_selection_bounds(start, end);
g_assert(start.get_offset() == 7);
g_assert(end.get_offset() == 16);
event.keyval = GDK_KEY_t;
view.on_key_press_event(&event);
g_assert(buffer->get_text() == "\\begin{t}\n \n\\end{t}");
event.keyval = GDK_KEY_e; event.keyval = GDK_KEY_e;
view.on_key_press_event(&event); view.on_key_press_event(&event);
assert(buffer->get_text() == "<te>test test</te>"); g_assert(buffer->get_text() == "\\begin{te}\n \n\\end{te}");
event.keyval = GDK_KEY_Tab;
view.on_key_press_event(&event);
g_assert(buffer->get_text() == "\\begin{te}\n \n\\end{te}");
g_assert(buffer->get_insert()->get_iter().get_offset() == 13);
} }
} }
} }

Loading…
Cancel
Save