Focus works now! :D
This commit is contained in:
parent
8ae8ce9ac7
commit
e1da270181
@ -48,7 +48,7 @@ pub const Button = struct {
|
||||
_ = term_io;
|
||||
var self: *Button = @fieldParentPtr("pane", pane_ptr);
|
||||
|
||||
if (key.type == .ASCII and key.value == '\r') {
|
||||
if (key.key == .Return) {
|
||||
self.callback();
|
||||
}
|
||||
|
||||
|
115
src/focus.zig
Normal file
115
src/focus.zig
Normal file
@ -0,0 +1,115 @@
|
||||
const std = @import("std");
|
||||
const pane = @import("pane.zig");
|
||||
const term = @import("term.zig");
|
||||
|
||||
const Pane = pane.Pane;
|
||||
const TermIO = term.TermIO;
|
||||
|
||||
var index: usize = 0;
|
||||
var focus_list: std.ArrayList(*Pane) = undefined;
|
||||
pub var current_focus: ?*Pane = null;
|
||||
|
||||
pub fn init(allocator: std.mem.Allocator) !void {
|
||||
focus_list = std.ArrayList(*Pane).init(allocator);
|
||||
}
|
||||
|
||||
pub fn deinit() void {
|
||||
focus_list.deinit();
|
||||
}
|
||||
|
||||
pub fn build_focus_list(top_pane: *Pane) !void {
|
||||
focus_list.clearAndFree();
|
||||
try add_children(top_pane);
|
||||
|
||||
if (current_focus) |current| {
|
||||
for (focus_list.items, 0..) |item, i| {
|
||||
if (item == current) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (focus_list.items.len != 0) {
|
||||
index = 0;
|
||||
current_focus = focus_list.items[index];
|
||||
current_focus.?.focused = true;
|
||||
}
|
||||
}
|
||||
|
||||
fn add_children(p: *Pane) !void {
|
||||
var iter = p.vtable.child_iterator(p);
|
||||
while (iter.next()) |child| {
|
||||
if (child.focusable) {
|
||||
try focus_list.append(child);
|
||||
}
|
||||
|
||||
try add_children(child);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn focus_first(term_io: *TermIO, p: *Pane) !void {
|
||||
if (p.focusable) {
|
||||
try focus_pane(term_io, p);
|
||||
return;
|
||||
}
|
||||
|
||||
try focus_first_child(term_io, p);
|
||||
}
|
||||
|
||||
fn focus_first_child(term_io: *TermIO, p: *Pane) !void {
|
||||
var iter = p.vtable.child_iterator(p);
|
||||
|
||||
while (iter.next()) |child| {
|
||||
if (child.focusable) {
|
||||
try focus_pane(term_io, child);
|
||||
return;
|
||||
}
|
||||
|
||||
try focus_first_child(term_io, p);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn focus_next(term_io: *TermIO) void {
|
||||
if (focus_list.items.len < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
const new_index = (index + 1) % focus_list.items.len;
|
||||
|
||||
focus_index(term_io, new_index);
|
||||
}
|
||||
|
||||
pub fn focus_prev(term_io: *TermIO) void {
|
||||
if (focus_list.items.len < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
var new_index = focus_list.items.len - 1;
|
||||
if (index != 0) {
|
||||
new_index = index - 1;
|
||||
}
|
||||
|
||||
focus_index(term_io, new_index);
|
||||
}
|
||||
|
||||
pub fn focus_pane(term_io: *TermIO, p: *Pane) !void {
|
||||
for (focus_list.items, 0..) |item, i| {
|
||||
if (item == p) {
|
||||
focus_index(term_io, i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn focus_index(term_io: *TermIO, idx: usize) void {
|
||||
if (idx > focus_list.items.len or idx == index) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (current_focus) |current| {
|
||||
current.focus(term_io, false);
|
||||
}
|
||||
|
||||
index = idx;
|
||||
current_focus = focus_list.items[index];
|
||||
current_focus.?.focus(term_io, true);
|
||||
}
|
15
src/main.zig
15
src/main.zig
@ -11,6 +11,7 @@ const line = @import("line.zig");
|
||||
const tabs = @import("tabs.zig");
|
||||
const stack = @import("stack.zig");
|
||||
const text = @import("text.zig");
|
||||
const focus = @import("focus.zig");
|
||||
|
||||
var term_io: term.TermIO = undefined;
|
||||
var side_menu: menu.Menu = undefined;
|
||||
@ -28,18 +29,26 @@ fn on_click() void {
|
||||
fn on_side_select(item: usize) void {
|
||||
log.debug("Side menu: Item {d} was selected", .{item});
|
||||
if (item == 0) {
|
||||
pane.focus(&m.pane, &term_io);
|
||||
focus.focus_pane(&term_io, &m.pane) catch {};
|
||||
}
|
||||
}
|
||||
|
||||
fn on_select(item: usize) void {
|
||||
log.debug("Main menu: Item {d} was selected", .{item});
|
||||
if (item == 0) {
|
||||
pane.focus(&side_menu.pane, &term_io);
|
||||
focus.focus_pane(&term_io, &side_menu.pane) catch {};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main() !void {
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
const allocator = gpa.allocator();
|
||||
defer {
|
||||
if (gpa.deinit() == .leak) {
|
||||
std.debug.print("Memory was leaked!! D:\n", .{});
|
||||
}
|
||||
}
|
||||
|
||||
if (@import("builtin").mode == .Debug) {
|
||||
try log.init("panes.log", .Debug);
|
||||
}
|
||||
@ -116,7 +125,7 @@ pub fn main() !void {
|
||||
});
|
||||
|
||||
pane.set_layout(&top.pane, &tabbar.pane);
|
||||
try pane.init(&term_io);
|
||||
try pane.init(allocator, &term_io);
|
||||
defer pane.cleanup(&term_io);
|
||||
|
||||
while (!pane.should_exit.load(.acquire)) {
|
||||
|
23
src/menu.zig
23
src/menu.zig
@ -71,25 +71,16 @@ pub const Menu = struct {
|
||||
|
||||
fn update(pane_ptr: *Pane, term_io: *TermIO, key: term.Key) !bool {
|
||||
var self: *Menu = @fieldParentPtr("pane", pane_ptr);
|
||||
if (self.index == self.items.len or key.type == .NO_KEY) {
|
||||
if (self.index == self.items.len or key.key == .None) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (key.type == term.KeyType.SEQUENCE) {
|
||||
const key_enum: term.SequenceKey = @enumFromInt(key.value);
|
||||
switch (key_enum) {
|
||||
term.SequenceKey.DOWN => try self.nextItem(term_io),
|
||||
term.SequenceKey.UP => try self.prevItem(term_io),
|
||||
else => return false,
|
||||
}
|
||||
} else {
|
||||
switch (key.value) {
|
||||
13 => self.on_select(self.index), // Enter
|
||||
0x1b, 'q' => {}, // self.index = 0,
|
||||
'j' => try self.nextItem(term_io),
|
||||
'k' => try self.prevItem(term_io),
|
||||
else => return false,
|
||||
}
|
||||
switch (key.key) {
|
||||
.Return => self.on_select(self.index),
|
||||
.Escape, .Q => {}, // self.index = 0,
|
||||
.J, .Down => try self.nextItem(term_io),
|
||||
.K, .Up => try self.prevItem(term_io),
|
||||
else => return false,
|
||||
}
|
||||
|
||||
return true;
|
||||
|
84
src/pane.zig
84
src/pane.zig
@ -4,13 +4,12 @@ const color = @import("colors.zig");
|
||||
const dim = @import("dimensions.zig");
|
||||
const stack = @import("stack.zig");
|
||||
const term = @import("term.zig");
|
||||
const focus = @import("focus.zig");
|
||||
const Border = @import("borders.zig").Border;
|
||||
|
||||
const TermIO = term.TermIO;
|
||||
|
||||
var window = Window{ .pane = Pane{}, .child = null };
|
||||
pub var focused_pane: *Pane = undefined;
|
||||
pub var focused_index: usize = 1;
|
||||
pub var should_exit: std.atomic.Value(bool) = std.atomic.Value(bool).init(false);
|
||||
var needs_redraw: std.atomic.Value(bool) = std.atomic.Value(bool).init(false);
|
||||
var redraw_count: usize = 0;
|
||||
@ -33,14 +32,12 @@ fn panic_signal(_: i32) callconv(.C) void {
|
||||
@panic("Segmentation fault!!");
|
||||
}
|
||||
|
||||
pub fn set_layout(layout: *Pane, initial_focus: *Pane) void {
|
||||
pub fn set_layout(layout: *Pane, _: *Pane) void {
|
||||
layout.parent = &window.pane;
|
||||
window.child = layout;
|
||||
focused_pane = initial_focus;
|
||||
focused_pane.focused = true;
|
||||
}
|
||||
|
||||
pub fn init(term_io: *TermIO) !void {
|
||||
pub fn init(allocator: std.mem.Allocator, term_io: *TermIO) !void {
|
||||
term_io.enterRawMode();
|
||||
term_io.saveScreen();
|
||||
term_io.hideCursor();
|
||||
@ -67,6 +64,8 @@ pub fn init(term_io: *TermIO) !void {
|
||||
};
|
||||
try std.posix.sigaction(std.posix.SIG.SEGV, &panic_handler, null);
|
||||
|
||||
try focus.init(allocator);
|
||||
|
||||
window.resize(term_io);
|
||||
try window.draw(term_io);
|
||||
}
|
||||
@ -78,17 +77,23 @@ pub fn cleanup(term_io: *TermIO) void {
|
||||
// term_io.stdout.context.flush() catch @panic("Failed to flush buffered writer\n");
|
||||
term_io.flush();
|
||||
term_io.close();
|
||||
|
||||
focus.deinit();
|
||||
}
|
||||
|
||||
pub fn tick(term_io: *TermIO) !void {
|
||||
const key = term_io.getKey(false);
|
||||
if (key.value == 113) {
|
||||
if (key.key == .Q or key.key == .Escape) {
|
||||
should_exit.store(true, .release);
|
||||
return;
|
||||
}
|
||||
|
||||
if (key.type == .ASCII and key.value == '\t') {
|
||||
cycle_focus(term_io);
|
||||
if (key.key == .Tab) {
|
||||
if (key.mod.shift) {
|
||||
focus.focus_prev(term_io);
|
||||
} else {
|
||||
focus.focus_next(term_io);
|
||||
}
|
||||
term_io.flush();
|
||||
return;
|
||||
}
|
||||
@ -104,38 +109,13 @@ pub fn tick(term_io: *TermIO) !void {
|
||||
log.debug("Resized {} times", .{redraw_count});
|
||||
}
|
||||
|
||||
if (try focused_pane.update(term_io, key)) {
|
||||
term_io.flush();
|
||||
if (focus.current_focus) |focused| {
|
||||
if (try focused.update(term_io, key)) {
|
||||
term_io.flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cycle_focus(term_io: *TermIO) void {
|
||||
// TODO: There must be a better way of doing this
|
||||
|
||||
const parent_stack: *stack.Stack = @fieldParentPtr("pane", focused_pane.parent);
|
||||
var index = (focused_index + 1) % parent_stack.children.len;
|
||||
var to_focus = parent_stack.children[index].pane;
|
||||
|
||||
while (!to_focus.focusable and index != focused_index) {
|
||||
index = (index + 1) % parent_stack.children.len;
|
||||
to_focus = parent_stack.children[index].pane;
|
||||
}
|
||||
|
||||
focus(to_focus, term_io);
|
||||
focused_index = index;
|
||||
}
|
||||
|
||||
pub fn focus(to_focus: *Pane, term_io: *TermIO) void {
|
||||
if (to_focus == focused_pane) return;
|
||||
|
||||
focused_pane.focus(term_io, false);
|
||||
|
||||
focused_pane = to_focus;
|
||||
focused_index = 0; // TODO: Fix this
|
||||
|
||||
to_focus.focus(term_io, true);
|
||||
}
|
||||
|
||||
pub const Overflow = struct {
|
||||
x: enum { Wrap, Hidden },
|
||||
y: enum { Scroll, Hidden },
|
||||
@ -166,6 +146,7 @@ pub const Pane = struct {
|
||||
}
|
||||
|
||||
const PaneVtable = struct {
|
||||
child_iterator: *const fn (*Pane) ChildIterator = ChildIterator.empty,
|
||||
draw: *const fn (*Pane, *TermIO) anyerror!void = defaultDraw,
|
||||
focus: *const fn (*Pane, *TermIO) anyerror!void = defaultFocus,
|
||||
resize: *const fn (*Pane) void = defaultResize,
|
||||
@ -292,7 +273,6 @@ pub const Pane = struct {
|
||||
}
|
||||
|
||||
pub fn focus(self: *Pane, term_io: *TermIO, focused: bool) void {
|
||||
focused_pane = self;
|
||||
self.focused = focused;
|
||||
self.cursor = .{ .x = 0, .y = 0 };
|
||||
|
||||
@ -361,6 +341,31 @@ pub const Pane = struct {
|
||||
}
|
||||
};
|
||||
|
||||
pub const ChildIterator = struct {
|
||||
parent: *Pane,
|
||||
index: usize = 0,
|
||||
vtable: VTable,
|
||||
|
||||
const VTable = struct {
|
||||
next: *const fn (self: *ChildIterator) ?*Pane,
|
||||
};
|
||||
|
||||
pub fn next(self: *ChildIterator) ?*Pane {
|
||||
return self.vtable.next(self);
|
||||
}
|
||||
|
||||
fn empty(_: *Pane) ChildIterator {
|
||||
return ChildIterator{
|
||||
.parent = undefined,
|
||||
.vtable = .{ .next = empty_next },
|
||||
};
|
||||
}
|
||||
|
||||
fn empty_next(_: *ChildIterator) ?*Pane {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
const Window = struct {
|
||||
pane: Pane,
|
||||
child: ?*Pane,
|
||||
@ -383,6 +388,7 @@ const Window = struct {
|
||||
|
||||
fn draw(self: *Window, term_io: *TermIO) !void {
|
||||
if (self.child) |child| {
|
||||
try focus.build_focus_list(child);
|
||||
try child.draw(term_io);
|
||||
term_io.flush();
|
||||
}
|
||||
|
@ -47,6 +47,7 @@ pub const Stack = struct {
|
||||
.focusable = false,
|
||||
.style = config.style,
|
||||
.vtable = .{
|
||||
.child_iterator = child_iterator,
|
||||
.resize = resize,
|
||||
.draw = draw,
|
||||
},
|
||||
@ -252,4 +253,22 @@ pub const Stack = struct {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn child_iterator(self: *Pane) pane.ChildIterator {
|
||||
return pane.ChildIterator{
|
||||
.parent = self,
|
||||
.vtable = .{ .next = iter_next },
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
fn iter_next(iter: *pane.ChildIterator) ?*Pane {
|
||||
const stack: *Stack = @fieldParentPtr("pane", iter.parent);
|
||||
|
||||
if (iter.index >= stack.children.len) {
|
||||
return null;
|
||||
}
|
||||
|
||||
defer iter.index += 1;
|
||||
return stack.children[iter.index].pane;
|
||||
}
|
||||
|
55
src/tabs.zig
55
src/tabs.zig
@ -5,6 +5,7 @@ const menu = @import("menu.zig");
|
||||
const pane = @import("pane.zig");
|
||||
const term = @import("term.zig");
|
||||
const std = @import("std");
|
||||
const focus = @import("focus.zig");
|
||||
|
||||
const Pane = pane.Pane;
|
||||
const Style = pane.Style;
|
||||
@ -40,7 +41,7 @@ pub const TabBar = struct {
|
||||
.style = config.style,
|
||||
.vtable = .{
|
||||
.draw = draw,
|
||||
.focus = focus,
|
||||
.focus = on_focus,
|
||||
.update = update,
|
||||
},
|
||||
};
|
||||
@ -87,29 +88,8 @@ pub const TabBar = struct {
|
||||
fn update(pane_ptr: *pane.Pane, term_io: *TermIO, key: term.Key) !bool {
|
||||
var self: *TabBar = @fieldParentPtr("pane", pane_ptr);
|
||||
|
||||
if (key.type == .SEQUENCE) {
|
||||
const seq: term.SequenceKey = @enumFromInt(key.value);
|
||||
switch (seq) {
|
||||
.LEFT => {
|
||||
if (self.index > 0) {
|
||||
self.index -= 1;
|
||||
try draw(pane_ptr, term_io);
|
||||
try self.config.target.update_content(self.tabs[self.index].pane, term_io);
|
||||
return true;
|
||||
}
|
||||
},
|
||||
.RIGHT => {
|
||||
self.index = @min(self.index + 1, self.tabs.len - 1);
|
||||
try draw(pane_ptr, term_io);
|
||||
try self.config.target.update_content(self.tabs[self.index].pane, term_io);
|
||||
return true;
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
|
||||
switch (key.value) {
|
||||
'h' => {
|
||||
switch (key.key) {
|
||||
.H, .Left => {
|
||||
if (self.index > 0) {
|
||||
self.index -= 1;
|
||||
try draw(pane_ptr, term_io);
|
||||
@ -117,14 +97,14 @@ pub const TabBar = struct {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
'l' => {
|
||||
.L, .Right => {
|
||||
self.index = @min(self.index + 1, self.tabs.len - 1);
|
||||
try draw(pane_ptr, term_io);
|
||||
try self.config.target.update_content(self.tabs[self.index].pane, term_io);
|
||||
return true;
|
||||
},
|
||||
'\r' => {
|
||||
pane.focus(self.config.target.content, term_io);
|
||||
.Return => {
|
||||
try focus.focus_first(term_io, self.config.target.content);
|
||||
return true;
|
||||
},
|
||||
else => {},
|
||||
@ -133,7 +113,7 @@ pub const TabBar = struct {
|
||||
return false;
|
||||
}
|
||||
|
||||
fn focus(pane_ptr: *Pane, term_io: *TermIO) !void {
|
||||
fn on_focus(pane_ptr: *Pane, term_io: *TermIO) !void {
|
||||
try draw(pane_ptr, term_io);
|
||||
}
|
||||
};
|
||||
@ -146,6 +126,7 @@ pub const TabbedTarget = struct {
|
||||
mem.pane = Pane{
|
||||
.style = style,
|
||||
.vtable = .{
|
||||
.child_iterator = child_iterator,
|
||||
.resize = resize,
|
||||
.draw = draw,
|
||||
},
|
||||
@ -175,4 +156,22 @@ pub const TabbedTarget = struct {
|
||||
|
||||
try self.content.draw(term_io);
|
||||
}
|
||||
|
||||
fn child_iterator(self: *Pane) pane.ChildIterator {
|
||||
return pane.ChildIterator{
|
||||
.parent = self,
|
||||
.vtable = .{ .next = iter_next },
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
fn iter_next(iter: *pane.ChildIterator) ?*Pane {
|
||||
const target: *TabbedTarget = @fieldParentPtr("pane", iter.parent);
|
||||
|
||||
if (iter.index > 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
iter.index += 1;
|
||||
return target.content;
|
||||
}
|
||||
|
92
src/term.zig
92
src/term.zig
@ -27,9 +27,65 @@ pub const SequenceKey = enum(u8) {
|
||||
UNKNOWN,
|
||||
};
|
||||
|
||||
pub const KeyCode = enum {
|
||||
None,
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
D,
|
||||
E,
|
||||
F,
|
||||
G,
|
||||
H,
|
||||
I,
|
||||
J,
|
||||
K,
|
||||
L,
|
||||
M,
|
||||
N,
|
||||
O,
|
||||
P,
|
||||
Q,
|
||||
R,
|
||||
S,
|
||||
T,
|
||||
U,
|
||||
V,
|
||||
W,
|
||||
X,
|
||||
Y,
|
||||
Z,
|
||||
Zero,
|
||||
One,
|
||||
Two,
|
||||
Three,
|
||||
Four,
|
||||
Five,
|
||||
Six,
|
||||
Seven,
|
||||
Eight,
|
||||
Nine,
|
||||
Space,
|
||||
Escape,
|
||||
Tab,
|
||||
Return,
|
||||
Backspace,
|
||||
Delete,
|
||||
Up,
|
||||
Down,
|
||||
Left,
|
||||
Right,
|
||||
};
|
||||
|
||||
const Modifiers = packed struct {
|
||||
ctrl: bool = false,
|
||||
shift: bool = false,
|
||||
alt: bool = false,
|
||||
};
|
||||
|
||||
pub const Key = struct {
|
||||
type: KeyType,
|
||||
value: u8,
|
||||
key: KeyCode,
|
||||
mod: Modifiers = .{},
|
||||
};
|
||||
|
||||
pub const PrintFlags = struct {
|
||||
@ -480,7 +536,7 @@ pub const TermIO = struct {
|
||||
if (!term_io.escape_sequence_queued) {
|
||||
const c = term_io.stdin.readByte() catch |err| {
|
||||
switch (err) {
|
||||
error.WouldBlock, error.EndOfStream => if (!block) return .{ .type = KeyType.NO_KEY, .value = 0 },
|
||||
error.WouldBlock, error.EndOfStream => if (!block) return .{ .key = .None },
|
||||
else => {
|
||||
log.err("{any}", .{err});
|
||||
@panic("Unexpected error when reading from stdin");
|
||||
@ -488,15 +544,27 @@ pub const TermIO = struct {
|
||||
}
|
||||
continue;
|
||||
};
|
||||
|
||||
if (c != 0x1b and sequence_len == 0) {
|
||||
return .{ .type = KeyType.ASCII, .value = c };
|
||||
switch (c) {
|
||||
1...8, 10...12, 14...26 => return Key{ .key = @enumFromInt(@intFromEnum(KeyCode.A) + (c - 'a')), .mod = .{ .ctrl = true } },
|
||||
'a'...'z' => return Key{ .key = @enumFromInt(@intFromEnum(KeyCode.A) + (c - 'a')) },
|
||||
'A'...'Z' => return Key{ .key = @enumFromInt(@intFromEnum(KeyCode.A) + (c - 'A')), .mod = .{ .shift = true } },
|
||||
'0'...'9' => return Key{ .key = @enumFromInt(@intFromEnum(KeyCode.Zero) + (c - '0')) },
|
||||
' ' => return Key{ .key = .Space },
|
||||
27 => return Key{ .key = .Escape },
|
||||
'\t' => return Key{ .key = .Tab },
|
||||
'\r' => return Key{ .key = .Return },
|
||||
127 => return Key{ .key = .Backspace },
|
||||
else => return Key{ .key = .None },
|
||||
}
|
||||
}
|
||||
}
|
||||
term_io.escape_sequence_queued = false;
|
||||
|
||||
// Escape sequence
|
||||
sequence_len = 0;
|
||||
escape_sequence[sequence_len] = term_io.stdin.readByte() catch return .{ .type = KeyType.ASCII, .value = 0x1b };
|
||||
escape_sequence[sequence_len] = term_io.stdin.readByte() catch return .{ .key = .Escape };
|
||||
|
||||
while (true) {
|
||||
sequence_len += 1;
|
||||
@ -535,16 +603,18 @@ pub fn getTermIO(stdin: std.io.AnyReader, stdout: std.io.BufferedWriter(4096, st
|
||||
}
|
||||
|
||||
fn decipherEscapeSequence(sequence: []u8) Key {
|
||||
// I should probably make this better
|
||||
if (sequence.len == 2) {
|
||||
if (std.mem.eql(u8, sequence, &[2]u8{ '[', 'A' })) return .{ .type = KeyType.SEQUENCE, .value = @intFromEnum(SequenceKey.UP) };
|
||||
if (std.mem.eql(u8, sequence, &[2]u8{ '[', 'B' })) return .{ .type = KeyType.SEQUENCE, .value = @intFromEnum(SequenceKey.DOWN) };
|
||||
if (std.mem.eql(u8, sequence, &[2]u8{ '[', 'C' })) return .{ .type = KeyType.SEQUENCE, .value = @intFromEnum(SequenceKey.RIGHT) };
|
||||
if (std.mem.eql(u8, sequence, &[2]u8{ '[', 'D' })) return .{ .type = KeyType.SEQUENCE, .value = @intFromEnum(SequenceKey.LEFT) };
|
||||
if (std.mem.eql(u8, sequence, &[2]u8{ '[', 'A' })) return .{ .key = .Up };
|
||||
if (std.mem.eql(u8, sequence, &[2]u8{ '[', 'B' })) return .{ .key = .Down };
|
||||
if (std.mem.eql(u8, sequence, &[2]u8{ '[', 'C' })) return .{ .key = .Right };
|
||||
if (std.mem.eql(u8, sequence, &[2]u8{ '[', 'D' })) return .{ .key = .Left };
|
||||
if (std.mem.eql(u8, sequence, &[2]u8{ '[', 'Z' })) return .{ .key = .Tab, .mod = .{ .shift = true } };
|
||||
} else if (sequence.len == 3) {
|
||||
if (std.mem.eql(u8, sequence, &[3]u8{ '[', '3', '~' })) return .{ .type = KeyType.SEQUENCE, .value = @intFromEnum(SequenceKey.DELETE) };
|
||||
if (std.mem.eql(u8, sequence, &[3]u8{ '[', '3', '~' })) return .{ .key = .Delete };
|
||||
}
|
||||
|
||||
return .{ .type = KeyType.SEQUENCE, .value = @intFromEnum(SequenceKey.UNKNOWN) };
|
||||
return .{ .key = .None };
|
||||
}
|
||||
|
||||
test "stdout" {
|
||||
|
Loading…
Reference in New Issue
Block a user