How to dynamically allocate memmory

    pub fn abAppend(ab: *abuf, s: []const u8) !void {
    if (ab.b) |buffer| {
        const new_buff = try std.heap.c_allocator.realloc(buffer, ab.len + s.len);
        @memcpy(new_buff[ab.len..], s);

        ab.b = new_buff;
        ab.len = ab.len + s.len;
    }
}

this gives nothing it ab.b is empty

const abuf = struct { b: ?[]u8, len: usize };

const ABUF_INIT = abuf{
    .b = null,
    .len = 0,
};
 pub fn editorRefreshScreen() !void {
    var ab = ABUF_INIT;

    try abAppend(&ab, "\x1b[2J");
    try abAppend(&ab, "\x1b[2H");
    try editorDrawRows(&ab);
    try abAppend(&ab, "\x1b[H");

    if (ab.b) |buffer| {
        _ = c.write(std.io.getStdOut().handle, buffer.ptr, ab.len);
    }

    try abFree(&ab);
}
pub fn main() !void {
    defer disableRawMode();
    enableRawMode();
    try initEditor();

    while (true) {
        editorRefreshScreen() catch {
            std.debug.print("editor refresh screen", .{});
            break;
        };
        editorProcessKeyPress() catch {
            break;
        };
    }
}

anybody help me to do it correct way

Your *ab starts with a .b = null field, so the if (ab.b) |buffer| check never succeeds (what would buffer point to?).

You probably want to allocate initial storage in that case, but you might like to use Zig’s built-in resizable array for this instead of rolling your own — std.ArrayList. For example:

var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();

var ab = std.ArrayListUnmanaged(u8){};
defer ab.deinit(allocator);

try ab.appendSlice(allocator, "\x1b[2J");
try ab.appendSlice(allocator, "\x1b[2H");
try editorDrawRows(allocator, &ab); // <-- TODO: update editorDrawRows to use the new type!
try ab.appendSlice(allocator, "\x1b[H");

try std.io.getStdOut().writeAll(ab.items);

You probably want to pass the allocator in from main, instead of initialising (and freeing it) every time you refresh the screen.

1 Like

thanks

this works

1 Like