window: add print method

Add a print method with multiple print options

Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
This commit is contained in:
Tim Culverhouse 2024-03-01 12:28:29 -06:00
parent 2fab89f2cb
commit e281a67a43

View file

@ -108,10 +108,57 @@ pub fn showCursor(self: Window, col: usize, row: usize) void {
self.screen.cursor_col = col + self.x_off;
}
/// prints text in the window with simple word wrapping.
pub fn wrap(self: Window, segments: []Segment) !void {
// pub fn wrap(self: Window, str: []const u8) !void {
var row: usize = 0;
/// Options to use when printing Segments to a window
pub const PrintOptions = struct {
/// vertical offset to start printing at
row_offset: usize = 0,
/// wrap behavior for printing
wrap: enum {
/// wrap at grapheme boundaries
grapheme,
/// wrap at word boundaries
word,
/// stop printing after one line
none,
} = .grapheme,
};
/// prints segments to the window. returns true if the text overflowed with the
/// given wrap strategy and size.
pub fn print(self: Window, segments: []Segment, opts: PrintOptions) !bool {
var row = opts.row_offset;
switch (opts.wrap) {
.grapheme => {
var col: usize = 0;
for (segments) |segment| {
var iter = GraphemeIterator.init(segment.text);
while (iter.next()) |grapheme| {
if (col >= self.width) {
row += 1;
col = 0;
}
if (row >= self.height) return true;
const s = grapheme.slice(segment.text);
if (std.mem.eql(u8, s, "\n")) {
row += 1;
col = 0;
continue;
}
const w = self.gwidth(s);
self.writeCell(col, row, .{
.char = .{
.grapheme = s,
.width = w,
},
.style = segment.style,
.link = segment.link,
});
col += w;
}
}
},
.word => {
var col: usize = 0;
var wrapped: bool = false;
for (segments) |segment| {
@ -132,6 +179,7 @@ pub fn wrap(self: Window, segments: []Segment) !void {
col = 0;
wrapped = true;
}
if (row >= self.height) return true;
// don't print whitespace in the first column, unless we had a hard
// break
if (col == 0 and std.mem.eql(u8, word.bytes, " ") and wrapped) continue;
@ -156,6 +204,35 @@ pub fn wrap(self: Window, segments: []Segment) !void {
}
}
}
},
.none => {
var col: usize = 0;
for (segments) |segment| {
var iter = GraphemeIterator.init(segment.text);
while (iter.next()) |grapheme| {
if (col >= self.width) return true;
const s = grapheme.slice(segment.text);
if (std.mem.eql(u8, s, "\n")) return true;
const w = self.gwidth(s);
self.writeCell(col, row, .{
.char = .{
.grapheme = s,
.width = w,
},
.style = segment.style,
.link = segment.link,
});
col += w;
}
}
},
}
return false;
}
/// prints text in the window with simple word wrapping.
pub fn wrap(self: Window, segments: []Segment) !void {
return self.print(segments, .{ .wrap = .word });
}
test "Window size set" {