examples(nvim): update example api
The nvim widget needs work, but at least you can run the example
This commit is contained in:
parent
a0db41f87c
commit
ed1867cf39
4 changed files with 141 additions and 14 deletions
|
@ -43,6 +43,7 @@ pub fn build(b: *std.Build) void {
|
||||||
main,
|
main,
|
||||||
nvim,
|
nvim,
|
||||||
pathological,
|
pathological,
|
||||||
|
shell,
|
||||||
table,
|
table,
|
||||||
text_input,
|
text_input,
|
||||||
};
|
};
|
||||||
|
|
|
@ -24,18 +24,18 @@ pub fn main() !void {
|
||||||
const alloc = gpa.allocator();
|
const alloc = gpa.allocator();
|
||||||
|
|
||||||
// Initialize Vaxis
|
// Initialize Vaxis
|
||||||
var vx = try vaxis.init(Event, .{});
|
var vx = try vaxis.init(alloc, .{});
|
||||||
defer vx.deinit(alloc);
|
defer vx.deinit(alloc);
|
||||||
|
|
||||||
// Start the read loop. This puts the terminal in raw mode and begins
|
var loop: vaxis.Loop(Event) = .{ .vaxis = &vx };
|
||||||
// reading user input
|
|
||||||
try vx.startReadThread();
|
try loop.run();
|
||||||
defer vx.stopReadThread();
|
defer loop.stop();
|
||||||
|
|
||||||
// Optionally enter the alternate screen
|
// Optionally enter the alternate screen
|
||||||
try vx.enterAltScreen();
|
try vx.enterAltScreen();
|
||||||
|
|
||||||
var nvim = try vaxis.widgets.nvim.Nvim(Event).init(alloc, &vx);
|
var nvim = try vaxis.widgets.nvim.Nvim(Event).init(alloc, &loop);
|
||||||
try nvim.spawn();
|
try nvim.spawn();
|
||||||
defer nvim.deinit();
|
defer nvim.deinit();
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ pub fn main() !void {
|
||||||
// queue which can serve as the primary event queue for an application
|
// queue which can serve as the primary event queue for an application
|
||||||
while (true) {
|
while (true) {
|
||||||
// nextEvent blocks until an event is in the queue
|
// nextEvent blocks until an event is in the queue
|
||||||
const event = vx.nextEvent();
|
const event = loop.nextEvent();
|
||||||
std.log.debug("event: {}", .{event});
|
std.log.debug("event: {}", .{event});
|
||||||
// exhaustive switching ftw. Vaxis will send events if your Event
|
// exhaustive switching ftw. Vaxis will send events if your Event
|
||||||
// enum has the fields for those events (ie "key_press", "winsize")
|
// enum has the fields for those events (ie "key_press", "winsize")
|
||||||
|
|
126
examples/shell.zig
Normal file
126
examples/shell.zig
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const vaxis = @import("vaxis");
|
||||||
|
const Cell = vaxis.Cell;
|
||||||
|
const TextInput = vaxis.widgets.TextInput;
|
||||||
|
|
||||||
|
const log = std.log.scoped(.main);
|
||||||
|
pub fn main() !void {
|
||||||
|
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||||
|
defer {
|
||||||
|
const deinit_status = gpa.deinit();
|
||||||
|
if (deinit_status == .leak) {
|
||||||
|
log.err("memory leak", .{});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const alloc = gpa.allocator();
|
||||||
|
|
||||||
|
var vx = try vaxis.init(alloc, .{});
|
||||||
|
defer vx.deinit(alloc);
|
||||||
|
|
||||||
|
var loop: vaxis.Loop(Event) = .{ .vaxis = &vx };
|
||||||
|
|
||||||
|
try loop.run();
|
||||||
|
defer loop.stop();
|
||||||
|
|
||||||
|
try vx.queryTerminal();
|
||||||
|
|
||||||
|
var text_input = TextInput.init(alloc, &vx.unicode);
|
||||||
|
defer text_input.deinit();
|
||||||
|
|
||||||
|
var selected_option: ?usize = null;
|
||||||
|
|
||||||
|
const options = [_][]const u8{
|
||||||
|
"yes",
|
||||||
|
"no",
|
||||||
|
};
|
||||||
|
|
||||||
|
// The main event loop. Vaxis provides a thread safe, blocking, buffered
|
||||||
|
// queue which can serve as the primary event queue for an application
|
||||||
|
while (true) {
|
||||||
|
// nextEvent blocks until an event is in the queue
|
||||||
|
const event = loop.nextEvent();
|
||||||
|
// exhaustive switching ftw. Vaxis will send events if your Event
|
||||||
|
// enum has the fields for those events (ie "key_press", "winsize")
|
||||||
|
switch (event) {
|
||||||
|
.key_press => |key| {
|
||||||
|
if (key.codepoint == 'c' and key.mods.ctrl) {
|
||||||
|
break;
|
||||||
|
} else if (key.matches(vaxis.Key.tab, .{})) {
|
||||||
|
if (selected_option == null) {
|
||||||
|
selected_option = 0;
|
||||||
|
} else {
|
||||||
|
selected_option.? = @min(options.len - 1, selected_option.? + 1);
|
||||||
|
}
|
||||||
|
} else if (key.matches(vaxis.Key.tab, .{ .shift = true })) {
|
||||||
|
if (selected_option == null) {
|
||||||
|
selected_option = 0;
|
||||||
|
} else {
|
||||||
|
selected_option.? = selected_option.? -| 1;
|
||||||
|
}
|
||||||
|
} else if (key.matches(vaxis.Key.enter, .{})) {
|
||||||
|
if (selected_option) |i| {
|
||||||
|
log.err("enter", .{});
|
||||||
|
try text_input.insertSliceAtCursor(options[i]);
|
||||||
|
selected_option = null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (selected_option == null)
|
||||||
|
try text_input.update(.{ .key_press = key });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.winsize => |ws| {
|
||||||
|
try vx.resize(alloc, ws);
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
|
||||||
|
const win = vx.window();
|
||||||
|
win.clear();
|
||||||
|
|
||||||
|
const right_win = win.child(.{
|
||||||
|
.x_off = win.width - 4,
|
||||||
|
});
|
||||||
|
const left_win = win.child(.{
|
||||||
|
.width = .{ .limit = 8 },
|
||||||
|
});
|
||||||
|
var right_prompt = [_]vaxis.Segment{
|
||||||
|
.{ .text = "👩🚀🏳️🌈" },
|
||||||
|
};
|
||||||
|
var left_prompt = [_]vaxis.Segment{
|
||||||
|
.{ .text = "👩🚀🏳️🌈~ ", .style = .{ .fg = .{ .index = 4 } } },
|
||||||
|
.{ .text = "", .style = .{ .fg = .{ .index = 5 } } },
|
||||||
|
};
|
||||||
|
_ = try right_win.print(&right_prompt, .{});
|
||||||
|
_ = try left_win.print(&left_prompt, .{});
|
||||||
|
|
||||||
|
const input_win = win.child(.{
|
||||||
|
.x_off = 8,
|
||||||
|
.width = .{ .limit = win.width - 12 },
|
||||||
|
});
|
||||||
|
|
||||||
|
text_input.draw(input_win);
|
||||||
|
|
||||||
|
if (selected_option) |i| {
|
||||||
|
win.hideCursor();
|
||||||
|
for (options, 0..) |opt, j| {
|
||||||
|
log.err("i = {d}, j = {d}, opt = {s}", .{ i, j, opt });
|
||||||
|
var seg = [_]vaxis.Segment{.{
|
||||||
|
.text = opt,
|
||||||
|
.style = if (j == i) .{ .reverse = true } else .{},
|
||||||
|
}};
|
||||||
|
_ = try win.print(&seg, .{ .row_offset = j + 1 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try vx.render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Our Event. This can contain internal events as well as Vaxis events.
|
||||||
|
// Internal events can be posted into the same queue as vaxis events to allow
|
||||||
|
// for a single event loop with exhaustive switching. Booya
|
||||||
|
const Event = union(enum) {
|
||||||
|
key_press: vaxis.Key,
|
||||||
|
winsize: vaxis.Winsize,
|
||||||
|
focus_in,
|
||||||
|
foo: u8,
|
||||||
|
};
|
|
@ -46,13 +46,13 @@ pub fn Nvim(comptime T: type) type {
|
||||||
|
|
||||||
hl_map: HighlightMap,
|
hl_map: HighlightMap,
|
||||||
|
|
||||||
vx: *vaxis.Vaxis(T),
|
loop: *vaxis.Loop(T),
|
||||||
dirty: bool = false,
|
dirty: bool = false,
|
||||||
mode_set: std.ArrayList(Mode),
|
mode_set: std.ArrayList(Mode),
|
||||||
|
|
||||||
/// initialize nvim. Starts the nvim process. UI is not attached until the first
|
/// initialize nvim. Starts the nvim process. UI is not attached until the first
|
||||||
/// call to draw
|
/// call to draw
|
||||||
pub fn init(alloc: std.mem.Allocator, vx: *vaxis.Vaxis(T)) !Self {
|
pub fn init(alloc: std.mem.Allocator, loop: *vaxis.Loop(T)) !Self {
|
||||||
const args = [_][]const u8{ "nvim", "--embed" };
|
const args = [_][]const u8{ "nvim", "--embed" };
|
||||||
var nvim = std.ChildProcess.init(&args, alloc);
|
var nvim = std.ChildProcess.init(&args, alloc);
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ pub fn Nvim(comptime T: type) type {
|
||||||
.alloc = alloc,
|
.alloc = alloc,
|
||||||
.process = nvim,
|
.process = nvim,
|
||||||
.hl_map = HighlightMap.init(alloc),
|
.hl_map = HighlightMap.init(alloc),
|
||||||
.vx = vx,
|
.loop = loop,
|
||||||
.mode_set = std.ArrayList(Mode).init(alloc),
|
.mode_set = std.ArrayList(Mode).init(alloc),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,7 @@ pub fn Nvim(comptime T: type) type {
|
||||||
self.alloc,
|
self.alloc,
|
||||||
);
|
);
|
||||||
|
|
||||||
self.thread = try std.Thread.spawn(.{}, Self.loop, .{self});
|
self.thread = try std.Thread.spawn(.{}, Self.nvimLoop, .{self});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *Self) void {
|
pub fn deinit(self: *Self) void {
|
||||||
|
@ -246,12 +246,12 @@ pub fn Nvim(comptime T: type) type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn loop(self: *Self) void {
|
fn nvimLoop(self: *Self) void {
|
||||||
if (self.client) |*client| {
|
if (self.client) |*client| {
|
||||||
while (true) {
|
while (true) {
|
||||||
client.loop() catch |err| {
|
client.loop() catch |err| {
|
||||||
log.err("rpc loop error: {}", .{err});
|
log.err("rpc loop error: {}", .{err});
|
||||||
self.vx.postEvent(.{ .nvim = .{ .quit = self } });
|
self.loop.postEvent(.{ .nvim = .{ .quit = self } });
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -456,7 +456,7 @@ pub fn Nvim(comptime T: type) type {
|
||||||
self.visible_screen.cursor_shape = self.screen.cursor_shape;
|
self.visible_screen.cursor_shape = self.screen.cursor_shape;
|
||||||
if (!self.dirty) {
|
if (!self.dirty) {
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
self.vx.postEvent(.{ .nvim = .{ .redraw = self } });
|
self.loop.postEvent(.{ .nvim = .{ .redraw = self } });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.grid_clear => {
|
.grid_clear => {
|
||||||
|
|
Loading…
Reference in a new issue