dte test coverage


Directory: ./
File: src/msg.c
Date: 2025-06-04 06:50:24
Exec Total Coverage
Lines: 40 80 50.0%
Functions: 6 7 85.7%
Branches: 12 42 28.6%

Line Branch Exec Source
1 #include <stdlib.h>
2 #include <string.h>
3 #include <unistd.h>
4 #include "msg.h"
5 #include "command/error.h"
6 #include "editor.h"
7 #include "util/debug.h"
8 #include "util/numtostr.h"
9 #include "util/path.h"
10 #include "util/xmalloc.h"
11
12 1 static void free_message(Message *m)
13 {
14
1/2
✓ Branch 0 (2→3) taken 1 times.
✗ Branch 1 (2→4) not taken.
1 if (m->loc) {
15 1 file_location_free(m->loc);
16 }
17 1 free(m);
18 1 }
19
20 Message *new_message(const char *msg, size_t len)
21 {
22 Message *m = xmalloc(sizeof(*m) + len + 1);
23 m->loc = NULL;
24 if (len) {
25 memcpy(m->msg, msg, len);
26 }
27 m->msg[len] = '\0';
28 return m;
29 }
30
31 1 void add_message(MessageArray *msgs, Message *m)
32 {
33 1 ptr_array_append(&msgs->array, m);
34 1 }
35
36 // Jump to the FileLocation of the current Message
37 1 bool activate_current_message(const MessageArray *msgs, Window *window)
38 {
39 1 size_t count = msgs->array.count;
40
1/2
✓ Branch 0 (2→3) taken 1 times.
✗ Branch 1 (2→12) not taken.
1 if (count == 0) {
41 return false;
42 }
43
44 1 size_t pos = msgs->pos;
45 1 BUG_ON(pos >= count);
46 1 const Message *m = msgs->array.ptrs[pos];
47 1 const FileLocation *loc = m->loc;
48
3/6
✓ Branch 0 (5→6) taken 1 times.
✗ Branch 1 (5→9) not taken.
✓ Branch 2 (6→7) taken 1 times.
✗ Branch 3 (6→9) not taken.
✓ Branch 4 (8→9) taken 1 times.
✗ Branch 5 (8→12) not taken.
1 if (loc && loc->filename && !file_location_go(window, loc)) {
49 // Failed to jump to location; error message is visible
50 return false;
51 }
52
53 1 ErrorBuffer *ebuf = &window->editor->err;
54
1/2
✓ Branch 0 (9→10) taken 1 times.
✗ Branch 1 (9→11) not taken.
1 if (count == 1) {
55 1 return info_msg(ebuf, "%s", m->msg);
56 }
57
58 return info_msg(ebuf, "[%zu/%zu] %s", pos + 1, count, m->msg);
59 }
60
61 // Like activate_current_message(), but also pushing the previous
62 // FileLocation on the bookmark stack if the cursor moves
63 1 void activate_current_message_save (
64 const MessageArray *msgs,
65 PointerArray *bookmarks,
66 const View *view
67 ) {
68 1 size_t nmsgs = msgs->array.count;
69
1/2
✓ Branch 0 (2→3) taken 1 times.
✗ Branch 1 (2→12) not taken.
1 if (nmsgs == 0) {
70 return;
71 }
72
73 1 const BlockIter save = view->cursor;
74 1 const unsigned long line = view->cy + 1;
75 1 const unsigned long col = view->cx_char + 1;
76 1 activate_current_message(msgs, view->window);
77
78 1 const BlockIter *cursor = &view->window->editor->view->cursor;
79
2/6
✓ Branch 0 (4→5) taken 1 times.
✗ Branch 1 (4→7) not taken.
✗ Branch 2 (5→6) not taken.
✓ Branch 3 (5→7) taken 1 times.
✗ Branch 4 (6→7) not taken.
✗ Branch 5 (6→12) not taken.
1 if (nmsgs == 1 && cursor->blk == save.blk && cursor->offset == save.offset) {
80 // Only one message and cursor position not changed; don't bookmark.
81 // TODO: Make this condition configurable (some people may prefer
82 // to *always* push a bookmark)
83 return;
84 }
85
86 // Active view or cursor position changed, or MAY change due to
87 // there being multiple Messages to navigate with `msg -n|-p`;
88 // bookmark the previous location
89 1 const Buffer *b = view->buffer;
90
1/2
✗ Branch 0 (7→8) not taken.
✓ Branch 1 (7→9) taken 1 times.
1 char *filename = b->abs_filename ? xstrdup(b->abs_filename) : NULL;
91 1 bookmark_push(bookmarks, new_file_location(filename, b->id, line, col));
92 }
93
94 31 void clear_messages(MessageArray *msgs)
95 {
96 31 msgs->pos = 0;
97 31 ptr_array_free_cb(&msgs->array, FREE_FUNC(free_message));
98 31 }
99
100 1 String dump_messages(const MessageArray *messages)
101 {
102 1 size_t count = messages->array.count;
103 1 char cwd[8192];
104
2/4
✓ Branch 0 (3→4) taken 1 times.
✗ Branch 1 (3→5) not taken.
✓ Branch 2 (4→5) taken 1 times.
✗ Branch 3 (4→6) not taken.
1 if (unlikely(!getcwd(cwd, sizeof cwd)) || count == 0) {
105 1 return string_new(0);
106 }
107
108 String buf = string_new(4096);
109 for (size_t i = 0; i < count; i++) {
110 char *ptr = string_reserve_space(&buf, DECIMAL_STR_MAX(i));
111 buf.len += buf_umax_to_str(i + 1, ptr);
112 string_append_literal(&buf, ": ");
113
114 const Message *m = messages->array.ptrs[i];
115 const FileLocation *loc = m->loc;
116 if (!loc || !loc->filename) {
117 goto append_msg;
118 }
119
120 if (path_is_absolute(loc->filename)) {
121 char *rel = path_relative(loc->filename, cwd);
122 string_append_cstring(&buf, rel);
123 free(rel);
124 } else {
125 string_append_cstring(&buf, loc->filename);
126 }
127
128 string_append_byte(&buf, ':');
129
130 if (loc->pattern) {
131 string_append_literal(&buf, " /");
132 string_append_cstring(&buf, loc->pattern);
133 string_append_literal(&buf, "/\n");
134 continue;
135 }
136
137 if (loc->line != 0) {
138 string_append_cstring(&buf, ulong_to_str(loc->line));
139 string_append_byte(&buf, ':');
140 if (loc->column != 0) {
141 string_append_cstring(&buf, ulong_to_str(loc->column));
142 string_append_byte(&buf, ':');
143 }
144 }
145
146 string_append_literal(&buf, " ");
147
148 append_msg:
149 string_append_cstring(&buf, m->msg);
150 string_append_byte(&buf, '\n');
151 }
152
153 return buf;
154 }
155