dte test coverage


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 50.0% high: ≥ 85.0%
Coverage Exec / Excl / Total
Lines: 62.2% 46 / 0 / 74
Functions: 85.7% 6 / 0 / 7
Branches: 38.2% 13 / 6 / 40

src/mode.c
Line Branch Exec Source
1 #include <stddef.h>
2 #include "mode.h"
3 #include "bind.h"
4 #include "change.h"
5 #include "cmdline.h"
6 #include "command/macro.h"
7 #include "completion.h"
8 #include "editor.h"
9 #include "indent.h"
10 #include "insert.h"
11 #include "terminal/paste.h"
12 #include "util/debug.h"
13 #include "util/intern.h"
14 #include "util/unicode.h"
15 #include "util/xmalloc.h"
16 #include "view.h"
17
18 34 ModeHandler *new_mode(HashMap *modes, const char *name, const CommandSet *cmds, size_t capacity)
19 {
20 34 BUG_ON(!(modes->flags & HMAP_BORROWED_KEYS));
21 34 ModeHandler *mode = xcalloc1(sizeof(*mode));
22 34 mode->name = str_intern(name);
23 34 mode->cmds = cmds;
24 34 mode->key_bindings = intmap_new(capacity);
25 34 return hashmap_insert(modes, (char*)mode->name, mode);
26 }
27
28 static bool insert_paste(EditorState *e, const ModeHandler *handler, bool bracketed)
29 {
30 String str = term_read_paste(&e->terminal.ibuf, bracketed);
31 if (handler->cmds == &normal_commands) {
32 StringView text = strview_from_string(&str);
33 begin_change(CHANGE_MERGE_NONE);
34 insert_text(e->view, text, true);
35 end_change();
36 macro_insert_text_hook(&e->macro, text);
37 } else {
38 CommandLine *c = &e->cmdline;
39 string_replace_byte(&str, '\n', ' ');
40 c->pos += string_insert_buf(&c->buf, c->pos, str.buffer, str.len);
41 c->search_pos = NULL;
42 }
43 string_free(&str);
44 return true;
45 }
46
47 7 static bool handle_input_single (
48 EditorState *e,
49 const ModeHandler *handler,
50 KeyCode key,
51 ModeHandlerFlags inherited_flags
52 ) {
53 7 bool bracketed_paste = (key == KEYCODE_BRACKETED_PASTE);
54
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 7 times.
7 if (bracketed_paste || key == KEYCODE_DETECTED_PASTE) {
55 return insert_paste(e, handler, bracketed_paste);
56 }
57
58 7 ModeHandlerFlags noinsert_flags = MHF_NO_TEXT_INSERTION | MHF_NO_TEXT_INSERTION_RECURSIVE;
59 7 ModeHandlerFlags flag_union = handler->flags | inherited_flags;
60 7 bool insert_unicode_range = !(flag_union & noinsert_flags);
61
62
1/2
✓ Branch 4 → 5 taken 7 times.
✗ Branch 4 → 25 not taken.
7 if (insert_unicode_range) {
63 7 const CommandSet *cmds = handler->cmds;
64
2/2
✓ Branch 5 → 6 taken 5 times.
✓ Branch 5 → 16 taken 2 times.
7 if (cmds == &normal_commands) {
65 5 View *view = e->view;
66 5 KeyCode shift = key & MOD_SHIFT;
67
1/4
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 12 taken 5 times.
✗ Branch 7 → 8 not taken.
✗ Branch 7 → 12 not taken.
5 if ((key & ~shift) == KEY_TAB && view->selection == SELECT_LINES) {
68 // In line selections, Tab/S-Tab behave like indent/indent -r
69 indent_lines(view, shift ? -1 : 1);
70 return true;
71 }
72
1/2
✓ Branch 12 → 13 taken 5 times.
✗ Branch 12 → 25 not taken.
5 if (u_is_unicode(key)) {
73 5 insert_ch(e->view, key);
74 5 macro_insert_char_hook(&e->macro, key);
75 5 return true;
76 }
77 } else {
78 2 BUG_ON(cmds != &cmd_mode_commands && cmds != &search_mode_commands);
79
2/4
✓ Branch 19 → 20 taken 2 times.
✗ Branch 19 → 25 not taken.
✓ Branch 20 → 21 taken 2 times.
✗ Branch 20 → 25 not taken.
2 if (u_is_unicode(key) && (key != KEY_TAB && key != KEY_ENTER)) {
80 2 CommandLine *c = &e->cmdline;
81 2 c->pos += string_insert_codepoint(&c->buf, c->pos, key);
82
1/2
✓ Branch 22 → 23 taken 2 times.
✗ Branch 22 → 24 not taken.
2 if (cmds == &cmd_mode_commands) {
83 2 maybe_reset_completion(c);
84 }
85 2 c->search_pos = NULL;
86 2 return true;
87 }
88 }
89 }
90
91 return handle_binding(e, handler, key);
92 }
93
94 // Recursion is bounded by the depth of fallthrough modes, which is
95 // typically not more than 5 or so
96 // NOLINTNEXTLINE(misc-no-recursion)
97 7 static bool handle_input_recursive (
98 EditorState *e,
99 const ModeHandler *handler,
100 KeyCode key,
101 ModeHandlerFlags inherited_flags
102 ) {
103
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 9 taken 7 times.
7 if (handle_input_single(e, handler, key, inherited_flags)) {
104 return true;
105 }
106
107 const PointerArray *ftmodes = &handler->fallthrough_modes;
108 inherited_flags |= (handler->flags & MHF_NO_TEXT_INSERTION_RECURSIVE);
109
110 for (size_t i = 0, n = ftmodes->count; i < n; i++) {
111 const ModeHandler *h = ftmodes->ptrs[i];
112 if (handle_input_recursive(e, h, key, inherited_flags)) {
113 return true;
114 }
115 }
116
117 return false;
118 }
119
120 3 void string_append_def_mode(String *buf, const ModeHandler *mode)
121 {
122 3 string_append_literal(buf, "def-mode ");
123
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 3 times.
3 if (mode->flags & MHF_NO_TEXT_INSERTION_RECURSIVE) {
124 string_append_literal(buf, "-U ");
125
1/2
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 3 times.
3 } else if (mode->flags & MHF_NO_TEXT_INSERTION) {
126 string_append_literal(buf, "-u ");
127 }
128
129 3 string_append_cstring(buf, mode->name);
130
131 3 const PointerArray *ftmodes = &mode->fallthrough_modes;
132
1/2
✗ Branch 12 → 9 not taken.
✓ Branch 12 → 13 taken 3 times.
3 for (size_t i = 0, n = ftmodes->count; i < n; i++) {
133 const ModeHandler *ftmode = ftmodes->ptrs[i];
134 string_append_byte(buf, ' ');
135 string_append_cstring(buf, ftmode->name);
136 }
137 3 }
138
139 7 bool handle_input(EditorState *e, KeyCode key)
140 {
141 7 return handle_input_recursive(e, e->mode, key, 0);
142 }
143
144 2 void collect_modes(const HashMap *modes, PointerArray *a, StringView prefix)
145 {
146 2 collect_hashmap_keys(modes, a, prefix);
147 2 }
148