Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Io.Reader

std.fs.File implements the Io.Reader interface, so we'll use that to read its lines. A simple pattern would be like the following:

Editor.zig
/// Read all lines from file.
fn readLines(e: *Editor, file: std.fs.File) !void {
    _ = e;
    var buf: [1024]u8 = undefined;
    var reader = file.reader(&buf);

    while (reader.interface.takeDelimiterExclusive('\n')) |line| {
        // we print the line to stderr, to see if it works
        std.debug.print("{s}\n", .{line});
    }
    else |err| if (err != error.EndOfStream) return err;
}

file is the file that has already been opened and is ready to be read. We create a buffer on the stack, then we initialize its reader. Io.Reader actually lives in reader.interface, so Io.Reader methods will be called on the interface.

We stop at error .EndOfStream, which means our file has been fully read. Other errors instead should be handled.

Now, this implementation is simple, but it has a problem: the buffer is on the stack, and has fixed size. Which means that we can't read lines longer than its size. If a file has lines that are longer than that, it will error out. We'll fix this later.

Anyway, let's test this. Create a file named kilo at the root of the project:

~/kilo-zig/kilo
#!/bin/sh

~/kilo-zig/zig-out/bin/kilo "$@" 2>err.txt

Then

chmod u+x kilo

It will run the program and write stderr output to err.txt. Compile and run with an argument, the lines of the file should be written into err.txt:

./kilo src/main.zig

Remember that we still have to press 3 times Ctrl-Q to quit.