Replace vaxis with zterm #1
23
README.md
23
README.md
@@ -21,20 +21,25 @@ delay for each frame in each line of the output.
|
||||
- [ ] Have clickable/navigatable links inside of the tui application
|
||||
- [ ] Launch simple http server alongside tui application
|
||||
|
||||
- [ ] Create other layouts
|
||||
- [ ] horizontal stack
|
||||
- [ ] vertical stack
|
||||
- [ ] `Layout` in `Layout`? -> interfaces are very similar anyway
|
||||
- [ ] Building Block `Layout`s
|
||||
- [ ] Framing `Layout`
|
||||
- [ ] Padding `Layout`
|
||||
---
|
||||
|
||||
- [ ] Split into own repository
|
||||
- [ ] Create other layouts
|
||||
- [ ] horizontal stack
|
||||
- [ ] vertical stack
|
||||
- [ ] `Layout` in `Layout`? -> interfaces are very similar anyway
|
||||
- [ ] Building Block `Layout`s
|
||||
- [ ] Framing `Layout`
|
||||
- [ ] Padding `Layout`
|
||||
- [ ] Create demo gifs using [vhs](https://github.com/charmbracelet/vhs)
|
||||
- [ ] Move documentation into new repository
|
||||
- [ ] add dependency to new repository into this project
|
||||
|
||||
---
|
||||
|
||||
## Branch: `own-tty-visuals`
|
||||
|
||||
- [ ] How can I support to run a sub-process inside of a given pane / layout?
|
||||
- [ ] Create demo gifs using [vhs](https://github.com/charmbracelet/vhs)
|
||||
|
||||
- [x] Could I simulate a corresponding event loop?
|
||||
- emmit as many as possible through another thread (until the event queue is full?) [1023]
|
||||
@@ -43,3 +48,5 @@ delay for each frame in each line of the output.
|
||||
-> Or buffered writer to the `std.posix.STDOUT_FILENO`?
|
||||
-> I could use this to see if it makes sense to implement a buffered version using a screen buffer (to only render the differences?)
|
||||
- seems pretty good (with some exceptions)
|
||||
|
||||
- [ ] styling could be tricky with a given layout (which introduces corresponding line breaks ...)
|
||||
|
||||
@@ -8,6 +8,8 @@ const isTaggedUnion = @import("../event.zig").isTaggedUnion;
|
||||
const Error = @import("../event.zig").Error;
|
||||
const Key = @import("../key.zig");
|
||||
|
||||
const log = std.log.scoped(.layout_vstack);
|
||||
|
||||
pub fn Layout(comptime Event: type) type {
|
||||
if (!isTaggedUnion(Event)) {
|
||||
@compileError("Provided user event `Event` for `Layout(comptime Event: type)` is not of type `union(enum)`.");
|
||||
@@ -78,9 +80,17 @@ pub fn Layout(comptime Event: type) type {
|
||||
switch (event) {
|
||||
.resize => |size| {
|
||||
this.size = size;
|
||||
log.debug("Using size: {{ .cols = {d}, .rows = {d} }}", .{ size.cols, size.rows });
|
||||
const len: u16 = @truncate(this.elements.items.len);
|
||||
const rows = size.rows / len;
|
||||
// adjust size according to the containing elements
|
||||
for (this.elements.items) |*element| {
|
||||
const sub_event = event;
|
||||
const sub_event: Event = .{
|
||||
.resize = .{
|
||||
.cols = size.cols,
|
||||
.rows = rows,
|
||||
},
|
||||
};
|
||||
switch (element.*) {
|
||||
.layout => |*layout| {
|
||||
const events = try layout.handle(sub_event);
|
||||
@@ -115,17 +125,22 @@ pub fn Layout(comptime Event: type) type {
|
||||
|
||||
pub fn content(this: *@This()) !*Contents {
|
||||
this.contents.clearRetainingCapacity();
|
||||
// TODO: concat contents accordingly to create a vertical stack
|
||||
for (this.elements.items) |*element| {
|
||||
// TODO: concat contents accordingly to create a horizontal stack
|
||||
for (this.elements.items, 1..) |*element, i| {
|
||||
switch (element.*) {
|
||||
.layout => |*layout| {
|
||||
const layout_content = try layout.content();
|
||||
try this.contents.appendSlice(layout_content.items);
|
||||
},
|
||||
.widget => |*widget| {
|
||||
try this.contents.appendSlice(try widget.content());
|
||||
const widget_content = try widget.content();
|
||||
try this.contents.appendSlice(widget_content);
|
||||
},
|
||||
}
|
||||
// TODO: support clear positioning of content on the tui screen
|
||||
if (i != this.elements.items.len) {
|
||||
try this.contents.appendSlice("\n"); // NOTE: this assumes that the previous content fills all the provided size.rows accordingly with content, such that a newline introduces the start of the next content
|
||||
}
|
||||
}
|
||||
return &this.contents;
|
||||
}
|
||||
|
||||
14
src/main.zig
14
src/main.zig
@@ -33,17 +33,21 @@ pub fn main() !void {
|
||||
var rawText = App.Widget.RawText.init(allocator, file);
|
||||
file.close();
|
||||
|
||||
const doc = try std.fs.cwd().openFile("./doc/test.md", .{});
|
||||
var docText = App.Widget.RawText.init(allocator, doc);
|
||||
doc.close();
|
||||
|
||||
var framing = App.Layout.Framing.init(allocator, .{
|
||||
.widget = App.Widget.createFrom(&rawText),
|
||||
});
|
||||
var vstack = App.Layout.VStack.init(allocator, .{
|
||||
var hstack = App.Layout.HStack.init(allocator, .{
|
||||
App.Layout.createFrom(&framing),
|
||||
});
|
||||
var hstack = App.Layout.HStack.init(allocator, .{
|
||||
App.Layout.createFrom(&vstack),
|
||||
var vstack = App.Layout.VStack.init(allocator, .{
|
||||
App.Widget.createFrom(&docText),
|
||||
App.Layout.createFrom(&hstack),
|
||||
});
|
||||
|
||||
var layout = App.Layout.createFrom(&hstack);
|
||||
var layout = App.Layout.createFrom(&vstack);
|
||||
defer layout.deinit();
|
||||
|
||||
try app.start();
|
||||
|
||||
@@ -6,30 +6,37 @@ const isTaggedUnion = @import("../event.zig").isTaggedUnion;
|
||||
const Error = @import("../event.zig").Error;
|
||||
const Key = @import("../key.zig");
|
||||
|
||||
const log = std.log.scoped(.widget_rawtext);
|
||||
|
||||
pub fn Widget(comptime Event: type) type {
|
||||
if (!isTaggedUnion(Event)) {
|
||||
@compileError("Provided user event `Event` for `Layout(comptime Event: type)` is not of type `union(enum)`.");
|
||||
}
|
||||
const Contents = std.ArrayList(u8);
|
||||
return struct {
|
||||
c: std.ArrayList(u8) = undefined,
|
||||
contents: Contents = undefined,
|
||||
line_index: std.ArrayList(usize) = undefined,
|
||||
line: usize = 0,
|
||||
size: terminal.Size = undefined,
|
||||
|
||||
pub fn init(allocator: std.mem.Allocator, file: std.fs.File) @This() {
|
||||
var c = std.ArrayList(u8).init(allocator);
|
||||
var contents = Contents.init(allocator);
|
||||
var line_index = std.ArrayList(usize).init(allocator);
|
||||
file.reader().readAllArrayList(&c, 4192) catch {};
|
||||
for (c.items, 0..) |item, i| {
|
||||
file.reader().readAllArrayList(&contents, std.math.maxInt(usize)) catch {};
|
||||
line_index.append(0) catch {};
|
||||
for (contents.items, 0..) |item, i| {
|
||||
if (item == '\n') {
|
||||
line_index.append(i) catch {};
|
||||
line_index.append(i + 1) catch {};
|
||||
}
|
||||
}
|
||||
return .{ .c = c, .line_index = line_index };
|
||||
return .{
|
||||
.contents = contents,
|
||||
.line_index = line_index,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deinit(this: *@This()) void {
|
||||
this.c.deinit();
|
||||
this.contents.deinit();
|
||||
this.line_index.deinit();
|
||||
this.* = undefined;
|
||||
}
|
||||
@@ -39,8 +46,9 @@ pub fn Widget(comptime Event: type) type {
|
||||
// store the received size
|
||||
.resize => |size| {
|
||||
this.size = size;
|
||||
if (this.line > this.line_index.items.len - 1 - size.rows) {
|
||||
this.line = this.line_index.items.len - 1 - size.rows;
|
||||
log.debug("Using size: {{ .cols = {d}, .rows = {d} }}", .{ size.cols, size.rows });
|
||||
if (this.line > this.line_index.items.len -| 1 -| size.rows) {
|
||||
this.line = this.line_index.items.len -| 1 -| size.rows;
|
||||
}
|
||||
},
|
||||
.key => |key| {
|
||||
@@ -50,11 +58,11 @@ pub fn Widget(comptime Event: type) type {
|
||||
}
|
||||
if (key.matches(.{ .cp = 'G' })) {
|
||||
// bottom
|
||||
this.line = this.line_index.items.len - 1 - this.size.rows;
|
||||
this.line = this.line_index.items.len -| 1 -| this.size.rows;
|
||||
}
|
||||
if (key.matches(.{ .cp = 'j' })) {
|
||||
// down
|
||||
if (this.line < this.line_index.items.len - 1 - this.size.rows) {
|
||||
if (this.line < this.line_index.items.len -| 1 -| this.size.rows) {
|
||||
this.line +|= 1;
|
||||
}
|
||||
}
|
||||
@@ -70,16 +78,17 @@ pub fn Widget(comptime Event: type) type {
|
||||
|
||||
pub fn content(this: *@This()) ![]u8 {
|
||||
if (this.size.rows >= this.line_index.items.len) {
|
||||
return this.c.items;
|
||||
return this.contents.items;
|
||||
} else {
|
||||
// more rows than we can display
|
||||
const i = this.line_index.items[this.line];
|
||||
log.debug("i := {d} this.line := {d}", .{ i, this.line });
|
||||
const e = this.size.rows + this.line;
|
||||
if (e >= this.line_index.items.len) {
|
||||
return this.c.items[i..];
|
||||
return this.contents.items[i..];
|
||||
}
|
||||
const x = this.line_index.items[e];
|
||||
return this.c.items[i..x];
|
||||
const x = this.line_index.items[e] - 1;
|
||||
return this.contents.items[i..x];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user