summaryrefslogtreecommitdiff
path: root/src/Buffer.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/Buffer.zig')
-rw-r--r--src/Buffer.zig128
1 files changed, 83 insertions, 45 deletions
diff --git a/src/Buffer.zig b/src/Buffer.zig
index 26f9a93..8cf7dc0 100644
--- a/src/Buffer.zig
+++ b/src/Buffer.zig
@@ -90,10 +90,25 @@ pub fn backwardChar(self: *Buffer) void {
90} 90}
91 91
92pub fn backwardDeleteChar(self: *Buffer) !void { 92pub fn backwardDeleteChar(self: *Buffer) !void {
93 if (self.cx == 0 and self.cy == 0) {
94 return;
95 }
93 self.backwardChar(); 96 self.backwardChar();
94 return self.deleteChar(); 97 return self.deleteChar();
95} 98}
96 99
100pub fn backwardDeleteWord(self: *Buffer) !void {
101 const start = self.findBackwardWordStart();
102 if (start == self.cx) {
103 return self.backwardDeleteChar();
104 } else {
105 var row = &self.rows.items[self.cy];
106 row.data.replaceRangeAssumeCapacity(start, self.cx - start, &.{});
107 self.cx = start;
108 return row.update(self);
109 }
110}
111
97pub fn backwardParagraph(self: *Buffer) void { 112pub fn backwardParagraph(self: *Buffer) void {
98 if (self.cy == 0) { 113 if (self.cy == 0) {
99 return; 114 return;
@@ -111,22 +126,11 @@ pub fn backwardParagraph(self: *Buffer) void {
111} 126}
112 127
113pub fn backwardWord(self: *Buffer) void { 128pub fn backwardWord(self: *Buffer) void {
114 if (self.cx == 0) { 129 const target = self.findBackwardWordStart();
115 return self.backwardChar(); 130 if (target == self.cx) {
116 } 131 self.backwardChar();
117 132 } else {
118 const chars = self.rows.items[self.cy].data.items; 133 self.cx = target;
119 // First we skip non-word
120 while (self.cx > 0) : (self.cx -= 1) {
121 if (std.ascii.isAlphanumeric(chars[self.cx - 1])) {
122 break;
123 }
124 }
125 // Then we skip word
126 while (self.cx > 0) : (self.cx -= 1) {
127 if (!std.ascii.isAlphanumeric(chars[self.cx - 1])) {
128 break;
129 }
130 } 134 }
131} 135}
132 136
@@ -176,6 +180,17 @@ pub fn deleteAllRows(self: *Buffer) void {
176 } 180 }
177} 181}
178 182
183pub fn deleteWord(self: *Buffer) !void {
184 const end = self.findForwardWordEnd();
185 if (end == self.cx) {
186 return self.deleteChar();
187 } else {
188 var row = &self.rows.items[self.cy];
189 row.data.replaceRangeAssumeCapacity(self.cx, end - self.cx, &.{});
190 return row.update(self);
191 }
192}
193
179pub fn deleteRow(self: *Buffer, at: usize) void { 194pub fn deleteRow(self: *Buffer, at: usize) void {
180 if (at == self.rows.items.len) { 195 if (at == self.rows.items.len) {
181 return; 196 return;
@@ -295,6 +310,50 @@ pub fn drawStatusBar(self: Buffer, writer: anytype, screencols: usize) !void {
295 try writer.writeAll("\x1b[m\r\n"); 310 try writer.writeAll("\x1b[m\r\n");
296} 311}
297 312
313pub fn findBackwardWordStart(self: Buffer) usize {
314 if (self.cy == self.rows.items.len) {
315 return 0;
316 }
317
318 const chars = self.rows.items[self.cy].data.items;
319 var start = self.cx;
320 // First we skip non-word
321 while (start > 0) : (start -= 1) {
322 if (std.ascii.isAlphanumeric(chars[start - 1])) {
323 break;
324 }
325 }
326 // Then we skip word
327 while (start > 0) : (start -= 1) {
328 if (!std.ascii.isAlphanumeric(chars[start - 1])) {
329 break;
330 }
331 }
332 return start;
333}
334
335pub fn findForwardWordEnd(self: Buffer) usize {
336 if (self.cy == self.rows.items.len) {
337 return 0;
338 }
339
340 const chars = self.rows.items[self.cy].data.items;
341 var end = self.cx;
342 // First we skip non-word
343 while (end < chars.len) : (end += 1) {
344 if (std.ascii.isAlphanumeric(chars[end])) {
345 break;
346 }
347 }
348 // Then we skip word
349 while (end < chars.len) : (end += 1) {
350 if (!std.ascii.isAlphanumeric(chars[end])) {
351 break;
352 }
353 }
354 return end;
355}
356
298pub fn forwardChar(self: *Buffer) void { 357pub fn forwardChar(self: *Buffer) void {
299 if (self.rows.items.len == self.cy) { 358 if (self.rows.items.len == self.cy) {
300 return; 359 return;
@@ -325,26 +384,11 @@ pub fn forwardParagraph(self: *Buffer) void {
325} 384}
326 385
327pub fn forwardWord(self: *Buffer) void { 386pub fn forwardWord(self: *Buffer) void {
328 if (self.cy == self.rows.items.len) { 387 const end = self.findForwardWordEnd();
329 return; 388 if (end == self.cx) {
330 } 389 self.forwardChar();
331 390 } else {
332 const chars = self.rows.items[self.cy].data.items; 391 self.cx = end;
333 if (self.cx == chars.len) {
334 return self.forwardChar();
335 }
336
337 // First we skip non-word
338 while (self.cx < chars.len) : (self.cx += 1) {
339 if (std.ascii.isAlphanumeric(chars[self.cx])) {
340 break;
341 }
342 }
343 // Then we skip word
344 while (self.cx < chars.len) : (self.cx += 1) {
345 if (!std.ascii.isAlphanumeric(chars[self.cx])) {
346 break;
347 }
348 } 392 }
349} 393}
350 394
@@ -440,18 +484,12 @@ pub fn killLine(self: *Buffer) !void {
440 484
441 var row = &self.rows.items[self.cy]; 485 var row = &self.rows.items[self.cy];
442 if (self.cx == row.data.items.len) { 486 if (self.cx == row.data.items.len) {
443 if (self.cy == self.rows.items.len - 1) { 487 return self.deleteChar();
444 return;
445 }
446
447 try row.appendString(self, self.rows.items[self.cy+1].data.items);
448 self.deleteRow(self.cy + 1);
449 } else { 488 } else {
489 self.dirty = true;
450 try row.data.resize(self.cx); 490 try row.data.resize(self.cx);
491 return row.update(self);
451 } 492 }
452
453 self.dirty = true;
454 return row.update(self);
455} 493}
456 494
457pub fn lineNumberDigits(self: Buffer) usize { 495pub fn lineNumberDigits(self: Buffer) usize {