1 #include "config.hpp"
2 #include "filesystem.hpp"
3 #include "source.hpp"
4 #include <glib.h>
5 
6 std::string hello_world = R"(#include <iostream>
7 
8 int main() {
9   std::cout << "hello world\n";
10 })";
11 
12 std::string hello_world_cleaned = R"(#include <iostream>
13 
14 int main() {
15   std::cout << "hello world\n";
16 }
17 )";
18 
19 //Requires display server to work
20 //However, it is possible to use the Broadway backend if the test is run in a pure terminal environment:
21 //broadwayd&
22 //make test
23 
main()24 int main() {
25   auto app = Gtk::Application::create();
26   Gsv::init();
27 
28   auto tests_path = boost::filesystem::canonical(JUCI_TESTS_PATH);
29   auto source_file = tests_path / "tmp" / "source_file.cpp";
30 
31   {
32     Source::View view(source_file, Glib::RefPtr<Gsv::Language>());
33     view.get_buffer()->set_text(hello_world);
34     g_assert(view.save());
35   }
36 
37   Source::View view(source_file, Glib::RefPtr<Gsv::Language>());
38   g_assert(view.get_buffer()->get_text() == hello_world);
39   view.cleanup_whitespace_characters();
40   g_assert(view.get_buffer()->get_text() == hello_world_cleaned);
41 
42   g_assert(boost::filesystem::remove(source_file));
43   g_assert(!boost::filesystem::exists(source_file));
44 
45   for(int c = 0; c < 2; ++c) {
46     size_t found = 0;
47     auto style_scheme_manager = Source::StyleSchemeManager::get_default();
48     for(auto &search_path : style_scheme_manager->get_search_path()) {
49       if(search_path == Config::get().home_juci_path / "styles") // found added style
50         ++found;
51     }
52     g_assert(found == 1);
53   }
54 
55   // replace_text tests
56   {
57     auto buffer = view.get_buffer();
58     {
59       auto text = "line 1\nline 2\nline3";
60       buffer->set_text(text);
61       buffer->place_cursor(buffer->begin());
62       view.replace_text(text);
63       g_assert(buffer->get_text() == text);
64       g_assert(buffer->get_insert()->get_iter() == buffer->begin());
65 
66       buffer->place_cursor(buffer->end());
67       view.replace_text(text);
68       g_assert(buffer->get_text() == text);
69       g_assert(buffer->get_insert()->get_iter() == buffer->end());
70 
71       view.place_cursor_at_line_offset(1, 0);
72       view.replace_text(text);
73       g_assert(buffer->get_text() == text);
74       g_assert(buffer->get_insert()->get_iter().get_line() == 1);
75       g_assert(buffer->get_insert()->get_iter().get_line_offset() == 0);
76     }
77     {
78       auto old_text = "line 1\nline3";
79       auto new_text = "line 1\nline 2\nline3";
80       buffer->set_text(old_text);
81       view.place_cursor_at_line_offset(1, 0);
82       view.replace_text(new_text);
83       g_assert(buffer->get_text() == new_text);
84       g_assert(buffer->get_insert()->get_iter().get_line() == 2);
85       g_assert(buffer->get_insert()->get_iter().get_line_offset() == 0);
86 
87       view.replace_text(old_text);
88       g_assert(buffer->get_text() == old_text);
89       g_assert(buffer->get_insert()->get_iter().get_line() == 1);
90       g_assert(buffer->get_insert()->get_iter().get_line_offset() == 0);
91 
92       view.place_cursor_at_line_offset(0, 0);
93       view.replace_text(new_text);
94       g_assert(buffer->get_text() == new_text);
95       g_assert(buffer->get_insert()->get_iter().get_line() == 0);
96       g_assert(buffer->get_insert()->get_iter().get_line_offset() == 0);
97 
98       view.replace_text(old_text);
99       g_assert(buffer->get_text() == old_text);
100       g_assert(buffer->get_insert()->get_iter().get_line() == 0);
101       g_assert(buffer->get_insert()->get_iter().get_line_offset() == 0);
102 
103       view.replace_text(new_text);
104       g_assert(buffer->get_text() == new_text);
105 
106       view.place_cursor_at_line_offset(2, 0);
107       view.replace_text(old_text);
108       g_assert(buffer->get_text() == old_text);
109       g_assert(buffer->get_insert()->get_iter().get_line() == 1);
110       g_assert(buffer->get_insert()->get_iter().get_line_offset() == 0);
111     }
112     {
113       auto old_text = "line 1\nline 3";
114       auto new_text = "";
115       buffer->set_text(old_text);
116       view.replace_text(new_text);
117       g_assert(buffer->get_text() == new_text);
118 
119       view.replace_text(old_text);
120       g_assert(buffer->get_text() == old_text);
121       g_assert(buffer->get_insert()->get_iter().get_line() == 1);
122       g_assert(buffer->get_insert()->get_iter().get_line_offset() == 6);
123     }
124     {
125       auto old_text = "";
126       auto new_text = "";
127       buffer->set_text(old_text);
128       view.replace_text(new_text);
129       g_assert(buffer->get_text() == new_text);
130     }
131     {
132       auto old_text = "line 1\nline 3\n";
133       auto new_text = "";
134       buffer->set_text(old_text);
135       view.replace_text(new_text);
136       g_assert(buffer->get_text() == new_text);
137 
138       view.replace_text(old_text);
139       g_assert(buffer->get_text() == old_text);
140       g_assert(buffer->get_insert()->get_iter().get_line() == 2);
141       g_assert(buffer->get_insert()->get_iter().get_line_offset() == 0);
142     }
143     {
144       auto old_text = "line 1\n\nline 3\nline 4\n\nline 5\n";
145       auto new_text = "line 1\n\nline 33\nline 44\n\nline 5\n";
146       buffer->set_text(old_text);
147       view.place_cursor_at_line_offset(2, 0);
148       view.replace_text(new_text);
149       g_assert(buffer->get_text() == new_text);
150       g_assert(buffer->get_insert()->get_iter().get_line() == 2);
151       g_assert(buffer->get_insert()->get_iter().get_line_offset() == 0);
152 
153       buffer->set_text(old_text);
154       view.place_cursor_at_line_offset(3, 0);
155       view.replace_text(new_text);
156       g_assert(buffer->get_text() == new_text);
157       g_assert(buffer->get_insert()->get_iter().get_line() == 3);
158       g_assert(buffer->get_insert()->get_iter().get_line_offset() == 0);
159     }
160     {
161       auto old_text = "line 1\n\nline 3\nline 4\n\nline 5\n";
162       auto new_text = "line 1\n\nline 33\nline 44\nline 45\nline 46\n\nline 5\n";
163       buffer->set_text(old_text);
164       view.place_cursor_at_line_offset(2, 0);
165       view.replace_text(new_text);
166       g_assert(buffer->get_text() == new_text);
167       g_assert(buffer->get_insert()->get_iter().get_line() == 2);
168       g_assert(buffer->get_insert()->get_iter().get_line_offset() == 0);
169 
170       buffer->set_text(old_text);
171       view.place_cursor_at_line_offset(3, 0);
172       view.replace_text(new_text);
173       g_assert(buffer->get_text() == new_text);
174       g_assert(buffer->get_insert()->get_iter().get_line() == 4);
175       g_assert(buffer->get_insert()->get_iter().get_line_offset() == 0);
176     }
177   }
178 
179   // extend_selection() tests
180   {
181     auto buffer = view.get_buffer();
182     view.is_bracket_language = true;
183     view.spellcheck_all = false;
184     std::string source = "test(1, test(10), \"100\");";
185     buffer->set_text(source);
186     {
187       view.place_cursor_at_line_offset(0, 0);
188       view.extend_selection();
189       g_assert(view.get_selected_text() == "test");
190 
191       view.extend_selection();
192       g_assert(view.get_selected_text() == "test(1, test(10), \"100\")");
193 
194       view.extend_selection();
195       g_assert(view.get_selected_text() == source);
196     }
197     {
198       view.place_cursor_at_line_offset(0, 5);
199       view.extend_selection();
200       g_assert(view.get_selected_text() == "1");
201 
202       view.extend_selection();
203       g_assert(view.get_selected_text() == "1, test(10), \"100\"");
204 
205       view.extend_selection();
206       g_assert(view.get_selected_text() == "test(1, test(10), \"100\")");
207     }
208     {
209       view.place_cursor_at_line_offset(0, 7);
210       view.extend_selection();
211       g_assert(view.get_selected_text() == " test(10)");
212     }
213     {
214       view.place_cursor_at_line_offset(0, 8);
215       view.extend_selection();
216       g_assert(view.get_selected_text() == "test");
217 
218       view.extend_selection();
219       g_assert(view.get_selected_text() == "test(10)");
220 
221       view.extend_selection();
222       g_assert(view.get_selected_text() == " test(10)");
223 
224       view.extend_selection();
225       g_assert(view.get_selected_text() == "1, test(10), \"100\"");
226     }
227     {
228       view.place_cursor_at_line_offset(0, 18);
229       view.extend_selection();
230       g_assert(view.get_selected_text() == " \"100\"");
231 
232       view.extend_selection();
233       g_assert(view.get_selected_text() == "1, test(10), \"100\"");
234     }
235     {
236       view.place_cursor_at_line_offset(0, 26);
237       view.extend_selection();
238       g_assert(view.get_selected_text() == source);
239     }
240     {
241       view.place_cursor_at_line_offset(0, 27);
242       view.extend_selection();
243       g_assert(view.get_selected_text() == source);
244     }
245 
246     source = "int main() {\n  return 1;\n}\n";
247     buffer->set_text(source);
248     {
249       view.place_cursor_at_line_offset(0, 0);
250       view.extend_selection();
251       g_assert(view.get_selected_text() == "int");
252 
253       view.extend_selection();
254       g_assert(view.get_selected_text() == source.substr(0, source.size() - 1));
255 
256       view.extend_selection();
257       g_assert(view.get_selected_text() == source);
258     }
259     {
260       view.place_cursor_at_line_offset(0, 4);
261       view.extend_selection();
262       g_assert(view.get_selected_text() == "main");
263 
264       view.extend_selection();
265       g_assert(view.get_selected_text() == source.substr(4, source.size() - 1 - 4));
266 
267       view.extend_selection();
268       g_assert(view.get_selected_text() == source.substr(0, source.size() - 1));
269 
270       view.extend_selection();
271       g_assert(view.get_selected_text() == source);
272     }
273     {
274       view.place_cursor_at_line_offset(1, 2);
275       view.extend_selection();
276       g_assert(view.get_selected_text() == "return");
277 
278       view.extend_selection();
279       g_assert(view.get_selected_text() == "return 1;");
280 
281       view.extend_selection();
282       g_assert(view.get_selected_text() == source.substr(12, 13));
283 
284       view.extend_selection();
285       g_assert(view.get_selected_text() == source.substr(4, source.size() - 1 - 4));
286 
287       view.extend_selection();
288       g_assert(view.get_selected_text() == source.substr(0, source.size() - 1));
289 
290       view.extend_selection();
291       g_assert(view.get_selected_text() == source);
292     }
293 
294     source = "test<int, int>(11, 22);";
295     buffer->set_text(source);
296     {
297       view.place_cursor_at_line_offset(0, 0);
298       view.extend_selection();
299       g_assert(view.get_selected_text() == "test");
300 
301       view.extend_selection();
302       g_assert(view.get_selected_text() == source.substr(0, source.size() - 1));
303 
304       view.extend_selection();
305       g_assert(view.get_selected_text() == source);
306     }
307     {
308       view.place_cursor_at_line_offset(0, 5);
309       view.extend_selection();
310       g_assert(view.get_selected_text() == "int");
311 
312       view.extend_selection();
313       g_assert(view.get_selected_text() == source.substr(5, 8));
314 
315       view.extend_selection();
316       g_assert(view.get_selected_text() == source.substr(0, source.size() - 1));
317     }
318     {
319       view.place_cursor_at_line_offset(0, 15);
320       view.extend_selection();
321       g_assert(view.get_selected_text() == "11");
322 
323       view.extend_selection();
324       g_assert(view.get_selected_text() == "11, 22");
325 
326       view.extend_selection();
327       g_assert(view.get_selected_text() == source.substr(0, source.size() - 1));
328     }
329 
330     source = "{\n  {\n    test;\n  }\n}\n";
331     buffer->set_text(source);
332     {
333       view.place_cursor_at_line_offset(2, 4);
334       view.extend_selection();
335       g_assert(view.get_selected_text() == "test");
336 
337       view.extend_selection();
338       g_assert(view.get_selected_text() == "test;");
339 
340       view.extend_selection();
341       g_assert(view.get_selected_text() == "\n    test;\n  ");
342 
343       view.extend_selection();
344       g_assert(view.get_selected_text() == "{\n    test;\n  }");
345 
346       view.extend_selection();
347       g_assert(view.get_selected_text() == "\n  {\n    test;\n  }\n");
348 
349       view.extend_selection();
350       g_assert(view.get_selected_text() == "{\n  {\n    test;\n  }\n}");
351 
352       view.extend_selection();
353       g_assert(view.get_selected_text() == source);
354 
355       view.shrink_selection();
356       g_assert(view.get_selected_text() == "{\n  {\n    test;\n  }\n}");
357 
358       view.shrink_selection();
359       g_assert(view.get_selected_text() == "\n  {\n    test;\n  }\n");
360 
361       view.shrink_selection();
362       g_assert(view.get_selected_text() == "{\n    test;\n  }");
363     }
364 
365     {
366       auto buffer = view.get_buffer();
367       view.is_js = true;
368       Gtk::TextIter start, end;
369 
370       buffer->set_text(R"(render(
371   <div></div>
372 );)");
373       view.place_cursor_at_line_offset(1, 7);
374       view.extend_selection();
375       buffer->get_selection_bounds(start, end);
376       g_assert(start.get_line() == 1 && start.get_line_offset() == 2 && end.get_line() == 1 && end.get_line_offset() == 13);
377       view.extend_selection();
378       buffer->get_selection_bounds(start, end);
379       g_assert(start.get_line() == 0 && start.get_line_offset() == 7 && end.get_line() == 2 && end.get_line_offset() == 0);
380 
381       view.place_cursor_at_line_offset(1, 4);
382       view.extend_selection();
383       buffer->get_selection_bounds(start, end);
384       g_assert(start.get_line() == 1 && start.get_line_offset() == 3 && end.get_line() == 1 && end.get_line_offset() == 6);
385       view.extend_selection();
386       buffer->get_selection_bounds(start, end);
387       g_assert(start.get_line() == 1 && start.get_line_offset() == 2 && end.get_line() == 1 && end.get_line_offset() == 13);
388       view.extend_selection();
389       buffer->get_selection_bounds(start, end);
390       g_assert(start.get_line() == 0 && start.get_line_offset() == 7 && end.get_line() == 2 && end.get_line_offset() == 0);
391 
392       buffer->set_text(R"(render(
393   <div id="test">test test</div>
394 );)");
395       view.place_cursor_at_line_offset(1, 18);
396       view.extend_selection();
397       buffer->get_selection_bounds(start, end);
398       g_assert(start.get_line() == 1 && start.get_line_offset() == 17 && end.get_line() == 1 && end.get_line_offset() == 21);
399       view.extend_selection();
400       buffer->get_selection_bounds(start, end);
401       g_assert(start.get_line() == 1 && start.get_line_offset() == 17 && end.get_line() == 1 && end.get_line_offset() == 26);
402       view.extend_selection();
403       buffer->get_selection_bounds(start, end);
404       g_assert(start.get_line() == 1 && start.get_line_offset() == 2 && end.get_line() == 1 && end.get_line_offset() == 32);
405       view.extend_selection();
406       buffer->get_selection_bounds(start, end);
407       g_assert(start.get_line() == 0 && start.get_line_offset() == 7 && end.get_line() == 2 && end.get_line_offset() == 0);
408 
409       view.place_cursor_at_line_offset(1, 4);
410       view.extend_selection();
411       buffer->get_selection_bounds(start, end);
412       g_assert(start.get_line() == 1 && start.get_line_offset() == 3 && end.get_line() == 1 && end.get_line_offset() == 6);
413       view.extend_selection();
414       buffer->get_selection_bounds(start, end);
415       g_assert(start.get_line() == 1 && start.get_line_offset() == 2 && end.get_line() == 1 && end.get_line_offset() == 32);
416       view.extend_selection();
417       buffer->get_selection_bounds(start, end);
418       g_assert(start.get_line() == 0 && start.get_line_offset() == 7 && end.get_line() == 2 && end.get_line_offset() == 0);
419 
420       buffer->set_text(R"(render(
421   <div onClick={() => {}}></div>
422 );)");
423       view.place_cursor_at_line_offset(1, 6);
424       view.extend_selection();
425       buffer->get_selection_bounds(start, end);
426       g_assert(start.get_line() == 1 && start.get_line_offset() == 2 && end.get_line() == 1 && end.get_line_offset() == 32);
427       view.extend_selection();
428       buffer->get_selection_bounds(start, end);
429       g_assert(start.get_line() == 0 && start.get_line_offset() == 7 && end.get_line() == 2 && end.get_line_offset() == 0);
430 
431       buffer->set_text(R"(render(
432   <div>
433     <div></div>
434     <div></div>
435   </div>
436 );)");
437       view.place_cursor_at_line_offset(2, 8);
438       view.extend_selection();
439       buffer->get_selection_bounds(start, end);
440       g_assert(start.get_line() == 2 && start.get_line_offset() == 4 && end.get_line() == 2 && end.get_line_offset() == 15);
441       view.extend_selection();
442       buffer->get_selection_bounds(start, end);
443       g_assert(start.get_line() == 1 && start.get_line_offset() == 7 && end.get_line() == 4 && end.get_line_offset() == 2);
444       view.extend_selection();
445       buffer->get_selection_bounds(start, end);
446       g_assert(start.get_line() == 1 && start.get_line_offset() == 2 && end.get_line() == 4 && end.get_line_offset() == 8);
447 
448       view.place_cursor_at_line_offset(3, 8);
449       view.extend_selection();
450       buffer->get_selection_bounds(start, end);
451       g_assert(start.get_line() == 3 && start.get_line_offset() == 4 && end.get_line() == 3 && end.get_line_offset() == 15);
452       view.extend_selection();
453       buffer->get_selection_bounds(start, end);
454       g_assert(start.get_line() == 1 && start.get_line_offset() == 7 && end.get_line() == 4 && end.get_line_offset() == 2);
455       view.extend_selection();
456       buffer->get_selection_bounds(start, end);
457       g_assert(start.get_line() == 1 && start.get_line_offset() == 2 && end.get_line() == 4 && end.get_line_offset() == 8);
458 
459       buffer->set_text(R"(render(
460   <div>
461     <div></div>
462     <img src="test">
463     <Test/>
464     <br>
465     <div></div>
466   </div>
467 );)");
468       view.place_cursor_at_line_offset(2, 8);
469       view.extend_selection();
470       buffer->get_selection_bounds(start, end);
471       g_assert(start.get_line() == 2 && start.get_line_offset() == 4 && end.get_line() == 2 && end.get_line_offset() == 15);
472       view.extend_selection();
473       buffer->get_selection_bounds(start, end);
474       g_assert(start.get_line() == 1 && start.get_line_offset() == 7 && end.get_line() == 7 && end.get_line_offset() == 2);
475       view.extend_selection();
476       buffer->get_selection_bounds(start, end);
477       g_assert(start.get_line() == 1 && start.get_line_offset() == 2 && end.get_line() == 7 && end.get_line_offset() == 8);
478 
479       view.place_cursor_at_line_offset(6, 8);
480       view.extend_selection();
481       buffer->get_selection_bounds(start, end);
482       g_assert(start.get_line() == 6 && start.get_line_offset() == 4 && end.get_line() == 6 && end.get_line_offset() == 15);
483       view.extend_selection();
484       buffer->get_selection_bounds(start, end);
485       g_assert(start.get_line() == 1 && start.get_line_offset() == 7 && end.get_line() == 7 && end.get_line_offset() == 2);
486       view.extend_selection();
487       buffer->get_selection_bounds(start, end);
488       g_assert(start.get_line() == 1 && start.get_line_offset() == 2 && end.get_line() == 7 && end.get_line_offset() == 8);
489 
490       view.is_js = false;
491     }
492   }
493 
494   // Snippet tests
495   {
496     auto buffer = view.get_buffer();
497     GdkEventKey event;
498     event.state = 0;
499     {
500       buffer->set_text("");
501       view.insert_snippet(buffer->get_insert()->get_iter(), "std::cout << ${1:content} << std::endl;");
502       g_assert(buffer->get_text() == "std::cout << content << std::endl;");
503       Gtk::TextIter start, end;
504       buffer->get_selection_bounds(start, end);
505       g_assert(start.get_offset() == 13);
506       g_assert(end.get_offset() == 20);
507 
508       event.keyval = GDK_KEY_t;
509       view.on_key_press_event(&event);
510       g_assert(buffer->get_text() == "std::cout << t << std::endl;");
511       event.keyval = GDK_KEY_e;
512       view.on_key_press_event(&event);
513       g_assert(buffer->get_text() == "std::cout << te << std::endl;");
514     }
515     {
516       buffer->set_text("");
517       view.insert_snippet(buffer->get_insert()->get_iter(), "std::cout << ${1:} << std::endl;");
518       g_assert(buffer->get_text() == "std::cout <<  << std::endl;");
519       Gtk::TextIter start, end;
520       buffer->get_selection_bounds(start, end);
521       g_assert(start.get_offset() == 13);
522       g_assert(end.get_offset() == 13);
523 
524       event.keyval = GDK_KEY_t;
525       view.on_key_press_event(&event);
526       g_assert(buffer->get_text() == "std::cout << t << std::endl;");
527       event.keyval = GDK_KEY_e;
528       view.on_key_press_event(&event);
529       g_assert(buffer->get_text() == "std::cout << te << std::endl;");
530     }
531     {
532       buffer->set_text("");
533       view.insert_snippet(buffer->get_insert()->get_iter(), "std::cout << $1 << std::endl;");
534       g_assert(buffer->get_text() == "std::cout <<  << std::endl;");
535       Gtk::TextIter start, end;
536       buffer->get_selection_bounds(start, end);
537       g_assert(start.get_offset() == 13);
538       g_assert(end.get_offset() == 13);
539 
540       event.keyval = GDK_KEY_t;
541       view.on_key_press_event(&event);
542       g_assert(buffer->get_text() == "std::cout << t << std::endl;");
543       event.keyval = GDK_KEY_e;
544       view.on_key_press_event(&event);
545       g_assert(buffer->get_text() == "std::cout << te << std::endl;");
546     }
547     {
548       buffer->set_text("");
549       view.insert_snippet(buffer->get_insert()->get_iter(), "std::cout << ${1:content} << ${1:content} << std::endl;");
550       g_assert(buffer->get_text() == "std::cout << content << content << std::endl;");
551       Gtk::TextIter start, end;
552       buffer->get_selection_bounds(start, end);
553       g_assert(start.get_offset() == 13);
554       g_assert(end.get_offset() == 20);
555 
556       event.keyval = GDK_KEY_t;
557       view.on_key_press_event(&event);
558       g_assert(buffer->get_text() == "std::cout << t << t << std::endl;");
559       event.keyval = GDK_KEY_e;
560       view.on_key_press_event(&event);
561       g_assert(buffer->get_text() == "std::cout << te << te << std::endl;");
562 
563       event.keyval = GDK_KEY_Escape;
564       view.on_key_press_event(&event);
565       g_assert(buffer->get_text() == "std::cout << te << te << std::endl;");
566       event.keyval = GDK_KEY_s;
567       view.on_key_press_event(&event);
568       g_assert(buffer->get_text() == "std::cout << tes << te << std::endl;");
569     }
570     {
571       buffer->set_text("");
572       view.insert_snippet(buffer->get_insert()->get_iter(), "std::cout << ${1:content} << ${1:cont} << std::endl;");
573       g_assert(buffer->get_text() == "std::cout << content << cont << std::endl;");
574       Gtk::TextIter start, end;
575       buffer->get_selection_bounds(start, end);
576       g_assert(start.get_offset() == 13);
577       g_assert(end.get_offset() == 20);
578 
579       event.keyval = GDK_KEY_t;
580       view.on_key_press_event(&event);
581       g_assert(buffer->get_text() == "std::cout << t << t << std::endl;");
582       event.keyval = GDK_KEY_e;
583       view.on_key_press_event(&event);
584       g_assert(buffer->get_text() == "std::cout << te << te << std::endl;");
585 
586       event.keyval = GDK_KEY_Escape;
587       view.on_key_press_event(&event);
588       g_assert(buffer->get_text() == "std::cout << te << te << std::endl;");
589       event.keyval = GDK_KEY_s;
590       view.on_key_press_event(&event);
591       g_assert(buffer->get_text() == "std::cout << tes << te << std::endl;");
592     }
593     {
594       buffer->set_text("");
595       view.insert_snippet(buffer->get_insert()->get_iter(), "std::cout << ${1:content} << $1 << std::endl;");
596       g_assert(buffer->get_text() == "std::cout << content <<  << std::endl;");
597       Gtk::TextIter start, end;
598       buffer->get_selection_bounds(start, end);
599       g_assert(start.get_offset() == 13);
600       g_assert(end.get_offset() == 20);
601 
602       event.keyval = GDK_KEY_t;
603       view.on_key_press_event(&event);
604       g_assert(buffer->get_text() == "std::cout << t << t << std::endl;");
605       event.keyval = GDK_KEY_e;
606       view.on_key_press_event(&event);
607       g_assert(buffer->get_text() == "std::cout << te << te << std::endl;");
608 
609       event.keyval = GDK_KEY_Escape;
610       view.on_key_press_event(&event);
611       g_assert(buffer->get_text() == "std::cout << te << te << std::endl;");
612       event.keyval = GDK_KEY_s;
613       view.on_key_press_event(&event);
614       g_assert(buffer->get_text() == "std::cout << tes << te << std::endl;");
615     }
616     {
617       buffer->set_text("");
618       view.insert_snippet(buffer->get_insert()->get_iter(), "std::cout << ${1:content1} << ${2:content2} << std::endl;");
619       g_assert(buffer->get_text() == "std::cout << content1 << content2 << std::endl;");
620       Gtk::TextIter start, end;
621       buffer->get_selection_bounds(start, end);
622       g_assert(start.get_offset() == 13);
623       g_assert(end.get_offset() == 21);
624 
625       event.keyval = GDK_KEY_t;
626       view.on_key_press_event(&event);
627       g_assert(buffer->get_text() == "std::cout << t << content2 << std::endl;");
628       event.keyval = GDK_KEY_e;
629       view.on_key_press_event(&event);
630       g_assert(buffer->get_text() == "std::cout << te << content2 << std::endl;");
631 
632       event.keyval = GDK_KEY_Tab;
633       view.on_key_press_event(&event);
634       g_assert(buffer->get_text() == "std::cout << te << content2 << std::endl;");
635       event.keyval = GDK_KEY_t;
636       view.on_key_press_event(&event);
637       g_assert(buffer->get_text() == "std::cout << te << t << std::endl;");
638     }
639     {
640       buffer->set_text("");
641       view.insert_snippet(buffer->get_insert()->get_iter(), "std::cout << ${1:content} << $0 << std::endl;");
642       g_assert(buffer->get_text() == "std::cout << content <<  << std::endl;");
643       Gtk::TextIter start, end;
644       buffer->get_selection_bounds(start, end);
645       g_assert(start.get_offset() == 13);
646       g_assert(end.get_offset() == 20);
647 
648       event.keyval = GDK_KEY_t;
649       view.on_key_press_event(&event);
650       g_assert(buffer->get_text() == "std::cout << t <<  << std::endl;");
651       event.keyval = GDK_KEY_e;
652       view.on_key_press_event(&event);
653       g_assert(buffer->get_text() == "std::cout << te <<  << std::endl;");
654 
655       event.keyval = GDK_KEY_Tab;
656       view.on_key_press_event(&event);
657       g_assert(buffer->get_text() == "std::cout << te <<  << std::endl;");
658       event.keyval = GDK_KEY_t;
659       view.on_key_press_event(&event);
660       g_assert(buffer->get_text() == "std::cout << te << t << std::endl;");
661     }
662     {
663       buffer->set_text("");
664       view.insert_snippet(buffer->get_insert()->get_iter(), "std::cout << ${2:content2} << ${1:content1} << std::endl;");
665       g_assert(buffer->get_text() == "std::cout << content2 << content1 << std::endl;");
666       Gtk::TextIter start, end;
667       buffer->get_selection_bounds(start, end);
668       g_assert(start.get_offset() == 25);
669       g_assert(end.get_offset() == 33);
670 
671       event.keyval = GDK_KEY_t;
672       view.on_key_press_event(&event);
673       g_assert(buffer->get_text() == "std::cout << content2 << t << std::endl;");
674       event.keyval = GDK_KEY_e;
675       view.on_key_press_event(&event);
676       g_assert(buffer->get_text() == "std::cout << content2 << te << std::endl;");
677 
678       event.keyval = GDK_KEY_Tab;
679       view.on_key_press_event(&event);
680       g_assert(buffer->get_text() == "std::cout << content2 << te << std::endl;");
681       event.keyval = GDK_KEY_t;
682       view.on_key_press_event(&event);
683       g_assert(buffer->get_text() == "std::cout << t << te << std::endl;");
684     }
685     {
686       buffer->set_text("test");
687       buffer->select_range(buffer->begin(), buffer->end());
688       view.insert_snippet(buffer->get_insert()->get_iter(), "<$1>${TM_SELECTED_TEXT}</$1>");
689       g_assert(buffer->get_text() == "<>test</>");
690       Gtk::TextIter start, end;
691       buffer->get_selection_bounds(start, end);
692       g_assert(start.get_offset() == 1);
693       g_assert(end.get_offset() == 1);
694 
695       event.keyval = GDK_KEY_t;
696       view.on_key_press_event(&event);
697       g_assert(buffer->get_text() == "<t>test</t>");
698       event.keyval = GDK_KEY_e;
699       view.on_key_press_event(&event);
700       g_assert(buffer->get_text() == "<te>test</te>");
701     }
702     {
703       buffer->set_text("test test");
704       Gtk::TextIter start, end;
705       start = buffer->begin();
706       end = start;
707       end.forward_chars(4);
708       buffer->select_range(start, end);
709       view.insert_snippet(buffer->get_insert()->get_iter(), "<$1>${TM_SELECTED_TEXT:TM_CURRENT_LINE}</$1>");
710       g_assert(buffer->get_text() == "<>test</> test");
711       buffer->get_selection_bounds(start, end);
712       g_assert(start.get_offset() == 1);
713       g_assert(end.get_offset() == 1);
714 
715       event.keyval = GDK_KEY_t;
716       view.on_key_press_event(&event);
717       g_assert(buffer->get_text() == "<t>test</t> test");
718       event.keyval = GDK_KEY_e;
719       view.on_key_press_event(&event);
720       g_assert(buffer->get_text() == "<te>test</te> test");
721     }
722     {
723       buffer->set_text("test test");
724       view.insert_snippet(buffer->get_insert()->get_iter(), "<$1>${TM_SELECTED_TEXT:TM_CURRENT_LINE}</$1>");
725       g_assert(buffer->get_text() == "<>test test</>");
726       Gtk::TextIter start, end;
727       buffer->get_selection_bounds(start, end);
728       g_assert(start.get_offset() == 1);
729       g_assert(end.get_offset() == 1);
730 
731       event.keyval = GDK_KEY_t;
732       view.on_key_press_event(&event);
733       g_assert(buffer->get_text() == "<t>test test</t>");
734       event.keyval = GDK_KEY_e;
735       view.on_key_press_event(&event);
736       g_assert(buffer->get_text() == "<te>test test</te>");
737     }
738     {
739       buffer->set_text("");
740       view.insert_snippet(buffer->get_insert()->get_iter(), "\\textbf{${TM_SELECTED_TEXT:no text was selected}}");
741       g_assert(buffer->get_text() == "\\textbf{no text was selected}");
742       g_assert(buffer->get_insert()->get_iter().get_offset() == 29);
743     }
744     {
745       buffer->set_text("");
746       view.insert_snippet(buffer->get_insert()->get_iter(), "<div${1: id=\"${2:some_id}\"}>\n  $0\n</div>");
747       auto result = "<div id=\"some_id\">\n  \n</div>";
748       g_assert(buffer->get_text() == result);
749       Gtk::TextIter start, end;
750       buffer->get_selection_bounds(start, end);
751       g_assert(start.get_offset() == 4);
752       g_assert(end.get_offset() == 17);
753 
754       event.keyval = GDK_KEY_Tab;
755       view.on_key_press_event(&event);
756       g_assert(buffer->get_text() == result);
757       buffer->get_selection_bounds(start, end);
758       g_assert(start.get_offset() == 9);
759       g_assert(end.get_offset() == 16);
760 
761       event.keyval = GDK_KEY_Tab;
762       view.on_key_press_event(&event);
763       g_assert(buffer->get_text() == result);
764       g_assert(buffer->get_insert()->get_iter().get_offset() == 21);
765     }
766     {
767       buffer->set_text("");
768       view.insert_snippet(buffer->get_insert()->get_iter(), "<div${1: id=\"${2:some_id}\"}>\n  $0\n</div>");
769       g_assert(buffer->get_text() == "<div id=\"some_id\">\n  \n</div>");
770       Gtk::TextIter start, end;
771       buffer->get_selection_bounds(start, end);
772       g_assert(start.get_offset() == 4);
773       g_assert(end.get_offset() == 17);
774 
775       event.keyval = GDK_KEY_t;
776       view.on_key_press_event(&event);
777       g_assert(buffer->get_text() == "<divt>\n  \n</div>");
778       buffer->get_selection_bounds(start, end);
779       g_assert(start.get_offset() == 5);
780       g_assert(end.get_offset() == 5);
781 
782       event.keyval = GDK_KEY_Tab;
783       view.on_key_press_event(&event);
784       g_assert(buffer->get_text() == "<divt>\n  \n</div>");
785       g_assert(buffer->get_insert()->get_iter().get_offset() == 9);
786     }
787     {
788       buffer->set_text("");
789       view.insert_snippet(buffer->get_insert()->get_iter(), "\\begin{${1:enumerate}}\n  $0\n\\end{$1}");
790       g_assert(buffer->get_text() == "\\begin{enumerate}\n  \n\\end{}");
791       Gtk::TextIter start, end;
792       buffer->get_selection_bounds(start, end);
793       g_assert(start.get_offset() == 7);
794       g_assert(end.get_offset() == 16);
795 
796       event.keyval = GDK_KEY_t;
797       view.on_key_press_event(&event);
798       g_assert(buffer->get_text() == "\\begin{t}\n  \n\\end{t}");
799       event.keyval = GDK_KEY_e;
800       view.on_key_press_event(&event);
801       g_assert(buffer->get_text() == "\\begin{te}\n  \n\\end{te}");
802 
803       event.keyval = GDK_KEY_Tab;
804       view.on_key_press_event(&event);
805       g_assert(buffer->get_text() == "\\begin{te}\n  \n\\end{te}");
806       g_assert(buffer->get_insert()->get_iter().get_offset() == 13);
807     }
808     {
809       buffer->set_text("");
810       view.insert_snippet(buffer->get_insert()->get_iter(), "test$test");
811       g_assert(buffer->get_text() == "test$test");
812 
813       buffer->set_text("");
814       view.insert_snippet(buffer->get_insert()->get_iter(), "${TM_SELECTED_TEXT}");
815       g_assert(buffer->get_text() == "");
816 
817       buffer->set_text("");
818       view.insert_snippet(buffer->get_insert()->get_iter(), "$TM_SELECTED_TEXT");
819       g_assert(buffer->get_text() == "");
820 
821       buffer->set_text("");
822       view.insert_snippet(buffer->get_insert()->get_iter(), "\\$");
823       g_assert(buffer->get_text() == "$");
824 
825       buffer->set_text("");
826       view.insert_snippet(buffer->get_insert()->get_iter(), "\\\\${0:test}");
827       g_assert(buffer->get_text() == "\\test");
828 
829       buffer->set_text("");
830       view.insert_snippet(buffer->get_insert()->get_iter(), "te{s}t");
831       g_assert(buffer->get_text() == "te{s}t");
832 
833       buffer->set_text("");
834       view.insert_snippet(buffer->get_insert()->get_iter(), "${0:te{s\\}t}");
835       g_assert(buffer->get_text() == "te{s}t");
836 
837       buffer->set_text("");
838       view.insert_snippet(buffer->get_insert()->get_iter(), "\\test\\");
839       g_assert(buffer->get_text() == "\\test\\");
840     }
841     {
842       Config::get().source.enable_multiple_cursors = true;
843       buffer->set_text("\n");
844       buffer->place_cursor(buffer->begin());
845       event.keyval = GDK_KEY_Down;
846       event.state = GDK_MOD1_MASK;
847       view.on_key_press_event(&event);
848       event.state = 0;
849 
850       view.enable_multiple_cursors = true;
851       view.insert_snippet(buffer->get_insert()->get_iter(), "\\begin{${1:enumerate}}\n  $0\n\\end{${1:enum}}");
852       g_assert(buffer->get_text() == "\\begin{enumerate}\n  \n\\end{enum}\n\\begin{enumerate}\n  \n\\end{enum}");
853       Gtk::TextIter start, end;
854       buffer->get_selection_bounds(start, end);
855       g_assert(start.get_offset() == 7);
856       g_assert(end.get_offset() == 16);
857 
858       event.keyval = GDK_KEY_t;
859       view.on_key_press_event(&event);
860       g_assert(buffer->get_text() == "\\begin{t}\n  \n\\end{t}\n\\begin{t}\n  \n\\end{t}");
861       event.keyval = GDK_KEY_e;
862       view.on_key_press_event(&event);
863       g_assert(buffer->get_text() == "\\begin{te}\n  \n\\end{te}\n\\begin{te}\n  \n\\end{te}");
864 
865       event.keyval = GDK_KEY_Tab;
866       view.on_key_press_event(&event);
867       g_assert(buffer->get_text() == "\\begin{te}\n  \n\\end{te}\n\\begin{te}\n  \n\\end{te}");
868       g_assert(buffer->get_insert()->get_iter().get_offset() == 13);
869 
870       event.keyval = GDK_KEY_t;
871       view.on_key_press_event(&event);
872       g_assert(buffer->get_text() == "\\begin{te}\n  t\n\\end{te}\n\\begin{te}\n  t\n\\end{te}");
873     }
874   }
875 }
876