dte test coverage


Directory: ./
File: src/bind.c
Date: 2025-02-14 16:55:22
Exec Total Coverage
Lines: 59 65 90.8%
Functions: 8 8 100.0%
Branches: 10 16 62.5%

Line Branch Exec Source
1 #include <limits.h>
2 #include <stdlib.h>
3 #include "bind.h"
4 #include "change.h"
5 #include "command/macro.h"
6 #include "command/run.h"
7 #include "command/serialize.h"
8 #include "util/debug.h"
9 #include "util/xmalloc.h"
10
11 1178 void add_binding(IntMap *bindings, KeyCode key, CachedCommand *cc)
12 {
13 1178 cached_command_free(intmap_insert_or_replace(bindings, key, cc));
14 1178 }
15
16 1 void remove_binding(IntMap *bindings, KeyCode key)
17 {
18 1 cached_command_free(intmap_remove(bindings, key));
19 1 }
20
21 10 const CachedCommand *lookup_binding(const IntMap *bindings, KeyCode key)
22 {
23 10 return intmap_get(bindings, key);
24 }
25
26 25 void free_bindings(IntMap *bindings)
27 {
28 25 intmap_free(bindings, (FreeFunction)cached_command_free);
29 25 }
30
31 3 bool handle_binding(EditorState *e, const ModeHandler *handler, KeyCode key)
32 {
33 3 const CachedCommand *binding = lookup_binding(&handler->key_bindings, key);
34
1/2
✓ Branch 0 (3→4) taken 3 times.
✗ Branch 1 (3→15) not taken.
3 if (!binding) {
35 return false;
36 }
37
38 3 const CommandSet *cmds = handler->cmds;
39 3 BUG_ON(!cmds);
40
41 // If the command isn't cached or a macro is being recorded
42
3/6
✓ Branch 0 (6→7) taken 3 times.
✗ Branch 1 (6→9) not taken.
✓ Branch 2 (7→8) taken 3 times.
✗ Branch 3 (7→11) not taken.
✗ Branch 4 (8→9) not taken.
✓ Branch 5 (8→11) taken 3 times.
3 if (!binding->cmd || (cmds->macro_record && macro_is_recording(&e->macro))) {
43 // Parse and run command string
44 CommandRunner runner = cmdrunner(e, cmds);
45 runner.allow_recording = true;
46 return handle_command(&runner, binding->cmd_str);
47 }
48
49 // Command is cached; call it directly
50 3 begin_change(CHANGE_MERGE_NONE);
51 3 command_func_call(e, &e->err, binding->cmd, &binding->a);
52 3 end_change();
53 3 return true;
54 }
55
56 typedef struct {
57 KeyCode key;
58 const char *cmd;
59 } KeyBinding;
60
61 1048 static int binding_cmp(const void *ap, const void *bp)
62 {
63 1048 static_assert((MOD_MASK | KEY_SPECIAL_MAX) <= INT_MAX);
64 1048 const KeyBinding *a = ap;
65 1048 const KeyBinding *b = bp;
66 1048 return (int)a->key - (int)b->key;
67 }
68
69 18 UNITTEST {
70 // NOLINTBEGIN(bugprone-assert-side-effect)
71 18 KeyBinding a = {.key = KEY_F5};
72 18 KeyBinding b = {.key = KEY_F5};
73 18 BUG_ON(binding_cmp(&a, &b) != 0);
74 18 b.key = KEY_F3;
75 18 BUG_ON(binding_cmp(&a, &b) <= 0);
76 18 b.key = KEY_F12;
77 18 BUG_ON(binding_cmp(&a, &b) >= 0);
78 // NOLINTEND(bugprone-assert-side-effect)
79 18 }
80
81 3 bool dump_bindings(const IntMap *bindings, const char *flag, String *buf)
82 {
83 3 const size_t count = bindings->count;
84
1/2
✓ Branch 0 (2→3) taken 3 times.
✗ Branch 1 (2→26) not taken.
3 if (unlikely(count == 0)) {
85 return false;
86 }
87
88 // Clone the contents of the map as an array of key/command pairs
89 3 KeyBinding *array = xnew(*array, count);
90 3 size_t n = 0;
91
2/2
✓ Branch 0 (7→5) taken 197 times.
✓ Branch 1 (7→8) taken 3 times.
200 for (IntMapIter it = intmap_iter(bindings); intmap_next(&it); ) {
92 197 const CachedCommand *cc = it.entry->value;
93 197 array[n++] = (KeyBinding) {
94 197 .key = it.entry->key,
95 197 .cmd = cc->cmd_str,
96 };
97 }
98
99 // Sort the array
100 3 BUG_ON(n != count);
101 3 qsort(array, count, sizeof(array[0]), binding_cmp);
102
103 // Serialize the bindings in sorted order
104 3 char keystr[KEYCODE_STR_MAX];
105
2/2
✓ Branch 0 (24→12) taken 197 times.
✓ Branch 1 (24→25) taken 3 times.
200 for (size_t i = 0; i < count; i++) {
106 197 string_append_literal(buf, "bind ");
107
1/2
✗ Branch 0 (13→14) not taken.
✓ Branch 1 (13→17) taken 197 times.
197 if (flag[0] != '\0' && flag[0] != '-') {
108 string_append_cstring(buf, "-T ");
109 string_append_escaped_arg(buf, flag, true);
110 string_append_byte(buf, ' ');
111 } else {
112 197 string_append_cstring(buf, flag);
113 }
114 197 size_t keylen = keycode_to_string(array[i].key, keystr);
115 197 string_append_escaped_arg_sv(buf, string_view(keystr, keylen), true);
116 197 string_append_byte(buf, ' ');
117 197 string_append_escaped_arg(buf, array[i].cmd, true);
118 197 string_append_byte(buf, '\n');
119 }
120
121 3 free(array);
122 3 return true;
123 }
124