silkdot/src/main.zig

310 lines
9.1 KiB
Zig
Raw Normal View History

2024-04-05 15:05:14 -06:00
const std = @import("std");
const os = std.os;
const io = std.io;
const fs = std.fs;
const mem = std.mem;
const heap = std.heap;
const fmt = std.fmt;
pub fn main() !void {
var gpa = heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
var term = try Terminal.init(allocator);
defer term.deinit();
try term.clearScreen();
var box = Terminal.Box.init(allocator);
defer box.deinit();
box.content = "hi";
box.border = true;
try term.box.addChild(&box);
term.box.border = true;
try term.draw();
// var box = Terminal.Box{
// .x = 0,
// .y = 0,
// .width = 13,
// .height = 1,
// .content = "hello world",
// .border = true,
// };
// try box.draw(&term);
// try term.clearScreen();
// try term.print("fooboo", .{});
// try term.cursorLeft();
// try term.cursorLeft();
// try term.print("ar", .{});
// // try term.cursorSet(12, 3);
// try term.blinkOn();
// try term.boldOn();
// try term.underlineOn();
// try term.italicsOn();
// try term.print("ABCDEFGHIJKLMNOPQRSTUVWXYZ", .{});
// try term.blinkOff();
// try term.boldOff();
// try term.underlineOff();
// try term.italicsOff();
// try term.print("eeheeveehee\n", .{});
2024-04-05 15:05:14 -06:00
}
pub const Terminal = struct {
tty: fs.File,
original_termios: os.linux.termios,
info: Info,
allocator: mem.Allocator,
box: Box,
2024-04-05 15:05:14 -06:00
pub fn init(allocator: mem.Allocator) !Terminal {
var term = Terminal{
.tty = try fs.openFileAbsolute("/dev/tty", .{ .mode = .read_write }),
.original_termios = undefined,
.info = try Info.init(allocator),
.allocator = allocator,
.box = Box.init(allocator),
2024-04-05 15:05:14 -06:00
};
errdefer term.tty.close();
errdefer term.info.deinit();
term.uncook();
return term;
}
pub fn deinit(self: *Terminal) void {
self.box.deinit();
2024-04-05 15:05:14 -06:00
self.cook();
self.tty.close();
self.info.deinit();
}
// pub fn poll(self: *Terminal) void {}
fn uncook(self: *Terminal) void {
_ = os.linux.tcgetattr(self.tty.handle, &self.original_termios);
var raw = self.original_termios;
raw.lflag.ECHO = false;
raw.lflag.ICANON = false;
raw.lflag.ISIG = false;
raw.lflag.IEXTEN = false;
raw.iflag.IXON = false;
raw.iflag.ICRNL = false;
raw.iflag.BRKINT = false;
raw.iflag.INPCK = false;
raw.iflag.ISTRIP = false;
raw.oflag.OPOST = false;
raw.cc[@intFromEnum(os.linux.V.TIME)] = 0;
raw.cc[@intFromEnum(os.linux.V.MIN)] = 1;
_ = os.linux.tcsetattr(self.tty.handle, .FLUSH, &raw);
}
fn cook(self: *Terminal) void {
_ = os.linux.tcsetattr(self.tty.handle, .FLUSH, &self.original_termios);
}
pub fn draw(self: *Terminal) !void {
try self.box.draw(self);
}
2024-04-05 15:05:14 -06:00
pub fn print(self: *Terminal, comptime format: []const u8, args: anytype) !void {
const formatted = try fmt.allocPrint(self.allocator, format, args);
defer self.allocator.free(formatted);
try self.tty.writeAll(formatted);
}
2024-04-05 18:03:30 -06:00
pub fn cursorUp(self: *Terminal) !void {
try self.info.writeString(.cursor_up, self.tty.writer(), &[_]u32{});
}
pub fn cursorDown(self: *Terminal) !void {
try self.info.writeString(.cursor_down, self.tty.writer(), &[_]u32{});
}
2024-04-05 15:05:14 -06:00
pub fn cursorLeft(self: *Terminal) !void {
2024-04-05 17:08:08 -06:00
try self.info.writeString(.cursor_left, self.tty.writer(), &[_]u32{});
2024-04-05 18:03:30 -06:00
}
pub fn cursorRight(self: *Terminal) !void {
try self.info.writeString(.cursor_right, self.tty.writer(), &[_]u32{});
}
pub fn cursorSet(self: *Terminal, x: u32, y: u32) !void {
try self.info.writeString(.cursor_address, self.tty.writer(), &[_]u32{ y, x });
}
pub fn blinkOn(self: *Terminal) !void {
try self.info.writeString(.enter_blink_mode, self.tty.writer(), &[_]u32{});
}
pub fn blinkOff(self: *Terminal) !void {
try self.info.writeString(.exit_blink_mode, self.tty.writer(), &[_]u32{});
}
pub fn boldOn(self: *Terminal) !void {
try self.info.writeString(.enter_bold_mode, self.tty.writer(), &[_]u32{});
}
pub fn boldOff(self: *Terminal) !void {
try self.info.writeString(.exit_bold_mode, self.tty.writer(), &[_]u32{});
}
pub fn italicsOn(self: *Terminal) !void {
try self.info.writeString(.enter_italics_mode, self.tty.writer(), &[_]u32{});
}
pub fn italicsOff(self: *Terminal) !void {
try self.info.writeString(.exit_italics_mode, self.tty.writer(), &[_]u32{});
}
pub fn underlineOn(self: *Terminal) !void {
try self.info.writeString(.enter_underline_mode, self.tty.writer(), &[_]u32{});
}
pub fn underlineOff(self: *Terminal) !void {
try self.info.writeString(.exit_underline_mode, self.tty.writer(), &[_]u32{});
2024-04-05 15:05:14 -06:00
}
pub fn clearScreen(self: *Terminal) !void {
try self.info.writeString(.clear_screen, self.tty.writer(), &[_]u32{});
}
2024-04-05 15:05:14 -06:00
pub const Info = @import("terminfo.zig");
pub const SpecialKey = enum(u16) {
home,
end,
page_up,
page_down,
delete,
backspace,
arrow_left,
arrow_right,
arrow_up,
arrow_down,
};
pub const Box = struct {
parent: ?*Box,
children: std.ArrayList(*Box),
// x: u32,
// y: u32,
// width: u32,
// height: u32,
left: u32,
right: u32,
top: u32,
bottom: u32,
border_type: enum { line, bg } = .line,
border_char: u8 = ' ',
border_bg: i16 = -1,
border_fg: i16 = -1,
content: []const u8 = "",
border: bool = false,
pub fn init(allocator: mem.Allocator) Box {
return .{
.parent = null,
.children = std.ArrayList(*Box).init(allocator),
.x = 0,
.y = 0,
.width = 20,
.height = 8,
};
}
pub fn deinit(self: *Box) void {
for (self.children.items) |child| child.deinit();
self.children.deinit();
}
pub fn draw(self: *Box, term: *Terminal) !void {
var x: u32 = 0;
var y: u32 = 0;
try term.cursorSet(self.x, self.y);
switch (self.border_type) {
.line => {
try term.print("", .{});
while (x < self.width) : (x += 1) try term.print("", .{});
try term.print("", .{});
y += 1;
while (y <= self.height) : (y += 1) {
try term.cursorSet(self.x, self.y + y);
try term.print("", .{});
try term.cursorSet(self.x + self.width + 1, self.y + y);
try term.print("", .{});
}
try term.cursorSet(self.x, self.y + y);
},
.bg => {},
}
// if (self.border) {
// try term.print("┌", .{});
// // x += 1;
// while (x < self.width) : (x += 1) try term.print("─", .{});
// try term.print("┐", .{});
// // x += 1;
// y += 1;
// while (y <= self.height) : (y += 1) {
// try term.cursorSet(self.x, self.y + y);
// try term.print("│", .{});
// try term.cursorSet(self.x + self.width + 1, self.y + y);
// try term.print("│", .{});
// }
// x = 0;
// try term.cursorSet(self.x + x, self.y + y);
// try term.print("└", .{});
// while (x < self.width) : (x += 1) try term.print("─", .{});
// try term.print("┘", .{});
// }
// x = self.x + 2;
// y = self.y + 1;
// try term.cursorSet(x, y);
// if (self.content.len < self.width) {
// try term.print("{s}", .{self.content});
// x += @intCast(self.content.len);
// } else {
// const space = mem.indexOfScalar(u8, self.content, ' ');
// if (space) |sp| {
// try term.print("{s}", .{self.content[0..sp]});
// y += 1;
// try term.cursorSet(x, y);
// try term.print("{s}", .{self.content[sp + 1 ..]});
// }
// }
for (self.children.items) |child| try child.draw(term);
try term.cursorSet(self.x + self.width + 2, self.y + self.height + 1);
}
pub fn addChild(self: *Box, child: *Box) !void {
std.debug.assert(child.parent == null);
child.parent = self;
child.x = self.x + 2;
child.y = self.y + 2;
child.width = self.width - 4;
child.height = self.height - 4;
try self.children.append(child);
}
};
2024-04-05 15:05:14 -06:00
};