| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "join.h" | ||
| 2 | #include "block-iter.h" | ||
| 3 | #include "change.h" | ||
| 4 | #include "selection.h" | ||
| 5 | #include "util/debug.h" | ||
| 6 | #include "util/unicode.h" | ||
| 7 | |||
| 8 | 4 | static void join_selection(View *view, const char *delim, size_t delim_len) | |
| 9 | { | ||
| 10 | 4 | size_t count = prepare_selection(view); | |
| 11 | 4 | BlockIter bi = view->cursor; | |
| 12 | 4 | size_t ws_len = 0; | |
| 13 | 4 | size_t join = 0; | |
| 14 | 4 | CodePoint ch = 0; | |
| 15 | 4 | unselect(view); | |
| 16 | 4 | begin_change_chain(); | |
| 17 | |||
| 18 |
2/2✓ Branch 17 → 6 taken 20 times.
✓ Branch 17 → 18 taken 4 times.
|
24 | while (count > 0) { |
| 19 |
2/2✓ Branch 6 → 7 taken 14 times.
✓ Branch 6 → 8 taken 6 times.
|
20 | if (!ws_len) { |
| 20 | 14 | view->cursor = bi; | |
| 21 | } | ||
| 22 | |||
| 23 | 20 | size_t n = block_iter_next_char(&bi, &ch); | |
| 24 | 20 | count -= MIN(n, count); | |
| 25 |
2/2✓ Branch 9 → 10 taken 10 times.
✓ Branch 9 → 11 taken 10 times.
|
20 | if (ch == '\n' || ch == '\t' || ch == ' ') { |
| 26 | 10 | join += (ch == '\n'); | |
| 27 | 10 | ws_len++; | |
| 28 | 10 | continue; | |
| 29 | } | ||
| 30 | |||
| 31 |
2/2✓ Branch 11 → 12 taken 6 times.
✓ Branch 11 → 16 taken 4 times.
|
10 | if (join) { |
| 32 | 6 | buffer_replace_bytes(view, ws_len, delim, delim_len); | |
| 33 | // Skip the delimiter we inserted and the char we read last | ||
| 34 | 6 | block_iter_skip_bytes(&view->cursor, delim_len); | |
| 35 | 6 | block_iter_next_char(&view->cursor, &ch); | |
| 36 | 6 | bi = view->cursor; | |
| 37 | } | ||
| 38 | |||
| 39 | ws_len = 0; | ||
| 40 | join = 0; | ||
| 41 | } | ||
| 42 | |||
| 43 |
2/4✓ Branch 18 → 19 taken 4 times.
✗ Branch 18 → 25 not taken.
✓ Branch 19 → 20 taken 4 times.
✗ Branch 19 → 21 not taken.
|
4 | if (join && ch == '\n') { |
| 44 | // Don't replace last newline at end of selection | ||
| 45 | 4 | join--; | |
| 46 | 4 | ws_len--; | |
| 47 | } | ||
| 48 | |||
| 49 |
1/2✗ Branch 21 → 22 not taken.
✓ Branch 21 → 25 taken 4 times.
|
4 | if (join) { |
| 50 | ✗ | size_t ins_len = (ch == '\n') ? 0 : delim_len; // Don't add delim, if at eol | |
| 51 | ✗ | buffer_replace_bytes(view, ws_len, delim, ins_len); | |
| 52 | } | ||
| 53 | |||
| 54 | 4 | end_change_chain(view); | |
| 55 | 4 | } | |
| 56 | |||
| 57 | 16 | void join_lines(View *view, const char *delim, size_t delim_len) | |
| 58 | { | ||
| 59 |
2/2✓ Branch 2 → 3 taken 4 times.
✓ Branch 2 → 4 taken 12 times.
|
16 | if (view->selection) { |
| 60 | 4 | join_selection(view, delim, delim_len); | |
| 61 | 14 | return; | |
| 62 | } | ||
| 63 | |||
| 64 | // Create an iterator and position it at the beginning of the next line | ||
| 65 | // (or return early, if there's no next line) | ||
| 66 | 12 | BlockIter next = view->cursor; | |
| 67 |
3/4✓ Branch 5 → 6 taken 6 times.
✓ Branch 5 → 19 taken 6 times.
✓ Branch 6 → 7 taken 6 times.
✗ Branch 6 → 19 not taken.
|
12 | if (!block_iter_next_line(&next) || block_iter_is_eof(&next)) { |
| 68 | return; | ||
| 69 | } | ||
| 70 | |||
| 71 | // Create a second iterator and position it at the end of the current line | ||
| 72 | 6 | BlockIter eol = next; | |
| 73 | 6 | CodePoint u; | |
| 74 | 6 | size_t nbytes = block_iter_prev_char(&eol, &u); | |
| 75 | 6 | BUG_ON(nbytes != 1); | |
| 76 | 6 | BUG_ON(u != '\n'); | |
| 77 | |||
| 78 | // Skip over trailing whitespace at the end of the current line | ||
| 79 | 6 | size_t del_count = 1 + block_iter_skip_blanks_bwd(&eol); | |
| 80 | |||
| 81 | // Skip over leading whitespace at the start of the next line | ||
| 82 | 6 | del_count += block_iter_skip_blanks_fwd(&next); | |
| 83 | |||
| 84 | // Move the cursor to the join position | ||
| 85 | 6 | view->cursor = eol; | |
| 86 | |||
| 87 |
2/2✓ Branch 14 → 15 taken 3 times.
✓ Branch 14 → 16 taken 3 times.
|
6 | if (block_iter_is_bol(&next)) { |
| 88 | // If the next line is empty (or whitespace only) just discard | ||
| 89 | // it, by deleting the newline and any whitespace | ||
| 90 | 3 | buffer_delete_bytes(view, del_count); | |
| 91 | } else { | ||
| 92 | // Otherwise, join the current and next lines together, by | ||
| 93 | // replacing the newline/whitespace with the delimiter string | ||
| 94 | 3 | buffer_replace_bytes(view, del_count, delim, delim_len); | |
| 95 | } | ||
| 96 | } | ||
| 97 |