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

Interacting with the user

At various points of our program, we'll want to interact with the users, either by notifying them of something, or by requesting something.

For example, we want to print a "help" sort of message when the editor starts, we must prompt for a filename when trying to save an unnamed buffer, or for a word when using the searching functionality.

We have already added the status_msg field in Editor, so we must add a function that prints it.

We'll have two ways to print, either normal messages (or prompts) using regular highlight, or error messages, which we'll print in a bright red color.

statusMessage()

What this function does, is clearing the previous content, and replace it with a new one, which we'll format on the fly by using the ArrayList(u8) method print(). Note that this method only works if the base type of the array is u8.

Editor.zig
///////////////////////////////////////////////////////////////////////////////
//
//                              Message area
//
///////////////////////////////////////////////////////////////////////////////

/// Set a status message, using regular highlight.
pub fn statusMessage(e: *Editor, comptime format: []const u8, args: anytype) !void {
    assert(format.len > 0);
    e.status_msg.clearRetainingCapacity();
    try e.status_msg.print(e.alc, format, args);
    e.status_msg_time = time();
}

print() uses std.Io.Writer, we'll see this interface again when we'll want to save a file.

We never pass an empty format, so we assert() that the format is not empty. You have to define a assert constant (do it yourself).

Finally we update status_msg_time, so that the message will be actually printed, then cleared after a while.

Note

This function doesn't really print anything on screen: the actual printing will be done in drawMessageBar(), which we already wrote.

Compile and run to see your "help" message printed in the message area when you start up the editor.

errorMessage()

This function is similar, but it will color the message in bright red, since it's supposed to be an error. Note that we can use the ++ string concatenation operator, since all values are comptime-known.

Editor.zig
/// Print an error message, using error highlight.
pub fn errorMessage(e: *Editor, comptime format: []const u8, args: anytype) !void {
    assert(format.len > 0);
    e.status_msg.clearRetainingCapacity();
    const fmt = ansi.ErrorColor ++ format ++ ansi.ResetColors;
    try e.status_msg.print(e.alc, fmt, args);
    e.status_msg_time = time();
}

The 'help' message

Let's take care of the "help" message.

Editor.zig: startUp()
pub fn startUp(e: *Editor, path: ?[]const u8) !void {
    try e.statusMessage(message.status.get("help").?, .{});

help should be a key in our message string map, but we don't have it yet, so add it to status_messages:

message.zig: status_messages
    .{ "help", "HELP: Ctrl-S = save | Ctrl-Q = quit | Ctrl-F = find" },

The 'unsaved' message

Let's add a message that warns us when we press Ctrl-Q and there are unsaved changes:

message.zig: status_messages
    .{ "unsaved", "WARNING!!! File has unsaved changes. Press Ctrl-Q {d} more times to quit." },

We print this message in processKeypress:

Editor.zig: processKeypress()
        .ctrl_q => {
            if (B.dirty and static.q > 0) {
                try e.statusMessage(message.status.get("unsaved").?, .{static.q});

Now, if we have unsaved changes, we'll get this warning, telling us how many times we must press Ctrl-Q to quit.

Needed constants:

Editor.zig
const assert = std.debug.assert;