dte test coverage


Directory: ./
File: src/shift.c
Date: 2025-02-14 16:55:22
Exec Total Coverage
Lines: 68 88 77.3%
Functions: 5 5 100.0%
Branches: 22 38 57.9%

Line Branch Exec Source
1 #include <stddef.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include "shift.h"
5 #include "block-iter.h"
6 #include "buffer.h"
7 #include "change.h"
8 #include "indent.h"
9 #include "move.h"
10 #include "options.h"
11 #include "selection.h"
12 #include "util/debug.h"
13 #include "util/macros.h"
14 #include "util/xmalloc.h"
15
16 10 static char *alloc_indent(const LocalOptions *options, size_t count, size_t *sizep)
17 {
18 10 bool use_spaces = use_spaces_for_indent(options);
19
2/2
✓ Branch 0 (2→3) taken 1 times.
✓ Branch 1 (2→4) taken 9 times.
10 size_t size = use_spaces ? count * options->indent_width : count;
20 10 *sizep = size;
21 10 return memset(xmalloc(size), use_spaces ? ' ' : '\t', size);
22 }
23
24 10 static void shift_right(View *view, size_t nr_lines, size_t count)
25 {
26 10 const LocalOptions *options = &view->buffer->options;
27 10 size_t indent_size;
28 10 char *indent = alloc_indent(options, count, &indent_size);
29
30 30 for (size_t i = 0; true; ) {
31 30 StringView line;
32 30 fetch_this_line(&view->cursor, &line);
33 30 IndentInfo info = get_indent_info(options, &line);
34
1/2
✗ Branch 0 (5→6) not taken.
✓ Branch 1 (5→8) taken 30 times.
30 if (info.wsonly) {
35 if (info.bytes) {
36 // Remove indentation
37 buffer_delete_bytes(view, info.bytes);
38 }
39
1/2
✓ Branch 0 (8→9) taken 30 times.
✗ Branch 1 (8→10) not taken.
30 } else if (info.sane) {
40 // Insert whitespace
41 30 buffer_insert_bytes(view, indent, indent_size);
42 } else {
43 // Replace whole indentation with sane one
44 size_t size;
45 char *buf = alloc_indent(options, info.level + count, &size);
46 buffer_replace_bytes(view, info.bytes, buf, size);
47 free(buf);
48 }
49
2/2
✓ Branch 0 (13→14) taken 20 times.
✓ Branch 1 (13→16) taken 10 times.
30 if (++i == nr_lines) {
50 break;
51 }
52 20 block_iter_eat_line(&view->cursor);
53 }
54
55 10 free(indent);
56 10 }
57
58 9 static void shift_left(View *view, size_t nr_lines, size_t count)
59 {
60 9 const LocalOptions *options = &view->buffer->options;
61 9 const size_t indent_width = options->indent_width;
62 9 const bool space_indent = use_spaces_for_indent(options);
63
64 25 for (size_t i = 0; true; ) {
65 25 StringView line;
66 25 fetch_this_line(&view->cursor, &line);
67 25 IndentInfo info = get_indent_info(options, &line);
68
1/2
✗ Branch 0 (5→6) not taken.
✓ Branch 1 (5→8) taken 25 times.
25 if (info.wsonly) {
69 if (info.bytes) {
70 // Remove indentation
71 buffer_delete_bytes(view, info.bytes);
72 }
73
3/4
✓ Branch 0 (8→9) taken 23 times.
✓ Branch 1 (8→14) taken 2 times.
✓ Branch 2 (9→10) taken 23 times.
✗ Branch 3 (9→14) not taken.
48 } else if (info.level && info.sane) {
74 23 size_t n = MIN(count, info.level);
75
1/2
✓ Branch 0 (10→11) taken 23 times.
✗ Branch 1 (10→12) not taken.
23 if (space_indent) {
76 23 n *= indent_width;
77 }
78 23 buffer_delete_bytes(view, n);
79
1/2
✗ Branch 0 (14→15) not taken.
✓ Branch 1 (14→20) taken 2 times.
2 } else if (info.bytes) {
80 // Replace whole indentation with sane one
81 if (info.level > count) {
82 size_t size;
83 char *buf = alloc_indent(options, info.level - count, &size);
84 buffer_replace_bytes(view, info.bytes, buf, size);
85 free(buf);
86 } else {
87 buffer_delete_bytes(view, info.bytes);
88 }
89 }
90
2/2
✓ Branch 0 (20→21) taken 16 times.
✓ Branch 1 (20→23) taken 9 times.
25 if (++i == nr_lines) {
91 break;
92 }
93 16 block_iter_eat_line(&view->cursor);
94 }
95 9 }
96
97 19 static void do_shift_lines(View *view, int count, size_t nr_lines)
98 {
99 19 begin_change_chain();
100 19 block_iter_bol(&view->cursor);
101
2/2
✓ Branch 0 (4→5) taken 10 times.
✓ Branch 1 (4→6) taken 9 times.
19 if (count > 0) {
102 10 shift_right(view, nr_lines, count);
103 } else {
104 9 shift_left(view, nr_lines, -count);
105 }
106 19 end_change_chain(view);
107 19 }
108
109 19 void shift_lines(View *view, int count)
110 {
111 19 int width = view->buffer->options.indent_width;
112 19 BUG_ON(width > INDENT_WIDTH_MAX || width < 1);
113 19 BUG_ON(count == 0);
114
115 19 long x = view_get_preferred_x(view) + (count * width);
116 19 x = MAX(x, 0);
117
118
2/2
✓ Branch 0 (7→8) taken 10 times.
✓ Branch 1 (7→10) taken 9 times.
19 if (view->selection == SELECT_NONE) {
119 10 do_shift_lines(view, count, 1);
120 10 goto out;
121 }
122
123 9 view->selection = SELECT_LINES;
124 9 SelectionInfo info = init_selection(view);
125 9 view->cursor = info.si;
126 9 size_t nr_lines = get_nr_selected_lines(&info);
127
1/2
✗ Branch 0 (12→13) not taken.
✓ Branch 1 (12→14) taken 9 times.
9 if (unlikely(nr_lines == 0)) {
128 return;
129 }
130
131 9 do_shift_lines(view, count, nr_lines);
132
1/2
✓ Branch 0 (15→16) taken 9 times.
✗ Branch 1 (15→21) not taken.
9 if (info.swapped) {
133 // Cursor should be at beginning of selection
134 9 block_iter_bol(&view->cursor);
135 9 view->sel_so = block_iter_get_offset(&view->cursor);
136
2/2
✓ Branch 0 (20→19) taken 36 times.
✓ Branch 1 (20→26) taken 9 times.
45 while (--nr_lines) {
137 36 block_iter_prev_line(&view->cursor);
138 }
139 } else {
140 BlockIter save = view->cursor;
141 while (--nr_lines) {
142 block_iter_prev_line(&view->cursor);
143 }
144 view->sel_so = block_iter_get_offset(&view->cursor);
145 view->cursor = save;
146 }
147
148 19 out:
149 19 move_to_preferred_x(view, x);
150 }
151