summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosias <justjosias@tutanota.com>2020-06-26 14:49:43 +0000
committerJosias <justjosias@tutanota.com>2020-06-26 14:49:43 +0000
commit4bff7abeb57fbaf6158c725f8eeb6ce1e7bfbd98 (patch)
tree2403e4b9558d218da86028b022a9f6ecb6aab19f
parent2447899e96d1a96f793f6bfb34303570fce4a777 (diff)
Stuff (clean up later)
-rw-r--r--README.md8
-rw-r--r--build.zig14
-rw-r--r--curses.zig106
-rwxr-xr-xexamplebin0 -> 865856 bytes
-rw-r--r--example.zig38
-rw-r--r--example.zig~38
-rwxr-xr-xsrc/cursebin0 -> 737608 bytes
-rw-r--r--src/curse.zig17
-rw-r--r--src/curse.zig~9
-rw-r--r--src/gapbuffer.zig152
-rw-r--r--src/gapbuffer.zig~149
-rw-r--r--src/main.zig188
-rw-r--r--src/main.zig~181
-rw-r--r--src/new.txt150
-rw-r--r--src/stack.zig66
-rw-r--r--src/stack.zig~66
16 files changed, 1076 insertions, 106 deletions
diff --git a/README.md b/README.md
index 402b859..12d24f2 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,11 @@
# zigcurses
A simple Zig library containing basic functions for making a TUI.
+
+Goals:
+1. Implement simple games with it (such as porting my other ncurses games)
+2. Port https://github.com/Akuli/curses-minesweeper to zigcurses
+3. Write a `vi` or `mg` clone with a zigcurses backend
+
+Ideas:
+- Use Zig's `comptime` feature to enable designing user interfaces that are processed at compile time
diff --git a/build.zig b/build.zig
new file mode 100644
index 0000000..783a54a
--- /dev/null
+++ b/build.zig
@@ -0,0 +1,14 @@
+const Builder = @import("std").build.Builder;
+
+pub fn build(b: *Builder) void {
+ const mode = b.standardReleaseOptions();
+ const lib = b.addStaticLibrary("zigcurses", "src/main.zig");
+ lib.setBuildMode(mode);
+ lib.install();
+
+ var main_tests = b.addTest("src/main.zig");
+ main_tests.setBuildMode(mode);
+
+ const test_step = b.step("test", "Run library tests");
+ test_step.dependOn(&main_tests.step);
+}
diff --git a/curses.zig b/curses.zig
deleted file mode 100644
index 0917222..0000000
--- a/curses.zig
+++ /dev/null
@@ -1,106 +0,0 @@
-const std = @import("std");
-const os = std.os;
-const warn = std.debug.warn;
-const termios = os.termios;
-const ascii = std.ascii;
-
-const STDIN_FILENO = 0;
-
-// TODO: make this work
-//pub fn CTRL_KEY(k: u8) u8 {
-// return ((k) & 0x1f);
-//}
-
-const Window = struct {
- original: termios,
-
- pub fn init() !Window {
- var original_termios = try os.tcgetattr(STDIN_FILENO);
- var raw = original_termios;
-
- raw.iflag &= ~(@as(u16, os.BRKINT | os.ICRNL | os.INPCK | os.ISTRIP | os.IXON));
- raw.oflag &= ~(@as(u8, os.OPOST));
- raw.cflag |= (os.CS8);
- raw.lflag &= ~(@as(u16, os.ECHO | os.ICANON | os.IEXTEN | os.ISIG));
-
- // My attempt at VTIME and VMIN
- raw.cc[5] = 0;
- raw.cc[7] = 1;
-
- try os.tcsetattr(STDIN_FILENO, os.TCSA.FLUSH, raw);
-
- if (!(os.isatty(STDIN_FILENO))) {
- // return error
- }
-
- return Window{
- .original = original_termios,
- };
- }
-
- pub fn getmax() ![2]i32 {
- // TODO: support other platforms and provide fallback
- var wsz: os.winsize = undefined;
- // TODO: test for false and return error
- _ = std.os.linux.syscall3(.ioctl, @bitCast(usize, @as(isize, 0)), os.TIOCGWINSZ, @ptrToInt(&wsz)) == 0;
- return [2]i32{wsz.ws_col, wsz.ws_row};
- }
-
- test "try to get max" {
- var hw = try getmax();
- warn("Width: {}. Height: {}\n", .{hw[0], hw[1]});
- }
-
- pub fn end(self: Window) !void {
- try os.tcsetattr(0, os.TCSA.FLUSH, self.original);
- }
-};
-
-
-test "Window open and close" {
- var window = try Window.init();
- try window.end();
-}
-
-pub fn readKey() !u8 {
- const in_stream = std.io.getStdOut().inStream();
- var c: u8 = try in_stream.readByte();
- return c;
-}
-
-test "try to read a key" {
- var window = try Window.init();
-
- warn("\r\nEnter a key: ", .{});
- var c: u8 = try readKey();
- warn("You entered: {}\n", .{c});
-
- try window.end();
-}
-
-// An example for main -- to be moved to an example directory
-pub fn main() !void {
- const in_stream = std.io.getStdOut().inStream();
-
- var w = try Window.init();
- while (true) {
- var c: u8 = undefined;
- c = try in_stream.readByte();
-
- if (ascii.isCntrl(c)) {
- warn("It's control! {}\r\n", .{c});
- } else {
- warn("{}\r\n", .{c});
- }
-
- if (ascii.isCntrl(c) and c == 'q') {
- break;
- }
- //warn("{}\n", .{CTRL_KEY(c)});
- if (c == 17) {
- break;
- }
- }
-
- try w.end();
-}
diff --git a/example b/example
new file mode 100755
index 0000000..61fbdc3
--- /dev/null
+++ b/example
Binary files differ
diff --git a/example.zig b/example.zig
new file mode 100644
index 0000000..18ca39b
--- /dev/null
+++ b/example.zig
@@ -0,0 +1,38 @@
+const std = @import("std");
+const ascii = std.ascii;
+const print = std.debug.print;
+
+const curses = @import("src/main.zig");
+
+pub fn main() anyerror!void {
+ const in_stream = std.io.getStdOut().inStream();
+
+ var w = try curses.Window.init(std.testing.allocator);
+ while (true) {
+ var c: u8 = undefined;
+ c = try in_stream.readByte();
+
+ if (ascii.isCntrl(c)) {
+ print("It's control! {}\r\n", .{c});
+ var text = "hi\n";
+
+ try w.mvprint(0, 0, text[0..]);
+ } else {
+ print("{}\r\n", .{c});
+ }
+
+ if (ascii.isCntrl(c) and c == 'q') {
+ break;
+ }
+
+ if (c == 'c') {
+ try w.clear();
+ }
+ //warn("{}\n", .{CTRL_KEY(c)});
+ if (c == 17) {
+ break;
+ }
+ }
+
+ try w.end();
+}
diff --git a/example.zig~ b/example.zig~
new file mode 100644
index 0000000..ecf0816
--- /dev/null
+++ b/example.zig~
@@ -0,0 +1,38 @@
+const std = @import("std");
+const ascii = std.ascii;
+const warn = std.debug.warn;
+
+const curses = @import("src/main.zig");
+
+pub fn main() anyerror!void {
+ const in_stream = std.io.getStdOut().inStream();
+
+ var w = try curses.Window.init(std.testing.allocator);
+ while (true) {
+ var c: u8 = undefined;
+ c = try in_stream.readByte();
+
+ if (ascii.isCntrl(c)) {
+ warn("It's control! {}\r\n", .{c});
+ var text = "hi\n";
+
+ try w.mvprint(0, 0, text[0..]);
+ } else {
+ warn("{}\r\n", .{c});
+ }
+
+ if (ascii.isCntrl(c) and c == 'q') {
+ break;
+ }
+
+ if (c == 'c') {
+ try w.clear();
+ }
+ //warn("{}\n", .{CTRL_KEY(c)});
+ if (c == 17) {
+ break;
+ }
+ }
+
+ try w.end();
+}
diff --git a/src/curse b/src/curse
new file mode 100755
index 0000000..ea03e2b
--- /dev/null
+++ b/src/curse
Binary files differ
diff --git a/src/curse.zig b/src/curse.zig
new file mode 100644
index 0000000..51bdbf5
--- /dev/null
+++ b/src/curse.zig
@@ -0,0 +1,17 @@
+const print = @import("std").debug.print;
+
+const c = @cImport({
+ // See https://github.com/ziglang/zig/issues/515
+ @cDefine("_NO_CRT_STDIO_INLINE", "1");
+ @cInclude("ncurses.h");
+ @cInclude("stdio.h");
+});
+pub fn main() void {
+ // _ = c.printf("hello\n");
+ _ = c.initscr();
+ _ = c.mvprintw(0, 0, "Hi");
+ _ = c.endwin();
+ _ = c.printf("HA\n");
+
+ print("hi\n", .{});
+}
diff --git a/src/curse.zig~ b/src/curse.zig~
new file mode 100644
index 0000000..d1e9c34
--- /dev/null
+++ b/src/curse.zig~
@@ -0,0 +1,9 @@
+const c = @cImport({
+ // See https://github.com/ziglang/zig/issues/515
+ @cDefine("_NO_CRT_STDIO_INLINE", "1");
+ @cInclude("ncurses.h");
+});
+pub fn main() void {
+ // _ = c.printf("hello\n");
+ c.initscr();
+}
diff --git a/src/gapbuffer.zig b/src/gapbuffer.zig
new file mode 100644
index 0000000..9e112f4
--- /dev/null
+++ b/src/gapbuffer.zig
@@ -0,0 +1,152 @@
+const std = @import("std");
+const print = std.debug.print;
+
+const GapBuffer = struct {
+ buffer: []u32,
+ leftIndex: usize,
+ rightIndex: usize,
+
+ allocator: *std.mem.Allocator,
+
+ // the caller is responsible for freeing memory
+ pub fn init(allocator: *std.mem.Allocator, buffer: []u32) !GapBuffer {
+ var newbuffer = try allocator.alloc(u32, buffer.len * 2);
+
+ for (buffer) |c, i| {
+ newbuffer[i] = c;
+ }
+
+ return GapBuffer{
+ .buffer = newbuffer,
+ .leftIndex = buffer.len,
+ .rightIndex = 0,
+
+ .allocator = allocator,
+ };
+ }
+
+ pub fn resize() void {}
+
+ pub fn left(self: *GapBuffer) !void {
+ // if (self.leftIndex == self.buffer.len + 1) {
+ // return error.StackOverflow;
+ // }
+ // self.leftIndex -= 1;
+
+ // self.buffer[self.leftIndex] = self.buffer[self.rightIndex];
+
+ // if (self.rightIndex == 0) {
+ // return error.StackUnderflow;
+ // }
+ // self.rightIndex -= 1;
+ if (self.leftIndex == 0) {
+ return error.StackUnderflow;
+ }
+
+ self.rightIndex += 1;
+ self.leftIndex -= 1;
+
+ self.buffer[self.buffer.len - self.rightIndex] = self.buffer[self.leftIndex];
+
+ self.buffer[self.leftIndex] = 0;
+ }
+
+ pub fn right(self: *GapBuffer) !void {
+ // if (self.rightIndex == 0) {
+ // return error.StackUnderflow;
+ // }
+ // self.rightIndex += 1;
+
+ // self.buffer[self.rightIndex] = self.buffer[self.leftIndex];
+
+ // if (self.leftIndex == self.buffer.len + 1) {
+ // return error.StackOverflow;
+ // }
+ // self.leftIndex += 1;
+ if (self.rightIndex == 0) {
+ return error.StackOverflow;
+ }
+
+ self.leftIndex += 1;
+
+ self.buffer[self.leftIndex] = self.buffer[self.buffer.len - self.rightIndex];
+
+ self.rightIndex -= 1;
+ }
+
+ pub fn delete(self: *GapBuffer) !u32 {
+ if (self.leftIndex == 0) {
+ return error.StackUnderflow;
+ }
+ self.buffer[self.leftIndex] = 0;
+ self.leftIndex -= 1;
+ return self.buffer[self.leftIndex];
+ }
+
+ pub fn insert(self: *GapBuffer, item: u32) !void {
+ self.buffer[self.rightIndex] = item;
+ self.rightIndex += 1;
+ }
+
+ /// returns the non-buffer parts of the slice
+ pub fn slice(self: GapBuffer) ![]u32 {
+ var buf = try self.allocator.alloc(u32, self.buffer.len);
+ //var buf = self.buffer;
+ var i: usize = 0;
+ print("\nLeftIndex: {}\n", .{self.leftIndex});
+ while (i < self.leftIndex) : (i += 1) {
+ buf[i] = self.buffer[i];
+ }
+
+ var n: usize = self.rightIndex;
+ print("\nRightIndex: {}\n", .{self.rightIndex});
+ print("Length: {}\n", .{self.buffer.len});
+ while (n < self.buffer.len or i < self.buffer.len) : ({
+ n += 1;
+ i += 1;
+ }) {
+ print(" {} {} {} \n", .{ i, n, self.buffer[n] });
+ buf[i] = self.buffer[n];
+ }
+
+ return buf;
+ }
+};
+
+test "" {
+ const assert = std.debug.assert;
+
+ //var buffer: [100]u32 = undefined;
+ var buffer = [_]u32{ 2, 3, 4, 1, 5, 6, 5, 1, 5, 2, 5, 1, 58, 433, 562, 45, 253, 23, 4, 4, 1, 5, 7, 45, 50 };
+ var b = try GapBuffer.init(std.testing.allocator, buffer[0..]);
+
+ print("\n{}\n", .{b});
+
+ assert(b.buffer[b.leftIndex - 1] == 50);
+
+ assert(b.buffer[0] == 2);
+
+ try b.left();
+ print("Current: {}\n", .{buffer[b.leftIndex]});
+ print("P: {}\n", .{b.leftIndex});
+ assert(b.buffer[b.leftIndex - 1] == 45);
+
+ for (b.buffer) |c| {
+ print("{} ", .{c});
+ }
+
+ var slice = try b.slice();
+ for (slice) |c| {
+ print("{} ", .{c});
+ }
+ b.allocator.free(slice);
+
+ print("\n", .{});
+
+ assert((try b.delete()) == 45);
+
+ try b.left();
+ assert(b.buffer[b.leftIndex - 1] == 5);
+
+ std.testing.allocator.free(b.buffer);
+}
diff --git a/src/gapbuffer.zig~ b/src/gapbuffer.zig~
new file mode 100644
index 0000000..cccce9c
--- /dev/null
+++ b/src/gapbuffer.zig~
@@ -0,0 +1,149 @@
+const std = @import("std");
+const print = std.debug.print;
+
+const GapBuffer = struct {
+ buffer: []u32,
+ leftIndex: usize,
+ rightIndex: usize,
+
+ allocator: *std.mem.Allocator,
+
+ // the caller is responsible for freeing memory
+ pub fn init(allocator: *std.mem.Allocator, buffer: []u32) !GapBuffer {
+ var newbuffer = try allocator.alloc(u32, buffer.len * 2);
+
+ for (buffer) |c, i| {
+ newbuffer[i] = c;
+ }
+
+ return GapBuffer{
+ .buffer = newbuffer,
+ .leftIndex = buffer.len,
+ .rightIndex = 0,
+
+ .allocator = allocator,
+ };
+ }
+
+ pub fn resize() void {}
+
+ pub fn left(self: *GapBuffer) !void {
+ // if (self.leftIndex == self.buffer.len + 1) {
+ // return error.StackOverflow;
+ // }
+ // self.leftIndex -= 1;
+
+ // self.buffer[self.leftIndex] = self.buffer[self.rightIndex];
+
+ // if (self.rightIndex == 0) {
+ // return error.StackUnderflow;
+ // }
+ // self.rightIndex -= 1;
+ if (self.leftIndex == 0) {
+ return error.StackUnderflow;
+ }
+
+ self.rightIndex += 1;
+ self.leftIndex -= 1;
+
+ self.buffer[self.buffer.len - self.rightIndex] = self.buffer[self.leftIndex];
+
+ self.buffer[self.leftIndex] = 0;
+ }
+
+ pub fn right(self: *GapBuffer) !void {
+ // if (self.rightIndex == 0) {
+ // return error.StackUnderflow;
+ // }
+ // self.rightIndex += 1;
+
+ // self.buffer[self.rightIndex] = self.buffer[self.leftIndex];
+
+ // if (self.leftIndex == self.buffer.len + 1) {
+ // return error.StackOverflow;
+ // }
+ // self.leftIndex += 1;
+ if (self.rightIndex == 0) {
+ return error.StackOverflow;
+ }
+
+ self.leftIndex += 1;
+
+ self.buffer[self.leftIndex] = self.buffer[self.buffer.len - self.rightIndex];
+
+ self.rightIndex -= 1;
+ }
+
+ pub fn delete(self: *GapBuffer) !u32 {
+ if (self.leftIndex == 0) {
+ return error.StackUnderflow;
+ }
+ self.buffer[self.leftIndex] = 0;
+ self.leftIndex -= 1;
+ return self.buffer[self.leftIndex];
+ }
+
+ pub fn insert(self: *GapBuffer, item: u32) !void {
+ self.buffer[self.rightIndex] = item;
+ self.rightIndex += 1;
+ }
+
+ /// returns the non-buffer parts of the slice
+ pub fn slice(self: GapBuffer) []u32 {
+ var buf = self.allocator.alloc(u32, self.buffer.len) catch unreachable;
+ //var buf = self.buffer;
+ var i: usize = 0;
+ while (i < self.leftIndex) : (i += 1) {
+ buf[i] = self.buffer[i];
+ }
+
+ var n: usize = self.rightIndex;
+ while (n < self.buffer.len) : ({
+ n += 1;
+ i += 1;
+ }) {
+ print(" {} {} \n", .{ i, self.buffer[n] });
+ buf[i] = self.buffer[n];
+ }
+
+ return buf;
+ }
+};
+
+test "" {
+ const assert = std.debug.assert;
+
+ //var buffer: [100]u32 = undefined;
+ var buffer = [_]u32{ 2, 3, 4, 1, 5, 6, 5, 1, 5, 2, 5, 1, 58, 433, 562, 45, 253, 23, 4, 4, 1, 5, 7, 45, 50 };
+ var b = try GapBuffer.init(std.testing.allocator, buffer[0..]);
+
+ print("\n{}\n", .{b});
+
+ assert(b.buffer[b.leftIndex - 1] == 50);
+
+ assert(b.buffer[0] == 2);
+
+ try b.left();
+ print("Current: {}\n", .{buffer[b.leftIndex]});
+ print("P: {}\n", .{b.leftIndex});
+ assert(b.buffer[b.leftIndex - 1] == 45);
+
+ for (b.buffer) |c| {
+ print("{} ", .{c});
+ }
+
+ var slice = b.slice();
+ for (slice) |c| {
+ print("{} ", .{c});
+ }
+ b.allocator.free(slice);
+
+ print("\n", .{});
+
+ assert((try b.delete()) == 45);
+
+ try b.left();
+ assert(b.buffer[b.leftIndex - 1] == 5);
+
+ std.testing.allocator.free(b.buffer);
+}
diff --git a/src/main.zig b/src/main.zig
new file mode 100644
index 0000000..53b3e74
--- /dev/null
+++ b/src/main.zig
@@ -0,0 +1,188 @@
+const std = @import("std");
+const os = std.os;
+const print = std.debug.print;
+const termios = os.termios;
+const ascii = std.ascii;
+
+const STDIN_FILENO = 0;
+const stdout = std.io.getStdOut().outStream();
+const in_stream = std.io.getStdOut().inStream();
+
+//pub fn new(allocator: *Allocator) !Window {}
+
+pub const Window = struct {
+ original: termios,
+ height: usize,
+ width: usize,
+ buffer: []u8,
+ /// buf contains a dynamic array of slices that will be combined upon print
+ buf: std.ArrayList([]const u8),
+
+ //allocator: *std.mem.Allocator,
+
+ /// init puts the window in raw mode and saves the original termios for switching back to normal mode
+ pub fn init(allocator: *std.mem.Allocator) !Window {
+ var window = Window{
+ .original = try os.tcgetattr(STDIN_FILENO),
+ .buffer = "",
+ .buf = undefined,
+ .height = 0,
+ .width = 0,
+ };
+
+ var raw = window.original;
+
+ raw.iflag &= ~(@as(u16, os.BRKINT | os.ICRNL | os.INPCK | os.ISTRIP | os.IXON));
+ raw.oflag &= ~(@as(u8, os.OPOST));
+ raw.cflag |= (os.CS8);
+ raw.lflag &= ~(@as(u16, os.ECHO | os.ICANON | os.IEXTEN | os.ISIG));
+
+ // My attempt at VTIME and VMIN
+ raw.cc[5] = 0;
+ raw.cc[7] = 1;
+
+ try os.tcsetattr(STDIN_FILENO, os.TCSA.FLUSH, raw);
+
+ if (!os.isatty(STDIN_FILENO)) {
+ return error.NotATTY;
+ }
+
+ const arrayList = std.ArrayList([]const u8);
+
+ var what = "hello";
+ var buf = arrayList.init(allocator);
+ _ = try buf.append(what[0..]);
+ _ = try buf.append("i"[0..]);
+ print("What? {}\n", .{buf.items});
+
+ window.buf = buf;
+
+ //const wh = try getmax();
+ // fill in the height and width information
+ try window.updatehw();
+
+ var text = try allocator.alloc(u8, window.height * window.width);
+ //warn("{}", .{text});
+ defer allocator.free(text);
+
+ var n: usize = 0;
+ while (n < window.height) : (n += 1) {
+ print("{}", .{n});
+ text[n] = 'h';
+
+ //warn("{}", .{});
+
+ if (n % window.width == 0) {
+ text[n * window.width] = 'c';
+ }
+
+ // var i: usize = 0;
+ // while (i < window.width) : (i += 1) {
+ // if (i == window.width) {
+ // text[n] = '\n';
+ // }
+ // }
+ }
+
+ print("{}", .{text});
+
+ // initialize text with spaces and newlines
+ //for ([]usize{ 0, 1, 2, 3, 4, 10 }) |i| {}
+
+ try window.clear();
+
+ // disable cursor
+ _ = try stdout.write("\x1B[?25l");
+
+ var i: usize = 0;
+
+ while (i < window.height) {
+ _ = try stdout.write("\r\n~");
+ i += 1;
+ }
+
+ return window;
+ }
+
+ /// updatehw gets the height and width for the window by making a syscall.
+ pub fn updatehw(self: *Window) !void {
+ // TODO: support other platforms and provide fallback
+ var wsz: os.winsize = undefined;
+ // TODO: test for false and return error
+ _ = std.os.linux.syscall3(.ioctl, @bitCast(usize, @as(isize, 0)), os.TIOCGWINSZ, @ptrToInt(&wsz)) == 0;
+ //const te = [2]u32{ wsz.ws_col, wsz.ws_row };
+ self.height = wsz.ws_row;
+ self.width = wsz.ws_col;
+ }
+
+ /// setchar puts a character at a specific point in the text based on height and width
+ pub fn setchar(self: *Window, x: u32, y: u32, insert: u8) !void {
+ if (x > self.width or y > self.height) {
+ return error.InvalidRange;
+ }
+
+ var newlines: usize = 0;
+ for (self.buffer) |char, i| {
+ if (newlines == y) {
+ for (self.buffer[i + 1 .. hw[1]]) |character, n| {
+ if (character == '\n' or character == '\r') {
+ break;
+ }
+
+ self.buffer[n] = insert;
+ }
+ }
+ }
+ }
+
+ pub fn mvprint(self: Window, x: usize, y: usize, text: []const u8) !void {
+ self.buf.append("\x1b[10;10H"[0..]);
+ self.buf.append([]u8{@as(u8, x)});
+ self.buf.append(text);
+ self.buf.append();
+ //_ = try buf.append('');
+ }
+
+ pub fn clear(self: Window) !void {
+ _ = try stdout.write("\x1b[2J");
+ _ = try stdout.write("\x1b[H");
+ }
+
+ pub fn erase() !void {}
+
+ pub fn flush() !void {}
+
+ pub fn refresh(self: Window) !void {
+ _ = stdout.write(self.buffer);
+ }
+
+ pub fn end(self: Window) !void {
+ // re-enable cursor
+ _ = try stdout.write("\x1B[?25h");
+
+ self.buf.deinit();
+
+ try self.clear();
+ try os.tcsetattr(STDIN_FILENO, os.TCSA.FLUSH, self.original);
+ }
+};
+
+test "Window open and close" {
+ var window = try Window.init(std.testing.allocator);
+ try window.end();
+}
+
+pub fn readKey() !u8 {
+ var c: u8 = try in_stream.readByte();
+ return c;
+}
+
+test "try to read a key" {
+ var window = try Window.init(std.testing.allocator);
+
+ print("\r\nEnter a key: ", .{});
+ const c: u8 = try readKey();
+ print("You entered: {}\n", .{c});
+
+ try window.end();
+}
diff --git a/src/main.zig~ b/src/main.zig~
new file mode 100644
index 0000000..e01051b
--- /dev/null
+++ b/src/main.zig~
@@ -0,0 +1,181 @@
+const std = @import("std");
+const os = std.os;
+const print = std.debug.print;
+const termios = os.termios;
+const ascii = std.ascii;
+
+const STDIN_FILENO = 0;
+const stdout = std.io.getStdOut().outStream();
+const in_stream = std.io.getStdOut().inStream();
+
+//pub fn new(allocator: *Allocator) !Window {}
+
+pub const Window = struct {
+ original: termios,
+ height: usize,
+ width: usize,
+ buffer: []u8,
+ /// buf contains a array of slices
+ buf: []u8,
+
+ //allocator: *std.mem.Allocator,
+
+ /// init puts the window in raw mode and saves the original termios for switching back to normal mode
+ pub fn init(allocator: *std.mem.Allocator) !Window {
+ var window = Window{
+ .original = try os.tcgetattr(STDIN_FILENO),
+ .buffer = "",
+ .buf = "",
+ .height = 0,
+ .width = 0,
+ };
+
+ var raw = window.original;
+
+ raw.iflag &= ~(@as(u16, os.BRKINT | os.ICRNL | os.INPCK | os.ISTRIP | os.IXON));
+ raw.oflag &= ~(@as(u8, os.OPOST));
+ raw.cflag |= (os.CS8);
+ raw.lflag &= ~(@as(u16, os.ECHO | os.ICANON | os.IEXTEN | os.ISIG));
+
+ // My attempt at VTIME and VMIN
+ raw.cc[5] = 0;
+ raw.cc[7] = 1;
+
+ try os.tcsetattr(STDIN_FILENO, os.TCSA.FLUSH, raw);
+
+ if (!os.isatty(STDIN_FILENO)) {
+ return error.NotATTY;
+ }
+
+ const arrayList = std.ArrayList([]u8);
+ var buf = arrayList.init(allocator);
+ _ = try buf.append("h"[0..]);
+ _ = try buf.append("i"[0..]);
+ print("What? {}\n", .{buf.items});
+
+ buf.deinit();
+
+ //const wh = try getmax();
+ // fill in the height and width information
+ try window.updatehw();
+
+ var text = try allocator.alloc(u8, window.height * window.width);
+ //warn("{}", .{text});
+ defer allocator.free(text);
+
+ var n: usize = 0;
+ while (n < window.height) : (n += 1) {
+ print("{}", .{n});
+ text[n] = 'h';
+
+ //warn("{}", .{});
+
+ if (n % window.width == 0) {
+ text[n * window.width] = 'c';
+ }
+
+ // var i: usize = 0;
+ // while (i < window.width) : (i += 1) {
+ // if (i == window.width) {
+ // text[n] = '\n';
+ // }
+ // }
+ }
+
+ print("{}", .{text});
+
+ // initialize text with spaces and newlines
+ //for ([]usize{ 0, 1, 2, 3, 4, 10 }) |i| {}
+
+ try window.clear();
+
+ // disable cursor
+ _ = try stdout.write("\x1B[?25l");
+
+ var i: usize = 0;
+
+ while (i < window.height) {
+ _ = try stdout.write("\r\n~");
+ i += 1;
+ }
+
+ return window;
+ }
+
+ /// updatehw gets the height and width for the window by making a syscall.
+ pub fn updatehw(self: *Window) !void {
+ // TODO: support other platforms and provide fallback
+ var wsz: os.winsize = undefined;
+ // TODO: test for false and return error
+ _ = std.os.linux.syscall3(.ioctl, @bitCast(usize, @as(isize, 0)), os.TIOCGWINSZ, @ptrToInt(&wsz)) == 0;
+ //const te = [2]u32{ wsz.ws_col, wsz.ws_row };
+ self.height = wsz.ws_row;
+ self.width = wsz.ws_col;
+ }
+
+ /// setchar puts a character at a specific point in the text based on height and width
+ pub fn setchar(self: *Window, x: u32, y: u32, insert: u8) !void {
+ if (x > self.width or y > self.height) {
+ return error.InvalidRange;
+ }
+
+ var newlines: usize = 0;
+ for (self.buffer) |char, i| {
+ if (newlines == y) {
+ for (self.buffer[i + 1 .. hw[1]]) |character, n| {
+ if (character == '\n' or character == '\r') {
+ break;
+ }
+
+ self.buffer[n] = insert;
+ }
+ }
+ }
+ }
+
+ pub fn mvprint(self: Window, x: usize, y: usize, text: []const u8) !void {
+ _ = try stdout.write("\x1b[10;10H");
+ _ = try stdout.write(text);
+ //_ = try buf.append('');
+ }
+
+ pub fn clear(self: Window) !void {
+ _ = try stdout.write("\x1b[2J");
+ _ = try stdout.write("\x1b[H");
+ }
+
+ pub fn erase() !void {}
+
+ pub fn flush() !void {}
+
+ pub fn refresh(self: Window) !void {
+ _ = stdout.write(self.buffer);
+ }
+
+ pub fn end(self: Window) !void {
+ // re-enable cursor
+ _ = try stdout.write("\x1B[?25h");
+ try self.clear();
+ try os.tcsetattr(STDIN_FILENO, os.TCSA.FLUSH, self.original);
+ }
+};
+
+test "Window open and close" {
+ var window = try Window.init(std.testing.allocator);
+ try window.end();
+}
+
+pub fn readKey() !u8 {
+ var c: u8 = try in_stream.readByte();
+ return c;
+}
+
+test "try to read a key" {
+ var window = try Window.init(std.testing.allocator);
+
+ print("\r\nEnter a key: ", .{});
+ const c: u8 = try readKey();
+ print("You entered: {}\n", .{c});
+
+ try window.end();
+}
diff --git a/src/new.txt b/src/new.txt
new file mode 100644
index 0000000..2e5cfbb
--- /dev/null
+++ b/src/new.txt
@@ -0,0 +1,150 @@
+/src/main.zig:13:12: error: missing parameter name
+pub fn new(*Allocator) Window {
+ ^
+./src/main.zig:6:19: note: referenced here
+const Allocator = std.mem.Allocator;
+ ^
+./src/main.zig:13:13: note: referenced here
+pub fn new(*Allocator) Window {
+ ^
+./src/main.zig:13:24: note: referenced here
+pub fn new(*Allocator) Window {
+ ^
+./src/main.zig:4:17: note: referenced here
+const termios = os.termios;
+ ^
+./src/main.zig:4:19: note: referenced here
+const termios = os.termios;
+ ^
+./src/main.zig:73:15: note: referenced here
+ original: termios,
+ ^
+/home/josias/git/zig-bin/lib/zig/std/os/bits/linux.zig:1699:12: note: referenced here
+ iflag: tcflag_t,
+ ^
+/home/josias/git/zig-bin/lib/zig/std/os/bits/linux.zig:1703:11: note: referenced here
+ line: cc_t,
+ ^
+/home/josias/git/zig-bin/lib/zig/std/os/bits/linux.zig:1704:10: note: referenced here
+ cc: [NCCS]cc_t,
+ ^
+/home/josias/git/zig-bin/lib/zig/std/os/bits/linux.zig:1705:13: note: referenced here
+ ispeed: speed_t,
+ ^
+./example.zig:10:19: note: referenced here
+ var w = curses.new(std.testing.allocator);
+ ^
+./example.zig:10:27: note: referenced here
+ var w = curses.new(std.testing.allocator);
+ ^
+/home/josias/git/zig-bin/lib/zig/std/testing.zig:4:75: note: referenced here
+pub const LeakCountAllocator = @import("testing/leak_count_allocator.zig").LeakCountAllocator;
+ ^
+/home/josias/git/zig-bin/lib/zig/std/testing.zig:9:30: note: referenced here
+pub var allocator_instance = LeakCountAllocator.init(&base_allocator_instance.allocator);
+ ^
+/home/josias/git/zig-bin/lib/zig/std/testing/leak_count_allocator.zig:13:29: note: referenced here
+ pub fn init(allocator: *std.mem.Allocator) LeakCountAllocator {
+ ^
+/home/josias/git/zig-bin/lib/zig/std/testing.zig:9:48: note: referenced here
+pub var allocator_instance = LeakCountAllocator.init(&base_allocator_instance.allocator);
+ ^
+/home/josias/git/zig-bin/lib/zig/std/testing.zig:14:35: note: referenced here
+pub var base_allocator_instance = std.heap.ThreadSafeFixedBufferAllocator.init(allocator_mem[0..]);
+ ^
+/home/josias/git/zig-bin/lib/zig/std/testing.zig:14:43: note: referenced here
+pub var base_allocator_instance = std.heap.ThreadSafeFixedBufferAllocator.init(allocator_mem[0..]);
+ ^
+/home/josias/git/zig-bin/lib/zig/std/testing.zig:14:74: note: referenced here
+pub var base_allocator_instance = std.heap.ThreadSafeFixedBufferAllocator.init(allocator_mem[0..]);
+ ^
+/home/josias/git/zig-bin/lib/zig/std/testing.zig:14:80: note: referenced here
+pub var base_allocator_instance = std.heap.ThreadSafeFixedBufferAllocator.init(allocator_mem[0..]);
+ ^
+/home/josias/git/zig-bin/lib/zig/std/heap.zig:584:38: note: referenced here
+ .reallocFn = realloc,
+ ^
+/home/josias/git/zig-bin/lib/zig/std/heap.zig:612:40: note: referenced here
+ const result = try alloc(allocator, new_size, new_align);
+ ^
+/home/josias/git/zig-bin/lib/zig/std/heap.zig:585:37: note: referenced here
+ .shrinkFn = shrink,
+ ^
+/home/josias/git/zig-bin/lib/zig/std/testing.zig:9:55: note: referenced here
+pub var allocator_instance = LeakCountAllocator.init(&base_allocator_instance.allocator);
+ ^
+/home/josias/git/zig-bin/lib/zig/std/testing/leak_count_allocator.zig:17:30: note: referenced here
+ .reallocFn = realloc,
+ ^
+/home/josias/git/zig-bin/lib/zig/std/testing/leak_count_allocator.zig:18:29: note: referenced here
+ .shrinkFn = shrink,
+ ^
+/home/josias/git/zig-bin/lib/zig/std/testing.zig:8:24: note: referenced here
+pub const allocator = &allocator_instance.allocator;
+ ^
+./example.zig:10:35: note: referenced here
+ var w = curses.new(std.testing.allocator);
+ ^
+/home/josias/git/zig-bin/lib/zig/std/io/reader.zig:175:31: note: referenced here
+ pub fn readByte(self: Self) !u8 {
+ ^
+./example.zig:13:26: note: referenced here
+ c = try in_stream.readByte();
+ ^
+/home/josias/git/zig-bin/lib/zig/std/io/reader.zig:26:47: note: referenced here
+ pub fn read(self: Self, buffer: []u8) Error!usize {
+ ^
+/home/josias/git/zig-bin/lib/zig/std/io/reader.zig:177:38: note: referenced here
+ const amt_read = try self.read(result[0..]);
+ ^
+./example.zig:2:18: note: referenced here
+const ascii = std.ascii;
+ ^
+./example.zig:15:13: note: referenced here
+ if (ascii.isCntrl(c)) {
+ ^
+./example.zig:15:18: note: referenced here
+ if (ascii.isCntrl(c)) {
+ ^
+./example.zig:16:13: note: referenced here
+ warn("It's control! {}\r\n", .{c});
+ ^
+./example.zig:26:18: note: referenced here
+ try w.clear();
+ ^
+/home/josias/git/zig-bin/lib/zig/std/io.zig:54:19: note: referenced here
+ .handle = getStdOutHandle(),
+ ^
+/home/josias/git/zig-bin/lib/zig/std/io.zig:56:29: note: referenced here
+ .intended_io_mode = default_mode,
+ ^
+./src/main.zig:9:34: note: referenced here
+const stdout = std.io.getStdOut().outStream();
+ ^
+./src/main.zig:113:17: note: referenced here
+ _ = try stdout.write("\x1b[2J");
+ ^
+./example.zig:34:10: note: referenced here
+ try w.end();
+ ^
+/home/josias/git/zig-bin/lib/zig/std/os.zig:4905:49: note: referenced here
+pub fn tcsetattr(handle: fd_t, optional_action: TCSA, termios_p: termios) TermiosSetError!void {
+ ^
+/home/josias/git/zig-bin/lib/zig/std/os.zig:4903:29: note: referenced here
+pub const TermiosSetError = TermiosGetError || error{ProcessOrphaned};
+ ^
+/home/josias/git/zig-bin/lib/zig/std/os.zig:4905:75: note: referenced here
+pub fn tcsetattr(handle: fd_t, optional_action: TCSA, termios_p: termios) TermiosSetError!void {
+ ^
+./src/main.zig:127:15: note: referenced here
+ try os.tcsetattr(STDIN_FILENO, os.TCSA.FLUSH, self.original);
+ ^
+./src/main.zig:127:26: note: referenced here
+ try os.tcsetattr(STDIN_FILENO, os.TCSA.FLUSH, self.original);
+ ^
+./src/main.zig:15:21: error: expected type 'src.main.Window', found 'std.os.TermiosGetError'
+ .original = try os.tcgetattr(STDIN_FILENO),
+ ^
+./src/main.zig:72:20: note: src.main.Window declared here
+pub const Window = struct {
+ ^
diff --git a/src/stack.zig b/src/stack.zig
new file mode 100644
index 0000000..2c442a4
--- /dev/null
+++ b/src/stack.zig
@@ -0,0 +1,66 @@
+const std = @import("std");
+const warn = std.debug.warn;
+const mem = std.mem;
+const assert = std.debug.assert;
+
+pub const Stack = struct {
+ buffer: []u8,
+ index: usize,
+
+ pub fn init(buffer: []u8) Stack {
+ return Stack{
+ .buffer = buffer,
+ .index = 0,
+ };
+ }
+
+ pub fn pop(self: *Stack) !u8 {
+ if (self.index == 0) return error.StackUnderflow;
+ self.index -= 1;
+ return self.buffer[self.index];
+ }
+
+ pub fn push(self: *Stack, item: u8) !void {
+ if (self.index == 0xff) return error.StackOverflow;
+ self.buffer[self.index] = item;
+ self.index += 1;
+ }
+
+ /// slice returns a slice of the array ending at the current index
+ pub fn slice(self: Stack) []u8 {
+ return self.buffer[0..self.index];
+ }
+};
+
+test "test stack" {
+ var buffer: [100]u8 = undefined;
+ var stack = Stack.init(buffer[0..]);
+
+ try stack.push('h');
+ try stack.push('e');
+ try stack.push('l');
+ try stack.push('l');
+ try stack.push('o');
+ try stack.push('!');
+
+ assert(mem.eql(u8, stack.buffer[0..6], "hello!"));
+ warn("\n{}\n", .{stack.slice()});
+
+ const char = try stack.pop();
+ assert(char == '!');
+
+ try stack.push('?');
+ assert(mem.eql(u8, stack.buffer[0..6], "hello?"));
+ warn("\n{}\n", .{stack.slice()});
+
+ _ = try stack.pop();
+ _ = try stack.pop();
+ _ = try stack.pop();
+
+ _ = try stack.pop();
+ _ = try stack.pop();
+ _ = try stack.pop();
+ _ = try stack.pop();
+
+ warn("\n{}\n", .{stack.slice()});
+}
diff --git a/src/stack.zig~ b/src/stack.zig~
new file mode 100644
index 0000000..2c442a4
--- /dev/null
+++ b/src/stack.zig~
@@ -0,0 +1,66 @@
+const std = @import("std");
+const warn = std.debug.warn;
+const mem = std.mem;
+const assert = std.debug.assert;
+
+pub const Stack = struct {
+ buffer: []u8,
+ index: usize,
+
+ pub fn init(buffer: []u8) Stack {
+ return Stack{
+ .buffer = buffer,
+ .index = 0,
+ };
+ }
+
+ pub fn pop(self: *Stack) !u8 {
+ if (self.index == 0) return error.StackUnderflow;
+ self.index -= 1;
+ return self.buffer[self.index];
+ }
+
+ pub fn push(self: *Stack, item: u8) !void {
+ if (self.index == 0xff) return error.StackOverflow;
+ self.buffer[self.index] = item;
+ self.index += 1;
+ }
+
+ /// slice returns a slice of the array ending at the current index
+ pub fn slice(self: Stack) []u8 {
+ return self.buffer[0..self.index];
+ }
+};
+
+test "test stack" {
+ var buffer: [100]u8 = undefined;
+ var stack = Stack.init(buffer[0..]);
+
+ try stack.push('h');
+ try stack.push('e');
+ try stack.push('l');
+ try stack.push('l');
+ try stack.push('o');
+ try stack.push('!');
+
+ assert(mem.eql(u8, stack.buffer[0..6], "hello!"));
+ warn("\n{}\n", .{stack.slice()});
+
+ const char = try stack.pop();
+ assert(char == '!');
+
+ try stack.push('?');
+ assert(mem.eql(u8, stack.buffer[0..6], "hello?"));
+ warn("\n{}\n", .{stack.slice()});
+
+ _ = try stack.pop();
+ _ = try stack.pop();
+ _ = try stack.pop();
+
+ _ = try stack.pop();
+ _ = try stack.pop();
+ _ = try stack.pop();
+ _ = try stack.pop();
+
+ warn("\n{}\n", .{stack.slice()});
+}