dte test coverage


Directory: ./
File: src/bind.c
Date: 2024-12-21 16:03:22
Exec Total Coverage
Lines: 61 67 91.0%
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 taken 3 times.
✗ Branch 1 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 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 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 current_command = binding->cmd;
52 3 binding->cmd->cmd(e, &binding->a);
53 3 current_command = NULL;
54 3 end_change();
55 3 return true;
56 }
57
58 typedef struct {
59 KeyCode key;
60 const char *cmd;
61 } KeyBinding;
62
63 1048 static int binding_cmp(const void *ap, const void *bp)
64 {
65 1048 static_assert((MOD_MASK | KEY_SPECIAL_MAX) <= INT_MAX);
66 1048 const KeyBinding *a = ap;
67 1048 const KeyBinding *b = bp;
68 1048 return (int)a->key - (int)b->key;
69 }
70
71 18 UNITTEST {
72 // NOLINTBEGIN(bugprone-assert-side-effect)
73 18 KeyBinding a = {.key = KEY_F5};
74 18 KeyBinding b = {.key = KEY_F5};
75 18 BUG_ON(binding_cmp(&a, &b) != 0);
76 18 b.key = KEY_F3;
77 18 BUG_ON(binding_cmp(&a, &b) <= 0);
78 18 b.key = KEY_F12;
79 18 BUG_ON(binding_cmp(&a, &b) >= 0);
80 // NOLINTEND(bugprone-assert-side-effect)
81 18 }
82
83 3 bool dump_bindings(const IntMap *bindings, const char *flag, String *buf)
84 {
85 3 const size_t count = bindings->count;
86
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (unlikely(count == 0)) {
87 return false;
88 }
89
90 // Clone the contents of the map as an array of key/command pairs
91 3 KeyBinding *array = xnew(*array, count);
92 3 size_t n = 0;
93
2/2
✓ Branch 0 taken 197 times.
✓ Branch 1 taken 3 times.
200 for (IntMapIter it = intmap_iter(bindings); intmap_next(&it); ) {
94 197 const CachedCommand *cc = it.entry->value;
95 197 array[n++] = (KeyBinding) {
96 197 .key = it.entry->key,
97 197 .cmd = cc->cmd_str,
98 };
99 }
100
101 // Sort the array
102 3 BUG_ON(n != count);
103 3 qsort(array, count, sizeof(array[0]), binding_cmp);
104
105 // Serialize the bindings in sorted order
106 3 char keystr[KEYCODE_STR_MAX];
107
2/2
✓ Branch 0 taken 197 times.
✓ Branch 1 taken 3 times.
200 for (size_t i = 0; i < count; i++) {
108 197 string_append_literal(buf, "bind ");
109
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 197 times.
197 if (flag[0] != '\0' && flag[0] != '-') {
110 string_append_cstring(buf, "-T ");
111 string_append_escaped_arg(buf, flag, true);
112 string_append_byte(buf, ' ');
113 } else {
114 197 string_append_cstring(buf, flag);
115 }
116 197 size_t keylen = keycode_to_string(array[i].key, keystr);
117 197 string_append_escaped_arg_sv(buf, string_view(keystr, keylen), true);
118 197 string_append_byte(buf, ' ');
119 197 string_append_escaped_arg(buf, array[i].cmd, true);
120 197 string_append_byte(buf, '\n');
121 }
122
123 3 free(array);
124 3 return true;
125 }
126