diff --git a/src/game/nucleus.zig b/src/game/nucleus.zig new file mode 100644 index 0000000..49be240 --- /dev/null +++ b/src/game/nucleus.zig @@ -0,0 +1,3 @@ +const std = @import("std"); +const grome = @import("root.zig"); +const style = grome.view.style; diff --git a/src/main.zig b/src/main.zig index 9091655..c337023 100644 --- a/src/main.zig +++ b/src/main.zig @@ -27,7 +27,7 @@ pub fn main(init: std.process.Init) !void { var viewport = try Viewport.init(arena, size); defer viewport.deinit(arena); - var text = Text.init("hello Grome", style.Red); + var text = Text.init("Hello Olive", style.Blue); try viewport.add_widget(arena, &text.widget); try viewport.hard_refresh(w); diff --git a/src/view/double_buffer.zig b/src/view/double_buffer.zig index d11822c..5daf0e4 100644 --- a/src/view/double_buffer.zig +++ b/src/view/double_buffer.zig @@ -2,6 +2,8 @@ const std = @import("std"); const mem = std.mem; const grome = @import("../root.zig"); +const term = grome.view.term; +const style = grome.view.style; const Allocator = mem.Allocator; const Matrix = grome.container.Matrix; @@ -26,14 +28,14 @@ pub const DoubleBuffer = struct { const a = try Matrix(Cell).init(gpa, .{ .char = [_]u8{' '} ** 8, .width = 1, - .style = null, + .style = style.BlackBg, }, size); errdefer a.deinit(gpa); const b = try Matrix(Cell).init(gpa, .{ .char = [_]u8{' '} ** 8, .width = 1, - .style = null, + .style = style.BlackBg, }, size); return .{ @@ -61,17 +63,17 @@ pub const DoubleBuffer = struct { // render outputs contents of the backbuffer to the writer. This function **does not** // call `flush` so you should! pub fn hard_refresh(self: *@This(), w: *std.Io.Writer) !void { - _ = try w.write("\x1b[H\x1b[2J"); + try term.clear(w); var back_iter = self.back.row_iterator(); while (back_iter.next()) |back_row| { for (back_row) |cell| { - _ = try cell.render(w); + try cell.render(w); } - _ = try w.write("\x1b[1E"); + try term.next_line(w); } - _ = try w.write("\x1b[H"); + try term.beginning(w); self.swap(); } @@ -91,13 +93,12 @@ pub const DoubleBuffer = struct { continue; } - // if it's a new character then write out the rest of the line and then - // continue - try w.print("\x1b[{d};{d}H", .{ skip_lines, x + 1 }); + try term.move(w, skip_lines, x + 1); + try term.clear_remaining_line(w); for (back_row[x..]) |*cell| { try cell.render(w); } - _ = try w.write("\x1b[1E"); + try term.next_line(w); skip_lines = 0; rendered = true; break; @@ -107,7 +108,7 @@ pub const DoubleBuffer = struct { } if (rendered) { - _ = try w.write("\x1b[H"); + try term.beginning(w); } self.swap(); } diff --git a/src/view/root.zig b/src/view/root.zig index 0b588c6..6a98fb9 100644 --- a/src/view/root.zig +++ b/src/view/root.zig @@ -1,6 +1,7 @@ const widget = @import("widget.zig"); pub const style = @import("style.zig"); +pub const term = @import("term.zig"); pub const DoubleBuffer = @import("double_buffer.zig").DoubleBuffer; pub const Cell = @import("cell.zig").Cell; diff --git a/src/view/style.zig b/src/view/style.zig index accc877..4966173 100644 --- a/src/view/style.zig +++ b/src/view/style.zig @@ -14,3 +14,30 @@ pub const Style = struct { /// Reset is a special case that will reset all styles pub const Reset = Style{ .escape = "\x1b[0m" }; pub const Red = Style{ .escape = "\x1b[31m" }; + +pub const Green = Style{ .escape = "\x1b[32m" }; +pub const Blue = Style{ .escape = "\x1b[34m" }; +pub const Yellow = Style{ .escape = "\x1b[33m" }; +pub const Magenta = Style{ .escape = "\x1b[35m" }; +pub const Cyan = Style{ .escape = "\x1b[36m" }; +pub const White = Style{ .escape = "\x1b[37m" }; +pub const Black = Style{ .escape = "\x1b[30m" }; + +// Background colors +pub const BlueBg = Style{ .escape = "\x1b[44m" }; +pub const RedBg = Style{ .escape = "\x1b[41m" }; +pub const GreenBg = Style{ .escape = "\x1b[42m" }; +pub const MagentaBg = Style{ .escape = "\x1b[45m" }; +pub const CyanBg = Style{ .escape = "\x1b[46m" }; +pub const YellowBg = Style{ .escape = "\x1b[43m" }; +pub const WhiteBg = Style{ .escape = "\x1b[47m" }; +pub const BlackBg = Style{ .escape = "\x1b[40m" }; + +// Bright colors +pub const BrightRed = Style{ .escape = "\x1b[91m" }; +pub const BrightGreen = Style{ .escape = "\x1b[92m" }; +pub const BrightYellow = Style{ .escape = "\x1b[93m" }; +pub const BrightBlue = Style{ .escape = "\x1b[94m" }; +pub const BrightMagenta = Style{ .escape = "\x1b[95m" }; +pub const BrightCyan = Style{ .escape = "\x1b[96m" }; +pub const BrightWhite = Style{ .escape = "\x1b[97m" }; diff --git a/src/view/term.zig b/src/view/term.zig new file mode 100644 index 0000000..f340f32 --- /dev/null +++ b/src/view/term.zig @@ -0,0 +1,35 @@ +const std = @import("std"); + +const Writer = std.Io.Writer; + +/// clear clears the terminal screen entierly +pub fn clear(w: *Writer) !void { + _ = try w.write("\x1b[H\x1b[2J"); +} + +/// nextline moves the cursor to the beginning of the next line +pub fn next_line(w: *Writer) !void { + _ = try w.write("\x1b[1E"); +} + +/// beginning returns the cursor to the top left +pub fn beginning(w: *Writer) !void { + _ = try w.write("\x1b[H"); +} + +/// moves the cursor the rows and columns specified +pub fn move(w: *Writer, rows: usize, cols: usize) !void { + try w.print("\x1b[{d};{d}H", .{ rows, cols }); +} + +/// clear_remaining_line clears the line from the current cursor +/// position +pub fn clear_remaining_line(w: *Writer) !void { + _ = try w.write("\x1b[K"); +} + +/// hide_cursor stops the cursor from showing and and blinking and +/// stuff. +pub fn hide_cursor(w: *Writer) !void { + _ = try w.write("\x1b[?25l"); +} diff --git a/src/view/viewport.zig b/src/view/viewport.zig index 17e2195..d745d0e 100644 --- a/src/view/viewport.zig +++ b/src/view/viewport.zig @@ -1,6 +1,7 @@ const std = @import("std"); const grome = @import("../root.zig"); const view = @import("root.zig"); +const term = view.term; const ArrayList = std.ArrayList; const Allocator = std.mem.Allocator; @@ -27,6 +28,7 @@ pub const Viewport = struct { } pub fn hard_refresh(self: *@This(), w: *Writer) !void { + try term.hide_cursor(w); try self.render(); try self.buffer.hard_refresh(w); }