+27
-27
src/widgets/TextInput.zig
+27
-27
src/widgets/TextInput.zig
···
88
88
}
89
89
90
90
/// calculates the display width from the draw_offset to the cursor
91
-
fn widthToCursor(self: *TextInput, win: Window) usize {
91
+
pub fn widthToCursor(self: *TextInput, win: Window) usize {
92
92
var width: usize = 0;
93
93
const first_half = self.buf.firstHalf();
94
94
var first_iter = self.unicode.graphemeIterator(first_half);
···
104
104
return width;
105
105
}
106
106
107
-
fn cursorLeft(self: *TextInput) void {
107
+
pub fn cursorLeft(self: *TextInput) void {
108
108
// We need to find the size of the last grapheme in the first half
109
109
var iter = self.unicode.graphemeIterator(self.buf.firstHalf());
110
110
var len: usize = 0;
···
114
114
self.buf.moveGapLeft(len);
115
115
}
116
116
117
-
fn cursorRight(self: *TextInput) void {
117
+
pub fn cursorRight(self: *TextInput) void {
118
118
var iter = self.unicode.graphemeIterator(self.buf.secondHalf());
119
119
const grapheme = iter.next() orelse return;
120
120
self.buf.moveGapRight(grapheme.len);
121
121
}
122
122
123
-
fn graphemesBeforeCursor(self: *const TextInput) usize {
123
+
pub fn graphemesBeforeCursor(self: *const TextInput) usize {
124
124
const first_half = self.buf.firstHalf();
125
125
var first_iter = self.unicode.graphemeIterator(first_half);
126
126
var i: usize = 0;
···
216
216
return self.buf.toOwnedSlice();
217
217
}
218
218
219
-
fn reset(self: *TextInput) void {
219
+
pub fn reset(self: *TextInput) void {
220
220
self.draw_offset = 0;
221
221
self.prev_cursor_col = 0;
222
222
self.prev_cursor_idx = 0;
···
227
227
return self.buf.cursor;
228
228
}
229
229
230
-
fn deleteToEnd(self: *TextInput) void {
230
+
pub fn deleteToEnd(self: *TextInput) void {
231
231
self.buf.growGapRight(self.buf.secondHalf().len);
232
232
}
233
233
234
-
fn deleteToStart(self: *TextInput) void {
234
+
pub fn deleteToStart(self: *TextInput) void {
235
235
self.buf.growGapLeft(self.buf.cursor);
236
236
}
237
237
238
-
fn deleteBeforeCursor(self: *TextInput) void {
238
+
pub fn deleteBeforeCursor(self: *TextInput) void {
239
239
// We need to find the size of the last grapheme in the first half
240
240
var iter = self.unicode.graphemeIterator(self.buf.firstHalf());
241
241
var len: usize = 0;
···
245
245
self.buf.growGapLeft(len);
246
246
}
247
247
248
-
fn deleteAfterCursor(self: *TextInput) void {
248
+
pub fn deleteAfterCursor(self: *TextInput) void {
249
249
var iter = self.unicode.graphemeIterator(self.buf.secondHalf());
250
250
const grapheme = iter.next() orelse return;
251
251
self.buf.growGapRight(grapheme.len);
···
253
253
254
254
/// Moves the cursor backward by words. If the character before the cursor is a space, the cursor is
255
255
/// positioned just after the next previous space
256
-
fn moveBackwardWordwise(self: *TextInput) void {
256
+
pub fn moveBackwardWordwise(self: *TextInput) void {
257
257
const trimmed = std.mem.trimRight(u8, self.buf.firstHalf(), " ");
258
258
const idx = if (std.mem.lastIndexOfScalar(u8, trimmed, ' ')) |last|
259
259
last + 1
···
262
262
self.buf.moveGapLeft(self.buf.cursor - idx);
263
263
}
264
264
265
-
fn moveForwardWordwise(self: *TextInput) void {
265
+
pub fn moveForwardWordwise(self: *TextInput) void {
266
266
const second_half = self.buf.secondHalf();
267
267
var i: usize = 0;
268
268
while (i < second_half.len and second_half[i] == ' ') : (i += 1) {}
···
270
270
self.buf.moveGapRight(idx);
271
271
}
272
272
273
-
fn deleteWordBefore(self: *TextInput) void {
273
+
pub fn deleteWordBefore(self: *TextInput) void {
274
274
// Store current cursor position. Move one word backward. Delete after the cursor the bytes we
275
275
// moved
276
276
const pre = self.buf.cursor;
···
278
278
self.buf.growGapRight(pre - self.buf.cursor);
279
279
}
280
280
281
-
fn deleteWordAfter(self: *TextInput) void {
281
+
pub fn deleteWordAfter(self: *TextInput) void {
282
282
// Store current cursor position. Move one word backward. Delete after the cursor the bytes we
283
283
// moved
284
284
const second_half = self.buf.secondHalf();
···
320
320
try std.testing.expectEqualStrings("hello, wor", input.sliceToCursor(&buf));
321
321
}
322
322
323
-
const Buffer = struct {
323
+
pub const Buffer = struct {
324
324
allocator: std.mem.Allocator,
325
325
buffer: []u8,
326
326
cursor: usize,
327
327
gap_size: usize,
328
328
329
-
fn init(allocator: std.mem.Allocator) Buffer {
329
+
pub fn init(allocator: std.mem.Allocator) Buffer {
330
330
return .{
331
331
.allocator = allocator,
332
332
.buffer = &.{},
···
335
335
};
336
336
}
337
337
338
-
fn deinit(self: *Buffer) void {
338
+
pub fn deinit(self: *Buffer) void {
339
339
self.allocator.free(self.buffer);
340
340
}
341
341
342
-
fn firstHalf(self: Buffer) []const u8 {
342
+
pub fn firstHalf(self: Buffer) []const u8 {
343
343
return self.buffer[0..self.cursor];
344
344
}
345
345
346
-
fn secondHalf(self: Buffer) []const u8 {
346
+
pub fn secondHalf(self: Buffer) []const u8 {
347
347
return self.buffer[self.cursor + self.gap_size ..];
348
348
}
349
349
350
-
fn grow(self: *Buffer, n: usize) std.mem.Allocator.Error!void {
350
+
pub fn grow(self: *Buffer, n: usize) std.mem.Allocator.Error!void {
351
351
// Always grow by 512 bytes
352
352
const new_size = self.buffer.len + n + 512;
353
353
// Allocate the new memory
···
362
362
self.gap_size = new_size - second_half.len - self.cursor;
363
363
}
364
364
365
-
fn insertSliceAtCursor(self: *Buffer, slice: []const u8) std.mem.Allocator.Error!void {
365
+
pub fn insertSliceAtCursor(self: *Buffer, slice: []const u8) std.mem.Allocator.Error!void {
366
366
if (slice.len == 0) return;
367
367
if (self.gap_size <= slice.len) try self.grow(slice.len);
368
368
@memcpy(self.buffer[self.cursor .. self.cursor + slice.len], slice);
···
371
371
}
372
372
373
373
/// Move the gap n bytes to the left
374
-
fn moveGapLeft(self: *Buffer, n: usize) void {
374
+
pub fn moveGapLeft(self: *Buffer, n: usize) void {
375
375
const new_idx = self.cursor -| n;
376
376
const dst = self.buffer[new_idx + self.gap_size ..];
377
377
const src = self.buffer[new_idx..self.cursor];
···
379
379
self.cursor = new_idx;
380
380
}
381
381
382
-
fn moveGapRight(self: *Buffer, n: usize) void {
382
+
pub fn moveGapRight(self: *Buffer, n: usize) void {
383
383
const new_idx = self.cursor + n;
384
384
const dst = self.buffer[self.cursor..];
385
385
const src = self.buffer[self.cursor + self.gap_size .. new_idx + self.gap_size];
···
388
388
}
389
389
390
390
/// grow the gap by moving the cursor n bytes to the left
391
-
fn growGapLeft(self: *Buffer, n: usize) void {
391
+
pub fn growGapLeft(self: *Buffer, n: usize) void {
392
392
// gap grows by the delta
393
393
self.gap_size += n;
394
394
self.cursor -|= n;
395
395
}
396
396
397
397
/// grow the gap by removing n bytes after the cursor
398
-
fn growGapRight(self: *Buffer, n: usize) void {
398
+
pub fn growGapRight(self: *Buffer, n: usize) void {
399
399
self.gap_size = @min(self.gap_size + n, self.buffer.len - self.cursor);
400
400
}
401
401
402
-
fn clearAndFree(self: *Buffer) void {
402
+
pub fn clearAndFree(self: *Buffer) void {
403
403
self.cursor = 0;
404
404
self.allocator.free(self.buffer);
405
405
self.buffer = &.{};
406
406
self.gap_size = 0;
407
407
}
408
408
409
-
fn clearRetainingCapacity(self: *Buffer) void {
409
+
pub fn clearRetainingCapacity(self: *Buffer) void {
410
410
self.cursor = 0;
411
411
self.gap_size = self.buffer.len;
412
412
}
413
413
414
-
fn toOwnedSlice(self: *Buffer) std.mem.Allocator.Error![]const u8 {
414
+
pub fn toOwnedSlice(self: *Buffer) std.mem.Allocator.Error![]const u8 {
415
415
const first_half = self.firstHalf();
416
416
const second_half = self.secondHalf();
417
417
const buf = try self.allocator.alloc(u8, first_half.len + second_half.len);