| 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(xadd3(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(MessageList *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 MessageList *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 MessageList *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 | 37 | void clear_messages(MessageList *msgs) | |
| 95 | { | ||
| 96 | 37 | msgs->pos = 0; | |
| 97 | 37 | ptr_array_free_cb(&msgs->array, FREE_FUNC(free_message)); | |
| 98 | 37 | } | |
| 99 | |||
| 100 | 1 | String dump_messages(const MessageList *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 |