ref(input): move mouse.zig and key.zig into public input.zig namespace
All checks were successful
Zig Project Action / Lint, Spell-check and test zig project (push) Successful in 1m41s
All checks were successful
Zig Project Action / Lint, Spell-check and test zig project (push) Successful in 1m41s
This commit is contained in:
@@ -119,9 +119,9 @@ pub fn main() !void {
|
|||||||
.quit => break,
|
.quit => break,
|
||||||
.resize => |size| try renderer.resize(size),
|
.resize => |size| try renderer.resize(size),
|
||||||
.key => |key| {
|
.key => |key| {
|
||||||
if (key.matches(.{ .cp = 'q' })) app.quit();
|
if (key.eql(.{ .cp = 'q' })) app.quit();
|
||||||
|
|
||||||
if (key.matches(.{ .cp = 'n', .mod = .{ .ctrl = true } })) {
|
if (key.eql(.{ .cp = 'n', .mod = .{ .ctrl = true } })) {
|
||||||
try app.interrupt();
|
try app.interrupt();
|
||||||
defer app.start() catch @panic("could not start app event loop");
|
defer app.start() catch @panic("could not start app event loop");
|
||||||
var child = std.process.Child.init(&.{"hx"}, allocator);
|
var child = std.process.Child.init(&.{"hx"}, allocator);
|
||||||
|
|||||||
122
src/app.zig
122
src/app.zig
@@ -1,14 +1,15 @@
|
|||||||
//! Application type for TUI-applications
|
//! Application type for TUI-applications
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const terminal = @import("terminal.zig");
|
const code_point = @import("code_point");
|
||||||
const event = @import("event.zig");
|
const event = @import("event.zig");
|
||||||
|
const input = @import("input.zig");
|
||||||
|
const terminal = @import("terminal.zig");
|
||||||
|
|
||||||
const mergeTaggedUnions = event.mergeTaggedUnions;
|
const mergeTaggedUnions = event.mergeTaggedUnions;
|
||||||
const isTaggedUnion = event.isTaggedUnion;
|
const isTaggedUnion = event.isTaggedUnion;
|
||||||
|
|
||||||
const key = @import("key.zig");
|
const Mouse = input.Mouse;
|
||||||
const Mouse = @import("mouse.zig").Mouse;
|
const Key = input.Key;
|
||||||
const Key = key.Key;
|
|
||||||
const Size = @import("size.zig").Size;
|
const Size = @import("size.zig").Size;
|
||||||
const Queue = @import("queue.zig").Queue;
|
const Queue = @import("queue.zig").Queue;
|
||||||
|
|
||||||
@@ -182,21 +183,21 @@ pub fn App(comptime E: type) type {
|
|||||||
0x4F => { // ss3
|
0x4F => { // ss3
|
||||||
if (read_bytes < 3) continue;
|
if (read_bytes < 3) continue;
|
||||||
|
|
||||||
const k: Key = switch (buf[2]) {
|
const key: Key = switch (buf[2]) {
|
||||||
'A' => .{ .cp = key.Up },
|
'A' => .{ .cp = input.Up },
|
||||||
'B' => .{ .cp = key.Down },
|
'B' => .{ .cp = input.Down },
|
||||||
'C' => .{ .cp = key.Right },
|
'C' => .{ .cp = input.Right },
|
||||||
'D' => .{ .cp = key.Left },
|
'D' => .{ .cp = input.Left },
|
||||||
'E' => .{ .cp = key.KpBegin },
|
'E' => .{ .cp = input.KpBegin },
|
||||||
'F' => .{ .cp = key.End },
|
'F' => .{ .cp = input.End },
|
||||||
'H' => .{ .cp = key.Home },
|
'H' => .{ .cp = input.Home },
|
||||||
'P' => .{ .cp = key.F1 },
|
'P' => .{ .cp = input.F1 },
|
||||||
'Q' => .{ .cp = key.F2 },
|
'Q' => .{ .cp = input.F2 },
|
||||||
'R' => .{ .cp = key.F3 },
|
'R' => .{ .cp = input.F3 },
|
||||||
'S' => .{ .cp = key.F4 },
|
'S' => .{ .cp = input.F4 },
|
||||||
else => continue,
|
else => continue,
|
||||||
};
|
};
|
||||||
this.postEvent(.{ .key = k });
|
this.postEvent(.{ .key = key });
|
||||||
},
|
},
|
||||||
0x5B => { // csi
|
0x5B => { // csi
|
||||||
if (read_bytes < 3) continue;
|
if (read_bytes < 3) continue;
|
||||||
@@ -215,23 +216,23 @@ pub fn App(comptime E: type) type {
|
|||||||
// Legacy keys
|
// Legacy keys
|
||||||
// CSI {ABCDEFHPQS}
|
// CSI {ABCDEFHPQS}
|
||||||
// CSI 1 ; modifier:event_type {ABCDEFHPQS}
|
// CSI 1 ; modifier:event_type {ABCDEFHPQS}
|
||||||
const k: Key = .{
|
const key: Key = .{
|
||||||
.cp = switch (final) {
|
.cp = switch (final) {
|
||||||
'A' => key.Up,
|
'A' => input.Up,
|
||||||
'B' => key.Down,
|
'B' => input.Down,
|
||||||
'C' => key.Right,
|
'C' => input.Right,
|
||||||
'D' => key.Left,
|
'D' => input.Left,
|
||||||
'E' => key.KpBegin,
|
'E' => input.KpBegin,
|
||||||
'F' => key.End,
|
'F' => input.End,
|
||||||
'H' => key.Home,
|
'H' => input.Home,
|
||||||
'P' => key.F1,
|
'P' => input.F1,
|
||||||
'Q' => key.F2,
|
'Q' => input.F2,
|
||||||
'R' => key.F3,
|
'R' => input.F3,
|
||||||
'S' => key.F4,
|
'S' => input.F4,
|
||||||
else => unreachable, // switch case prevents in this case form ever happening
|
else => unreachable, // switch case prevents in this case form ever happening
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
this.postEvent(.{ .key = k });
|
this.postEvent(.{ .key = key });
|
||||||
},
|
},
|
||||||
'~' => {
|
'~' => {
|
||||||
// Legacy keys
|
// Legacy keys
|
||||||
@@ -242,34 +243,35 @@ pub fn App(comptime E: type) type {
|
|||||||
const number_buf = field_iter.next() orelse unreachable; // always will have one field
|
const number_buf = field_iter.next() orelse unreachable; // always will have one field
|
||||||
const number = std.fmt.parseUnsigned(u16, number_buf, 10) catch break;
|
const number = std.fmt.parseUnsigned(u16, number_buf, 10) catch break;
|
||||||
|
|
||||||
const k: Key = .{
|
const key: Key = .{
|
||||||
.cp = switch (number) {
|
.cp = switch (number) {
|
||||||
2 => key.Insert,
|
2 => input.Insert,
|
||||||
3 => key.Delete,
|
3 => input.Delete,
|
||||||
5 => key.PageUp,
|
5 => input.PageUp,
|
||||||
6 => key.PageDown,
|
6 => input.PageDown,
|
||||||
7 => key.Home,
|
7 => input.Home,
|
||||||
8 => key.End,
|
8 => input.End,
|
||||||
11 => key.F1,
|
11 => input.F1,
|
||||||
12 => key.F2,
|
12 => input.F2,
|
||||||
13 => key.F3,
|
13 => input.F3,
|
||||||
14 => key.F4,
|
14 => input.F4,
|
||||||
15 => key.F5,
|
15 => input.F5,
|
||||||
17 => key.F6,
|
17 => input.F6,
|
||||||
18 => key.F7,
|
18 => input.F7,
|
||||||
19 => key.F8,
|
19 => input.F8,
|
||||||
20 => key.F9,
|
20 => input.F9,
|
||||||
21 => key.F10,
|
21 => input.F10,
|
||||||
23 => key.F11,
|
23 => input.F11,
|
||||||
24 => key.F12,
|
24 => input.F12,
|
||||||
// 200 => return .{ .event = .paste_start, .n = sequence.len },
|
// 200 => return .{ .event = .paste_start, .n = sequence.len },
|
||||||
// 201 => return .{ .event = .paste_end, .n = sequence.len },
|
// 201 => return .{ .event = .paste_end, .n = sequence.len },
|
||||||
57427 => key.KpBegin,
|
57427 => input.KpBegin,
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
this.postEvent(.{ .key = k });
|
this.postEvent(.{ .key = key });
|
||||||
},
|
},
|
||||||
|
// TODO: focus usage? should this even be in the default event system?
|
||||||
'I' => this.postEvent(.{ .focus = true }),
|
'I' => this.postEvent(.{ .focus = true }),
|
||||||
'O' => this.postEvent(.{ .focus = false }),
|
'O' => this.postEvent(.{ .focus = false }),
|
||||||
'M', 'm' => {
|
'M', 'm' => {
|
||||||
@@ -296,7 +298,7 @@ pub fn App(comptime E: type) type {
|
|||||||
// const alt = button_mask & mouse_bits.alt > 0;
|
// const alt = button_mask & mouse_bits.alt > 0;
|
||||||
// const ctrl = button_mask & mouse_bits.ctrl > 0;
|
// const ctrl = button_mask & mouse_bits.ctrl > 0;
|
||||||
|
|
||||||
const mouse = Mouse{
|
const mouse: Mouse = .{
|
||||||
.button = button,
|
.button = button,
|
||||||
.col = px -| 1,
|
.col = px -| 1,
|
||||||
.row = py -| 1,
|
.row = py -| 1,
|
||||||
@@ -363,24 +365,24 @@ pub fn App(comptime E: type) type {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const b = buf[0];
|
const b = buf[0];
|
||||||
const k: Key = switch (b) {
|
const key: Key = switch (b) {
|
||||||
0x00 => .{ .cp = '@', .mod = .{ .ctrl = true } },
|
0x00 => .{ .cp = '@', .mod = .{ .ctrl = true } },
|
||||||
0x08 => .{ .cp = key.Backspace },
|
0x08 => .{ .cp = input.Backspace },
|
||||||
0x09 => .{ .cp = key.Tab },
|
0x09 => .{ .cp = input.Tab },
|
||||||
0x0a, 0x0d => .{ .cp = key.Enter },
|
0x0a, 0x0d => .{ .cp = input.Enter },
|
||||||
0x01...0x07, 0x0b...0x0c, 0x0e...0x1a => .{ .cp = b + 0x60, .mod = .{ .ctrl = true } },
|
0x01...0x07, 0x0b...0x0c, 0x0e...0x1a => .{ .cp = b + 0x60, .mod = .{ .ctrl = true } },
|
||||||
0x1b => escape: {
|
0x1b => escape: {
|
||||||
std.debug.assert(read_bytes == 1);
|
std.debug.assert(read_bytes == 1);
|
||||||
break :escape .{ .cp = key.Escape };
|
break :escape .{ .cp = input.Escape };
|
||||||
},
|
},
|
||||||
0x7f => .{ .cp = key.Backspace },
|
0x7f => .{ .cp = input.Backspace },
|
||||||
else => {
|
else => {
|
||||||
var iter = terminal.code_point.Iterator{ .bytes = buf[0..read_bytes] };
|
var iter = code_point.Iterator{ .bytes = buf[0..read_bytes] };
|
||||||
while (iter.next()) |cp| this.postEvent(.{ .key = .{ .cp = cp.code } });
|
while (iter.next()) |cp| this.postEvent(.{ .key = .{ .cp = cp.code } });
|
||||||
continue;
|
continue;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
this.postEvent(.{ .key = k });
|
this.postEvent(.{ .key = key });
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
//! Events which are defined by the library. They might be extended by user
|
//! Events which are defined by the library. They might be extended by user
|
||||||
//! events. See `App` for more details about user defined events.
|
//! events. See `App` for more details about user defined events.
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const input = @import("input.zig");
|
||||||
const terminal = @import("terminal.zig");
|
const terminal = @import("terminal.zig");
|
||||||
|
|
||||||
const Mouse = @import("mouse.zig").Mouse;
|
const Key = input.Key;
|
||||||
|
const Mouse = input.Mouse;
|
||||||
const Size = @import("size.zig").Size;
|
const Size = @import("size.zig").Size;
|
||||||
const Key = @import("key.zig").Key;
|
|
||||||
|
|
||||||
/// System events available to every `zterm.App`
|
/// System events available to every `zterm.App`
|
||||||
pub const SystemEvent = union(enum) {
|
pub const SystemEvent = union(enum) {
|
||||||
|
|||||||
@@ -1,8 +1,46 @@
|
|||||||
//! Keybindings and Modifiers for user input detection and selection.
|
//! Input module for `zterm`. Contains structs to represent key events and mouse events.
|
||||||
|
|
||||||
// TODO: rename this module to 'input' and include the mouse.zig contents as well!
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
|
const Size = @import("size.zig").Size;
|
||||||
|
|
||||||
|
pub const Mouse = packed struct {
|
||||||
|
col: u16,
|
||||||
|
row: u16,
|
||||||
|
button: Button,
|
||||||
|
kind: Kind,
|
||||||
|
|
||||||
|
pub const Button = enum(u8) {
|
||||||
|
left,
|
||||||
|
middle,
|
||||||
|
right,
|
||||||
|
none,
|
||||||
|
wheel_up = 64,
|
||||||
|
wheel_down = 65,
|
||||||
|
wheel_right = 66,
|
||||||
|
wheel_left = 67,
|
||||||
|
button_8 = 128,
|
||||||
|
button_9 = 129,
|
||||||
|
button_10 = 130,
|
||||||
|
button_11 = 131,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Kind = enum(u2) {
|
||||||
|
press,
|
||||||
|
release,
|
||||||
|
motion,
|
||||||
|
drag,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn eql(this: @This(), other: @This()) bool {
|
||||||
|
return std.meta.eql(this, other);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn in(this: @This(), size: Size) bool {
|
||||||
|
return this.col >= size.anchor.col and this.col <= size.cols -| size.anchor.col and
|
||||||
|
this.row >= size.anchor.row and this.row <= size.rows -| size.anchor.row;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
pub const Key = packed struct {
|
pub const Key = packed struct {
|
||||||
cp: u21,
|
cp: u21,
|
||||||
mod: Modifier = .{},
|
mod: Modifier = .{},
|
||||||
@@ -24,14 +62,13 @@ pub const Key = packed struct {
|
|||||||
/// .quit => break,
|
/// .quit => break,
|
||||||
/// .key => |key| {
|
/// .key => |key| {
|
||||||
/// // ctrl+c to quit
|
/// // ctrl+c to quit
|
||||||
/// if (terminal.Key.matches(key, .{ .cp = 'c', .mod = .{ .ctrl = true } })) {
|
/// if (key.eql(.{ .cp = 'c', .mod = .{ .ctrl = true } }))
|
||||||
/// app.quit.set();
|
/// app.quit.set();
|
||||||
/// }
|
|
||||||
/// },
|
/// },
|
||||||
/// else => {},
|
/// else => {},
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn matches(this: @This(), other: @This()) bool {
|
pub fn eql(this: @This(), other: @This()) bool {
|
||||||
return std.meta.eql(this, other);
|
return std.meta.eql(this, other);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const zterm = @import("zterm");
|
const zterm = @import("zterm");
|
||||||
|
|
||||||
|
const input = zterm.input;
|
||||||
const App = zterm.App(union(enum) {});
|
const App = zterm.App(union(enum) {});
|
||||||
|
|
||||||
const log = std.log.scoped(.default);
|
const log = std.log.scoped(.default);
|
||||||
@@ -42,7 +43,7 @@ pub const HelloWorldText = packed struct {
|
|||||||
switch (event) {
|
switch (event) {
|
||||||
.init => log.debug(".init event", .{}),
|
.init => log.debug(".init event", .{}),
|
||||||
.key => |key| {
|
.key => |key| {
|
||||||
if (key.matches(.{ .cp = zterm.key.Space })) {
|
if (key.eql(.{ .cp = input.Space })) {
|
||||||
var next_color_idx = @intFromEnum(this.text_color);
|
var next_color_idx = @intFromEnum(this.text_color);
|
||||||
next_color_idx += 1;
|
next_color_idx += 1;
|
||||||
next_color_idx %= 17; // iterate over the first 16 colors (but exclude `.default` == 0)
|
next_color_idx %= 17; // iterate over the first 16 colors (but exclude `.default` == 0)
|
||||||
@@ -142,13 +143,13 @@ pub fn main() !void {
|
|||||||
.quit => break,
|
.quit => break,
|
||||||
.resize => |size| try renderer.resize(size),
|
.resize => |size| try renderer.resize(size),
|
||||||
.key => |key| {
|
.key => |key| {
|
||||||
if (key.matches(.{ .cp = 'q' })) app.quit();
|
if (key.eql(.{ .cp = 'q' })) app.quit();
|
||||||
|
|
||||||
// corresponding element could even be changed from the 'outside' (not forced through the event system)
|
// corresponding element could even be changed from the 'outside' (not forced through the event system)
|
||||||
// event system however allows for cross element communication (i.e. broadcasting messages, etc.)
|
// event system however allows for cross element communication (i.e. broadcasting messages, etc.)
|
||||||
if (key.matches(.{ .cp = zterm.key.Escape })) element_wrapper.text_color = .black;
|
if (key.eql(.{ .cp = input.Escape })) element_wrapper.text_color = .black;
|
||||||
|
|
||||||
if (key.matches(.{ .cp = 'n', .mod = .{ .ctrl = true } })) {
|
if (key.eql(.{ .cp = 'n', .mod = .{ .ctrl = true } })) {
|
||||||
try app.interrupt();
|
try app.interrupt();
|
||||||
defer app.start() catch @panic("could not start app event loop");
|
defer app.start() catch @panic("could not start app event loop");
|
||||||
var child = std.process.Child.init(&.{"hx"}, allocator);
|
var child = std.process.Child.init(&.{"hx"}, allocator);
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
/// Mouse input detection.
|
|
||||||
pub const Mouse = packed struct {
|
|
||||||
col: u16,
|
|
||||||
row: u16,
|
|
||||||
button: Button,
|
|
||||||
kind: Kind,
|
|
||||||
|
|
||||||
pub const Button = enum(u8) {
|
|
||||||
left,
|
|
||||||
middle,
|
|
||||||
right,
|
|
||||||
none,
|
|
||||||
wheel_up = 64,
|
|
||||||
wheel_down = 65,
|
|
||||||
wheel_right = 66,
|
|
||||||
wheel_left = 67,
|
|
||||||
button_8 = 128,
|
|
||||||
button_9 = 129,
|
|
||||||
button_10 = 130,
|
|
||||||
button_11 = 131,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const Kind = enum(u2) {
|
|
||||||
press,
|
|
||||||
release,
|
|
||||||
motion,
|
|
||||||
drag,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
pub const code_point = @import("code_point");
|
const code_point = @import("code_point");
|
||||||
const ctlseqs = @import("ctlseqs.zig");
|
const ctlseqs = @import("ctlseqs.zig");
|
||||||
|
const input = @import("input.zig");
|
||||||
|
|
||||||
const Key = @import("key.zig").Key;
|
const Key = input.Key;
|
||||||
const Position = @import("size.zig").Position;
|
const Position = @import("size.zig").Position;
|
||||||
const Size = @import("size.zig").Size;
|
const Size = @import("size.zig").Size;
|
||||||
const Cell = @import("cell.zig");
|
const Cell = @import("cell.zig");
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ const color = @import("color.zig");
|
|||||||
const size = @import("size.zig");
|
const size = @import("size.zig");
|
||||||
|
|
||||||
// public exports
|
// public exports
|
||||||
pub const key = @import("key.zig");
|
pub const input = @import("input.zig");
|
||||||
|
|
||||||
pub const App = @import("app.zig").App;
|
pub const App = @import("app.zig").App;
|
||||||
// App also exports further types once initialized with the user events at compile time:
|
// App also exports further types once initialized with the user events at compile time:
|
||||||
@@ -20,7 +20,8 @@ pub const Layout = container.Layout;
|
|||||||
|
|
||||||
pub const Cell = @import("cell.zig");
|
pub const Cell = @import("cell.zig");
|
||||||
pub const Color = color.Color;
|
pub const Color = color.Color;
|
||||||
pub const Key = key.Key;
|
pub const Key = input.Key;
|
||||||
|
pub const Mouse = input.Mouse;
|
||||||
pub const Position = size.Position;
|
pub const Position = size.Position;
|
||||||
pub const Size = size.Size;
|
pub const Size = size.Size;
|
||||||
pub const Style = @import("style.zig");
|
pub const Style = @import("style.zig");
|
||||||
|
|||||||
Reference in New Issue
Block a user