dte test coverage


Directory: ./
File: src/config.c
Date: 2025-02-14 16:55:22
Exec Total Coverage
Lines: 122 122 100.0%
Functions: 14 14 100.0%
Branches: 41 42 97.6%

Line Branch Exec Source
1 #include <errno.h>
2 #include <stdbool.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <sys/types.h>
6 #include "config.h"
7 #include "builtin-config.h"
8 #include "command/error.h"
9 #include "commands.h"
10 #include "editor.h"
11 #include "syntax/color.h"
12 #include "util/debug.h"
13 #include "util/readfile.h"
14 #include "util/str-util.h"
15
16 // Odd number of backslashes at end of line?
17 8437 static bool has_line_continuation(StringView line)
18 {
19 8437 ssize_t pos = line.length - 1;
20
4/4
✓ Branch 0 (4→5) taken 7869 times.
✓ Branch 1 (4→6) taken 1381 times.
✓ Branch 2 (5→3) taken 813 times.
✓ Branch 3 (5→6) taken 7056 times.
9250 while (pos >= 0 && line.data[pos] == '\\') {
21 813 pos--;
22 }
23 8437 return (line.length - 1 - pos) & 1;
24 }
25
26 18 UNITTEST {
27 // NOLINTBEGIN(bugprone-assert-side-effect)
28 18 BUG_ON(has_line_continuation(string_view(NULL, 0)));
29 18 BUG_ON(has_line_continuation(strview_from_cstring("0")));
30 18 BUG_ON(!has_line_continuation(strview_from_cstring("1 \\")));
31 18 BUG_ON(has_line_continuation(strview_from_cstring("2 \\\\")));
32 18 BUG_ON(!has_line_continuation(strview_from_cstring("3 \\\\\\")));
33 18 BUG_ON(has_line_continuation(strview_from_cstring("4 \\\\\\\\")));
34 // NOLINTEND(bugprone-assert-side-effect)
35 18 }
36
37 187 void exec_config(CommandRunner *runner, StringView config)
38 {
39 187 EditorState *e = runner->e;
40 187 ErrorBuffer *ebuf = runner->ebuf;
41
2/2
✓ Branch 0 (2→3) taken 1 times.
✓ Branch 1 (2→5) taken 186 times.
187 if (unlikely(e->include_recursion_count > 64)) {
42 1 error_msg_for_cmd(ebuf, NULL, "config recursion limit reached");
43 1 return;
44 }
45
46 186 String buf = string_new(1024);
47 186 e->include_recursion_count++;
48
49
2/2
✓ Branch 0 (21→7) taken 8500 times.
✓ Branch 1 (21→22) taken 186 times.
8686 for (size_t i = 0, n = config.length; i < n; ebuf->config_line++) {
50 8500 StringView line = buf_slice_next_line(config.data, &i, n);
51 8500 strview_trim_left(&line);
52
4/4
✓ Branch 0 (9→10) taken 7869 times.
✓ Branch 1 (9→13) taken 631 times.
✓ Branch 2 (11→12) taken 171 times.
✓ Branch 3 (11→13) taken 7698 times.
8500 if (buf.len == 0 && strview_has_prefix(&line, "#")) {
53 // Comment line
54 171 continue;
55 }
56
2/2
✓ Branch 0 (13→14) taken 633 times.
✓ Branch 1 (13→15) taken 7696 times.
8329 if (has_line_continuation(line)) {
57 633 line.length--;
58 633 string_append_strview(&buf, &line);
59 } else {
60 7696 string_append_strview(&buf, &line);
61 7696 handle_command(runner, string_borrow_cstring(&buf));
62 7696 string_clear(&buf);
63 }
64 }
65
66
2/2
✓ Branch 0 (22→23) taken 2 times.
✓ Branch 1 (22→25) taken 184 times.
186 if (unlikely(buf.len)) {
67 // This can only happen if the last line had a line continuation
68 2 handle_command(runner, string_borrow_cstring(&buf));
69 }
70
71 186 e->include_recursion_count--;
72 186 string_free(&buf);
73 }
74
75 2 String dump_builtin_configs(void)
76 {
77 2 String str = string_new(1024);
78
2/2
✓ Branch 0 (7→4) taken 126 times.
✓ Branch 1 (7→8) taken 2 times.
128 for (size_t i = 0; i < ARRAYLEN(builtin_configs); i++) {
79 126 string_append_cstring(&str, builtin_configs[i].name);
80 126 string_append_byte(&str, '\n');
81 }
82 2 return str;
83 }
84
85 174 const BuiltinConfig *get_builtin_config(const char *name)
86 {
87
2/2
✓ Branch 0 (6→3) taken 5723 times.
✓ Branch 1 (6→7) taken 55 times.
5778 for (size_t i = 0; i < ARRAYLEN(builtin_configs); i++) {
88
2/2
✓ Branch 0 (3→4) taken 119 times.
✓ Branch 1 (3→5) taken 5604 times.
5723 if (streq(name, builtin_configs[i].name)) {
89 119 return &builtin_configs[i];
90 }
91 }
92 return NULL;
93 }
94
95 1 const BuiltinConfig *get_builtin_configs_array(size_t *nconfigs)
96 {
97 1 *nconfigs = ARRAYLEN(builtin_configs);
98 1 return &builtin_configs[0];
99 }
100
101 260 int do_read_config(CommandRunner *runner, const char *filename, ConfigFlags flags)
102 {
103 260 ErrorBuffer *ebuf = runner->ebuf;
104 260 bool must_exist = flags & CFG_MUST_EXIST;
105
106
2/2
✓ Branch 0 (2→3) taken 134 times.
✓ Branch 1 (2→9) taken 126 times.
260 if (flags & CFG_BUILTIN) {
107 134 const BuiltinConfig *cfg = get_builtin_config(filename);
108
2/2
✓ Branch 0 (3→4) taken 81 times.
✓ Branch 1 (3→6) taken 53 times.
134 if (cfg) {
109 81 ebuf->config_filename = filename;
110 81 ebuf->config_line = 1;
111 81 exec_config(runner, cfg->text);
112 81 return 0;
113 }
114
2/2
✓ Branch 0 (6→7) taken 1 times.
✓ Branch 1 (6→17) taken 52 times.
53 if (!must_exist) {
115 return 0;
116 }
117 1 error_msg(ebuf, "no built-in config with name '%s'", filename);
118 1 return 1;
119 }
120
121 126 char *buf;
122 126 ssize_t size = read_file(filename, &buf, 0);
123
2/2
✓ Branch 0 (10→11) taken 58 times.
✓ Branch 1 (10→15) taken 68 times.
126 if (size < 0) {
124 58 int err = errno;
125
2/2
✓ Branch 0 (11→12) taken 1 times.
✓ Branch 1 (11→14) taken 57 times.
58 if (err != ENOENT || must_exist) {
126 1 error_msg(ebuf, "Error reading %s: %s", filename, strerror(err));
127 }
128 58 return err;
129 }
130
131 68 ebuf->config_filename = filename;
132 68 ebuf->config_line = 1;
133 68 exec_config(runner, string_view(buf, size));
134 68 free(buf);
135 68 return 0;
136 }
137
138 101 int read_config(CommandRunner *runner, const char *filename, ConfigFlags flags)
139 {
140 // Recursive
141 101 ErrorBuffer *ebuf = runner->ebuf;
142 101 const char *saved_file = ebuf->config_filename;
143 101 const unsigned int saved_line = ebuf->config_line;
144 101 int ret = do_read_config(runner, filename, flags);
145 101 ebuf->config_filename = saved_file;
146 101 ebuf->config_line = saved_line;
147 101 return ret;
148 }
149
150 18 static void exec_builtin_config(EditorState *e, StringView cfg, const char *name)
151 {
152 18 ErrorBuffer *ebuf = &e->err;
153 18 const char *saved_file = ebuf->config_filename;
154 18 const unsigned int saved_line = ebuf->config_line;
155 18 ebuf->config_filename = name;
156 18 ebuf->config_line = 1;
157 18 exec_normal_config(e, cfg);
158 18 ebuf->config_filename = saved_file;
159 18 ebuf->config_line = saved_line;
160 18 }
161
162 12 void exec_builtin_color_reset(EditorState *e)
163 {
164 12 clear_hl_styles(&e->styles);
165 12 StringView reset = string_view(builtin_color_reset, sizeof(builtin_color_reset) - 1);
166 12 exec_builtin_config(e, reset, "color/reset");
167 12 }
168
169 6 void exec_builtin_rc(EditorState *e)
170 {
171 6 exec_builtin_color_reset(e);
172 6 StringView rc = string_view(builtin_rc, sizeof(builtin_rc) - 1);
173 6 exec_builtin_config(e, rc, "rc");
174 6 }
175
176 1 void collect_builtin_configs(PointerArray *a, const char *prefix)
177 {
178 1 size_t prefix_len = strlen(prefix);
179
2/2
✓ Branch 0 (7→3) taken 63 times.
✓ Branch 1 (7→8) taken 1 times.
64 for (size_t i = 0; i < ARRAYLEN(builtin_configs); i++) {
180 63 const char *name = builtin_configs[i].name;
181
2/2
✓ Branch 0 (3→4) taken 1 times.
✓ Branch 1 (3→6) taken 62 times.
63 if (str_has_strn_prefix(name, prefix, prefix_len)) {
182 1 ptr_array_append(a, xstrdup(name));
183 }
184 }
185 1 }
186
187 1 void collect_builtin_includes(PointerArray *a, const char *prefix)
188 {
189 1 size_t prefix_len = strlen(prefix);
190
2/2
✓ Branch 0 (8→3) taken 63 times.
✓ Branch 1 (8→9) taken 1 times.
64 for (size_t i = 0; i < ARRAYLEN(builtin_configs); i++) {
191 63 const char *name = builtin_configs[i].name;
192 63 if (
193
2/2
✓ Branch 0 (3→4) taken 1 times.
✓ Branch 1 (3→7) taken 62 times.
63 str_has_strn_prefix(name, prefix, prefix_len)
194
1/2
✓ Branch 0 (4→5) taken 1 times.
✗ Branch 1 (4→7) not taken.
1 && !str_has_prefix(name, "syntax/")
195 ) {
196 1 ptr_array_append(a, xstrdup(name));
197 }
198 }
199 1 }
200
201 18 UNITTEST {
202 // NOLINTBEGIN(bugprone-assert-side-effect)
203 18 BUG_ON(!get_builtin_config("rc"));
204 18 BUG_ON(!get_builtin_config("color/reset"));
205 // NOLINTEND(bugprone-assert-side-effect)
206 18 }
207