refactor: move input types to new module and use directly use libvaxis types

This commit is contained in:
CJ van den Berg 2024-11-15 21:01:50 +01:00
parent e08c2aa3ba
commit 18f321bf41
Signed by: neurocyte
GPG key ID: 8EB1E1BB660E3FB9
36 changed files with 1224 additions and 1363 deletions

View file

@ -0,0 +1,10 @@
const std = @import("std");
const input = @import("input");
key: input.Key = 0,
event: input.Event = input.event.press,
modifiers: input.Mods = 0,
pub fn eql(self: @This(), other: @This()) bool {
return std.meta.eql(self, other);
}

View file

@ -8,14 +8,12 @@ const cbor = @import("cbor");
const builtin = @import("builtin");
const log = @import("log");
const renderer = @import("renderer");
const key = @import("renderer").input.key;
const mod = @import("renderer").input.modifier;
const event_type = @import("renderer").input.event_type;
const ucs32_to_utf8 = @import("renderer").ucs32_to_utf8;
const input = @import("input");
const command = @import("command");
const EventHandler = @import("EventHandler");
const KeyEvent = @import("KeyEvent.zig");
pub const mode = struct {
pub const input = struct {
pub const flow = Handler("flow", "normal");
@ -73,7 +71,7 @@ pub const Mode = struct {
name: []const u8 = "",
line_numbers: enum { absolute, relative } = .absolute,
keybind_hints: ?*const KeybindHints = null,
cursor_shape: renderer.CursorShape = .block,
cursor_shape: CursorShape = .block,
pub fn deinit(self: *Mode) void {
self.input_handler.deinit();
@ -83,17 +81,6 @@ pub const Mode = struct {
pub const KeybindHints = std.static_string_map.StaticStringMap([]const u8);
//A single key event, such as Ctrl-E
const KeyEvent = struct {
key: u32 = 0, //keypress value
event_type: usize = event_type.PRESS,
modifiers: u32 = 0,
fn eql(self: @This(), other: @This()) bool {
return std.meta.eql(self, other);
}
};
fn peek(str: []const u8, i: usize) !u8 {
if (i + 1 < str.len) {
return str[i + 1];
@ -121,7 +108,7 @@ pub fn parse_key_events(allocator: std.mem.Allocator, str: []const u8) ![]KeyEve
};
var state: State = .base;
var function_key_number: u8 = 0;
var modifiers: u32 = 0;
var modifiers: input.Mods = 0;
var result = std.ArrayList(KeyEvent).init(allocator);
defer result.deinit();
@ -213,7 +200,7 @@ pub fn parse_key_events(allocator: std.mem.Allocator, str: []const u8) ![]KeyEve
},
.cr => {
if (std.mem.indexOf(u8, str[i..], "CR") == 0) {
try result.append(.{ .key = key.ENTER, .modifiers = modifiers });
try result.append(.{ .key = input.key.enter, .modifiers = modifiers });
modifiers = 0;
state = .escape_sequence_end;
i += 2;
@ -221,7 +208,7 @@ pub fn parse_key_events(allocator: std.mem.Allocator, str: []const u8) ![]KeyEve
},
.space => {
if (std.mem.indexOf(u8, str[i..], "Space") == 0) {
try result.append(.{ .key = key.SPACE, .modifiers = modifiers });
try result.append(.{ .key = input.key.space, .modifiers = modifiers });
modifiers = 0;
state = .escape_sequence_end;
i += 5;
@ -232,7 +219,7 @@ pub fn parse_key_events(allocator: std.mem.Allocator, str: []const u8) ![]KeyEve
},
.del => {
if (std.mem.indexOf(u8, str[i..], "Del") == 0) {
try result.append(.{ .key = key.DEL, .modifiers = modifiers });
try result.append(.{ .key = input.key.delete, .modifiers = modifiers });
modifiers = 0;
state = .escape_sequence_end;
i += 3;
@ -240,7 +227,7 @@ pub fn parse_key_events(allocator: std.mem.Allocator, str: []const u8) ![]KeyEve
},
.tab => {
if (std.mem.indexOf(u8, str[i..], "Tab") == 0) {
try result.append(.{ .key = key.TAB, .modifiers = modifiers });
try result.append(.{ .key = input.key.tab, .modifiers = modifiers });
modifiers = 0;
state = .escape_sequence_end;
i += 3;
@ -248,7 +235,7 @@ pub fn parse_key_events(allocator: std.mem.Allocator, str: []const u8) ![]KeyEve
},
.up => {
if (std.mem.indexOf(u8, str[i..], "Up") == 0) {
try result.append(.{ .key = key.UP, .modifiers = modifiers });
try result.append(.{ .key = input.key.up, .modifiers = modifiers });
modifiers = 0;
state = .escape_sequence_end;
i += 2;
@ -256,7 +243,7 @@ pub fn parse_key_events(allocator: std.mem.Allocator, str: []const u8) ![]KeyEve
},
.esc => {
if (std.mem.indexOf(u8, str[i..], "Esc") == 0) {
try result.append(.{ .key = key.ESC, .modifiers = modifiers });
try result.append(.{ .key = input.key.escape, .modifiers = modifiers });
modifiers = 0;
state = .escape_sequence_end;
i += 3;
@ -264,7 +251,7 @@ pub fn parse_key_events(allocator: std.mem.Allocator, str: []const u8) ![]KeyEve
},
.down => {
if (std.mem.indexOf(u8, str[i..], "Down") == 0) {
try result.append(.{ .key = key.DOWN, .modifiers = modifiers });
try result.append(.{ .key = input.key.down, .modifiers = modifiers });
modifiers = 0;
state = .escape_sequence_end;
i += 4;
@ -272,7 +259,7 @@ pub fn parse_key_events(allocator: std.mem.Allocator, str: []const u8) ![]KeyEve
},
.left => {
if (std.mem.indexOf(u8, str[i..], "Left") == 0) {
try result.append(.{ .key = key.LEFT, .modifiers = modifiers });
try result.append(.{ .key = input.key.left, .modifiers = modifiers });
modifiers = 0;
state = .escape_sequence_end;
i += 4;
@ -280,7 +267,7 @@ pub fn parse_key_events(allocator: std.mem.Allocator, str: []const u8) ![]KeyEve
},
.right => {
if (std.mem.indexOf(u8, str[i..], "Right") == 0) {
try result.append(.{ .key = key.RIGHT, .modifiers = modifiers });
try result.append(.{ .key = input.key.right, .modifiers = modifiers });
modifiers = 0;
state = .escape_sequence_end;
i += 5;
@ -298,7 +285,7 @@ pub fn parse_key_events(allocator: std.mem.Allocator, str: []const u8) ![]KeyEve
i += 1;
},
'>' => {
const function_key = key.F01 - 1 + function_key_number;
const function_key = input.key.f1 - 1 + function_key_number;
try result.append(.{ .key = function_key, .modifiers = modifiers });
modifiers = 0;
function_key_number = 0;
@ -334,10 +321,10 @@ pub fn parse_key_events(allocator: std.mem.Allocator, str: []const u8) ![]KeyEve
},
.modifier => {
modifiers |= switch (str[i]) {
'A' => mod.ALT,
'C' => mod.CTRL,
'D' => mod.SUPER,
'S' => mod.SHIFT,
'A' => input.mod.alt,
'C' => input.mod.ctrl,
'D' => input.mod.super,
'S' => input.mod.shift,
else => return error.parseModifier,
};
@ -552,22 +539,22 @@ const BindingSet = struct {
}
fn receive(self: *@This(), _: tp.pid_ref, m: tp.message) error{Exit}!bool {
var evtype: u32 = 0;
var keypress: u32 = 0;
var egc: u32 = 0;
var modifiers: u32 = 0;
var event: input.Event = 0;
var keypress: input.Key = 0;
var egc: input.Key = 0;
var modifiers: input.Mods = 0;
var text: []const u8 = "";
if (try m.match(.{
"I",
tp.extract(&evtype),
tp.extract(&event),
tp.extract(&keypress),
tp.extract(&egc),
tp.string,
tp.extract(&modifiers),
})) {
self.process_key_event(egc, .{
.event_type = evtype,
.event = event,
.key = keypress,
.modifiers = modifiers,
}) catch |e| return tp.exit_error(e, @errorReturnTrace());
@ -582,10 +569,10 @@ const BindingSet = struct {
}
//register a key press and try to match it with a binding
fn process_key_event(self: *BindingSet, egc: u32, event: KeyEvent) !void {
fn process_key_event(self: *BindingSet, egc: input.Key, event: KeyEvent) !void {
//hacky fix since we are ignoring repeats and keyups right now
if (event.event_type != event_type.PRESS) return;
if (event.event != input.event.press) return;
//clear key history if enough time has passed since last key press
const timestamp = std.time.milliTimestamp();
@ -596,7 +583,7 @@ const BindingSet = struct {
try self.current_sequence.append(event);
var buf: [6]u8 = undefined;
const bytes = try ucs32_to_utf8(&[_]u32{egc}, &buf);
const bytes = try input.ucs32_to_utf8(&[_]u32{egc}, &buf);
try self.current_sequence_egc.appendSlice(buf[0..bytes]);
var all_matches_impossible = true;
@ -641,7 +628,7 @@ const BindingSet = struct {
}
const AbortType = enum { timeout, match_impossible };
fn terminate_sequence(self: *@This(), abort_type: AbortType, egc: u32, key_event: KeyEvent) anyerror!void {
fn terminate_sequence(self: *@This(), abort_type: AbortType, egc: input.Key, key_event: KeyEvent) anyerror!void {
_ = egc;
_ = key_event;
if (abort_type == .match_impossible) {
@ -692,16 +679,26 @@ const Namespace = struct {
}
};
pub const CursorShape = enum {
default,
block_blink,
block,
underline_blink,
underline,
beam_blink,
beam,
};
const expectEqual = std.testing.expectEqual;
const parse_test_cases = .{
//input, expected
.{ "j", &.{KeyEvent{ .key = 'j' }} },
.{ "jk", &.{ KeyEvent{ .key = 'j' }, KeyEvent{ .key = 'k' } } },
.{ "<Space>", &.{KeyEvent{ .key = key.SPACE }} },
.{ "<C-x><C-c>", &.{ KeyEvent{ .key = 'x', .modifiers = mod.CTRL }, KeyEvent{ .key = 'c', .modifiers = mod.CTRL } } },
.{ "<A-x><Tab>", &.{ KeyEvent{ .key = 'x', .modifiers = mod.ALT }, KeyEvent{ .key = key.TAB } } },
.{ "<S-A-x><D-Del>", &.{ KeyEvent{ .key = 'x', .modifiers = mod.ALT | mod.SHIFT }, KeyEvent{ .key = key.DEL, .modifiers = mod.SUPER } } },
.{ "<Space>", &.{KeyEvent{ .key = input.key.space }} },
.{ "<C-x><C-c>", &.{ KeyEvent{ .key = 'x', .modifiers = input.mod.ctrl }, KeyEvent{ .key = 'c', .modifiers = input.mod.ctrl } } },
.{ "<A-x><Tab>", &.{ KeyEvent{ .key = 'x', .modifiers = input.mod.alt }, KeyEvent{ .key = input.key.tab } } },
.{ "<S-A-x><D-Del>", &.{ KeyEvent{ .key = 'x', .modifiers = input.mod.alt | input.mod.shift }, KeyEvent{ .key = input.key.delete, .modifiers = input.mod.super } } },
};
test "parse" {
@ -733,8 +730,8 @@ const match_test_cases = .{
test "match" {
const alloc = std.testing.allocator;
inline for (match_test_cases) |case| {
const input = try parse_key_events(alloc, case[0]);
defer alloc.free(input);
const events = try parse_key_events(alloc, case[0]);
defer alloc.free(events);
const binding: Binding = .{
.keys = try parse_key_events(alloc, case[1]),
.command = undefined,
@ -742,7 +739,7 @@ test "match" {
};
defer alloc.free(binding.keys);
try expectEqual(case[2], binding.match(input));
try expectEqual(case[2], binding.match(events));
}
}
@ -754,5 +751,5 @@ test "json" {
try bindings.process_key_event('k', .{ .key = 'k' });
try bindings.process_key_event('g', .{ .key = 'g' });
try bindings.process_key_event('i', .{ .key = 'i' });
try bindings.process_key_event(0, .{ .key = 'i', .modifiers = mod.CTRL });
try bindings.process_key_event(0, .{ .key = 'i', .modifiers = input.mod.ctrl });
}

View file

@ -1,9 +1,6 @@
const std = @import("std");
const tp = @import("thespian");
const key = @import("renderer").input.key;
const mod = @import("renderer").input.modifier;
const event_type = @import("renderer").input.event_type;
const ucs32_to_utf8 = @import("renderer").ucs32_to_utf8;
const input = @import("input");
const command = @import("command");
const EventHandler = @import("EventHandler");
const keybind = @import("../keybind.zig");
@ -14,7 +11,7 @@ const input_buffer_size = 1024;
allocator: std.mem.Allocator,
input: std.ArrayList(u8),
last_cmd: []const u8 = "",
leader: ?struct { keypress: u32, modifiers: u32 } = null,
leader: ?struct { keypress: input.Key, modifiers: input.Mods } = null,
pub fn create(allocator: std.mem.Allocator, _: anytype) !EventHandler {
const self: *Self = try allocator.create(Self);
@ -31,14 +28,14 @@ pub fn deinit(self: *Self) void {
}
pub fn receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
var evtype: u32 = undefined;
var keypress: u32 = undefined;
var egc: u32 = undefined;
var modifiers: u32 = undefined;
var event: input.Event = undefined;
var keypress: input.Key = undefined;
var egc: input.Key = undefined;
var modifiers: input.Mods = undefined;
var text: []const u8 = undefined;
if (try m.match(.{ "I", tp.extract(&evtype), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) {
self.mapEvent(evtype, keypress, egc, modifiers) catch |e| return tp.exit_error(e, @errorReturnTrace());
if (try m.match(.{ "I", tp.extract(&event), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) {
self.map_event(event, keypress, egc, modifiers) catch |e| return tp.exit_error(e, @errorReturnTrace());
} else if (try m.match(.{"F"})) {
self.flush_input() catch |e| return tp.exit_error(e, @errorReturnTrace());
} else if (try m.match(.{ "system_clipboard", tp.extract(&text) })) {
@ -49,25 +46,25 @@ pub fn receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
pub fn add_keybind() void {}
fn mapEvent(self: *Self, evtype: u32, keypress: u32, egc: u32, modifiers: u32) !void {
return switch (evtype) {
event_type.PRESS => self.mapPress(keypress, egc, modifiers),
event_type.REPEAT => self.mapPress(keypress, egc, modifiers),
event_type.RELEASE => self.mapRelease(keypress, egc, modifiers),
fn map_event(self: *Self, event: input.Event, keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void {
return switch (event) {
input.event.press => self.map_press(keypress, egc, modifiers),
input.event.repeat => self.map_press(keypress, egc, modifiers),
input.event.release => self.map_release(keypress, egc, modifiers),
else => {},
};
}
fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
fn map_press(self: *Self, keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void {
const keynormal = if ('a' <= keypress and keypress <= 'z') keypress - ('a' - 'A') else keypress;
if (self.leader) |_| return self.mapFollower(keynormal, egc, modifiers);
if (self.leader) |_| return self.map_follower(keynormal, modifiers);
switch (keypress) {
key.LCTRL, key.RCTRL => return self.cmd("enable_fast_scroll", .{}),
key.LALT, key.RALT => return self.cmd("enable_jump_mode", .{}),
input.key.left_control, input.key.right_control => return self.cmd("enable_fast_scroll", .{}),
input.key.left_alt, input.key.right_alt => return self.cmd("enable_jump_mode", .{}),
else => {},
}
return switch (modifiers) {
mod.CTRL => switch (keynormal) {
input.mod.ctrl => switch (keynormal) {
'E' => self.cmd("open_recent", .{}),
'R' => self.cmd("open_recent_project", .{}),
'J' => self.cmd("toggle_panel", .{}),
@ -93,24 +90,24 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
'A' => self.cmd("select_all", .{}),
'I' => self.insert_bytes("\t"),
'/' => self.cmd("toggle_comment", .{}),
key.ENTER => self.cmd("smart_insert_line_after", .{}),
key.SPACE => self.cmd("completion", .{}),
key.END => self.cmd("move_buffer_end", .{}),
key.HOME => self.cmd("move_buffer_begin", .{}),
key.UP => self.cmd("move_scroll_up", .{}),
key.DOWN => self.cmd("move_scroll_down", .{}),
key.PGUP => self.cmd("move_scroll_page_up", .{}),
key.PGDOWN => self.cmd("move_scroll_page_down", .{}),
key.LEFT => self.cmd("move_word_left", .{}),
key.RIGHT => self.cmd("move_word_right", .{}),
key.BACKSPACE => self.cmd("delete_word_left", .{}),
key.DEL => self.cmd("delete_word_right", .{}),
key.F05 => self.cmd("toggle_inspector_view", .{}),
key.F10 => self.cmd("toggle_whitespace_mode", .{}), // aka F34
key.F12 => self.cmd("goto_implementation", .{}),
input.key.enter => self.cmd("smart_insert_line_after", .{}),
input.key.space => self.cmd("completion", .{}),
input.key.end => self.cmd("move_buffer_end", .{}),
input.key.home => self.cmd("move_buffer_begin", .{}),
input.key.up => self.cmd("move_scroll_up", .{}),
input.key.down => self.cmd("move_scroll_down", .{}),
input.key.page_up => self.cmd("move_scroll_page_up", .{}),
input.key.page_down => self.cmd("move_scroll_page_down", .{}),
input.key.left => self.cmd("move_word_left", .{}),
input.key.right => self.cmd("move_word_right", .{}),
input.key.backspace => self.cmd("delete_word_left", .{}),
input.key.delete => self.cmd("delete_word_right", .{}),
input.key.f5 => self.cmd("toggle_inspector_view", .{}),
input.key.f10 => self.cmd("toggle_whitespace_mode", .{}), // aka F34
input.key.f12 => self.cmd("goto_implementation", .{}),
else => {},
},
mod.CTRL | mod.SHIFT => switch (keynormal) {
input.mod.ctrl | input.mod.shift => switch (keynormal) {
'S' => self.cmd("save_as", .{}),
'P' => self.cmd("open_command_palette", .{}),
'D' => self.cmd("dupe_down", .{}),
@ -121,17 +118,17 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
'L' => self.cmd_async("add_cursor_all_matches"),
'I' => self.cmd_async("toggle_inspector_view"),
'M' => self.cmd("show_diagnostics", .{}),
key.ENTER => self.cmd("smart_insert_line_before", .{}),
key.END => self.cmd("select_buffer_end", .{}),
key.HOME => self.cmd("select_buffer_begin", .{}),
key.UP => self.cmd("select_scroll_up", .{}),
key.DOWN => self.cmd("select_scroll_down", .{}),
key.LEFT => self.cmd("select_word_left", .{}),
key.RIGHT => self.cmd("select_word_right", .{}),
key.SPACE => self.cmd("selections_reverse", .{}),
input.key.enter => self.cmd("smart_insert_line_before", .{}),
input.key.end => self.cmd("select_buffer_end", .{}),
input.key.home => self.cmd("select_buffer_begin", .{}),
input.key.up => self.cmd("select_scroll_up", .{}),
input.key.down => self.cmd("select_scroll_down", .{}),
input.key.left => self.cmd("select_word_left", .{}),
input.key.right => self.cmd("select_word_right", .{}),
input.key.space => self.cmd("selections_reverse", .{}),
else => {},
},
mod.ALT => switch (keynormal) {
input.mod.alt => switch (keynormal) {
'O' => self.cmd("open_previous_file", .{}),
'J' => self.cmd("join_next_line", .{}),
'N' => self.cmd("goto_next_file_or_diagnostic", .{}),
@ -145,16 +142,16 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
'S' => self.cmd("filter", command.fmt(.{"sort"})),
'V' => self.cmd("paste", .{}),
'X' => self.cmd("open_command_palette", .{}),
key.LEFT => self.cmd("jump_back", .{}),
key.RIGHT => self.cmd("jump_forward", .{}),
key.UP => self.cmd("pull_up", .{}),
key.DOWN => self.cmd("pull_down", .{}),
key.ENTER => self.cmd("insert_line", .{}),
key.F10 => self.cmd("gutter_mode_next", .{}), // aka F58
key.F12 => self.cmd("goto_declaration", .{}),
input.key.left => self.cmd("jump_back", .{}),
input.key.right => self.cmd("jump_forward", .{}),
input.key.up => self.cmd("pull_up", .{}),
input.key.down => self.cmd("pull_down", .{}),
input.key.enter => self.cmd("insert_line", .{}),
input.key.f10 => self.cmd("gutter_mode_next", .{}), // aka F58
input.key.f12 => self.cmd("goto_declaration", .{}),
else => {},
},
mod.ALT | mod.SHIFT => switch (keynormal) {
input.mod.alt | input.mod.shift => switch (keynormal) {
'P' => self.cmd("open_command_palette", .{}),
'D' => self.cmd("dupe_up", .{}),
// 'B' => self.cmd("select_word_left", .{}),
@ -163,61 +160,60 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
'S' => self.cmd("filter", command.fmt(.{ "sort", "-u" })),
'V' => self.cmd("paste", .{}),
'I' => self.cmd("add_cursors_to_line_ends", .{}),
key.LEFT => self.cmd("shrink_selection", .{}),
key.RIGHT => self.cmd("expand_selection", .{}),
key.HOME => self.cmd("move_scroll_left", .{}),
key.END => self.cmd("move_scroll_right", .{}),
key.UP => self.cmd("add_cursor_up", .{}),
key.DOWN => self.cmd("add_cursor_down", .{}),
key.F12 => self.cmd("goto_type_definition", .{}),
input.key.left => self.cmd("shrink_selection", .{}),
input.key.right => self.cmd("expand_selection", .{}),
input.key.home => self.cmd("move_scroll_left", .{}),
input.key.end => self.cmd("move_scroll_right", .{}),
input.key.up => self.cmd("add_cursor_up", .{}),
input.key.down => self.cmd("add_cursor_down", .{}),
input.key.f12 => self.cmd("goto_type_definition", .{}),
else => {},
},
mod.SHIFT => switch (keypress) {
key.F03 => self.cmd("goto_prev_match", .{}),
key.F10 => self.cmd("toggle_syntax_highlighting", .{}),
key.F12 => self.cmd("references", .{}),
key.LEFT => self.cmd("select_left", .{}),
key.RIGHT => self.cmd("select_right", .{}),
key.UP => self.cmd("select_up", .{}),
key.DOWN => self.cmd("select_down", .{}),
key.HOME => self.cmd("smart_select_begin", .{}),
key.END => self.cmd("select_end", .{}),
key.PGUP => self.cmd("select_page_up", .{}),
key.PGDOWN => self.cmd("select_page_down", .{}),
key.ENTER => self.cmd("smart_insert_line_before", .{}),
key.BACKSPACE => self.cmd("delete_backward", .{}),
key.TAB => self.cmd("unindent", .{}),
else => if (!key.synthesized_p(keypress))
input.mod.shift => switch (keypress) {
input.key.f3 => self.cmd("goto_prev_match", .{}),
input.key.f10 => self.cmd("toggle_syntax_highlighting", .{}),
input.key.f12 => self.cmd("references", .{}),
input.key.left => self.cmd("select_left", .{}),
input.key.right => self.cmd("select_right", .{}),
input.key.up => self.cmd("select_up", .{}),
input.key.down => self.cmd("select_down", .{}),
input.key.home => self.cmd("smart_select_begin", .{}),
input.key.end => self.cmd("select_end", .{}),
input.key.page_up => self.cmd("select_page_up", .{}),
input.key.page_down => self.cmd("select_page_down", .{}),
input.key.enter => self.cmd("smart_insert_line_before", .{}),
input.key.backspace => self.cmd("delete_backward", .{}),
input.key.tab => self.cmd("unindent", .{}),
else => if (!input.is_non_input_key(keypress))
self.insert_code_point(egc)
else {},
},
0 => switch (keypress) {
key.F02 => self.cmd("toggle_input_mode", .{}),
key.F03 => self.cmd("goto_next_match", .{}),
key.F15 => self.cmd("goto_prev_match", .{}), // S-F3
key.F05 => self.cmd("toggle_inspector_view", .{}), // C-F5
key.F06 => self.cmd("dump_current_line_tree", .{}),
key.F07 => self.cmd("dump_current_line", .{}),
key.F09 => self.cmd("theme_prev", .{}),
key.F10 => self.cmd("theme_next", .{}),
key.F11 => self.cmd("toggle_panel", .{}),
key.F12 => self.cmd("goto_definition", .{}),
key.F34 => self.cmd("toggle_whitespace_mode", .{}), // C-F10
key.F58 => self.cmd("gutter_mode_next", .{}), // A-F10
key.ESC => self.cmd("cancel", .{}),
key.ENTER => self.cmd("smart_insert_line", .{}),
key.DEL => self.cmd("delete_forward", .{}),
key.BACKSPACE => self.cmd("delete_backward", .{}),
key.LEFT => self.cmd("move_left", .{}),
key.RIGHT => self.cmd("move_right", .{}),
key.UP => self.cmd("move_up", .{}),
key.DOWN => self.cmd("move_down", .{}),
key.HOME => self.cmd("smart_move_begin", .{}),
key.END => self.cmd("move_end", .{}),
key.PGUP => self.cmd("move_page_up", .{}),
key.PGDOWN => self.cmd("move_page_down", .{}),
key.TAB => self.cmd("indent", .{}),
else => if (!key.synthesized_p(keypress))
input.key.f2 => self.cmd("toggle_input_mode", .{}),
input.key.f3 => self.cmd("goto_next_match", .{}),
input.key.f15 => self.cmd("goto_prev_match", .{}), // S-F3
input.key.f5 => self.cmd("toggle_inspector_view", .{}), // C-F5
input.key.f6 => self.cmd("dump_current_line_tree", .{}),
input.key.f7 => self.cmd("dump_current_line", .{}),
input.key.f9 => self.cmd("theme_prev", .{}),
input.key.f10 => self.cmd("theme_next", .{}),
input.key.f11 => self.cmd("toggle_panel", .{}),
input.key.f12 => self.cmd("goto_definition", .{}),
input.key.f34 => self.cmd("toggle_whitespace_mode", .{}), // C-F10
input.key.escape => self.cmd("cancel", .{}),
input.key.enter => self.cmd("smart_insert_line", .{}),
input.key.delete => self.cmd("delete_forward", .{}),
input.key.backspace => self.cmd("delete_backward", .{}),
input.key.left => self.cmd("move_left", .{}),
input.key.right => self.cmd("move_right", .{}),
input.key.up => self.cmd("move_up", .{}),
input.key.down => self.cmd("move_down", .{}),
input.key.home => self.cmd("smart_move_begin", .{}),
input.key.end => self.cmd("move_end", .{}),
input.key.page_up => self.cmd("move_page_up", .{}),
input.key.page_down => self.cmd("move_page_down", .{}),
input.key.tab => self.cmd("indent", .{}),
else => if (!input.is_non_input_key(keypress))
self.insert_code_point(egc)
else {},
},
@ -225,13 +221,13 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
};
}
fn mapFollower(self: *Self, keypress: u32, _: u32, modifiers: u32) !void {
fn map_follower(self: *Self, keypress: input.Key, modifiers: input.Mods) !void {
defer self.leader = null;
const ldr = if (self.leader) |leader| leader else return;
return switch (ldr.modifiers) {
mod.CTRL => switch (ldr.keypress) {
input.mod.ctrl => switch (ldr.keypress) {
'K' => switch (modifiers) {
mod.CTRL => switch (keypress) {
input.mod.ctrl => switch (keypress) {
'U' => self.cmd("delete_to_begin", .{}),
'K' => self.cmd("delete_to_end", .{}),
'D' => self.cmd("move_cursor_next_match", .{}),
@ -247,10 +243,10 @@ fn mapFollower(self: *Self, keypress: u32, _: u32, modifiers: u32) !void {
};
}
fn mapRelease(self: *Self, keypress: u32, _: u32, _: u32) !void {
fn map_release(self: *Self, keypress: input.Key, _: u32, _: u32) !void {
return switch (keypress) {
key.LCTRL, key.RCTRL => self.cmd("disable_fast_scroll", .{}),
key.LALT, key.RALT => self.cmd("disable_jump_mode", .{}),
input.key.left_control, input.key.right_control => self.cmd("disable_fast_scroll", .{}),
input.key.left_alt, input.key.right_alt => self.cmd("disable_jump_mode", .{}),
else => {},
};
}
@ -259,7 +255,7 @@ fn insert_code_point(self: *Self, c: u32) !void {
if (self.input.items.len + 4 > input_buffer_size)
try self.flush_input();
var buf: [6]u8 = undefined;
const bytes = try ucs32_to_utf8(&[_]u32{c}, &buf);
const bytes = try input.ucs32_to_utf8(&[_]u32{c}, &buf);
try self.input.appendSlice(buf[0..bytes]);
}

View file

@ -1,9 +1,6 @@
const std = @import("std");
const tp = @import("thespian");
const key = @import("renderer").input.key;
const mod = @import("renderer").input.modifier;
const event_type = @import("renderer").input.event_type;
const ucs32_to_utf8 = @import("renderer").ucs32_to_utf8;
const input = @import("input");
const command = @import("command");
const EventHandler = @import("EventHandler");
const keybind = @import("../../keybind.zig");
@ -14,7 +11,7 @@ const input_buffer_size = 1024;
allocator: std.mem.Allocator,
input: std.ArrayList(u8),
last_cmd: []const u8 = "",
leader: ?struct { keypress: u32, modifiers: u32 } = null,
leader: ?struct { keypress: input.Key, modifiers: input.Mods } = null,
commands: Commands = undefined,
pub fn create(allocator: std.mem.Allocator, _: anytype) !EventHandler {
@ -34,14 +31,14 @@ pub fn deinit(self: *Self) void {
}
pub fn receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
var evtype: u32 = undefined;
var keypress: u32 = undefined;
var egc: u32 = undefined;
var modifiers: u32 = undefined;
var event: input.Event = undefined;
var keypress: input.Key = undefined;
var egc: input.Key = undefined;
var modifiers: input.Mods = undefined;
var text: []const u8 = undefined;
if (try m.match(.{ "I", tp.extract(&evtype), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) {
self.mapEvent(evtype, keypress, egc, modifiers) catch |e| return tp.exit_error(e, @errorReturnTrace());
if (try m.match(.{ "I", tp.extract(&event), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) {
self.mapEvent(event, keypress, egc, modifiers) catch |e| return tp.exit_error(e, @errorReturnTrace());
} else if (try m.match(.{"F"})) {
self.flush_input() catch |e| return tp.exit_error(e, @errorReturnTrace());
} else if (try m.match(.{ "system_clipboard", tp.extract(&text) })) {
@ -54,25 +51,25 @@ pub fn receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
pub fn add_keybind() void {}
fn mapEvent(self: *Self, evtype: u32, keypress: u32, egc: u32, modifiers: u32) !void {
return switch (evtype) {
event_type.PRESS => self.mapPress(keypress, egc, modifiers),
event_type.REPEAT => self.mapPress(keypress, egc, modifiers),
event_type.RELEASE => self.mapRelease(keypress, egc, modifiers),
fn mapEvent(self: *Self, event: input.Event, keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void {
return switch (event) {
input.event.press => self.map_press(keypress, egc, modifiers),
input.event.repeat => self.map_press(keypress, egc, modifiers),
input.event.release => self.map_release(keypress),
else => {},
};
}
fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
fn map_press(self: *Self, keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void {
const keynormal = if ('a' <= keypress and keypress <= 'z') keypress - ('a' - 'A') else keypress;
if (self.leader) |_| return self.mapFollower(keynormal, egc, modifiers);
if (self.leader) |_| return self.map_follower(keynormal, modifiers);
switch (keypress) {
key.LCTRL, key.RCTRL => return self.cmd("enable_fast_scroll", .{}),
key.LALT, key.RALT => return self.cmd("enable_jump_mode", .{}),
input.key.left_control, input.key.right_control => return self.cmd("enable_fast_scroll", .{}),
input.key.left_alt, input.key.right_alt => return self.cmd("enable_jump_mode", .{}),
else => {},
}
return switch (modifiers) {
mod.CTRL => switch (keynormal) {
input.mod.ctrl => switch (keynormal) {
'E' => self.cmd("open_recent", .{}),
'U' => self.cmd("move_scroll_page_up", .{}),
'D' => self.cmd("move_scroll_page_down", .{}),
@ -97,23 +94,23 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
'A' => self.cmd("select_all", .{}),
'I' => self.insert_bytes("\t"),
'/' => self.cmd("toggle_comment", .{}),
key.ENTER => self.cmd("smart_insert_line_after", .{}),
key.SPACE => self.cmd("selections_reverse", .{}),
key.END => self.cmd("move_buffer_end", .{}),
key.HOME => self.cmd("move_buffer_begin", .{}),
key.UP => self.cmd("move_scroll_up", .{}),
key.DOWN => self.cmd("move_scroll_down", .{}),
key.PGUP => self.cmd("move_scroll_page_up", .{}),
key.PGDOWN => self.cmd("move_scroll_page_down", .{}),
key.LEFT => self.cmd("move_word_left", .{}),
key.RIGHT => self.cmd("move_word_right", .{}),
key.BACKSPACE => self.cmd("delete_word_left", .{}),
key.DEL => self.cmd("delete_word_right", .{}),
key.F05 => self.cmd("toggle_inspector_view", .{}),
key.F10 => self.cmd("toggle_whitespace_mode", .{}), // aka F34
input.key.enter => self.cmd("smart_insert_line_after", .{}),
input.key.space => self.cmd("selections_reverse", .{}),
input.key.end => self.cmd("move_buffer_end", .{}),
input.key.home => self.cmd("move_buffer_begin", .{}),
input.key.up => self.cmd("move_scroll_up", .{}),
input.key.down => self.cmd("move_scroll_down", .{}),
input.key.page_up => self.cmd("move_scroll_page_up", .{}),
input.key.page_down => self.cmd("move_scroll_page_down", .{}),
input.key.left => self.cmd("move_word_left", .{}),
input.key.right => self.cmd("move_word_right", .{}),
input.key.backspace => self.cmd("delete_word_left", .{}),
input.key.delete => self.cmd("delete_word_right", .{}),
input.key.f5 => self.cmd("toggle_inspector_view", .{}),
input.key.f10 => self.cmd("toggle_whitespace_mode", .{}), // aka F34
else => {},
},
mod.CTRL | mod.SHIFT => switch (keynormal) {
input.mod.ctrl | input.mod.shift => switch (keynormal) {
'P' => self.cmd("open_command_palette", .{}),
'D' => self.cmd("dupe_down", .{}),
'Z' => self.cmd("redo", .{}),
@ -122,16 +119,16 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
'F' => self.cmd("find_in_files", .{}),
'L' => self.cmd_async("add_cursor_all_matches"),
'I' => self.cmd_async("toggle_inspector_view"),
key.ENTER => self.cmd("smart_insert_line_before", .{}),
key.END => self.cmd("select_buffer_end", .{}),
key.HOME => self.cmd("select_buffer_begin", .{}),
key.UP => self.cmd("select_scroll_up", .{}),
key.DOWN => self.cmd("select_scroll_down", .{}),
key.LEFT => self.cmd("select_word_left", .{}),
key.RIGHT => self.cmd("select_word_right", .{}),
input.key.enter => self.cmd("smart_insert_line_before", .{}),
input.key.end => self.cmd("select_buffer_end", .{}),
input.key.home => self.cmd("select_buffer_begin", .{}),
input.key.up => self.cmd("select_scroll_up", .{}),
input.key.down => self.cmd("select_scroll_down", .{}),
input.key.left => self.cmd("select_word_left", .{}),
input.key.right => self.cmd("select_word_right", .{}),
else => {},
},
mod.ALT => switch (keynormal) {
input.mod.alt => switch (keynormal) {
'J' => self.cmd("join_next_line", .{}),
'N' => self.cmd("goto_next_match", .{}),
'P' => self.cmd("goto_prev_match", .{}),
@ -142,71 +139,70 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
'F' => self.cmd("move_word_right", .{}),
'S' => self.cmd("filter", command.fmt(.{"sort"})),
'V' => self.cmd("paste", .{}),
key.LEFT => self.cmd("jump_back", .{}),
key.RIGHT => self.cmd("jump_forward", .{}),
key.UP => self.cmd("pull_up", .{}),
key.DOWN => self.cmd("pull_down", .{}),
key.ENTER => self.cmd("insert_line", .{}),
key.F10 => self.cmd("gutter_mode_next", .{}), // aka F58
input.key.left => self.cmd("jump_back", .{}),
input.key.right => self.cmd("jump_forward", .{}),
input.key.up => self.cmd("pull_up", .{}),
input.key.down => self.cmd("pull_down", .{}),
input.key.enter => self.cmd("insert_line", .{}),
input.key.f10 => self.cmd("gutter_mode_next", .{}), // aka F58
else => {},
},
mod.ALT | mod.SHIFT => switch (keynormal) {
input.mod.alt | input.mod.shift => switch (keynormal) {
'P' => self.cmd("open_command_palette", .{}),
'D' => self.cmd("dupe_up", .{}),
'F' => self.cmd("filter", command.fmt(.{ "zig", "fmt", "--stdin" })),
'S' => self.cmd("filter", command.fmt(.{ "sort", "-u" })),
'V' => self.cmd("paste", .{}),
'I' => self.cmd("add_cursors_to_line_ends", .{}),
key.LEFT => self.cmd("move_scroll_left", .{}),
key.RIGHT => self.cmd("move_scroll_right", .{}),
key.UP => self.cmd("add_cursor_up", .{}),
key.DOWN => self.cmd("add_cursor_down", .{}),
input.key.left => self.cmd("move_scroll_left", .{}),
input.key.right => self.cmd("move_scroll_right", .{}),
input.key.up => self.cmd("add_cursor_up", .{}),
input.key.down => self.cmd("add_cursor_down", .{}),
else => {},
},
mod.SHIFT => switch (keypress) {
key.F03 => self.cmd("goto_prev_match", .{}),
key.LEFT => self.cmd("select_left", .{}),
key.RIGHT => self.cmd("select_right", .{}),
key.UP => self.cmd("select_up", .{}),
key.DOWN => self.cmd("select_down", .{}),
key.HOME => self.cmd("smart_select_begin", .{}),
key.END => self.cmd("select_end", .{}),
key.PGUP => self.cmd("select_page_up", .{}),
key.PGDOWN => self.cmd("select_page_down", .{}),
key.ENTER => self.cmd("smart_insert_line_before", .{}),
key.BACKSPACE => self.cmd("delete_backward", .{}),
key.TAB => self.cmd("unindent", .{}),
else => if (!key.synthesized_p(keypress))
input.mod.shift => switch (keypress) {
input.key.f3 => self.cmd("goto_prev_match", .{}),
input.key.left => self.cmd("select_left", .{}),
input.key.right => self.cmd("select_right", .{}),
input.key.up => self.cmd("select_up", .{}),
input.key.down => self.cmd("select_down", .{}),
input.key.home => self.cmd("smart_select_begin", .{}),
input.key.end => self.cmd("select_end", .{}),
input.key.page_up => self.cmd("select_page_up", .{}),
input.key.page_down => self.cmd("select_page_down", .{}),
input.key.enter => self.cmd("smart_insert_line_before", .{}),
input.key.backspace => self.cmd("delete_backward", .{}),
input.key.tab => self.cmd("unindent", .{}),
else => if (!input.is_non_input_key(keypress))
self.insert_code_point(egc)
else {},
},
0 => switch (keypress) {
key.F02 => self.cmd("toggle_input_mode", .{}),
key.F03 => self.cmd("goto_next_match", .{}),
key.F15 => self.cmd("goto_prev_match", .{}), // S-F3
key.F05 => self.cmd("toggle_inspector_view", .{}), // C-F5
key.F06 => self.cmd("dump_current_line_tree", .{}),
key.F07 => self.cmd("dump_current_line", .{}),
key.F09 => self.cmd("theme_prev", .{}),
key.F10 => self.cmd("theme_next", .{}),
key.F11 => self.cmd("toggle_panel", .{}),
key.F12 => self.cmd("goto_definition", .{}),
key.F34 => self.cmd("toggle_whitespace_mode", .{}), // C-F10
key.F58 => self.cmd("gutter_mode_next", .{}), // A-F10
key.ESC => self.cmd("enter_mode", command.fmt(.{"helix/normal"})),
key.ENTER => self.cmd("smart_insert_line", .{}),
key.DEL => self.cmd("delete_forward", .{}),
key.BACKSPACE => self.cmd("delete_backward", .{}),
key.LEFT => self.cmd("move_left", .{}),
key.RIGHT => self.cmd("move_right", .{}),
key.UP => self.cmd("move_up", .{}),
key.DOWN => self.cmd("move_down", .{}),
key.HOME => self.cmd("smart_move_begin", .{}),
key.END => self.cmd("move_end", .{}),
key.PGUP => self.cmd("move_page_up", .{}),
key.PGDOWN => self.cmd("move_page_down", .{}),
key.TAB => self.cmd("indent", .{}),
else => if (!key.synthesized_p(keypress))
input.key.f2 => self.cmd("toggle_input_mode", .{}),
input.key.f3 => self.cmd("goto_next_match", .{}),
input.key.f15 => self.cmd("goto_prev_match", .{}), // S-F3
input.key.f5 => self.cmd("toggle_inspector_view", .{}), // C-F5
input.key.f6 => self.cmd("dump_current_line_tree", .{}),
input.key.f7 => self.cmd("dump_current_line", .{}),
input.key.f9 => self.cmd("theme_prev", .{}),
input.key.f10 => self.cmd("theme_next", .{}),
input.key.f11 => self.cmd("toggle_panel", .{}),
input.key.f12 => self.cmd("goto_definition", .{}),
input.key.f34 => self.cmd("toggle_whitespace_mode", .{}), // C-F10
input.key.escape => self.cmd("enter_mode", command.fmt(.{"helix/normal"})),
input.key.enter => self.cmd("smart_insert_line", .{}),
input.key.delete => self.cmd("delete_forward", .{}),
input.key.backspace => self.cmd("delete_backward", .{}),
input.key.left => self.cmd("move_left", .{}),
input.key.right => self.cmd("move_right", .{}),
input.key.up => self.cmd("move_up", .{}),
input.key.down => self.cmd("move_down", .{}),
input.key.home => self.cmd("smart_move_begin", .{}),
input.key.end => self.cmd("move_end", .{}),
input.key.page_up => self.cmd("move_page_up", .{}),
input.key.page_down => self.cmd("move_page_down", .{}),
input.key.tab => self.cmd("indent", .{}),
else => if (!input.is_non_input_key(keypress))
self.insert_code_point(egc)
else {},
},
@ -214,13 +210,13 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
};
}
fn mapFollower(self: *Self, keypress: u32, _: u32, modifiers: u32) !void {
fn map_follower(self: *Self, keypress: input.Key, modifiers: input.Mods) !void {
defer self.leader = null;
const ldr = if (self.leader) |leader| leader else return;
return switch (ldr.modifiers) {
mod.CTRL => switch (ldr.keypress) {
input.mod.ctrl => switch (ldr.keypress) {
'K' => switch (modifiers) {
mod.CTRL => switch (keypress) {
input.mod.ctrl => switch (keypress) {
'U' => self.cmd("delete_to_begin", .{}),
'K' => self.cmd("delete_to_end", .{}),
'D' => self.cmd("move_cursor_next_match", .{}),
@ -235,10 +231,10 @@ fn mapFollower(self: *Self, keypress: u32, _: u32, modifiers: u32) !void {
};
}
fn mapRelease(self: *Self, keypress: u32, _: u32, _: u32) !void {
fn map_release(self: *Self, keypress: input.Key) !void {
return switch (keypress) {
key.LCTRL, key.RCTRL => self.cmd("disable_fast_scroll", .{}),
key.LALT, key.RALT => self.cmd("disable_jump_mode", .{}),
input.key.left_control, input.key.right_control => self.cmd("disable_fast_scroll", .{}),
input.key.left_alt, input.key.right_alt => self.cmd("disable_jump_mode", .{}),
else => {},
};
}
@ -247,7 +243,7 @@ fn insert_code_point(self: *Self, c: u32) !void {
if (self.input.items.len + 4 > input_buffer_size)
try self.flush_input();
var buf: [6]u8 = undefined;
const bytes = try ucs32_to_utf8(&[_]u32{c}, &buf);
const bytes = try input.ucs32_to_utf8(&[_]u32{c}, &buf);
try self.input.appendSlice(buf[0..bytes]);
}

View file

@ -1,9 +1,6 @@
const std = @import("std");
const tp = @import("thespian");
const key = @import("renderer").input.key;
const mod = @import("renderer").input.modifier;
const event_type = @import("renderer").input.event_type;
const ucs32_to_utf8 = @import("renderer").ucs32_to_utf8;
const input = @import("input");
const command = @import("command");
const EventHandler = @import("EventHandler");
const keybind = @import("../../keybind.zig");
@ -14,7 +11,7 @@ const input_buffer_size = 1024;
allocator: std.mem.Allocator,
input: std.ArrayList(u8),
last_cmd: []const u8 = "",
leader: ?struct { keypress: u32, modifiers: u32 } = null,
leader: ?struct { keypress: input.Key, modifiers: input.Mods } = null,
count: usize = 0,
commands: Commands = undefined,
@ -35,14 +32,14 @@ pub fn deinit(self: *Self) void {
}
pub fn receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
var evtype: u32 = undefined;
var keypress: u32 = undefined;
var egc: u32 = undefined;
var modifiers: u32 = undefined;
var event: input.Event = undefined;
var keypress: input.Key = undefined;
var egc: input.Key = undefined;
var modifiers: input.Mods = undefined;
var text: []const u8 = undefined;
if (try m.match(.{ "I", tp.extract(&evtype), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) {
self.mapEvent(evtype, keypress, egc, modifiers) catch |e| return tp.exit_error(e, @errorReturnTrace());
if (try m.match(.{ "I", tp.extract(&event), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) {
self.map_event(event, keypress, egc, modifiers) catch |e| return tp.exit_error(e, @errorReturnTrace());
} else if (try m.match(.{"F"})) {
self.flush_input() catch |e| return tp.exit_error(e, @errorReturnTrace());
} else if (try m.match(.{ "system_clipboard", tp.extract(&text) })) {
@ -55,26 +52,26 @@ pub fn receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
pub fn add_keybind() void {}
fn mapEvent(self: *Self, evtype: u32, keypress: u32, egc: u32, modifiers: u32) !void {
return switch (evtype) {
event_type.PRESS => self.mapPress(keypress, egc, modifiers),
event_type.REPEAT => self.mapPress(keypress, egc, modifiers),
event_type.RELEASE => self.mapRelease(keypress, egc, modifiers),
fn map_event(self: *Self, event: input.Event, keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void {
return switch (event) {
input.event.press => self.map_press(keypress, egc, modifiers),
input.event.repeat => self.map_press(keypress, egc, modifiers),
input.event.release => self.map_release(keypress),
else => {},
};
}
fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
fn map_press(self: *Self, keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void {
if (self.count > 0 and modifiers == 0 and '0' <= keypress and keypress <= '9') return self.add_count(keypress - '0');
const keynormal = if ('a' <= keypress and keypress <= 'z') keypress - ('a' - 'A') else keypress;
if (self.leader) |_| return self.mapFollower(keynormal, egc, modifiers);
switch (keypress) {
key.LCTRL, key.RCTRL => return self.cmd("enable_fast_scroll", .{}),
key.LALT, key.RALT => return self.cmd("enable_jump_mode", .{}),
input.key.left_control, input.key.right_control => return self.cmd("enable_fast_scroll", .{}),
input.key.left_alt, input.key.right_alt => return self.cmd("enable_jump_mode", .{}),
else => {},
}
return switch (modifiers) {
mod.CTRL => switch (keynormal) {
input.mod.ctrl => switch (keynormal) {
'B' => self.cmd("move_scroll_page_up", .{}),
'F' => self.cmd("move_scroll_page_down", .{}),
'U' => self.cmd("page_cursor_half_up", .{}),
@ -91,12 +88,12 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
'X' => self.cmd("decrement", .{}),
else => {},
},
mod.CTRL | mod.SHIFT => switch (keynormal) {
input.mod.ctrl | input.mod.shift => switch (keynormal) {
'P' => self.cmd("open_command_palette", .{}),
'6' => self.cmd("open_previous_file", .{}),
else => {},
},
mod.ALT => switch (keynormal) {
input.mod.alt => switch (keynormal) {
'.' => self.cmd("repeat_last_motion", .{}),
'`' => self.cmd("switch_to_uppercase", .{}),
@ -112,10 +109,10 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
'_' => self.cmd("merge_consecutive_selections", .{}),
';' => self.cmd("flip_selections", .{}),
'O', key.UP => self.cmd("expand_selection", .{}),
'I', key.DOWN => self.cmd("shrink_selection", .{}),
'P', key.LEFT => self.cmd("select_prev_sibling", .{}),
'N', key.RIGHT => self.cmd("select_next_sibling", .{}),
'O', input.key.up => self.cmd("expand_selection", .{}),
'I', input.key.down => self.cmd("shrink_selection", .{}),
'P', input.key.left => self.cmd("select_prev_sibling", .{}),
'N', input.key.right => self.cmd("select_next_sibling", .{}),
'E' => self.cmd("move_parent_node_end", .{}),
'B' => self.cmd("move_parent_node_start", .{}),
@ -128,12 +125,12 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
',' => self.cmd("remove_primary_selection", .{}),
else => {},
},
mod.ALT | mod.SHIFT => switch (keynormal) {
input.mod.alt | input.mod.shift => switch (keynormal) {
'P' => self.cmd("open_command_palette", .{}),
'C' => self.cmd("copy_selection_on_next_line", .{}),
'I', key.DOWN => self.cmd("select_all_children", .{}),
'I', input.key.down => self.cmd("select_all_children", .{}),
'U' => self.cmd("redo", .{}),
@ -146,7 +143,7 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
'1' => self.cmd("shell_append_output", .{}),
else => {},
},
mod.SHIFT => switch (keypress) {
input.mod.shift => switch (keypress) {
'`' => self.cmd("switch_case", .{}),
't' => self.cmd("till_prev_char", .{}),
@ -209,11 +206,11 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
else => {},
},
0 => switch (keypress) {
key.F02 => self.cmd("toggle_input_mode", .{}),
'h', key.LEFT => self.cmd_count("move_left", .{}),
'j', key.DOWN => self.cmd_count("move_down", .{}),
'k', key.UP => self.cmd_count("move_up", .{}),
'l', key.RIGHT => self.cmd_count("move_right", .{}),
input.key.f2 => self.cmd("toggle_input_mode", .{}),
'h', input.key.left => self.cmd_count("move_left", .{}),
'j', input.key.down => self.cmd_count("move_down", .{}),
'k', input.key.up => self.cmd_count("move_up", .{}),
'l', input.key.right => self.cmd_count("move_right", .{}),
't' => self.cmd("find_till_char", .{}),
'f' => self.cmd("find_next_char", .{}),
@ -221,8 +218,8 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
'`' => self.cmd("switch_to_lowercase", .{}),
key.HOME => self.cmd("move_begin", .{}),
key.END => self.cmd("move_end", .{}),
input.key.home => self.cmd("move_begin", .{}),
input.key.end => self.cmd("move_end", .{}),
'w' => self.cmd_count("move_next_word_start", .{}),
'b' => self.cmd_count("move_prev_word_start", .{}),
@ -263,10 +260,10 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
',' => self.cmd("keep_primary_selection", .{}),
key.ESC => self.cmd("cancel", .{}),
input.key.escape => self.cmd("cancel", .{}),
key.PGUP => self.cmd("move_scroll_page_up", .{}),
key.PGDOWN => self.cmd("move_scroll_page_down", .{}),
input.key.page_up => self.cmd("move_scroll_page_up", .{}),
input.key.page_down => self.cmd("move_scroll_page_down", .{}),
' ' => self.leader = .{ .keypress = keynormal, .modifiers = modifiers },
'z' => self.leader = .{ .keypress = keynormal, .modifiers = modifiers },
@ -286,15 +283,15 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
};
}
fn mapFollower(self: *Self, keypress: u32, _: u32, modifiers: u32) !void {
if (keypress == key.LCTRL or
keypress == key.RCTRL or
keypress == key.LALT or
keypress == key.RALT or
keypress == key.LSHIFT or
keypress == key.RSHIFT or
keypress == key.LSUPER or
keypress == key.RSUPER) return;
fn mapFollower(self: *Self, keypress: input.Key, _: u32, modifiers: input.Mods) !void {
if (keypress == input.key.left_control or
keypress == input.key.right_control or
keypress == input.key.left_alt or
keypress == input.key.right_alt or
keypress == input.key.left_shift or
keypress == input.key.right_shift or
keypress == input.key.left_super or
keypress == input.key.right_super) return;
defer self.leader = null;
const ldr = if (self.leader) |leader| leader else return;
@ -324,7 +321,7 @@ fn mapFollower(self: *Self, keypress: u32, _: u32, modifiers: u32) !void {
'W' => self.cmd("goto_word", .{}),
else => {},
},
mod.SHIFT => switch (keypress) {
input.mod.shift => switch (keypress) {
'D' => self.cmd("goto_declaration", .{}),
else => {},
},
@ -346,7 +343,7 @@ fn mapFollower(self: *Self, keypress: u32, _: u32, modifiers: u32) !void {
},
'[' => {
try switch (modifiers) {
mod.SHIFT => switch (keypress) {
input.mod.shift => switch (keypress) {
'D' => self.cmd("goto_first_diag", .{}),
'G' => self.cmd("goto_first_change", .{}),
'T' => self.cmd("goto_prev_test", .{}),
@ -369,7 +366,7 @@ fn mapFollower(self: *Self, keypress: u32, _: u32, modifiers: u32) !void {
},
']' => {
try switch (modifiers) {
mod.SHIFT => switch (keypress) {
input.mod.shift => switch (keypress) {
'D' => self.cmd("goto_last_diag", .{}),
'G' => self.cmd("goto_last_change", .{}),
'T' => self.cmd("goto_next_test", .{}),
@ -392,7 +389,7 @@ fn mapFollower(self: *Self, keypress: u32, _: u32, modifiers: u32) !void {
},
'W' => switch (modifiers) {
// way too much stuff if someone wants they can implement it
mod.SHIFT => switch (keypress) {
input.mod.shift => switch (keypress) {
else => {},
},
0 => switch (keypress) {
@ -401,7 +398,7 @@ fn mapFollower(self: *Self, keypress: u32, _: u32, modifiers: u32) !void {
else => {},
},
' ' => switch (modifiers) {
mod.SHIFT => switch (keypress) {
input.mod.shift => switch (keypress) {
'F' => self.cmd("file_picker_in_current_directory", .{}),
'S' => self.cmd("workspace_symbol_picker", .{}),
'D' => self.cmd("workspace_diagnostics_picker", .{}),
@ -436,10 +433,10 @@ fn mapFollower(self: *Self, keypress: u32, _: u32, modifiers: u32) !void {
};
}
fn mapRelease(self: *Self, keypress: u32, _: u32, _: u32) !void {
fn map_release(self: *Self, keypress: input.Key) !void {
return switch (keypress) {
key.LCTRL, key.RCTRL => self.cmd("disable_fast_scroll", .{}),
key.LALT, key.RALT => self.cmd("disable_jump_mode", .{}),
input.key.left_control, input.key.right_control => self.cmd("disable_fast_scroll", .{}),
input.key.left_alt, input.key.right_alt => self.cmd("disable_jump_mode", .{}),
else => {},
};
}
@ -453,7 +450,7 @@ fn insert_code_point(self: *Self, c: u32) !void {
if (self.input.items.len + 4 > input_buffer_size)
try self.flush_input();
var buf: [6]u8 = undefined;
const bytes = try ucs32_to_utf8(&[_]u32{c}, &buf);
const bytes = try input.ucs32_to_utf8(&[_]u32{c}, &buf);
try self.input.appendSlice(buf[0..bytes]);
}

View file

@ -1,9 +1,6 @@
const std = @import("std");
const tp = @import("thespian");
const key = @import("renderer").input.key;
const mod = @import("renderer").input.modifier;
const event_type = @import("renderer").input.event_type;
const ucs32_to_utf8 = @import("renderer").ucs32_to_utf8;
const input = @import("input");
const command = @import("command");
const EventHandler = @import("EventHandler");
const keybind = @import("../../keybind.zig");
@ -14,7 +11,7 @@ const input_buffer_size = 1024;
allocator: std.mem.Allocator,
input: std.ArrayList(u8),
last_cmd: []const u8 = "",
leader: ?struct { keypress: u32, modifiers: u32 } = null,
leader: ?struct { keypress: input.Key, modifiers: input.Mods } = null,
count: usize = 0,
commands: Commands = undefined,
@ -35,14 +32,14 @@ pub fn deinit(self: *Self) void {
}
pub fn receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
var evtype: u32 = undefined;
var keypress: u32 = undefined;
var egc: u32 = undefined;
var modifiers: u32 = undefined;
var event: input.Event = undefined;
var keypress: input.Key = undefined;
var egc: input.Key = undefined;
var modifiers: input.Mods = undefined;
var text: []const u8 = undefined;
if (try m.match(.{ "I", tp.extract(&evtype), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) {
self.mapEvent(evtype, keypress, egc, modifiers) catch |e| return tp.exit_error(e, @errorReturnTrace());
if (try m.match(.{ "I", tp.extract(&event), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) {
self.map_event(event, keypress, egc, modifiers) catch |e| return tp.exit_error(e, @errorReturnTrace());
} else if (try m.match(.{"F"})) {
self.flush_input() catch |e| return tp.exit_error(e, @errorReturnTrace());
} else if (try m.match(.{ "system_clipboard", tp.extract(&text) })) {
@ -55,26 +52,26 @@ pub fn receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
pub fn add_keybind() void {}
fn mapEvent(self: *Self, evtype: u32, keypress: u32, egc: u32, modifiers: u32) !void {
return switch (evtype) {
event_type.PRESS => self.mapPress(keypress, egc, modifiers),
event_type.REPEAT => self.mapPress(keypress, egc, modifiers),
event_type.RELEASE => self.mapRelease(keypress, egc, modifiers),
fn map_event(self: *Self, event: input.Event, keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void {
return switch (event) {
input.event.press => self.map_press(keypress, egc, modifiers),
input.event.repeat => self.map_press(keypress, egc, modifiers),
input.event.release => self.map_release(keypress),
else => {},
};
}
fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
fn map_press(self: *Self, keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void {
if (self.count > 0 and modifiers == 0 and '0' <= keypress and keypress <= '9') return self.add_count(keypress - '0');
const keynormal = if ('a' <= keypress and keypress <= 'z') keypress - ('a' - 'A') else keypress;
if (self.leader) |_| return self.mapFollower(keynormal, egc, modifiers);
switch (keypress) {
key.LCTRL, key.RCTRL => return self.cmd("enable_fast_scroll", .{}),
key.LALT, key.RALT => return self.cmd("enable_jump_mode", .{}),
input.key.left_control, input.key.right_control => return self.cmd("enable_fast_scroll", .{}),
input.key.left_alt, input.key.right_alt => return self.cmd("enable_jump_mode", .{}),
else => {},
}
return switch (modifiers) {
mod.CTRL => switch (keynormal) {
input.mod.ctrl => switch (keynormal) {
'B' => self.cmd("move_scroll_page_up", .{}),
'F' => self.cmd("move_scroll_page_down", .{}),
'U' => self.cmd("page_cursor_half_up", .{}),
@ -91,12 +88,12 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
'X' => self.cmd("decrement", .{}),
else => {},
},
mod.CTRL | mod.SHIFT => switch (keynormal) {
input.mod.ctrl | input.mod.shift => switch (keynormal) {
'P' => self.cmd("open_command_palette", .{}),
'6' => self.cmd("open_previous_file", .{}),
else => {},
},
mod.ALT => switch (keynormal) {
input.mod.alt => switch (keynormal) {
'.' => self.cmd("repeat_last_motion", .{}),
'`' => self.cmd("switch_to_uppercase", .{}),
@ -112,10 +109,10 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
'_' => self.cmd("merge_consecutive_selections", .{}),
';' => self.cmd("flip_selections", .{}),
'O', key.UP => self.cmd("expand_selection", .{}),
'I', key.DOWN => self.cmd("shrink_selection", .{}),
'P', key.LEFT => self.cmd("select_prev_sibling", .{}),
'N', key.RIGHT => self.cmd("select_next_sibling", .{}),
'O', input.key.up => self.cmd("expand_selection", .{}),
'I', input.key.down => self.cmd("shrink_selection", .{}),
'P', input.key.left => self.cmd("select_prev_sibling", .{}),
'N', input.key.right => self.cmd("select_next_sibling", .{}),
'E' => self.cmd("extend_parent_node_end", .{}),
'B' => self.cmd("extend_parent_node_start", .{}),
@ -128,12 +125,12 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
',' => self.cmd("remove_primary_selection", .{}),
else => {},
},
mod.ALT | mod.SHIFT => switch (keynormal) {
input.mod.alt | input.mod.shift => switch (keynormal) {
'P' => self.cmd("open_command_palette", .{}),
'C' => self.cmd("copy_selection_on_next_line", .{}),
'I', key.DOWN => self.cmd("select_all_children", .{}),
'I', input.key.down => self.cmd("select_all_children", .{}),
'U' => self.cmd("redo", .{}),
@ -146,7 +143,7 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
'1' => self.cmd("shell_append_output", .{}),
else => {},
},
mod.SHIFT => switch (keypress) {
input.mod.shift => switch (keypress) {
'`' => self.cmd("switch_case", .{}),
't' => self.cmd("extend_till_prev_char", .{}),
@ -209,11 +206,11 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
else => {},
},
0 => switch (keypress) {
key.F02 => self.cmd("toggle_input_mode", .{}),
'h', key.LEFT => self.cmd_count("select_left", .{}),
'j', key.DOWN => self.cmd_count("select_down", .{}),
'k', key.UP => self.cmd_count("select_up", .{}),
'l', key.RIGHT => self.cmd_count("select_right", .{}),
input.key.f2 => self.cmd("toggle_input_mode", .{}),
'h', input.key.left => self.cmd_count("select_left", .{}),
'j', input.key.down => self.cmd_count("select_down", .{}),
'k', input.key.up => self.cmd_count("select_up", .{}),
'l', input.key.right => self.cmd_count("select_right", .{}),
't' => self.cmd("extend_till_char", .{}),
'f' => self.cmd("extend_next_char", .{}),
@ -221,8 +218,8 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
'`' => self.cmd("switch_to_lowercase", .{}),
key.HOME => self.cmd("extend_to_line_start", .{}),
key.END => self.cmd("extend_to_line_end", .{}),
input.key.home => self.cmd("extend_to_line_start", .{}),
input.key.end => self.cmd("extend_to_line_end", .{}),
'w' => self.cmd_count("extend_next_word_start", .{}),
'b' => self.cmd_count("extend_pre_word_start", .{}),
@ -263,10 +260,10 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
',' => self.cmd("keep_primary_selection", .{}),
key.ESC => self.cmd("enter_mode", command.fmt(.{"helix/normal"})),
input.key.escape => self.cmd("enter_mode", command.fmt(.{"helix/normal"})),
key.PGUP => self.cmd("move_scroll_page_up", .{}),
key.PGDOWN => self.cmd("move_scroll_page_down", .{}),
input.key.page_up => self.cmd("move_scroll_page_up", .{}),
input.key.page_down => self.cmd("move_scroll_page_down", .{}),
' ' => self.leader = .{ .keypress = keynormal, .modifiers = modifiers },
'z' => self.leader = .{ .keypress = keynormal, .modifiers = modifiers },
@ -286,15 +283,15 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
};
}
fn mapFollower(self: *Self, keypress: u32, _: u32, modifiers: u32) !void {
if (keypress == key.LCTRL or
keypress == key.RCTRL or
keypress == key.LALT or
keypress == key.RALT or
keypress == key.LSHIFT or
keypress == key.RSHIFT or
keypress == key.LSUPER or
keypress == key.RSUPER) return;
fn mapFollower(self: *Self, keypress: input.Key, _: u32, modifiers: input.Mods) !void {
if (keypress == input.key.left_control or
keypress == input.key.right_control or
keypress == input.key.left_alt or
keypress == input.key.right_alt or
keypress == input.key.left_shift or
keypress == input.key.right_shift or
keypress == input.key.left_super or
keypress == input.key.right_super) return;
defer self.leader = null;
const ldr = if (self.leader) |leader| leader else return;
@ -324,7 +321,7 @@ fn mapFollower(self: *Self, keypress: u32, _: u32, modifiers: u32) !void {
'W' => self.cmd("goto_word", .{}),
else => {},
},
mod.SHIFT => switch (keypress) {
input.mod.shift => switch (keypress) {
'D' => self.cmd("goto_declaration", .{}),
else => {},
},
@ -346,7 +343,7 @@ fn mapFollower(self: *Self, keypress: u32, _: u32, modifiers: u32) !void {
},
'[' => {
try switch (modifiers) {
mod.SHIFT => switch (keypress) {
input.mod.shift => switch (keypress) {
'D' => self.cmd("goto_first_diag", .{}),
'G' => self.cmd("goto_first_change", .{}),
'T' => self.cmd("goto_prev_test", .{}),
@ -369,7 +366,7 @@ fn mapFollower(self: *Self, keypress: u32, _: u32, modifiers: u32) !void {
},
']' => {
try switch (modifiers) {
mod.SHIFT => switch (keypress) {
input.mod.shift => switch (keypress) {
'D' => self.cmd("goto_last_diag", .{}),
'G' => self.cmd("goto_last_change", .{}),
'T' => self.cmd("goto_next_test", .{}),
@ -392,7 +389,7 @@ fn mapFollower(self: *Self, keypress: u32, _: u32, modifiers: u32) !void {
},
'W' => switch (modifiers) {
// way too much stuff if someone wants they can implement it
mod.SHIFT => switch (keypress) {
input.mod.shift => switch (keypress) {
else => {},
},
0 => switch (keypress) {
@ -401,7 +398,7 @@ fn mapFollower(self: *Self, keypress: u32, _: u32, modifiers: u32) !void {
else => {},
},
' ' => switch (modifiers) {
mod.SHIFT => switch (keypress) {
input.mod.shift => switch (keypress) {
'F' => self.cmd("file_picker_in_current_directory", .{}),
'S' => self.cmd("workspace_symbol_picker", .{}),
'D' => self.cmd("workspace_diagnostics_picker", .{}),
@ -436,10 +433,10 @@ fn mapFollower(self: *Self, keypress: u32, _: u32, modifiers: u32) !void {
};
}
fn mapRelease(self: *Self, keypress: u32, _: u32, _: u32) !void {
fn map_release(self: *Self, keypress: input.Key) !void {
return switch (keypress) {
key.LCTRL, key.RCTRL => self.cmd("disable_fast_scroll", .{}),
key.LALT, key.RALT => self.cmd("disable_jump_mode", .{}),
input.key.left_control, input.key.right_control => self.cmd("disable_fast_scroll", .{}),
input.key.left_alt, input.key.right_alt => self.cmd("disable_jump_mode", .{}),
else => {},
};
}
@ -453,7 +450,7 @@ fn insert_code_point(self: *Self, c: u32) !void {
if (self.input.items.len + 4 > input_buffer_size)
try self.flush_input();
var buf: [6]u8 = undefined;
const bytes = try ucs32_to_utf8(&[_]u32{c}, &buf);
const bytes = try input.ucs32_to_utf8(&[_]u32{c}, &buf);
try self.input.appendSlice(buf[0..bytes]);
}

View file

@ -1,8 +1,6 @@
const std = @import("std");
const tp = @import("thespian");
const key = @import("renderer").input.key;
const event_type = @import("renderer").input.event_type;
const mod = @import("renderer").input.modifier;
const input = @import("input");
const command = @import("command");
const EventHandler = @import("EventHandler");
const keybind = @import("../keybind.zig");
@ -26,20 +24,20 @@ pub fn deinit(self: *Self) void {
}
pub fn receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
var evtype: u32 = undefined;
var keypress: u32 = undefined;
var modifiers: u32 = undefined;
var event: input.Event = undefined;
var keypress: input.Key = undefined;
var modifiers: input.Mods = undefined;
if (try m.match(.{ "I", tp.extract(&evtype), tp.extract(&keypress), tp.any, tp.string, tp.extract(&modifiers) })) {
try self.mapEvent(evtype, keypress, modifiers);
if (try m.match(.{ "I", tp.extract(&event), tp.extract(&keypress), tp.any, tp.string, tp.extract(&modifiers) })) {
try self.map_event(event, keypress, modifiers);
}
return false;
}
fn mapEvent(self: *Self, evtype: u32, keypress: u32, modifiers: u32) tp.result {
return switch (evtype) {
event_type.PRESS => self.mapPress(keypress, modifiers),
event_type.REPEAT => self.mapPress(keypress, modifiers),
fn map_event(self: *Self, event: u32, keypress: u32, modifiers: u32) tp.result {
return switch (event) {
input.event.press => self.mapPress(keypress, modifiers),
input.event.repeat => self.mapPress(keypress, modifiers),
else => {},
};
}
@ -48,7 +46,7 @@ fn mapPress(self: *Self, keypress: u32, modifiers: u32) tp.result {
const keynormal = if ('a' <= keypress and keypress <= 'z') keypress - ('a' - 'A') else keypress;
if (self.leader) |_| return self.mapFollower(keynormal, modifiers);
return switch (modifiers) {
mod.CTRL => switch (keynormal) {
input.mod.ctrl => switch (keynormal) {
'F' => self.sheeran(),
'J' => self.cmd("toggle_panel", .{}),
'Q' => self.cmd("quit", .{}),
@ -61,7 +59,7 @@ fn mapPress(self: *Self, keypress: u32, modifiers: u32) tp.result {
'K' => self.leader = .{ .keypress = keynormal, .modifiers = modifiers },
else => {},
},
mod.CTRL | mod.SHIFT => switch (keynormal) {
input.mod.ctrl | input.mod.shift => switch (keynormal) {
'P' => self.cmd("open_command_palette", .{}),
'Q' => self.cmd("quit_without_saving", .{}),
'R' => self.cmd("restart", .{}),
@ -70,22 +68,22 @@ fn mapPress(self: *Self, keypress: u32, modifiers: u32) tp.result {
'/' => self.cmd("open_help", .{}),
else => {},
},
mod.ALT | mod.SHIFT => switch (keynormal) {
input.mod.alt | input.mod.shift => switch (keynormal) {
'P' => self.cmd("open_command_palette", .{}),
else => {},
},
mod.ALT => switch (keynormal) {
input.mod.alt => switch (keynormal) {
'N' => self.cmd("goto_next_file_or_diagnostic", .{}),
'P' => self.cmd("goto_prev_file_or_diagnostic", .{}),
'L' => self.cmd("toggle_panel", .{}),
'I' => self.cmd("toggle_inputview", .{}),
'X' => self.cmd("open_command_palette", .{}),
key.LEFT => self.cmd("jump_back", .{}),
key.RIGHT => self.cmd("jump_forward", .{}),
input.key.left => self.cmd("jump_back", .{}),
input.key.right => self.cmd("jump_forward", .{}),
else => {},
},
0 => switch (keypress) {
key.F02 => self.cmd("toggle_input_mode", .{}),
input.key.f2 => self.cmd("toggle_input_mode", .{}),
'h' => self.cmd("open_help", .{}),
'o' => self.cmd("open_file", .{}),
'e' => self.cmd("open_recent", .{}),
@ -95,15 +93,15 @@ fn mapPress(self: *Self, keypress: u32, modifiers: u32) tp.result {
't' => self.cmd("change_theme", .{}),
'q' => self.cmd("quit", .{}),
key.F01 => self.cmd("open_help", .{}),
key.F06 => self.cmd("open_config", .{}),
key.F09 => self.cmd("theme_prev", .{}),
key.F10 => self.cmd("theme_next", .{}),
key.F11 => self.cmd("toggle_panel", .{}),
key.F12 => self.cmd("toggle_inputview", .{}),
key.UP => self.cmd("home_menu_up", .{}),
key.DOWN => self.cmd("home_menu_down", .{}),
key.ENTER => self.cmd("home_menu_activate", .{}),
input.key.f1 => self.cmd("open_help", .{}),
input.key.f6 => self.cmd("open_config", .{}),
input.key.f9 => self.cmd("theme_prev", .{}),
input.key.f10 => self.cmd("theme_next", .{}),
input.key.f11 => self.cmd("toggle_panel", .{}),
input.key.f12 => self.cmd("toggle_inputview", .{}),
input.key.up => self.cmd("home_menu_up", .{}),
input.key.down => self.cmd("home_menu_down", .{}),
input.key.enter => self.cmd("home_menu_activate", .{}),
else => {},
},
else => {},
@ -114,9 +112,9 @@ fn mapFollower(self: *Self, keypress: u32, modifiers: u32) !void {
defer self.leader = null;
const ldr = if (self.leader) |leader| leader else return;
return switch (ldr.modifiers) {
mod.CTRL => switch (ldr.keypress) {
input.mod.ctrl => switch (ldr.keypress) {
'K' => switch (modifiers) {
mod.CTRL => switch (keypress) {
input.mod.ctrl => switch (keypress) {
'T' => self.cmd("change_theme", .{}),
else => {},
},

View file

@ -1,9 +1,6 @@
const std = @import("std");
const tp = @import("thespian");
const key = @import("renderer").input.key;
const mod = @import("renderer").input.modifier;
const event_type = @import("renderer").input.event_type;
const ucs32_to_utf8 = @import("renderer").ucs32_to_utf8;
const input = @import("input");
const command = @import("command");
const EventHandler = @import("EventHandler");
const keybind = @import("../../keybind.zig");
@ -14,15 +11,15 @@ const input_buffer_size = 1024;
allocator: std.mem.Allocator,
input: std.ArrayList(u8),
last_cmd: []const u8 = "",
leader: ?struct { keypress: u32, modifiers: u32 } = null,
leader: ?struct { keypress: input.Key, modifiers: input.Mods } = null,
commands: Commands = undefined,
last_key: KeyPressEvent = .{},
enable_chording: bool,
pub const KeyPressEvent = struct {
keypress: u32 = 0,
modifiers: u32 = std.math.maxInt(u32),
egc: u32 = 0,
keypress: input.Key = 0,
modifiers: input.Mods = std.math.maxInt(input.Mods),
egc: input.Key = 0,
timestamp_ms: i64 = 0,
};
@ -44,14 +41,14 @@ pub fn deinit(self: *Self) void {
}
pub fn receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
var evtype: u32 = undefined;
var keypress: u32 = undefined;
var egc: u32 = undefined;
var modifiers: u32 = undefined;
var event: input.Event = undefined;
var keypress: input.Key = undefined;
var egc: input.Key = undefined;
var modifiers: input.Mods = undefined;
var text: []const u8 = undefined;
if (try m.match(.{ "I", tp.extract(&evtype), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) {
self.mapEvent(evtype, keypress, egc, modifiers) catch |e| return tp.exit_error(e, @errorReturnTrace());
if (try m.match(.{ "I", tp.extract(&event), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) {
self.map_event(event, keypress, egc, modifiers) catch |e| return tp.exit_error(e, @errorReturnTrace());
} else if (try m.match(.{"F"})) {
self.flush_input() catch |e| return tp.exit_error(e, @errorReturnTrace());
} else if (try m.match(.{ "system_clipboard", tp.extract(&text) })) {
@ -64,21 +61,21 @@ pub fn receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
pub fn add_keybind() void {}
fn mapEvent(self: *Self, evtype: u32, keypress: u32, egc: u32, modifiers: u32) !void {
return switch (evtype) {
event_type.PRESS => self.mapPress(keypress, egc, modifiers),
event_type.REPEAT => self.mapPress(keypress, egc, modifiers),
event_type.RELEASE => self.mapRelease(keypress, egc, modifiers),
fn map_event(self: *Self, event: input.Event, keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void {
return switch (event) {
input.event.press => self.map_press(keypress, egc, modifiers),
input.event.repeat => self.map_press(keypress, egc, modifiers),
input.event.release => self.map_release(keypress),
else => {},
};
}
fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
fn map_press(self: *Self, keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void {
const keynormal = if ('a' <= keypress and keypress <= 'z') keypress - ('a' - 'A') else keypress;
if (self.leader) |_| return self.mapFollower(keynormal, egc, modifiers);
if (self.leader) |_| return self.map_follower(keynormal, egc, modifiers);
switch (keypress) {
key.LCTRL, key.RCTRL => return self.cmd("enable_fast_scroll", .{}),
key.LALT, key.RALT => return self.cmd("enable_jump_mode", .{}),
input.key.left_control, input.key.right_control => return self.cmd("enable_fast_scroll", .{}),
input.key.left_alt, input.key.right_alt => return self.cmd("enable_jump_mode", .{}),
else => {},
}
@ -122,7 +119,7 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
}
return switch (modifiers) {
mod.CTRL => switch (keynormal) {
input.mod.ctrl => switch (keynormal) {
'E' => self.cmd("open_recent", .{}),
'U' => self.cmd("move_scroll_page_up", .{}),
'D' => self.cmd("move_scroll_page_down", .{}),
@ -147,23 +144,23 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
'A' => self.cmd("select_all", .{}),
'I' => self.insert_bytes("\t"),
'/' => self.cmd("toggle_comment", .{}),
key.ENTER => self.cmd("smart_insert_line_after", .{}),
key.SPACE => self.cmd("selections_reverse", .{}),
key.END => self.cmd("move_buffer_end", .{}),
key.HOME => self.cmd("move_buffer_begin", .{}),
key.UP => self.cmd("move_scroll_up", .{}),
key.DOWN => self.cmd("move_scroll_down", .{}),
key.PGUP => self.cmd("move_scroll_page_up", .{}),
key.PGDOWN => self.cmd("move_scroll_page_down", .{}),
key.LEFT => self.cmd("move_word_left", .{}),
key.RIGHT => self.cmd("move_word_right", .{}),
key.BACKSPACE => self.cmd("delete_word_left", .{}),
key.DEL => self.cmd("delete_word_right", .{}),
key.F05 => self.cmd("toggle_inspector_view", .{}),
key.F10 => self.cmd("toggle_whitespace_mode", .{}), // aka F34
input.key.enter => self.cmd("smart_insert_line_after", .{}),
input.key.space => self.cmd("selections_reverse", .{}),
input.key.end => self.cmd("move_buffer_end", .{}),
input.key.home => self.cmd("move_buffer_begin", .{}),
input.key.up => self.cmd("move_scroll_up", .{}),
input.key.down => self.cmd("move_scroll_down", .{}),
input.key.page_up => self.cmd("move_scroll_page_up", .{}),
input.key.page_down => self.cmd("move_scroll_page_down", .{}),
input.key.left => self.cmd("move_word_left", .{}),
input.key.right => self.cmd("move_word_right", .{}),
input.key.backspace => self.cmd("delete_word_left", .{}),
input.key.delete => self.cmd("delete_word_right", .{}),
input.key.f5 => self.cmd("toggle_inspector_view", .{}),
input.key.f10 => self.cmd("toggle_whitespace_mode", .{}), // aka F34
else => {},
},
mod.CTRL | mod.SHIFT => switch (keynormal) {
input.mod.ctrl | input.mod.shift => switch (keynormal) {
'P' => self.cmd("open_command_palette", .{}),
'D' => self.cmd("dupe_down", .{}),
'Z' => self.cmd("redo", .{}),
@ -172,16 +169,16 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
'F' => self.cmd("find_in_files", .{}),
'L' => self.cmd_async("add_cursor_all_matches"),
'I' => self.cmd_async("toggle_inspector_view"),
key.ENTER => self.cmd("smart_insert_line_before", .{}),
key.END => self.cmd("select_buffer_end", .{}),
key.HOME => self.cmd("select_buffer_begin", .{}),
key.UP => self.cmd("select_scroll_up", .{}),
key.DOWN => self.cmd("select_scroll_down", .{}),
key.LEFT => self.cmd("select_word_left", .{}),
key.RIGHT => self.cmd("select_word_right", .{}),
input.key.enter => self.cmd("smart_insert_line_before", .{}),
input.key.end => self.cmd("select_buffer_end", .{}),
input.key.home => self.cmd("select_buffer_begin", .{}),
input.key.up => self.cmd("select_scroll_up", .{}),
input.key.down => self.cmd("select_scroll_down", .{}),
input.key.left => self.cmd("select_word_left", .{}),
input.key.right => self.cmd("select_word_right", .{}),
else => {},
},
mod.ALT => switch (keynormal) {
input.mod.alt => switch (keynormal) {
'J' => self.cmd("join_next_line", .{}),
'N' => self.cmd("goto_next_match", .{}),
'P' => self.cmd("goto_prev_match", .{}),
@ -192,72 +189,71 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
'F' => self.cmd("move_word_right", .{}),
'S' => self.cmd("filter", command.fmt(.{"sort"})),
'V' => self.cmd("paste", .{}),
key.LEFT => self.cmd("jump_back", .{}),
key.RIGHT => self.cmd("jump_forward", .{}),
key.UP => self.cmd("pull_up", .{}),
key.DOWN => self.cmd("pull_down", .{}),
key.ENTER => self.cmd("insert_line", .{}),
key.F10 => self.cmd("gutter_mode_next", .{}), // aka F58
input.key.left => self.cmd("jump_back", .{}),
input.key.right => self.cmd("jump_forward", .{}),
input.key.up => self.cmd("pull_up", .{}),
input.key.down => self.cmd("pull_down", .{}),
input.key.enter => self.cmd("insert_line", .{}),
input.key.f10 => self.cmd("gutter_mode_next", .{}), // aka F58
else => {},
},
mod.ALT | mod.SHIFT => switch (keynormal) {
input.mod.alt | input.mod.shift => switch (keynormal) {
'P' => self.cmd("open_command_palette", .{}),
'D' => self.cmd("dupe_up", .{}),
'F' => self.cmd("filter", command.fmt(.{ "zig", "fmt", "--stdin" })),
'S' => self.cmd("filter", command.fmt(.{ "sort", "-u" })),
'V' => self.cmd("paste", .{}),
'I' => self.cmd("add_cursors_to_line_ends", .{}),
key.LEFT => self.cmd("move_scroll_left", .{}),
key.RIGHT => self.cmd("move_scroll_right", .{}),
key.UP => self.cmd("add_cursor_up", .{}),
key.DOWN => self.cmd("add_cursor_down", .{}),
input.key.left => self.cmd("move_scroll_left", .{}),
input.key.right => self.cmd("move_scroll_right", .{}),
input.key.up => self.cmd("add_cursor_up", .{}),
input.key.down => self.cmd("add_cursor_down", .{}),
else => {},
},
mod.SHIFT => switch (keypress) {
key.F03 => self.cmd("goto_prev_match", .{}),
key.F10 => self.cmd("toggle_syntax_highlighting", .{}),
key.LEFT => self.cmd("select_left", .{}),
key.RIGHT => self.cmd("select_right", .{}),
key.UP => self.cmd("select_up", .{}),
key.DOWN => self.cmd("select_down", .{}),
key.HOME => self.cmd("smart_select_begin", .{}),
key.END => self.cmd("select_end", .{}),
key.PGUP => self.cmd("select_page_up", .{}),
key.PGDOWN => self.cmd("select_page_down", .{}),
key.ENTER => self.cmd("smart_insert_line_before", .{}),
key.BACKSPACE => self.cmd("delete_backward", .{}),
key.TAB => self.cmd("unindent", .{}),
else => if (!key.synthesized_p(keypress))
input.mod.shift => switch (keypress) {
input.key.f3 => self.cmd("goto_prev_match", .{}),
input.key.f10 => self.cmd("toggle_syntax_highlighting", .{}),
input.key.left => self.cmd("select_left", .{}),
input.key.right => self.cmd("select_right", .{}),
input.key.up => self.cmd("select_up", .{}),
input.key.down => self.cmd("select_down", .{}),
input.key.home => self.cmd("smart_select_begin", .{}),
input.key.end => self.cmd("select_end", .{}),
input.key.page_up => self.cmd("select_page_up", .{}),
input.key.page_down => self.cmd("select_page_down", .{}),
input.key.enter => self.cmd("smart_insert_line_before", .{}),
input.key.backspace => self.cmd("delete_backward", .{}),
input.key.tab => self.cmd("unindent", .{}),
else => if (!input.is_non_input_key(keypress))
self.insert_code_point(egc)
else {},
},
0 => switch (keypress) {
key.F02 => self.cmd("toggle_input_mode", .{}),
key.F03 => self.cmd("goto_next_match", .{}),
key.F15 => self.cmd("goto_prev_match", .{}), // S-F3
key.F05 => self.cmd("toggle_inspector_view", .{}), // C-F5
key.F06 => self.cmd("dump_current_line_tree", .{}),
key.F07 => self.cmd("dump_current_line", .{}),
key.F09 => self.cmd("theme_prev", .{}),
key.F10 => self.cmd("theme_next", .{}),
key.F11 => self.cmd("toggle_panel", .{}),
key.F12 => self.cmd("goto_definition", .{}),
key.F34 => self.cmd("toggle_whitespace_mode", .{}), // C-F10
key.F58 => self.cmd("gutter_mode_next", .{}), // A-F10
key.ESC => self.cmd("enter_mode", command.fmt(.{"vim/normal"})),
key.ENTER => self.cmd("smart_insert_line", .{}),
key.DEL => self.cmd("delete_forward", .{}),
key.BACKSPACE => self.cmd("delete_backward", .{}),
key.LEFT => self.cmd("move_left", .{}),
key.RIGHT => self.cmd("move_right", .{}),
key.UP => self.cmd("move_up", .{}),
key.DOWN => self.cmd("move_down", .{}),
key.HOME => self.cmd("smart_move_begin", .{}),
key.END => self.cmd("move_end", .{}),
key.PGUP => self.cmd("move_page_up", .{}),
key.PGDOWN => self.cmd("move_page_down", .{}),
key.TAB => self.cmd("indent", .{}),
else => if (!key.synthesized_p(keypress))
input.key.f2 => self.cmd("toggle_input_mode", .{}),
input.key.f3 => self.cmd("goto_next_match", .{}),
input.key.f15 => self.cmd("goto_prev_match", .{}), // S-F3
input.key.f5 => self.cmd("toggle_inspector_view", .{}), // C-F5
input.key.f6 => self.cmd("dump_current_line_tree", .{}),
input.key.f7 => self.cmd("dump_current_line", .{}),
input.key.f9 => self.cmd("theme_prev", .{}),
input.key.f10 => self.cmd("theme_next", .{}),
input.key.f11 => self.cmd("toggle_panel", .{}),
input.key.f12 => self.cmd("goto_definition", .{}),
input.key.f34 => self.cmd("toggle_whitespace_mode", .{}), // C-F10
input.key.escape => self.cmd("enter_mode", command.fmt(.{"vim/normal"})),
input.key.enter => self.cmd("smart_insert_line", .{}),
input.key.delete => self.cmd("delete_forward", .{}),
input.key.backspace => self.cmd("delete_backward", .{}),
input.key.left => self.cmd("move_left", .{}),
input.key.right => self.cmd("move_right", .{}),
input.key.up => self.cmd("move_up", .{}),
input.key.down => self.cmd("move_down", .{}),
input.key.home => self.cmd("smart_move_begin", .{}),
input.key.end => self.cmd("move_end", .{}),
input.key.page_up => self.cmd("move_page_up", .{}),
input.key.page_down => self.cmd("move_page_down", .{}),
input.key.tab => self.cmd("indent", .{}),
else => if (!input.is_non_input_key(keypress))
self.insert_code_point(egc)
else {},
},
@ -265,13 +261,13 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
};
}
fn mapFollower(self: *Self, keypress: u32, _: u32, modifiers: u32) !void {
fn map_follower(self: *Self, keypress: input.Key, _: u32, modifiers: input.Mods) !void {
defer self.leader = null;
const ldr = if (self.leader) |leader| leader else return;
return switch (ldr.modifiers) {
mod.CTRL => switch (ldr.keypress) {
input.mod.ctrl => switch (ldr.keypress) {
'K' => switch (modifiers) {
mod.CTRL => switch (keypress) {
input.mod.ctrl => switch (keypress) {
'U' => self.cmd("delete_to_begin", .{}),
'K' => self.cmd("delete_to_end", .{}),
'D' => self.cmd("move_cursor_next_match", .{}),
@ -286,10 +282,10 @@ fn mapFollower(self: *Self, keypress: u32, _: u32, modifiers: u32) !void {
};
}
fn mapRelease(self: *Self, keypress: u32, _: u32, _: u32) !void {
fn map_release(self: *Self, keypress: input.Key) !void {
return switch (keypress) {
key.LCTRL, key.RCTRL => self.cmd("disable_fast_scroll", .{}),
key.LALT, key.RALT => self.cmd("disable_jump_mode", .{}),
input.key.left_control, input.key.right_control => self.cmd("disable_fast_scroll", .{}),
input.key.left_alt, input.key.right_alt => self.cmd("disable_jump_mode", .{}),
else => {},
};
}
@ -298,7 +294,7 @@ fn insert_code_point(self: *Self, c: u32) !void {
if (self.input.items.len + 4 > input_buffer_size)
try self.flush_input();
var buf: [6]u8 = undefined;
const bytes = try ucs32_to_utf8(&[_]u32{c}, &buf);
const bytes = try input.ucs32_to_utf8(&[_]u32{c}, &buf);
try self.input.appendSlice(buf[0..bytes]);
}

View file

@ -1,9 +1,6 @@
const std = @import("std");
const tp = @import("thespian");
const key = @import("renderer").input.key;
const mod = @import("renderer").input.modifier;
const event_type = @import("renderer").input.event_type;
const ucs32_to_utf8 = @import("renderer").ucs32_to_utf8;
const input = @import("input");
const command = @import("command");
const EventHandler = @import("EventHandler");
const keybind = @import("../../keybind.zig");
@ -14,7 +11,7 @@ const input_buffer_size = 1024;
allocator: std.mem.Allocator,
input: std.ArrayList(u8),
last_cmd: []const u8 = "",
leader: ?struct { keypress: u32, modifiers: u32 } = null,
leader: ?struct { keypress: input.Key, modifiers: input.Mods } = null,
count: usize = 0,
commands: Commands = undefined,
@ -35,14 +32,14 @@ pub fn deinit(self: *Self) void {
}
pub fn receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
var evtype: u32 = undefined;
var keypress: u32 = undefined;
var egc: u32 = undefined;
var modifiers: u32 = undefined;
var event: input.Event = undefined;
var keypress: input.Key = undefined;
var egc: input.Key = undefined;
var modifiers: input.Mods = undefined;
var text: []const u8 = undefined;
if (try m.match(.{ "I", tp.extract(&evtype), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) {
self.mapEvent(evtype, keypress, egc, modifiers) catch |e| return tp.exit_error(e, @errorReturnTrace());
if (try m.match(.{ "I", tp.extract(&event), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) {
self.mapEvent(event, keypress, egc, modifiers) catch |e| return tp.exit_error(e, @errorReturnTrace());
} else if (try m.match(.{"F"})) {
self.flush_input() catch |e| return tp.exit_error(e, @errorReturnTrace());
} else if (try m.match(.{ "system_clipboard", tp.extract(&text) })) {
@ -55,26 +52,26 @@ pub fn receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
pub fn add_keybind() void {}
fn mapEvent(self: *Self, evtype: u32, keypress: u32, egc: u32, modifiers: u32) !void {
return switch (evtype) {
event_type.PRESS => self.mapPress(keypress, egc, modifiers),
event_type.REPEAT => self.mapPress(keypress, egc, modifiers),
event_type.RELEASE => self.mapRelease(keypress, egc, modifiers),
fn mapEvent(self: *Self, event: input.Event, keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void {
return switch (event) {
input.event.press => self.mapPress(keypress, egc, modifiers),
input.event.repeat => self.mapPress(keypress, egc, modifiers),
input.event.release => self.mapRelease(keypress, egc, modifiers),
else => {},
};
}
fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
fn mapPress(self: *Self, keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void {
if (self.count > 0 and modifiers == 0 and '0' <= keypress and keypress <= '9') return self.add_count(keypress - '0');
const keynormal = if ('a' <= keypress and keypress <= 'z') keypress - ('a' - 'A') else keypress;
if (self.leader) |_| return self.mapFollower(keynormal, egc, modifiers);
switch (keypress) {
key.LCTRL, key.RCTRL => return self.cmd("enable_fast_scroll", .{}),
key.LALT, key.RALT => return self.cmd("enable_jump_mode", .{}),
input.key.left_control, input.key.right_control => return self.cmd("enable_fast_scroll", .{}),
input.key.left_alt, input.key.right_alt => return self.cmd("enable_jump_mode", .{}),
else => {},
}
return switch (modifiers) {
mod.CTRL => switch (keynormal) {
input.mod.ctrl => switch (keynormal) {
'E' => self.cmd("open_recent", .{}),
'U' => self.cmd("move_scroll_page_up", .{}),
'D' => self.cmd("move_scroll_page_down", .{}),
@ -101,23 +98,23 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
'G' => self.cmd("goto", .{}),
'A' => self.cmd("select_all", .{}),
'/' => self.cmd("toggle_comment", .{}),
key.ENTER => self.cmd("smart_insert_line_after", .{}),
key.SPACE => self.cmd("selections_reverse", .{}),
key.END => self.cmd("move_buffer_end", .{}),
key.HOME => self.cmd("move_buffer_begin", .{}),
key.UP => self.cmd("move_scroll_up", .{}),
key.DOWN => self.cmd("move_scroll_down", .{}),
key.PGUP => self.cmd("move_scroll_page_up", .{}),
key.PGDOWN => self.cmd("move_scroll_page_down", .{}),
key.LEFT => self.cmd("move_word_left", .{}),
key.RIGHT => self.cmd("move_word_right", .{}),
key.BACKSPACE => self.cmd("delete_word_left", .{}),
key.DEL => self.cmd("delete_word_right", .{}),
key.F05 => self.cmd("toggle_inspector_view", .{}),
key.F10 => self.cmd("toggle_whitespace_mode", .{}), // aka F34
input.key.enter => self.cmd("smart_insert_line_after", .{}),
input.key.space => self.cmd("selections_reverse", .{}),
input.key.end => self.cmd("move_buffer_end", .{}),
input.key.home => self.cmd("move_buffer_begin", .{}),
input.key.up => self.cmd("move_scroll_up", .{}),
input.key.down => self.cmd("move_scroll_down", .{}),
input.key.page_up => self.cmd("move_scroll_page_up", .{}),
input.key.page_down => self.cmd("move_scroll_page_down", .{}),
input.key.left => self.cmd("move_word_left", .{}),
input.key.right => self.cmd("move_word_right", .{}),
input.key.backspace => self.cmd("delete_word_left", .{}),
input.key.delete => self.cmd("delete_word_right", .{}),
input.key.f5 => self.cmd("toggle_inspector_view", .{}),
input.key.f10 => self.cmd("toggle_whitespace_mode", .{}), // aka F34
else => {},
},
mod.CTRL | mod.SHIFT => switch (keynormal) {
input.mod.ctrl | input.mod.shift => switch (keynormal) {
'P' => self.cmd("open_command_palette", .{}),
'D' => self.cmd("dupe_down", .{}),
'Z' => self.cmd("redo", .{}),
@ -127,16 +124,16 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
'L' => self.cmd_async("add_cursor_all_matches"),
'I' => self.cmd_async("toggle_inspector_view"),
'6' => self.cmd("open_previous_file", .{}),
key.ENTER => self.cmd("smart_insert_line_before", .{}),
key.END => self.cmd("select_buffer_end", .{}),
key.HOME => self.cmd("select_buffer_begin", .{}),
key.UP => self.cmd("select_scroll_up", .{}),
key.DOWN => self.cmd("select_scroll_down", .{}),
key.LEFT => self.cmd("select_word_left", .{}),
key.RIGHT => self.cmd("select_word_right", .{}),
input.key.enter => self.cmd("smart_insert_line_before", .{}),
input.key.end => self.cmd("select_buffer_end", .{}),
input.key.home => self.cmd("select_buffer_begin", .{}),
input.key.up => self.cmd("select_scroll_up", .{}),
input.key.down => self.cmd("select_scroll_down", .{}),
input.key.left => self.cmd("select_word_left", .{}),
input.key.right => self.cmd("select_word_right", .{}),
else => {},
},
mod.ALT => switch (keynormal) {
input.mod.alt => switch (keynormal) {
'J' => self.cmd("join_next_line", .{}),
'N' => self.cmd("goto_next_match", .{}),
'P' => self.cmd("goto_prev_match", .{}),
@ -147,41 +144,41 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
'F' => self.cmd("move_word_right", .{}),
'S' => self.cmd("filter", command.fmt(.{"sort"})),
'V' => self.cmd("paste", .{}),
key.LEFT => self.cmd("jump_back", .{}),
key.RIGHT => self.cmd("jump_forward", .{}),
key.UP => self.cmd("pull_up", .{}),
key.DOWN => self.cmd("pull_down", .{}),
key.ENTER => self.cmd("insert_line", .{}),
key.F10 => self.cmd("gutter_mode_next", .{}), // aka F58
input.key.left => self.cmd("jump_back", .{}),
input.key.right => self.cmd("jump_forward", .{}),
input.key.up => self.cmd("pull_up", .{}),
input.key.down => self.cmd("pull_down", .{}),
input.key.enter => self.cmd("insert_line", .{}),
input.key.f10 => self.cmd("gutter_mode_next", .{}), // aka F58
else => {},
},
mod.ALT | mod.SHIFT => switch (keynormal) {
input.mod.alt | input.mod.shift => switch (keynormal) {
'P' => self.cmd("open_command_palette", .{}),
'D' => self.cmd("dupe_up", .{}),
'F' => self.cmd("filter", command.fmt(.{ "zig", "fmt", "--stdin" })),
'S' => self.cmd("filter", command.fmt(.{ "sort", "-u" })),
'V' => self.cmd("paste", .{}),
'I' => self.cmd("add_cursors_to_line_ends", .{}),
key.LEFT => self.cmd("move_scroll_left", .{}),
key.RIGHT => self.cmd("move_scroll_right", .{}),
key.UP => self.cmd("add_cursor_up", .{}),
key.DOWN => self.cmd("add_cursor_down", .{}),
input.key.left => self.cmd("move_scroll_left", .{}),
input.key.right => self.cmd("move_scroll_right", .{}),
input.key.up => self.cmd("add_cursor_up", .{}),
input.key.down => self.cmd("add_cursor_down", .{}),
else => {},
},
mod.SHIFT => switch (keypress) {
key.F03 => self.cmd("goto_prev_match", .{}),
key.F10 => self.cmd("toggle_syntax_highlighting", .{}),
key.LEFT => self.cmd("select_left", .{}),
key.RIGHT => self.cmd("select_right", .{}),
key.UP => self.cmd("select_up", .{}),
key.DOWN => self.cmd("select_down", .{}),
key.HOME => self.cmd("smart_select_begin", .{}),
key.END => self.cmd("select_end", .{}),
key.PGUP => self.cmd("select_page_up", .{}),
key.PGDOWN => self.cmd("select_page_down", .{}),
key.ENTER => self.cmd("smart_insert_line_before", .{}),
key.BACKSPACE => self.cmd("delete_backward", .{}),
key.TAB => self.cmd("unindent", .{}),
input.mod.shift => switch (keypress) {
input.key.f3 => self.cmd("goto_prev_match", .{}),
input.key.f10 => self.cmd("toggle_syntax_highlighting", .{}),
input.key.left => self.cmd("select_left", .{}),
input.key.right => self.cmd("select_right", .{}),
input.key.up => self.cmd("select_up", .{}),
input.key.down => self.cmd("select_down", .{}),
input.key.home => self.cmd("smart_select_begin", .{}),
input.key.end => self.cmd("select_end", .{}),
input.key.page_up => self.cmd("select_page_up", .{}),
input.key.page_down => self.cmd("select_page_down", .{}),
input.key.enter => self.cmd("smart_insert_line_before", .{}),
input.key.backspace => self.cmd("delete_backward", .{}),
input.key.tab => self.cmd("unindent", .{}),
';' => self.cmd("open_command_palette", .{}),
'n' => self.cmd("goto_prev_match", .{}),
@ -205,22 +202,21 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
else => {},
},
0 => switch (keypress) {
key.F02 => self.cmd("toggle_input_mode", .{}),
key.F03 => self.cmd("goto_next_match", .{}),
key.F15 => self.cmd("goto_prev_match", .{}), // S-F3
key.F05 => self.cmd("toggle_inspector_view", .{}), // C-F5
key.F06 => self.cmd("dump_current_line_tree", .{}),
key.F07 => self.cmd("dump_current_line", .{}),
key.F09 => self.cmd("theme_prev", .{}),
key.F10 => self.cmd("theme_next", .{}),
key.F11 => self.cmd("toggle_panel", .{}),
key.F12 => self.cmd("goto_definition", .{}),
key.F34 => self.cmd("toggle_whitespace_mode", .{}), // C-F10
key.F58 => self.cmd("gutter_mode_next", .{}), // A-F10
key.ESC => self.cmd("cancel", .{}),
key.ENTER => self.cmd("smart_insert_line", .{}),
key.DEL => self.cmd("delete_forward", .{}),
key.BACKSPACE => self.cmd("delete_backward", .{}),
input.key.f2 => self.cmd("toggle_input_mode", .{}),
input.key.f3 => self.cmd("goto_next_match", .{}),
input.key.f15 => self.cmd("goto_prev_match", .{}), // S-F3
input.key.f5 => self.cmd("toggle_inspector_view", .{}), // C-F5
input.key.f6 => self.cmd("dump_current_line_tree", .{}),
input.key.f7 => self.cmd("dump_current_line", .{}),
input.key.f9 => self.cmd("theme_prev", .{}),
input.key.f10 => self.cmd("theme_next", .{}),
input.key.f11 => self.cmd("toggle_panel", .{}),
input.key.f12 => self.cmd("goto_definition", .{}),
input.key.f34 => self.cmd("toggle_whitespace_mode", .{}), // C-F10
input.key.escape => self.cmd("cancel", .{}),
input.key.enter => self.cmd("smart_insert_line", .{}),
input.key.delete => self.cmd("delete_forward", .{}),
input.key.backspace => self.cmd("delete_backward", .{}),
':' => self.cmd("open_command_palette", .{}),
'i' => self.cmd("enter_mode", command.fmt(.{"vim/insert"})),
@ -266,37 +262,37 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
'p' => self.cmd("paste", .{}),
'o' => self.seq(.{ "smart_insert_line_after", "enter_mode" }, command.fmt(.{"vim/insert"})),
key.LEFT => self.cmd("move_left_vim", .{}),
key.RIGHT => self.cmd("move_right_vim", .{}),
key.UP => self.cmd("move_up", .{}),
key.DOWN => self.cmd("move_down", .{}),
key.HOME => self.cmd("smart_move_begin", .{}),
key.END => self.cmd("move_end", .{}),
key.PGUP => self.cmd("move_page_up", .{}),
key.PGDOWN => self.cmd("move_page_down", .{}),
key.TAB => self.cmd("indent", .{}),
input.key.left => self.cmd("move_left_vim", .{}),
input.key.right => self.cmd("move_right_vim", .{}),
input.key.up => self.cmd("move_up", .{}),
input.key.down => self.cmd("move_down", .{}),
input.key.home => self.cmd("smart_move_begin", .{}),
input.key.end => self.cmd("move_end", .{}),
input.key.page_up => self.cmd("move_page_up", .{}),
input.key.page_down => self.cmd("move_page_down", .{}),
input.key.tab => self.cmd("indent", .{}),
else => {},
},
else => {},
};
}
fn mapFollower(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
if (keypress == key.LCTRL or
keypress == key.RCTRL or
keypress == key.LALT or
keypress == key.RALT or
keypress == key.LSHIFT or
keypress == key.RSHIFT or
keypress == key.LSUPER or
keypress == key.RSUPER) return;
fn mapFollower(self: *Self, keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void {
if (keypress == input.key.left_control or
keypress == input.key.right_control or
keypress == input.key.left_alt or
keypress == input.key.right_alt or
keypress == input.key.left_shift or
keypress == input.key.right_shift or
keypress == input.key.left_super or
keypress == input.key.right_super) return;
defer self.leader = null;
const ldr = if (self.leader) |leader| leader else return;
return switch (ldr.modifiers) {
mod.CTRL => switch (ldr.keypress) {
input.mod.ctrl => switch (ldr.keypress) {
'K' => switch (modifiers) {
mod.CTRL => switch (keypress) {
input.mod.ctrl => switch (keypress) {
'U' => self.cmd("delete_to_begin", .{}),
'K' => self.cmd("delete_to_end", .{}),
'D' => self.cmd("move_cursor_next_match", .{}),
@ -311,7 +307,7 @@ fn mapFollower(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
0 => switch (ldr.keypress) {
'C' => {
try switch (modifiers) {
mod.SHIFT => switch (egc) {
input.mod.shift => switch (egc) {
'$' => self.cmd("delete_to_end", .{}),
else => {},
},
@ -329,7 +325,7 @@ fn mapFollower(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
},
'D' => {
try switch (modifiers) {
mod.SHIFT => switch (egc) {
input.mod.shift => switch (egc) {
'$' => self.cmd("delete_to_end", .{}),
else => {},
},
@ -348,7 +344,7 @@ fn mapFollower(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
try self.cmd("enter_mode", command.fmt(.{"vim/insert"}));
},
'R' => switch (modifiers) {
mod.SHIFT, 0 => if (!key.synthesized_p(keypress)) {
input.mod.shift, 0 => if (!input.is_non_input_key(keypress)) {
var count = self.count;
try self.cmd_count("delete_forward", .{});
while (count > 0) : (count -= 1)
@ -371,7 +367,7 @@ fn mapFollower(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
'Y' => self.cmd("goto_type_definition", .{}),
else => {},
},
mod.SHIFT => switch (keypress) {
input.mod.shift => switch (keypress) {
'D' => self.cmd("goto_declaration", .{}),
else => {},
},
@ -379,7 +375,7 @@ fn mapFollower(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
},
'Y' => {
try switch (modifiers) {
mod.SHIFT => switch (keypress) {
input.mod.shift => switch (keypress) {
'4' => self.seq(.{ "select_to_end", "copy" }, .{}),
else => {},
},
@ -403,10 +399,10 @@ fn mapFollower(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
};
}
fn mapRelease(self: *Self, keypress: u32, _: u32, _: u32) !void {
fn mapRelease(self: *Self, keypress: input.Key, _: u32, _: u32) !void {
return switch (keypress) {
key.LCTRL, key.RCTRL => self.cmd("disable_fast_scroll", .{}),
key.LALT, key.RALT => self.cmd("disable_jump_mode", .{}),
input.key.left_control, input.key.right_control => self.cmd("disable_fast_scroll", .{}),
input.key.left_alt, input.key.right_alt => self.cmd("disable_jump_mode", .{}),
else => {},
};
}
@ -420,7 +416,7 @@ fn insert_code_point(self: *Self, c: u32) !void {
if (self.input.items.len + 4 > input_buffer_size)
try self.flush_input();
var buf: [6]u8 = undefined;
const bytes = try ucs32_to_utf8(&[_]u32{c}, &buf);
const bytes = try input.ucs32_to_utf8(&[_]u32{c}, &buf);
try self.input.appendSlice(buf[0..bytes]);
}

View file

@ -1,9 +1,6 @@
const std = @import("std");
const tp = @import("thespian");
const key = @import("renderer").input.key;
const mod = @import("renderer").input.modifier;
const event_type = @import("renderer").input.event_type;
const ucs32_to_utf8 = @import("renderer").ucs32_to_utf8;
const input = @import("input");
const command = @import("command");
const EventHandler = @import("EventHandler");
const keybind = @import("../../keybind.zig");
@ -14,7 +11,7 @@ const input_buffer_size = 1024;
allocator: std.mem.Allocator,
input: std.ArrayList(u8),
last_cmd: []const u8 = "",
leader: ?struct { keypress: u32, modifiers: u32 } = null,
leader: ?struct { keypress: input.Key, modifiers: input.Mods } = null,
count: usize = 0,
commands: Commands = undefined,
@ -35,14 +32,14 @@ pub fn deinit(self: *Self) void {
}
pub fn receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
var evtype: u32 = undefined;
var keypress: u32 = undefined;
var egc: u32 = undefined;
var modifiers: u32 = undefined;
var event: input.Event = undefined;
var keypress: input.Key = undefined;
var egc: input.Key = undefined;
var modifiers: input.Mods = undefined;
var text: []const u8 = undefined;
if (try m.match(.{ "I", tp.extract(&evtype), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) {
self.mapEvent(evtype, keypress, egc, modifiers) catch |e| return tp.exit_error(e, @errorReturnTrace());
if (try m.match(.{ "I", tp.extract(&event), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) {
self.map_event(event, keypress, egc, modifiers) catch |e| return tp.exit_error(e, @errorReturnTrace());
} else if (try m.match(.{"F"})) {
self.flush_input() catch |e| return tp.exit_error(e, @errorReturnTrace());
} else if (try m.match(.{ "system_clipboard", tp.extract(&text) })) {
@ -55,26 +52,26 @@ pub fn receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
pub fn add_keybind() void {}
fn mapEvent(self: *Self, evtype: u32, keypress: u32, egc: u32, modifiers: u32) !void {
return switch (evtype) {
event_type.PRESS => self.mapPress(keypress, egc, modifiers),
event_type.REPEAT => self.mapPress(keypress, egc, modifiers),
event_type.RELEASE => self.mapRelease(keypress, egc, modifiers),
fn map_event(self: *Self, event: input.Event, keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void {
return switch (event) {
input.event.press => self.map_press(keypress, egc, modifiers),
input.event.repeat => self.map_press(keypress, egc, modifiers),
input.event.release => self.map_release(keypress),
else => {},
};
}
fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
fn map_press(self: *Self, keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void {
if (self.count > 0 and modifiers == 0 and '0' <= keypress and keypress <= '9') return self.add_count(keypress - '0');
const keynormal = if ('a' <= keypress and keypress <= 'z') keypress - ('a' - 'A') else keypress;
if (self.leader) |_| return self.mapFollower(keynormal, egc, modifiers);
switch (keypress) {
key.LCTRL, key.RCTRL => return self.cmd("enable_fast_scroll", .{}),
key.LALT, key.RALT => return self.cmd("enable_jump_mode", .{}),
input.key.left_control, input.key.right_control => return self.cmd("enable_fast_scroll", .{}),
input.key.left_alt, input.key.right_alt => return self.cmd("enable_jump_mode", .{}),
else => {},
}
return switch (modifiers) {
mod.CTRL => switch (keynormal) {
input.mod.ctrl => switch (keynormal) {
'E' => self.cmd("open_recent", .{}),
'U' => self.cmd("move_scroll_page_up", .{}),
'D' => self.cmd("move_scroll_page_down", .{}),
@ -101,23 +98,23 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
'G' => self.cmd("goto", .{}),
'A' => self.cmd("select_all", .{}),
'/' => self.cmd("toggle_comment", .{}),
key.ENTER => self.cmd("smart_insert_line_after", .{}),
key.SPACE => self.cmd("selections_reverse", .{}),
key.END => self.cmd("select_buffer_end", .{}),
key.HOME => self.cmd("select_buffer_begin", .{}),
key.UP => self.cmd("select_scroll_up", .{}),
key.DOWN => self.cmd("select_scroll_down", .{}),
key.PGUP => self.cmd("select_scroll_page_up", .{}),
key.PGDOWN => self.cmd("select_scroll_page_down", .{}),
key.LEFT => self.cmd("select_word_left", .{}),
key.RIGHT => self.cmd("select_word_right", .{}),
key.BACKSPACE => self.cmd("delete_word_left", .{}),
key.DEL => self.cmd("delete_word_right", .{}),
key.F05 => self.cmd("toggle_inspector_view", .{}),
key.F10 => self.cmd("toggle_whitespace_mode", .{}), // aka F34
input.key.enter => self.cmd("smart_insert_line_after", .{}),
input.key.space => self.cmd("selections_reverse", .{}),
input.key.end => self.cmd("select_buffer_end", .{}),
input.key.home => self.cmd("select_buffer_begin", .{}),
input.key.up => self.cmd("select_scroll_up", .{}),
input.key.down => self.cmd("select_scroll_down", .{}),
input.key.page_up => self.cmd("select_scroll_page_up", .{}),
input.key.page_down => self.cmd("select_scroll_page_down", .{}),
input.key.left => self.cmd("select_word_left", .{}),
input.key.right => self.cmd("select_word_right", .{}),
input.key.backspace => self.cmd("delete_word_left", .{}),
input.key.delete => self.cmd("delete_word_right", .{}),
input.key.f5 => self.cmd("toggle_inspector_view", .{}),
input.key.f10 => self.cmd("toggle_whitespace_mode", .{}), // aka F34
else => {},
},
mod.CTRL | mod.SHIFT => switch (keynormal) {
input.mod.ctrl | input.mod.shift => switch (keynormal) {
'P' => self.cmd("open_command_palette", .{}),
'D' => self.cmd("dupe_down", .{}),
'Z' => self.cmd("redo", .{}),
@ -127,16 +124,16 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
'L' => self.cmd_async("add_cursor_all_matches"),
'I' => self.cmd_async("toggle_inspector_view"),
'6' => self.cmd("open_previous_file", .{}),
key.ENTER => self.cmd("smart_insert_line_before", .{}),
key.END => self.cmd("select_buffer_end", .{}),
key.HOME => self.cmd("select_buffer_begin", .{}),
key.UP => self.cmd("select_scroll_up", .{}),
key.DOWN => self.cmd("select_scroll_down", .{}),
key.LEFT => self.cmd("select_word_left", .{}),
key.RIGHT => self.cmd("select_word_right", .{}),
input.key.enter => self.cmd("smart_insert_line_before", .{}),
input.key.end => self.cmd("select_buffer_end", .{}),
input.key.home => self.cmd("select_buffer_begin", .{}),
input.key.up => self.cmd("select_scroll_up", .{}),
input.key.down => self.cmd("select_scroll_down", .{}),
input.key.left => self.cmd("select_word_left", .{}),
input.key.right => self.cmd("select_word_right", .{}),
else => {},
},
mod.ALT => switch (keynormal) {
input.mod.alt => switch (keynormal) {
'J' => self.cmd("join_next_line", .{}),
'N' => self.cmd("goto_next_match", .{}),
'P' => self.cmd("goto_prev_match", .{}),
@ -147,39 +144,39 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
'F' => self.cmd("select_word_right", .{}),
'S' => self.cmd("filter", command.fmt(.{"sort"})),
'V' => self.cmd("paste", .{}),
key.LEFT => self.cmd("jump_back", .{}),
key.RIGHT => self.cmd("jump_forward", .{}),
key.UP => self.cmd("pull_up", .{}),
key.DOWN => self.cmd("pull_down", .{}),
key.ENTER => self.cmd("insert_line", .{}),
key.F10 => self.cmd("gutter_mode_next", .{}), // aka F58
input.key.left => self.cmd("jump_back", .{}),
input.key.right => self.cmd("jump_forward", .{}),
input.key.up => self.cmd("pull_up", .{}),
input.key.down => self.cmd("pull_down", .{}),
input.key.enter => self.cmd("insert_line", .{}),
input.key.f10 => self.cmd("gutter_mode_next", .{}), // aka F58
else => {},
},
mod.ALT | mod.SHIFT => switch (keynormal) {
input.mod.alt | input.mod.shift => switch (keynormal) {
'P' => self.cmd("open_command_palette", .{}),
'D' => self.cmd("dupe_up", .{}),
'F' => self.cmd("filter", command.fmt(.{ "zig", "fmt", "--stdin" })),
'S' => self.cmd("filter", command.fmt(.{ "sort", "-u" })),
'V' => self.cmd("paste", .{}),
'I' => self.cmd("add_cursors_to_line_ends", .{}),
key.LEFT => self.cmd("move_scroll_left", .{}),
key.RIGHT => self.cmd("move_scroll_right", .{}),
input.key.left => self.cmd("move_scroll_left", .{}),
input.key.right => self.cmd("move_scroll_right", .{}),
else => {},
},
mod.SHIFT => switch (keypress) {
key.F03 => self.cmd("goto_prev_match", .{}),
key.F10 => self.cmd("toggle_syntax_highlighting", .{}),
key.LEFT => self.cmd("select_left", .{}),
key.RIGHT => self.cmd("select_right", .{}),
key.UP => self.cmd("select_up", .{}),
key.DOWN => self.cmd("select_down", .{}),
key.HOME => self.cmd("smart_select_begin", .{}),
key.END => self.cmd("select_end", .{}),
key.PGUP => self.cmd("select_page_up", .{}),
key.PGDOWN => self.cmd("select_page_down", .{}),
key.ENTER => self.cmd("smart_insert_line_before", .{}),
key.BACKSPACE => self.cmd("delete_backward", .{}),
key.TAB => self.cmd("unindent", .{}),
input.mod.shift => switch (keypress) {
input.key.f3 => self.cmd("goto_prev_match", .{}),
input.key.f10 => self.cmd("toggle_syntax_highlighting", .{}),
input.key.left => self.cmd("select_left", .{}),
input.key.right => self.cmd("select_right", .{}),
input.key.up => self.cmd("select_up", .{}),
input.key.down => self.cmd("select_down", .{}),
input.key.home => self.cmd("smart_select_begin", .{}),
input.key.end => self.cmd("select_end", .{}),
input.key.page_up => self.cmd("select_page_up", .{}),
input.key.page_down => self.cmd("select_page_down", .{}),
input.key.enter => self.cmd("smart_insert_line_before", .{}),
input.key.backspace => self.cmd("delete_backward", .{}),
input.key.tab => self.cmd("unindent", .{}),
';' => self.cmd("open_command_palette", .{}),
'n' => self.cmd("goto_prev_match", .{}),
@ -201,22 +198,21 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
else => {},
},
0 => switch (keypress) {
key.F02 => self.cmd("toggle_input_mode", .{}),
key.F03 => self.cmd("goto_next_match", .{}),
key.F15 => self.cmd("goto_prev_match", .{}), // S-F3
key.F05 => self.cmd("toggle_inspector_view", .{}), // C-F5
key.F06 => self.cmd("dump_current_line_tree", .{}),
key.F07 => self.cmd("dump_current_line", .{}),
key.F09 => self.cmd("theme_prev", .{}),
key.F10 => self.cmd("theme_next", .{}),
key.F11 => self.cmd("toggle_panel", .{}),
key.F12 => self.cmd("goto_definition", .{}),
key.F34 => self.cmd("toggle_whitespace_mode", .{}), // C-F10
key.F58 => self.cmd("gutter_mode_next", .{}), // A-F10
key.ESC => self.seq(.{ "cancel", "enter_mode" }, command.fmt(.{"vim/normal"})),
key.ENTER => self.cmd("smart_insert_line", .{}),
key.DEL => self.cmd("delete_forward", .{}),
key.BACKSPACE => self.cmd("delete_backward", .{}),
input.key.f2 => self.cmd("toggle_input_mode", .{}),
input.key.f3 => self.cmd("goto_next_match", .{}),
input.key.f15 => self.cmd("goto_prev_match", .{}), // S-F3
input.key.f5 => self.cmd("toggle_inspector_view", .{}), // C-F5
input.key.f6 => self.cmd("dump_current_line_tree", .{}),
input.key.f7 => self.cmd("dump_current_line", .{}),
input.key.f9 => self.cmd("theme_prev", .{}),
input.key.f10 => self.cmd("theme_next", .{}),
input.key.f11 => self.cmd("toggle_panel", .{}),
input.key.f12 => self.cmd("goto_definition", .{}),
input.key.f34 => self.cmd("toggle_whitespace_mode", .{}), // C-F10
input.key.escape => self.seq(.{ "cancel", "enter_mode" }, command.fmt(.{"vim/normal"})),
input.key.enter => self.cmd("smart_insert_line", .{}),
input.key.delete => self.cmd("delete_forward", .{}),
input.key.backspace => self.cmd("delete_backward", .{}),
':' => self.cmd("open_command_palette", .{}),
'i' => self.cmd("enter_mode", command.fmt(.{"vim/insert"})),
@ -262,37 +258,37 @@ fn mapPress(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
'p' => self.cmd("paste", .{}),
'o' => self.seq(.{ "insert_line_after", "enter_mode" }, command.fmt(.{"vim/insert"})),
key.LEFT => self.cmd("select_left", .{}),
key.RIGHT => self.cmd("select_right", .{}),
key.UP => self.cmd("select_up", .{}),
key.DOWN => self.cmd("select_down", .{}),
key.HOME => self.cmd("smart_select_begin", .{}),
key.END => self.cmd("select_end", .{}),
key.PGUP => self.cmd("select_page_up", .{}),
key.PGDOWN => self.cmd("select_page_down", .{}),
key.TAB => self.cmd("indent", .{}),
input.key.left => self.cmd("select_left", .{}),
input.key.right => self.cmd("select_right", .{}),
input.key.up => self.cmd("select_up", .{}),
input.key.down => self.cmd("select_down", .{}),
input.key.home => self.cmd("smart_select_begin", .{}),
input.key.end => self.cmd("select_end", .{}),
input.key.page_up => self.cmd("select_page_up", .{}),
input.key.page_down => self.cmd("select_page_down", .{}),
input.key.tab => self.cmd("indent", .{}),
else => {},
},
else => {},
};
}
fn mapFollower(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
if (keypress == key.LCTRL or
keypress == key.RCTRL or
keypress == key.LALT or
keypress == key.RALT or
keypress == key.LSHIFT or
keypress == key.RSHIFT or
keypress == key.LSUPER or
keypress == key.RSUPER) return;
fn mapFollower(self: *Self, keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void {
if (keypress == input.key.left_control or
keypress == input.key.right_control or
keypress == input.key.left_alt or
keypress == input.key.right_alt or
keypress == input.key.left_shift or
keypress == input.key.right_shift or
keypress == input.key.left_super or
keypress == input.key.right_super) return;
defer self.leader = null;
const ldr = if (self.leader) |leader| leader else return;
return switch (ldr.modifiers) {
mod.CTRL => switch (ldr.keypress) {
input.mod.ctrl => switch (ldr.keypress) {
'K' => switch (modifiers) {
mod.CTRL => switch (keypress) {
input.mod.ctrl => switch (keypress) {
'U' => self.cmd("delete_to_begin", .{}),
'K' => self.cmd("delete_to_end", .{}),
'D' => self.cmd("move_cursor_next_match", .{}),
@ -307,7 +303,7 @@ fn mapFollower(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
0 => switch (ldr.keypress) {
'D', 'C' => {
try switch (modifiers) {
mod.SHIFT => switch (keypress) {
input.mod.shift => switch (keypress) {
'4' => self.cmd("delete_to_end", .{}),
else => {},
},
@ -326,7 +322,7 @@ fn mapFollower(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
try self.cmd("enter_mode", command.fmt(.{"vim/insert"}));
},
'R' => switch (modifiers) {
mod.SHIFT, 0 => if (!key.synthesized_p(keypress)) {
input.mod.shift, 0 => if (!input.is_non_input_key(keypress)) {
var count = self.count;
try self.cmd_count("delete_forward", .{});
while (count > 0) : (count -= 1)
@ -354,10 +350,10 @@ fn mapFollower(self: *Self, keypress: u32, egc: u32, modifiers: u32) !void {
};
}
fn mapRelease(self: *Self, keypress: u32, _: u32, _: u32) !void {
fn map_release(self: *Self, keypress: input.Key) !void {
return switch (keypress) {
key.LCTRL, key.RCTRL => self.cmd("disable_fast_scroll", .{}),
key.LALT, key.RALT => self.cmd("disable_jump_mode", .{}),
input.key.left_control, input.key.right_control => self.cmd("disable_fast_scroll", .{}),
input.key.left_alt, input.key.right_alt => self.cmd("disable_jump_mode", .{}),
else => {},
};
}
@ -371,7 +367,7 @@ fn insert_code_point(self: *Self, c: u32) !void {
if (self.input.items.len + 4 > input_buffer_size)
try self.flush_input();
var buf: [6]u8 = undefined;
const bytes = try ucs32_to_utf8(&[_]u32{c}, &buf);
const bytes = try input.ucs32_to_utf8(&[_]u32{c}, &buf);
try self.input.appendSlice(buf[0..bytes]);
}

View file

@ -32,7 +32,7 @@ pub const Mode = struct {
name: []const u8 = "",
line_numbers: enum { absolute, relative } = .absolute,
keybind_hints: ?*const KeybindHints = null,
cursor_shape: renderer.CursorShape = .block,
cursor_shape: CursorShape = .block,
pub fn deinit(self: *Mode) void {
self.input_handler.deinit();
@ -42,6 +42,15 @@ pub const Mode = struct {
pub const KeybindHints = std.static_string_map.StaticStringMap([]const u8);
const renderer = @import("renderer");
pub const CursorShape = enum {
default,
block_blink,
block,
underline_blink,
underline,
beam_blink,
beam,
};
const EventHandler = @import("EventHandler");
const std = @import("std");

View file

@ -1,7 +1,5 @@
const tp = @import("thespian");
const key = @import("renderer").input.key;
const mod = @import("renderer").input.modifier;
const event_type = @import("renderer").input.event_type;
const input = @import("input");
const command = @import("command");
const EventHandler = @import("EventHandler");
@ -10,29 +8,29 @@ pub fn create(_: @import("std").mem.Allocator, _: anytype) !EventHandler {
}
pub fn receive(_: tp.pid_ref, m: tp.message) error{Exit}!bool {
var evtype: u32 = undefined;
var keypress: u32 = undefined;
var egc: u32 = undefined;
var modifiers: u32 = undefined;
var event: input.Event = undefined;
var keypress: input.Key = undefined;
var egc: input.Key = undefined;
var modifiers: input.Mods = undefined;
if (try m.match(.{ "I", tp.extract(&evtype), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) {
mapEvent(evtype, keypress, egc, modifiers) catch |e| return tp.exit_error(e, @errorReturnTrace());
if (try m.match(.{ "I", tp.extract(&event), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) {
map_event(event, keypress, egc, modifiers) catch |e| return tp.exit_error(e, @errorReturnTrace());
}
return false;
}
fn mapEvent(evtype: u32, keypress: u32, egc: u32, modifiers: u32) !void {
switch (evtype) {
event_type.PRESS => try mapPress(keypress, egc, modifiers),
event_type.REPEAT => try mapPress(keypress, egc, modifiers),
fn map_event(event: input.Event, keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void {
switch (event) {
input.event.press => try map_press(keypress, egc, modifiers),
input.event.repeat => try map_press(keypress, egc, modifiers),
else => {},
}
}
fn mapPress(keypress: u32, egc: u32, modifiers: u32) !void {
fn map_press(keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void {
const keynormal = if ('a' <= keypress and keypress <= 'z') keypress - ('a' - 'A') else keypress;
return switch (modifiers) {
mod.CTRL => switch (keynormal) {
input.mod.ctrl => switch (keynormal) {
'Q' => command.executeName("quit", .{}),
'V' => command.executeName("system_paste", .{}),
'U' => command.executeName("mini_mode_reset", .{}),
@ -40,34 +38,34 @@ fn mapPress(keypress: u32, egc: u32, modifiers: u32) !void {
'C' => command.executeName("mini_mode_cancel", .{}),
'L' => command.executeName("scroll_view_center", .{}),
'I' => command.executeName("mini_mode_insert_bytes", command.fmt(.{"\t"})),
key.SPACE => command.executeName("mini_mode_cancel", .{}),
key.BACKSPACE => command.executeName("mini_mode_delete_to_previous_path_segment", .{}),
input.key.space => command.executeName("mini_mode_cancel", .{}),
input.key.backspace => command.executeName("mini_mode_delete_to_previous_path_segment", .{}),
else => {},
},
mod.ALT => switch (keynormal) {
input.mod.alt => switch (keynormal) {
'V' => command.executeName("system_paste", .{}),
else => {},
},
mod.ALT | mod.SHIFT => switch (keynormal) {
input.mod.alt | input.mod.shift => switch (keynormal) {
'V' => command.executeName("system_paste", .{}),
else => {},
},
mod.SHIFT => switch (keypress) {
key.TAB => command.executeName("mini_mode_reverse_complete_file", .{}),
else => if (!key.synthesized_p(keypress))
input.mod.shift => switch (keypress) {
input.key.tab => command.executeName("mini_mode_reverse_complete_file", .{}),
else => if (!input.is_non_input_key(keypress))
command.executeName("mini_mode_insert_code_point", command.fmt(.{egc}))
else {},
},
0 => switch (keypress) {
key.UP => command.executeName("mini_mode_reverse_complete_file", .{}),
key.DOWN => command.executeName("mini_mode_try_complete_file", .{}),
key.RIGHT => command.executeName("mini_mode_try_complete_file_forward", .{}),
key.LEFT => command.executeName("mini_mode_delete_to_previous_path_segment", .{}),
key.TAB => command.executeName("mini_mode_try_complete_file", .{}),
key.ESC => command.executeName("mini_mode_cancel", .{}),
key.ENTER => command.executeName("mini_mode_select", .{}),
key.BACKSPACE => command.executeName("mini_mode_delete_backwards", .{}),
else => if (!key.synthesized_p(keypress))
input.key.up => command.executeName("mini_mode_reverse_complete_file", .{}),
input.key.down => command.executeName("mini_mode_try_complete_file", .{}),
input.key.right => command.executeName("mini_mode_try_complete_file_forward", .{}),
input.key.left => command.executeName("mini_mode_delete_to_previous_path_segment", .{}),
input.key.tab => command.executeName("mini_mode_try_complete_file", .{}),
input.key.escape => command.executeName("mini_mode_cancel", .{}),
input.key.enter => command.executeName("mini_mode_select", .{}),
input.key.backspace => command.executeName("mini_mode_delete_backwards", .{}),
else => if (!input.is_non_input_key(keypress))
command.executeName("mini_mode_insert_code_point", command.fmt(.{egc}))
else {},
},

View file

@ -1,7 +1,5 @@
const tp = @import("thespian");
const key = @import("renderer").input.key;
const mod = @import("renderer").input.modifier;
const event_type = @import("renderer").input.event_type;
const input = @import("input");
const command = @import("command");
const EventHandler = @import("EventHandler");
@ -10,29 +8,29 @@ pub fn create(_: @import("std").mem.Allocator, _: anytype) !EventHandler {
}
pub fn receive(_: tp.pid_ref, m: tp.message) error{Exit}!bool {
var evtype: u32 = undefined;
var keypress: u32 = undefined;
var egc: u32 = undefined;
var modifiers: u32 = undefined;
var event: input.Event = undefined;
var keypress: input.Key = undefined;
var egc: input.Key = undefined;
var modifiers: input.Mods = undefined;
if (try m.match(.{ "I", tp.extract(&evtype), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) {
mapEvent(evtype, keypress, egc, modifiers) catch |e| return tp.exit_error(e, @errorReturnTrace());
if (try m.match(.{ "I", tp.extract(&event), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) {
map_event(event, keypress, egc, modifiers) catch |e| return tp.exit_error(e, @errorReturnTrace());
}
return false;
}
fn mapEvent(evtype: u32, keypress: u32, egc: u32, modifiers: u32) !void {
switch (evtype) {
event_type.PRESS => try mapPress(keypress, egc, modifiers),
event_type.REPEAT => try mapPress(keypress, egc, modifiers),
fn map_event(event: input.Event, keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void {
switch (event) {
input.event.press => try map_press(keypress, egc, modifiers),
input.event.repeat => try map_press(keypress, egc, modifiers),
else => {},
}
}
fn mapPress(keypress: u32, egc: u32, modifiers: u32) !void {
fn map_press(keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void {
const keynormal = if ('a' <= keypress and keypress <= 'z') keypress - ('a' - 'A') else keypress;
return switch (modifiers) {
mod.CTRL => switch (keynormal) {
input.mod.ctrl => switch (keynormal) {
'Q' => command.executeName("quit", .{}),
'V' => command.executeName("system_paste", .{}),
'U' => command.executeName("mini_mode_reset", .{}),
@ -43,41 +41,41 @@ fn mapPress(keypress: u32, egc: u32, modifiers: u32) !void {
'N' => command.executeName("goto_next_match", .{}),
'P' => command.executeName("goto_prev_match", .{}),
'I' => command.executeName("mini_mode_insert_bytes", command.fmt(.{"\t"})),
key.SPACE => command.executeName("mini_mode_cancel", .{}),
key.ENTER => command.executeName("mini_mode_insert_bytes", command.fmt(.{"\n"})),
key.BACKSPACE => command.executeName("mini_mode_reset", .{}),
input.key.space => command.executeName("mini_mode_cancel", .{}),
input.key.enter => command.executeName("mini_mode_insert_bytes", command.fmt(.{"\n"})),
input.key.backspace => command.executeName("mini_mode_reset", .{}),
else => {},
},
mod.ALT => switch (keynormal) {
input.mod.alt => switch (keynormal) {
'V' => command.executeName("system_paste", .{}),
'N' => command.executeName("goto_next_match", .{}),
'P' => command.executeName("goto_prev_match", .{}),
else => {},
},
mod.ALT | mod.SHIFT => switch (keynormal) {
input.mod.alt | input.mod.shift => switch (keynormal) {
'V' => command.executeName("system_paste", .{}),
else => {},
},
mod.SHIFT => switch (keypress) {
key.ENTER => command.executeName("goto_prev_match", .{}),
key.F03 => command.executeName("goto_prev_match", .{}),
else => if (!key.synthesized_p(keypress))
input.mod.shift => switch (keypress) {
input.key.enter => command.executeName("goto_prev_match", .{}),
input.key.f3 => command.executeName("goto_prev_match", .{}),
else => if (!input.is_non_input_key(keypress))
command.executeName("mini_mode_insert_code_point", command.fmt(.{egc}))
else {},
},
0 => switch (keypress) {
key.UP => command.executeName("mini_mode_history_prev", .{}),
key.DOWN => command.executeName("mini_mode_history_next", .{}),
key.F03 => command.executeName("goto_next_match", .{}),
key.F15 => command.executeName("goto_prev_match", .{}),
key.F09 => command.executeName("theme_prev", .{}),
key.F10 => command.executeName("theme_next", .{}),
key.ESC => command.executeName("mini_mode_cancel", .{}),
key.ENTER => command.executeName("mini_mode_select", .{}),
key.BACKSPACE => command.executeName("mini_mode_delete_backwards", .{}),
key.LCTRL, key.RCTRL => command.executeName("enable_fast_scroll", .{}),
key.LALT, key.RALT => command.executeName("enable_fast_scroll", .{}),
else => if (!key.synthesized_p(keypress))
input.key.up => command.executeName("mini_mode_history_prev", .{}),
input.key.down => command.executeName("mini_mode_history_next", .{}),
input.key.f3 => command.executeName("goto_next_match", .{}),
input.key.f15 => command.executeName("goto_prev_match", .{}),
input.key.f9 => command.executeName("theme_prev", .{}),
input.key.f10 => command.executeName("theme_next", .{}),
input.key.escape => command.executeName("mini_mode_cancel", .{}),
input.key.enter => command.executeName("mini_mode_select", .{}),
input.key.backspace => command.executeName("mini_mode_delete_backwards", .{}),
input.key.left_control, input.key.right_control => command.executeName("enable_fast_scroll", .{}),
input.key.left_alt, input.key.right_alt => command.executeName("enable_fast_scroll", .{}),
else => if (!input.is_non_input_key(keypress))
command.executeName("mini_mode_insert_code_point", command.fmt(.{egc}))
else {},
},

View file

@ -1,7 +1,5 @@
const tp = @import("thespian");
const key = @import("renderer").input.key;
const mod = @import("renderer").input.modifier;
const event_type = @import("renderer").input.event_type;
const input = @import("input");
const command = @import("command");
const EventHandler = @import("EventHandler");
@ -10,30 +8,30 @@ pub fn create(_: @import("std").mem.Allocator, _: anytype) !EventHandler {
}
pub fn receive(_: tp.pid_ref, m: tp.message) error{Exit}!bool {
var evtype: u32 = undefined;
var keypress: u32 = undefined;
var egc: u32 = undefined;
var modifiers: u32 = undefined;
var event: input.Event = undefined;
var keypress: input.Key = undefined;
var egc: input.Key = undefined;
var modifiers: input.Mods = undefined;
if (try m.match(.{ "I", tp.extract(&evtype), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) {
mapEvent(evtype, keypress, egc, modifiers) catch |e| return tp.exit_error(e, @errorReturnTrace());
if (try m.match(.{ "I", tp.extract(&event), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) {
map_event(event, keypress, egc, modifiers) catch |e| return tp.exit_error(e, @errorReturnTrace());
}
return false;
}
fn mapEvent(evtype: u32, keypress: u32, egc: u32, modifiers: u32) !void {
switch (evtype) {
event_type.PRESS => try mapPress(keypress, egc, modifiers),
event_type.REPEAT => try mapPress(keypress, egc, modifiers),
event_type.RELEASE => try mapRelease(keypress, egc, modifiers),
fn map_event(event: input.Event, keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void {
switch (event) {
input.event.press => try map_press(keypress, egc, modifiers),
input.event.repeat => try map_press(keypress, egc, modifiers),
input.event.release => try map_release(keypress, egc, modifiers),
else => {},
}
}
fn mapPress(keypress: u32, egc: u32, modifiers: u32) !void {
fn map_press(keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void {
const keynormal = if ('a' <= keypress and keypress <= 'z') keypress - ('a' - 'A') else keypress;
return switch (modifiers) {
mod.CTRL => switch (keynormal) {
input.mod.ctrl => switch (keynormal) {
'Q' => command.executeName("quit", .{}),
'V' => command.executeName("system_paste", .{}),
'U' => command.executeName("mini_mode_reset", .{}),
@ -44,41 +42,41 @@ fn mapPress(keypress: u32, egc: u32, modifiers: u32) !void {
'N' => command.executeName("goto_next_match", .{}),
'P' => command.executeName("goto_prev_match", .{}),
'I' => command.executeName("mini_mode_insert_bytes", command.fmt(.{"\t"})),
key.SPACE => command.executeName("exit_mini_mode", .{}),
key.ENTER => command.executeName("mini_mode_insert_bytes", command.fmt(.{"\n"})),
key.BACKSPACE => command.executeName("mini_mode_reset", .{}),
input.key.space => command.executeName("exit_mini_mode", .{}),
input.key.enter => command.executeName("mini_mode_insert_bytes", command.fmt(.{"\n"})),
input.key.backspace => command.executeName("mini_mode_reset", .{}),
else => {},
},
mod.ALT => switch (keynormal) {
input.mod.alt => switch (keynormal) {
'V' => command.executeName("system_paste", .{}),
'N' => command.executeName("goto_next_file", .{}),
'P' => command.executeName("goto_prev_file", .{}),
else => {},
},
mod.ALT | mod.SHIFT => switch (keynormal) {
input.mod.alt | input.mod.shift => switch (keynormal) {
'V' => command.executeName("system_paste", .{}),
else => {},
},
mod.SHIFT => switch (keypress) {
key.ENTER => command.executeName("goto_prev_match", .{}),
key.F03 => command.executeName("goto_prev_match", .{}),
else => if (!key.synthesized_p(keypress))
input.mod.shift => switch (keypress) {
input.key.enter => command.executeName("goto_prev_match", .{}),
input.key.f3 => command.executeName("goto_prev_match", .{}),
else => if (!input.is_non_input_key(keypress))
command.executeName("mini_mode_insert_code_point", command.fmt(.{egc}))
else {},
},
0 => switch (keypress) {
key.UP => command.executeName("select_prev_file", .{}),
key.DOWN => command.executeName("select_next_file", .{}),
key.F03 => command.executeName("goto_next_match", .{}),
key.F15 => command.executeName("goto_prev_match", .{}),
key.F09 => command.executeName("theme_prev", .{}),
key.F10 => command.executeName("theme_next", .{}),
key.ESC => command.executeName("exit_mini_mode", .{}),
key.ENTER => command.executeName("mini_mode_select", .{}),
key.BACKSPACE => command.executeName("mini_mode_delete_backwards", .{}),
key.LCTRL, key.RCTRL => command.executeName("enable_fast_scroll", .{}),
key.LALT, key.RALT => command.executeName("enable_fast_scroll", .{}),
else => if (!key.synthesized_p(keypress))
input.key.up => command.executeName("select_prev_file", .{}),
input.key.down => command.executeName("select_next_file", .{}),
input.key.f3 => command.executeName("goto_next_match", .{}),
input.key.f15 => command.executeName("goto_prev_match", .{}),
input.key.f9 => command.executeName("theme_prev", .{}),
input.key.f10 => command.executeName("theme_next", .{}),
input.key.escape => command.executeName("exit_mini_mode", .{}),
input.key.enter => command.executeName("mini_mode_select", .{}),
input.key.backspace => command.executeName("mini_mode_delete_backwards", .{}),
input.key.left_control, input.key.right_control => command.executeName("enable_fast_scroll", .{}),
input.key.left_alt, input.key.right_alt => command.executeName("enable_fast_scroll", .{}),
else => if (!input.is_non_input_key(keypress))
command.executeName("mini_mode_insert_code_point", command.fmt(.{egc}))
else {},
},
@ -86,10 +84,10 @@ fn mapPress(keypress: u32, egc: u32, modifiers: u32) !void {
};
}
fn mapRelease(keypress: u32, _: u32, _: u32) !void {
fn map_release(keypress: input.Key, _: input.Key, _: input.Mods) !void {
return switch (keypress) {
key.LCTRL, key.RCTRL => command.executeName("disable_fast_scroll", .{}),
key.LALT, key.RALT => command.executeName("disable_fast_scroll", .{}),
input.key.left_control, input.key.right_control => command.executeName("disable_fast_scroll", .{}),
input.key.left_alt, input.key.right_alt => command.executeName("disable_fast_scroll", .{}),
else => {},
};
}

View file

@ -1,7 +1,5 @@
const tp = @import("thespian");
const key = @import("renderer").input.key;
const mod = @import("renderer").input.modifier;
const event_type = @import("renderer").input.event_type;
const input = @import("input");
const command = @import("command");
const EventHandler = @import("EventHandler");
@ -10,41 +8,41 @@ pub fn create(_: @import("std").mem.Allocator, _: anytype) !EventHandler {
}
pub fn receive(_: tp.pid_ref, m: tp.message) error{Exit}!bool {
var evtype: u32 = undefined;
var keypress: u32 = undefined;
var modifiers: u32 = undefined;
if (try m.match(.{ "I", tp.extract(&evtype), tp.extract(&keypress), tp.any, tp.string, tp.extract(&modifiers) }))
try mapEvent(evtype, keypress, modifiers);
var event: input.Event = undefined;
var keypress: input.Key = undefined;
var modifiers: input.Mods = undefined;
if (try m.match(.{ "I", tp.extract(&event), tp.extract(&keypress), tp.any, tp.string, tp.extract(&modifiers) }))
try map_event(event, keypress, modifiers);
return false;
}
fn mapEvent(evtype: u32, keypress: u32, modifiers: u32) tp.result {
switch (evtype) {
event_type.PRESS => try mapPress(keypress, modifiers),
event_type.REPEAT => try mapPress(keypress, modifiers),
event_type.RELEASE => try mapRelease(keypress, modifiers),
fn map_event(event: input.Event, keypress: input.Key, modifiers: input.Mods) tp.result {
switch (event) {
input.event.press => try map_press(keypress, modifiers),
input.event.repeat => try map_press(keypress, modifiers),
input.event.release => try map_release(keypress),
else => {},
}
}
fn mapPress(keypress: u32, modifiers: u32) tp.result {
fn map_press(keypress: input.Key, modifiers: input.Mods) tp.result {
const keynormal = if ('a' <= keypress and keypress <= 'z') keypress - ('a' - 'A') else keypress;
return switch (modifiers) {
mod.CTRL => switch (keynormal) {
input.mod.ctrl => switch (keynormal) {
'Q' => command.executeName("quit", .{}),
'U' => command.executeName("mini_mode_reset", .{}),
'G' => command.executeName("mini_mode_cancel", .{}),
'C' => command.executeName("mini_mode_cancel", .{}),
'L' => command.executeName("scroll_view_center", .{}),
key.SPACE => command.executeName("mini_mode_cancel", .{}),
input.key.space => command.executeName("mini_mode_cancel", .{}),
else => {},
},
0 => switch (keypress) {
key.LCTRL, key.RCTRL => command.executeName("enable_fast_scroll", .{}),
key.LALT, key.RALT => command.executeName("enable_fast_scroll", .{}),
key.ESC => command.executeName("mini_mode_cancel", .{}),
key.ENTER => command.executeName("exit_mini_mode", .{}),
key.BACKSPACE => command.executeName("mini_mode_delete_backwards", .{}),
input.key.left_control, input.key.right_control => command.executeName("enable_fast_scroll", .{}),
input.key.left_alt, input.key.right_alt => command.executeName("enable_fast_scroll", .{}),
input.key.escape => command.executeName("mini_mode_cancel", .{}),
input.key.enter => command.executeName("exit_mini_mode", .{}),
input.key.backspace => command.executeName("mini_mode_delete_backwards", .{}),
'0'...'9' => command.executeName("mini_mode_insert_code_point", command.fmt(.{keypress})),
else => {},
},
@ -52,10 +50,10 @@ fn mapPress(keypress: u32, modifiers: u32) tp.result {
};
}
fn mapRelease(keypress: u32, _: u32) tp.result {
fn map_release(keypress: input.Key) tp.result {
return switch (keypress) {
key.LCTRL, key.RCTRL => command.executeName("disable_fast_scroll", .{}),
key.LALT, key.RALT => command.executeName("disable_fast_scroll", .{}),
input.key.left_control, input.key.right_control => command.executeName("disable_fast_scroll", .{}),
input.key.left_alt, input.key.right_alt => command.executeName("disable_fast_scroll", .{}),
else => {},
};
}

View file

@ -1,7 +1,5 @@
const tp = @import("thespian");
const key = @import("renderer").input.key;
const mod = @import("renderer").input.modifier;
const event_type = @import("renderer").input.event_type;
const input = @import("input");
const command = @import("command");
const EventHandler = @import("EventHandler");
@ -10,39 +8,39 @@ pub fn create(_: @import("std").mem.Allocator, _: anytype) !EventHandler {
}
pub fn receive(_: tp.pid_ref, m: tp.message) error{Exit}!bool {
var evtype: u32 = undefined;
var keypress: u32 = undefined;
var modifiers: u32 = undefined;
var egc: u32 = undefined;
if (try m.match(.{ "I", tp.extract(&evtype), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) }))
try mapEvent(evtype, keypress, egc, modifiers);
var event: input.Event = undefined;
var keypress: input.Key = undefined;
var egc: input.Key = undefined;
var modifiers: input.Mods = undefined;
if (try m.match(.{ "I", tp.extract(&event), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) }))
try map_event(event, keypress, egc, modifiers);
return false;
}
fn mapEvent(evtype: u32, keypress: u32, egc: u32, modifiers: u32) tp.result {
switch (evtype) {
event_type.PRESS => try mapPress(keypress, egc, modifiers),
fn map_event(event: input.Event, keypress: input.Key, egc: input.Key, modifiers: input.Mods) tp.result {
switch (event) {
input.event.press => try map_press(keypress, egc, modifiers),
else => {},
}
}
fn mapPress(keypress: u32, egc: u32, modifiers: u32) tp.result {
fn map_press(keypress: input.Key, egc: input.Key, modifiers: input.Mods) tp.result {
switch (keypress) {
key.LSUPER, key.RSUPER => return,
key.LSHIFT, key.RSHIFT => return,
key.LCTRL, key.RCTRL => return,
key.LALT, key.RALT => return,
input.key.left_super, input.key.right_super => return,
input.key.left_shift, input.key.right_shift => return,
input.key.left_control, input.key.right_control => return,
input.key.left_alt, input.key.right_alt => return,
else => {},
}
return switch (modifiers) {
mod.SHIFT => if (!key.synthesized_p(keypress))
input.mod.shift => if (!input.is_non_input_key(keypress))
command.executeName("mini_mode_insert_code_point", command.fmt(.{egc}))
else
command.executeName("mini_mode_cancel", .{}),
0 => switch (keypress) {
key.ESC => command.executeName("mini_mode_cancel", .{}),
key.ENTER => command.executeName("mini_mode_cancel", .{}),
else => if (!key.synthesized_p(keypress))
input.key.escape => command.executeName("mini_mode_cancel", .{}),
input.key.enter => command.executeName("mini_mode_cancel", .{}),
else => if (!input.is_non_input_key(keypress))
command.executeName("mini_mode_insert_code_point", command.fmt(.{egc}))
else
command.executeName("mini_mode_cancel", .{}),

View file

@ -1,7 +1,5 @@
const tp = @import("thespian");
const key = @import("renderer").input.key;
const mod = @import("renderer").input.modifier;
const event_type = @import("renderer").input.event_type;
const input = @import("input");
const command = @import("command");
const EventHandler = @import("EventHandler");
@ -10,30 +8,30 @@ pub fn create(_: @import("std").mem.Allocator, _: anytype) !EventHandler {
}
pub fn receive(_: tp.pid_ref, m: tp.message) error{Exit}!bool {
var evtype: u32 = undefined;
var keypress: u32 = undefined;
var egc: u32 = undefined;
var modifiers: u32 = undefined;
var event: input.Event = undefined;
var keypress: input.Key = undefined;
var egc: input.Key = undefined;
var modifiers: input.Mods = undefined;
if (try m.match(.{ "I", tp.extract(&evtype), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) {
mapEvent(evtype, keypress, egc, modifiers) catch |e| return tp.exit_error(e, @errorReturnTrace());
if (try m.match(.{ "I", tp.extract(&event), tp.extract(&keypress), tp.extract(&egc), tp.string, tp.extract(&modifiers) })) {
map_event(event, keypress, egc, modifiers) catch |e| return tp.exit_error(e, @errorReturnTrace());
}
return false;
}
fn mapEvent(evtype: u32, keypress: u32, egc: u32, modifiers: u32) !void {
return switch (evtype) {
event_type.PRESS => mapPress(keypress, egc, modifiers),
event_type.REPEAT => mapPress(keypress, egc, modifiers),
event_type.RELEASE => mapRelease(keypress, modifiers),
fn map_event(event: input.Event, keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void {
return switch (event) {
input.event.press => map_press(keypress, egc, modifiers),
input.event.repeat => map_press(keypress, egc, modifiers),
input.event.release => map_release(keypress),
else => {},
};
}
fn mapPress(keypress: u32, egc: u32, modifiers: u32) !void {
fn map_press(keypress: input.Key, egc: input.Key, modifiers: input.Mods) !void {
const keynormal = if ('a' <= keypress and keypress <= 'z') keypress - ('a' - 'A') else keypress;
return switch (modifiers) {
mod.CTRL => switch (keynormal) {
input.mod.ctrl => switch (keynormal) {
'J' => command.executeName("toggle_panel", .{}),
'Q' => command.executeName("quit", .{}),
'W' => command.executeName("close_file", .{}),
@ -45,16 +43,16 @@ fn mapPress(keypress: u32, egc: u32, modifiers: u32) !void {
'V' => command.executeName("system_paste", .{}),
'C' => command.executeName("palette_menu_cancel", .{}),
'G' => command.executeName("palette_menu_cancel", .{}),
key.ESC => command.executeName("palette_menu_cancel", .{}),
key.UP => command.executeName("palette_menu_up", .{}),
key.DOWN => command.executeName("palette_menu_down", .{}),
key.PGUP => command.executeName("palette_menu_pageup", .{}),
key.PGDOWN => command.executeName("palette_menu_pagedown", .{}),
key.ENTER => command.executeName("palette_menu_activate", .{}),
key.BACKSPACE => command.executeName("overlay_delete_word_left", .{}),
input.key.escape => command.executeName("palette_menu_cancel", .{}),
input.key.up => command.executeName("palette_menu_up", .{}),
input.key.down => command.executeName("palette_menu_down", .{}),
input.key.page_up => command.executeName("palette_menu_pageup", .{}),
input.key.page_down => command.executeName("palette_menu_pagedown", .{}),
input.key.enter => command.executeName("palette_menu_activate", .{}),
input.key.backspace => command.executeName("overlay_delete_word_left", .{}),
else => {},
},
mod.CTRL | mod.SHIFT => switch (keynormal) {
input.mod.ctrl | input.mod.shift => switch (keynormal) {
'E' => command.executeName("palette_menu_up", .{}), // open recent repeat key
'R' => command.executeName("palette_menu_up", .{}), // open recent project repeat key
'P' => command.executeName("palette_menu_down", .{}), // command palette repeat key
@ -64,34 +62,34 @@ fn mapPress(keypress: u32, egc: u32, modifiers: u32) !void {
'I' => command.executeName("overlay_toggle_inputview", .{}),
else => {},
},
mod.ALT | mod.SHIFT => switch (keynormal) {
input.mod.alt | input.mod.shift => switch (keynormal) {
'P' => command.executeName("palette_menu_down", .{}),
else => {},
},
mod.ALT => switch (keynormal) {
input.mod.alt => switch (keynormal) {
'P' => command.executeName("palette_menu_up", .{}),
'L' => command.executeName("toggle_panel", .{}),
'I' => command.executeName("toggle_inputview", .{}),
else => {},
},
mod.SHIFT => switch (keypress) {
else => if (!key.synthesized_p(keypress))
input.mod.shift => switch (keypress) {
else => if (!input.is_non_input_key(keypress))
command.executeName("overlay_insert_code_point", command.fmt(.{egc}))
else {},
},
0 => switch (keypress) {
key.F09 => command.executeName("theme_prev", .{}),
key.F10 => command.executeName("theme_next", .{}),
key.F11 => command.executeName("toggle_panel", .{}),
key.F12 => command.executeName("toggle_inputview", .{}),
key.ESC => command.executeName("palette_menu_cancel", .{}),
key.UP => command.executeName("palette_menu_up", .{}),
key.DOWN => command.executeName("palette_menu_down", .{}),
key.PGUP => command.executeName("palette_menu_pageup", .{}),
key.PGDOWN => command.executeName("palette_menu_pagedown", .{}),
key.ENTER => command.executeName("palette_menu_activate", .{}),
key.BACKSPACE => command.executeName("overlay_delete_backwards", .{}),
else => if (!key.synthesized_p(keypress))
input.key.f9 => command.executeName("theme_prev", .{}),
input.key.f10 => command.executeName("theme_next", .{}),
input.key.f11 => command.executeName("toggle_panel", .{}),
input.key.f12 => command.executeName("toggle_inputview", .{}),
input.key.escape => command.executeName("palette_menu_cancel", .{}),
input.key.up => command.executeName("palette_menu_up", .{}),
input.key.down => command.executeName("palette_menu_down", .{}),
input.key.page_up => command.executeName("palette_menu_pageup", .{}),
input.key.page_down => command.executeName("palette_menu_pagedown", .{}),
input.key.enter => command.executeName("palette_menu_activate", .{}),
input.key.backspace => command.executeName("overlay_delete_backwards", .{}),
else => if (!input.is_non_input_key(keypress))
command.executeName("overlay_insert_code_point", command.fmt(.{egc}))
else {},
},
@ -99,9 +97,9 @@ fn mapPress(keypress: u32, egc: u32, modifiers: u32) !void {
};
}
fn mapRelease(keypress: u32, _: u32) !void {
fn map_release(keypress: input.Key) !void {
return switch (keypress) {
key.LCTRL, key.RCTRL => command.executeName("overlay_release_control", .{}),
input.key.left_control, input.key.right_control => command.executeName("overlay_release_control", .{}),
else => {},
};
}

View file

@ -1,265 +1,167 @@
const Key = @import("vaxis").Key;
const Mouse = @import("vaxis").Mouse;
const vaxis = @import("vaxis");
pub const key = struct {
pub const ENTER: key_type = Key.enter;
pub const TAB: key_type = Key.tab;
pub const ESC: key_type = Key.escape;
pub const SPACE: key_type = Key.space;
pub const BACKSPACE: key_type = Key.backspace;
const utf8Encode = @import("std").unicode.utf8Encode;
pub const INS: key_type = Key.insert;
pub const DEL: key_type = Key.delete;
pub const LEFT: key_type = Key.left;
pub const RIGHT: key_type = Key.right;
pub const UP: key_type = Key.up;
pub const DOWN: key_type = Key.down;
pub const PGDOWN: key_type = Key.page_down;
pub const PGUP: key_type = Key.page_up;
pub const HOME: key_type = Key.home;
pub const END: key_type = Key.end;
pub const CAPS_LOCK: key_type = Key.caps_lock;
pub const SCROLL_LOCK: key_type = Key.scroll_lock;
pub const NUM_LOCK: key_type = Key.num_lock;
pub const PRINT_SCREEN: key_type = Key.print_screen;
pub const PAUSE: key_type = Key.pause;
pub const MENU: key_type = Key.menu;
pub const F01: key_type = Key.f1;
pub const F02: key_type = Key.f2;
pub const F03: key_type = Key.f3;
pub const F04: key_type = Key.f4;
pub const F05: key_type = Key.f5;
pub const F06: key_type = Key.f6;
pub const F07: key_type = Key.f7;
pub const F08: key_type = Key.f8;
pub const F09: key_type = Key.f9;
pub const F10: key_type = Key.f10;
pub const F11: key_type = Key.f11;
pub const F12: key_type = Key.f12;
pub const F13: key_type = Key.f13;
pub const F14: key_type = Key.f14;
pub const F15: key_type = Key.f15;
pub const F16: key_type = Key.f16;
pub const F17: key_type = Key.f17;
pub const F18: key_type = Key.f18;
pub const F19: key_type = Key.f19;
pub const F20: key_type = Key.f20;
pub const F21: key_type = Key.f21;
pub const F22: key_type = Key.f22;
pub const F23: key_type = Key.f23;
pub const F24: key_type = Key.f24;
pub const F25: key_type = Key.f25;
pub const F26: key_type = Key.f26;
pub const F27: key_type = Key.f27;
pub const F28: key_type = Key.f28;
pub const F29: key_type = Key.f29;
pub const F30: key_type = Key.f30;
pub const F31: key_type = Key.f31;
pub const F32: key_type = Key.f32;
pub const F33: key_type = Key.f33;
pub const F34: key_type = Key.f34;
pub const F35: key_type = Key.f35;
pub const key = vaxis.Key;
pub const Key = u21;
pub const F58: key_type = Key.iso_level_5_shift + 1; // FIXME bogus
pub const Mouse = vaxis.Mouse.Button;
pub const MouseType = @typeInfo(Mouse).Enum.tag_type;
pub const MEDIA_PLAY: key_type = Key.media_play;
pub const MEDIA_PAUSE: key_type = Key.media_pause;
pub const MEDIA_PPAUSE: key_type = Key.media_play_pause;
pub const MEDIA_REV: key_type = Key.media_reverse;
pub const MEDIA_STOP: key_type = Key.media_stop;
pub const MEDIA_FF: key_type = Key.media_fast_forward;
pub const MEDIA_REWIND: key_type = Key.media_rewind;
pub const MEDIA_NEXT: key_type = Key.media_track_next;
pub const MEDIA_PREV: key_type = Key.media_track_previous;
pub const MEDIA_RECORD: key_type = Key.media_record;
pub const MEDIA_LVOL: key_type = Key.lower_volume;
pub const MEDIA_RVOL: key_type = Key.raise_volume;
pub const MEDIA_MUTE: key_type = Key.mute_volume;
pub const LSHIFT: key_type = Key.left_shift;
pub const LCTRL: key_type = Key.left_control;
pub const LALT: key_type = Key.left_alt;
pub const LSUPER: key_type = Key.left_super;
pub const LHYPER: key_type = Key.left_hyper;
pub const LMETA: key_type = Key.left_meta;
pub const RSHIFT: key_type = Key.right_shift;
pub const RCTRL: key_type = Key.right_control;
pub const RALT: key_type = Key.right_alt;
pub const RSUPER: key_type = Key.right_super;
pub const RHYPER: key_type = Key.right_hyper;
pub const RMETA: key_type = Key.right_meta;
pub const L3SHIFT: key_type = Key.iso_level_3_shift;
pub const L5SHIFT: key_type = Key.iso_level_5_shift;
pub const MOTION: key_type = @intCast(@intFromEnum(Mouse.Button.none));
pub const BUTTON1: key_type = @intCast(@intFromEnum(Mouse.Button.left));
pub const BUTTON2: key_type = @intCast(@intFromEnum(Mouse.Button.middle));
pub const BUTTON3: key_type = @intCast(@intFromEnum(Mouse.Button.right));
pub const BUTTON4: key_type = @intCast(@intFromEnum(Mouse.Button.wheel_up));
pub const BUTTON5: key_type = @intCast(@intFromEnum(Mouse.Button.wheel_down));
// pub const BUTTON6: key_type = @intCast(@intFromEnum(Mouse.Button.button_6));
// pub const BUTTON7: key_type = @intCast(@intFromEnum(Mouse.Button.button_7));
pub const BUTTON8: key_type = @intCast(@intFromEnum(Mouse.Button.button_8));
pub const BUTTON9: key_type = @intCast(@intFromEnum(Mouse.Button.button_9));
pub const BUTTON10: key_type = @intCast(@intFromEnum(Mouse.Button.button_10));
pub const BUTTON11: key_type = @intCast(@intFromEnum(Mouse.Button.button_11));
// pub const SIGNAL: key_type = Key.SIGNAL;
// pub const EOF: key_type = Key.EOF;
// pub const SCROLL_UP: key_type = Key.SCROLL_UP;
// pub const SCROLL_DOWN: key_type = Key.SCROLL_DOWN;
/// Is this uint32_t a synthesized event?
pub fn synthesized_p(w: u32) bool {
return switch (w) {
Key.insert...Key.iso_level_5_shift => true,
Key.enter => true,
Key.tab => true,
Key.escape => true,
Key.backspace => true,
else => false,
};
}
pub const mouse = struct {
pub const MOTION: Mouse = vaxis.Mouse.Button.none;
pub const BUTTON1: Mouse = vaxis.Mouse.Button.left;
pub const BUTTON2: Mouse = vaxis.Mouse.Button.middle;
pub const BUTTON3: Mouse = vaxis.Mouse.Button.right;
pub const BUTTON4: Mouse = vaxis.Mouse.Button.wheel_up;
pub const BUTTON5: Mouse = vaxis.Mouse.Button.wheel_down;
// pub const BUTTON6: Mouse = vaxis.Mouse.Button.button_6;
// pub const BUTTON7: Mouse = vaxis.Mouse.Button.button_7;
pub const BUTTON8: Mouse = vaxis.Mouse.Button.button_8;
pub const BUTTON9: Mouse = vaxis.Mouse.Button.button_9;
pub const BUTTON10: Mouse = vaxis.Mouse.Button.button_10;
pub const BUTTON11: Mouse = vaxis.Mouse.Button.button_11;
};
pub const key_type = u21;
pub const modifier = struct {
pub const SHIFT: modifier_type = 1;
pub const ALT: modifier_type = 2;
pub const CTRL: modifier_type = 4;
pub const SUPER: modifier_type = 8;
pub const HYPER: modifier_type = 16;
pub const META: modifier_type = 32;
pub const CAPSLOCK: modifier_type = 64;
pub const NUMLOCK: modifier_type = 128;
};
pub const modifier_type = u32;
/// Does this key represent input?
pub fn is_non_input_key(w: Key) bool {
return switch (w) {
vaxis.Key.insert...vaxis.Key.iso_level_5_shift => true,
vaxis.Key.enter => true,
vaxis.Key.tab => true,
vaxis.Key.escape => true,
vaxis.Key.backspace => true,
else => false,
};
}
pub const event_type = struct {
pub const PRESS: usize = 1;
pub const REPEAT: usize = 2;
pub const RELEASE: usize = 3;
pub const ModSet = vaxis.Key.Modifiers;
pub const Mods = u8;
pub const mod = struct {
pub const shift: u8 = @bitCast(ModSet{ .shift = true });
pub const alt: u8 = @bitCast(ModSet{ .alt = true });
pub const ctrl: u8 = @bitCast(ModSet{ .ctrl = true });
pub const super: u8 = @bitCast(ModSet{ .super = true });
pub const caps_lock: u8 = @bitCast(ModSet{ .caps_lock = true });
pub const num_lock: u8 = @bitCast(ModSet{ .num_lock = true });
};
pub const Event = u8;
pub const event = struct {
pub const press: Event = 1;
pub const repeat: Event = 2;
pub const release: Event = 3;
};
pub fn ucs32_to_utf8(ucs32: []const u32, utf8: []u8) !usize {
return @intCast(try utf8Encode(@intCast(ucs32[0]), utf8));
}
pub const utils = struct {
pub fn isSuper(modifiers: u32) bool {
return modifiers & modifier.SUPER != 0;
}
pub fn isCtrl(modifiers: u32) bool {
return modifiers & modifier.CTRL != 0;
}
pub fn isShift(modifiers: u32) bool {
return modifiers & modifier.SHIFT != 0;
}
pub fn isAlt(modifiers: u32) bool {
return modifiers & modifier.ALT != 0;
}
pub fn key_id_string(k: u32) []const u8 {
pub fn key_id_string(k: Key) []const u8 {
return switch (k) {
key.ENTER => "enter",
key.TAB => "tab",
key.ESC => "esc",
key.SPACE => "space",
key.BACKSPACE => "backspace",
key.INS => "ins",
key.DEL => "del",
key.LEFT => "left",
key.RIGHT => "right",
key.UP => "up",
key.DOWN => "down",
key.PGDOWN => "pgdown",
key.PGUP => "pgup",
key.HOME => "home",
key.END => "end",
key.CAPS_LOCK => "caps_lock",
key.SCROLL_LOCK => "scroll_lock",
key.NUM_LOCK => "num_lock",
key.PRINT_SCREEN => "print_screen",
key.PAUSE => "pause",
key.MENU => "menu",
key.F01 => "f01",
key.F02 => "f02",
key.F03 => "f03",
key.F04 => "f04",
key.F05 => "f05",
key.F06 => "f06",
key.F07 => "f07",
key.F08 => "f08",
key.F09 => "f09",
key.F10 => "f10",
key.F11 => "f11",
key.F12 => "f12",
key.F13 => "f13",
key.F14 => "f14",
key.F15 => "f15",
key.F16 => "f16",
key.F17 => "f17",
key.F18 => "f18",
key.F19 => "f19",
key.F20 => "f20",
key.F21 => "f21",
key.F22 => "f22",
key.F23 => "f23",
key.F24 => "f24",
key.F25 => "f25",
key.F26 => "f26",
key.F27 => "f27",
key.F28 => "f28",
key.F29 => "f29",
key.F30 => "f30",
key.F31 => "f31",
key.F32 => "f32",
key.F33 => "f33",
key.F34 => "f34",
key.F35 => "f35",
key.MEDIA_PLAY => "media_play",
key.MEDIA_PAUSE => "media_pause",
key.MEDIA_PPAUSE => "media_ppause",
key.MEDIA_REV => "media_rev",
key.MEDIA_STOP => "media_stop",
key.MEDIA_FF => "media_ff",
key.MEDIA_REWIND => "media_rewind",
key.MEDIA_NEXT => "media_next",
key.MEDIA_PREV => "media_prev",
key.MEDIA_RECORD => "media_record",
key.MEDIA_LVOL => "media_lvol",
key.MEDIA_RVOL => "media_rvol",
key.MEDIA_MUTE => "media_mute",
key.LSHIFT => "lshift",
key.LCTRL => "lctrl",
key.LALT => "lalt",
key.LSUPER => "lsuper",
key.LHYPER => "lhyper",
key.LMETA => "lmeta",
key.RSHIFT => "rshift",
key.RCTRL => "rctrl",
key.RALT => "ralt",
key.RSUPER => "rsuper",
key.RHYPER => "rhyper",
key.RMETA => "rmeta",
key.L3SHIFT => "l3shift",
key.L5SHIFT => "l5shift",
vaxis.Key.enter => "enter",
vaxis.Key.tab => "tab",
vaxis.Key.escape => "escape",
vaxis.Key.space => "space",
vaxis.Key.backspace => "backspace",
vaxis.Key.insert => "insert",
vaxis.Key.delete => "delete",
vaxis.Key.left => "left",
vaxis.Key.right => "right",
vaxis.Key.up => "up",
vaxis.Key.down => "down",
vaxis.Key.page_down => "page_down",
vaxis.Key.page_up => "page_up",
vaxis.Key.home => "home",
vaxis.Key.end => "end",
vaxis.Key.caps_lock => "caps_lock",
vaxis.Key.scroll_lock => "scroll_lock",
vaxis.Key.num_lock => "num_lock",
vaxis.Key.print_screen => "print_screen",
vaxis.Key.pause => "pause",
vaxis.Key.menu => "menu",
vaxis.Key.f1 => "f1",
vaxis.Key.f2 => "f2",
vaxis.Key.f3 => "f3",
vaxis.Key.f4 => "f4",
vaxis.Key.f5 => "f5",
vaxis.Key.f6 => "f6",
vaxis.Key.f7 => "f7",
vaxis.Key.f8 => "f8",
vaxis.Key.f9 => "f9",
vaxis.Key.f10 => "f10",
vaxis.Key.f11 => "f11",
vaxis.Key.f12 => "f12",
vaxis.Key.f13 => "f13",
vaxis.Key.f14 => "f14",
vaxis.Key.f15 => "f15",
vaxis.Key.f16 => "f16",
vaxis.Key.f17 => "f17",
vaxis.Key.f18 => "f18",
vaxis.Key.f19 => "f19",
vaxis.Key.f20 => "f20",
vaxis.Key.f21 => "f21",
vaxis.Key.f22 => "f22",
vaxis.Key.f23 => "f23",
vaxis.Key.f24 => "f24",
vaxis.Key.f25 => "f25",
vaxis.Key.f26 => "f26",
vaxis.Key.f27 => "f27",
vaxis.Key.f28 => "f28",
vaxis.Key.f29 => "f29",
vaxis.Key.f30 => "f30",
vaxis.Key.f31 => "f31",
vaxis.Key.f32 => "f32",
vaxis.Key.f33 => "f33",
vaxis.Key.f34 => "f34",
vaxis.Key.f35 => "f35",
vaxis.Key.media_play => "media_play",
vaxis.Key.media_pause => "media_pause",
vaxis.Key.media_play_pause => "media_play_pause",
vaxis.Key.media_reverse => "media_reverse",
vaxis.Key.media_stop => "media_stop",
vaxis.Key.media_fast_forward => "media_fast_forward",
vaxis.Key.media_rewind => "media_rewind",
vaxis.Key.media_track_next => "media_track_next",
vaxis.Key.media_track_previous => "media_track_previous",
vaxis.Key.media_record => "media_record",
vaxis.Key.lower_volume => "lower_volume",
vaxis.Key.raise_volume => "raise_volume",
vaxis.Key.mute_volume => "mute_volume",
vaxis.Key.left_shift => "left_shift",
vaxis.Key.left_control => "left_control",
vaxis.Key.left_alt => "left_alt",
vaxis.Key.left_super => "left_super",
vaxis.Key.left_hyper => "left_hyper",
vaxis.Key.left_meta => "left_meta",
vaxis.Key.right_shift => "right_shift",
vaxis.Key.right_control => "right_control",
vaxis.Key.right_alt => "right_alt",
vaxis.Key.right_super => "right_super",
vaxis.Key.right_hyper => "right_hyper",
vaxis.Key.right_meta => "right_meta",
vaxis.Key.iso_level_3_shift => "iso_level_3_shift",
vaxis.Key.iso_level_5_shift => "iso_level_5_shift",
else => "",
};
}
pub fn button_id_string(k: u32) []const u8 {
return switch (k) {
key.MOTION => "motion",
key.BUTTON1 => "button1",
key.BUTTON2 => "button2",
key.BUTTON3 => "button3",
key.BUTTON4 => "button4",
key.BUTTON5 => "button5",
// key.BUTTON6 => "button6",
// key.BUTTON7 => "button7",
key.BUTTON8 => "button8",
key.BUTTON9 => "button9",
key.BUTTON10 => "button10",
key.BUTTON11 => "button11",
pub fn button_id_string(m: Mouse) []const u8 {
return switch (m) {
mouse.MOTION => "motion",
mouse.BUTTON1 => "button1",
mouse.BUTTON2 => "button2",
mouse.BUTTON3 => "button3",
mouse.BUTTON4 => "button4",
mouse.BUTTON5 => "button5",
// mouse.BUTTON6 => "button6",
// mouse.BUTTON7 => "button7",
mouse.BUTTON8 => "button8",
mouse.BUTTON9 => "button9",
mouse.BUTTON10 => "button10",
mouse.BUTTON11 => "button11",
else => "",
};
}

View file

@ -4,19 +4,15 @@ const log = @import("log");
const Style = @import("theme").Style;
const Color = @import("theme").Color;
const vaxis = @import("vaxis");
const input = @import("input");
const builtin = @import("builtin");
pub const input = @import("input.zig");
pub const Plane = @import("Plane.zig");
pub const Cell = @import("Cell.zig");
pub const CursorShape = vaxis.Cell.CursorShape;
pub const style = @import("style.zig").StyleBits;
const key = input.key;
const event_type = input.event_type;
const Self = @This();
pub const log_name = "vaxis";
@ -158,7 +154,7 @@ pub fn process_input_event(self: *Self, input_: []const u8, text: ?[]const u8) !
try self.sync_mod_state(key_.codepoint, key_.mods);
const cbor_msg = try self.fmtmsg(.{
"I",
event_type.PRESS,
input.event.press,
key_.codepoint,
key_.shifted_codepoint orelse key_.codepoint,
text orelse input.utils.key_id_string(key_.base_layout_codepoint orelse key_.codepoint),
@ -172,7 +168,7 @@ pub fn process_input_event(self: *Self, input_: []const u8, text: ?[]const u8) !
const key_ = filter_mods(key__);
const cbor_msg = try self.fmtmsg(.{
"I",
event_type.RELEASE,
input.event.release,
key_.codepoint,
key_.shifted_codepoint orelse key_.codepoint,
text orelse input.utils.key_id_string(key_.base_layout_codepoint orelse key_.codepoint),
@ -193,9 +189,9 @@ pub fn process_input_event(self: *Self, input_: []const u8, text: ?[]const u8) !
})),
.press => f(self.handler_ctx, @intCast(mouse.row), @intCast(mouse.col), try self.fmtmsg(.{
"B",
event_type.PRESS,
input.event.press,
@intFromEnum(mouse.button),
input.utils.button_id_string(@intFromEnum(mouse.button)),
input.utils.button_id_string(mouse.button),
mouse.col,
mouse.row,
mouse.xoffset,
@ -203,9 +199,9 @@ pub fn process_input_event(self: *Self, input_: []const u8, text: ?[]const u8) !
})),
.release => f(self.handler_ctx, @intCast(mouse.row), @intCast(mouse.col), try self.fmtmsg(.{
"B",
event_type.RELEASE,
input.event.release,
@intFromEnum(mouse.button),
input.utils.button_id_string(@intFromEnum(mouse.button)),
input.utils.button_id_string(mouse.button),
mouse.col,
mouse.row,
mouse.xoffset,
@ -214,9 +210,9 @@ pub fn process_input_event(self: *Self, input_: []const u8, text: ?[]const u8) !
.drag => if (self.dispatch_mouse_drag) |f_|
f_(self.handler_ctx, @intCast(mouse.row), @intCast(mouse.col), try self.fmtmsg(.{
"D",
event_type.PRESS,
input.event.press,
@intFromEnum(mouse.button),
input.utils.button_id_string(@intFromEnum(mouse.button)),
input.utils.button_id_string(mouse.button),
mouse.col,
mouse.row,
mouse.xoffset,
@ -282,19 +278,19 @@ fn fmtmsg(self: *Self, value: anytype) ![]const u8 {
}
fn handle_bracketed_paste_input(self: *Self, cbor_msg: []const u8) !bool {
var keypress: u32 = undefined;
var egc_: u32 = undefined;
var keypress: input.Key = undefined;
var egc_: input.Key = undefined;
if (try cbor.match(cbor_msg, .{ "I", cbor.number, cbor.extract(&keypress), cbor.extract(&egc_), cbor.string, 0 })) {
switch (keypress) {
key.ENTER => try self.bracketed_paste_buffer.appendSlice("\n"),
key.TAB => try self.bracketed_paste_buffer.appendSlice("\t"),
else => if (!key.synthesized_p(keypress)) {
input.key.enter => try self.bracketed_paste_buffer.appendSlice("\n"),
input.key.tab => try self.bracketed_paste_buffer.appendSlice("\t"),
else => if (!input.is_non_input_key(keypress)) {
var buf: [6]u8 = undefined;
const bytes = try ucs32_to_utf8(&[_]u32{egc_}, &buf);
const bytes = try input.ucs32_to_utf8(&[_]u32{egc_}, &buf);
try self.bracketed_paste_buffer.appendSlice(buf[0..bytes]);
} else {
var buf: [6]u8 = undefined;
const bytes = try ucs32_to_utf8(&[_]u32{egc_}, &buf);
const bytes = try input.ucs32_to_utf8(&[_]u32{egc_}, &buf);
self.logger.print("unexpected codepoint in paste: {d} {s}", .{ keypress, buf[0..bytes] });
},
}
@ -336,7 +332,7 @@ pub fn set_terminal_style(self: *Self, style_: Style) void {
}
pub fn set_terminal_cursor_color(self: *Self, color: Color) void {
self.vx.setTerminalCursorColor(self.tty.anyWriter(), vaxis.Cell.Color.rgbFromUint(@intCast(color.color)).rgb) catch {};
self.vx.setTerminalCursorColor(self.tty.anyWriter(), vaxis.Cell.Color.rgbFromUint(@intCast(color.color)).rgb) catch {};
}
pub fn set_terminal_working_directory(self: *Self, absolute_path: []const u8) void {
@ -376,32 +372,28 @@ pub fn cursor_disable(self: *Self) void {
self.vx.screen.cursor_vis = false;
}
pub fn ucs32_to_utf8(ucs32: []const u32, utf8: []u8) !usize {
return @intCast(try std.unicode.utf8Encode(@intCast(ucs32[0]), utf8));
}
fn sync_mod_state(self: *Self, keypress: u32, modifiers: vaxis.Key.Modifiers) !void {
if (modifiers.ctrl and !self.mods.ctrl and !(keypress == key.LCTRL or keypress == key.RCTRL))
try self.send_sync_key(event_type.PRESS, key.LCTRL, "lctrl", modifiers);
if (!modifiers.ctrl and self.mods.ctrl and !(keypress == key.LCTRL or keypress == key.RCTRL))
try self.send_sync_key(event_type.RELEASE, key.LCTRL, "lctrl", modifiers);
if (modifiers.alt and !self.mods.alt and !(keypress == key.LALT or keypress == key.RALT))
try self.send_sync_key(event_type.PRESS, key.LALT, "lalt", modifiers);
if (!modifiers.alt and self.mods.alt and !(keypress == key.LALT or keypress == key.RALT))
try self.send_sync_key(event_type.RELEASE, key.LALT, "lalt", modifiers);
if (modifiers.shift and !self.mods.shift and !(keypress == key.LSHIFT or keypress == key.RSHIFT))
try self.send_sync_key(event_type.PRESS, key.LSHIFT, "lshift", modifiers);
if (!modifiers.shift and self.mods.shift and !(keypress == key.LSHIFT or keypress == key.RSHIFT))
try self.send_sync_key(event_type.RELEASE, key.LSHIFT, "lshift", modifiers);
if (modifiers.ctrl and !self.mods.ctrl and !(keypress == input.key.left_control or keypress == input.key.right_control))
try self.send_sync_key(input.event.press, input.key.left_control, "lctrl", modifiers);
if (!modifiers.ctrl and self.mods.ctrl and !(keypress == input.key.left_control or keypress == input.key.right_control))
try self.send_sync_key(input.event.release, input.key.left_control, "lctrl", modifiers);
if (modifiers.alt and !self.mods.alt and !(keypress == input.key.left_alt or keypress == input.key.right_alt))
try self.send_sync_key(input.event.press, input.key.left_alt, "lalt", modifiers);
if (!modifiers.alt and self.mods.alt and !(keypress == input.key.left_alt or keypress == input.key.right_alt))
try self.send_sync_key(input.event.release, input.key.left_alt, "lalt", modifiers);
if (modifiers.shift and !self.mods.shift and !(keypress == input.key.left_shift or keypress == input.key.right_shift))
try self.send_sync_key(input.event.press, input.key.left_shift, "lshift", modifiers);
if (!modifiers.shift and self.mods.shift and !(keypress == input.key.left_shift or keypress == input.key.right_shift))
try self.send_sync_key(input.event.release, input.key.left_shift, "lshift", modifiers);
self.mods = modifiers;
}
fn send_sync_key(self: *Self, event_type_: usize, keypress: u32, key_string: []const u8, modifiers: vaxis.Key.Modifiers) !void {
fn send_sync_key(self: *Self, event: input.Event, keypress: u32, key_string: []const u8, modifiers: vaxis.Key.Modifiers) !void {
if (self.dispatch_input) |f| f(
self.handler_ctx,
try self.fmtmsg(.{
"I",
event_type_,
event,
keypress,
keypress,
key_string,

View file

@ -3,8 +3,7 @@ const tp = @import("thespian");
const EventHandler = @import("EventHandler");
const Plane = @import("renderer").Plane;
const key = @import("renderer").input.key;
const event_type = @import("renderer").input.event_type;
const input = @import("input");
const Widget = @import("Widget.zig");
const tui = @import("tui.zig");
@ -92,36 +91,37 @@ pub fn State(ctx_type: type) type {
}
pub fn receive(self: *Self, from: tp.pid_ref, m: tp.message) error{Exit}!bool {
var btn: u32 = 0;
if (try m.match(.{ "B", event_type.PRESS, tp.extract(&btn), tp.more })) {
switch (btn) {
key.BUTTON1 => {
var btn: input.MouseType = 0;
if (try m.match(.{ "B", input.event.press, tp.extract(&btn), tp.more })) {
const btn_enum: input.Mouse = @enumFromInt(btn);
switch (btn_enum) {
input.mouse.BUTTON1 => {
self.active = true;
tui.need_render();
},
key.BUTTON4, key.BUTTON5 => {
self.call_click_handler(btn);
input.mouse.BUTTON4, input.mouse.BUTTON5 => {
self.call_click_handler(btn_enum);
return true;
},
else => {},
}
return true;
} else if (try m.match(.{ "B", event_type.RELEASE, tp.extract(&btn), tp.more })) {
self.call_click_handler(btn);
} else if (try m.match(.{ "B", input.event.release, tp.extract(&btn), tp.more })) {
self.call_click_handler(@enumFromInt(btn));
tui.need_render();
return true;
} else if (try m.match(.{ "D", event_type.PRESS, tp.extract(&btn), tp.more })) {
} else if (try m.match(.{ "D", input.event.press, tp.extract(&btn), tp.more })) {
if (self.opts.on_event) |h| {
self.active = false;
h.send(from, m) catch {};
}
return true;
} else if (try m.match(.{ "D", event_type.RELEASE, tp.extract(&btn), tp.more })) {
} else if (try m.match(.{ "D", input.event.release, tp.extract(&btn), tp.more })) {
if (self.opts.on_event) |h| {
self.active = false;
h.send(from, m) catch {};
}
self.call_click_handler(btn);
self.call_click_handler(@enumFromInt(btn));
tui.need_render();
return true;
} else if (try m.match(.{ "H", tp.extract(&self.hover) })) {
@ -132,18 +132,18 @@ pub fn State(ctx_type: type) type {
return self.opts.on_receive(&self.opts.ctx, self, from, m);
}
fn call_click_handler(self: *Self, btn: u32) void {
if (btn == key.BUTTON1) {
fn call_click_handler(self: *Self, btn: input.Mouse) void {
if (btn == input.mouse.BUTTON1) {
if (!self.active) return;
self.active = false;
}
if (!self.hover) return;
switch (btn) {
key.BUTTON1 => self.opts.on_click(&self.opts.ctx, self),
key.BUTTON2 => self.opts.on_click2(&self.opts.ctx, self),
key.BUTTON3 => self.opts.on_click3(&self.opts.ctx, self),
key.BUTTON4 => self.opts.on_click4(&self.opts.ctx, self),
key.BUTTON5 => self.opts.on_click5(&self.opts.ctx, self),
input.mouse.BUTTON1 => self.opts.on_click(&self.opts.ctx, self),
input.mouse.BUTTON2 => self.opts.on_click2(&self.opts.ctx, self),
input.mouse.BUTTON3 => self.opts.on_click3(&self.opts.ctx, self),
input.mouse.BUTTON4 => self.opts.on_click4(&self.opts.ctx, self),
input.mouse.BUTTON5 => self.opts.on_click5(&self.opts.ctx, self),
else => {},
}
}

View file

@ -2,8 +2,7 @@ const std = @import("std");
const tp = @import("thespian");
const Plane = @import("renderer").Plane;
const key = @import("renderer").input.key;
const event_type = @import("renderer").input.event_type;
const input = @import("input");
const Widget = @import("Widget.zig");
const tui = @import("tui.zig");
@ -99,16 +98,16 @@ pub fn State(ctx_type: type) type {
}
pub fn receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
if (try m.match(.{ "B", event_type.PRESS, key.BUTTON1, tp.any, tp.any, tp.any, tp.any, tp.any })) {
if (try m.match(.{ "B", input.event.press, @intFromEnum(input.mouse.BUTTON1), tp.any, tp.any, tp.any, tp.any, tp.any })) {
self.active = true;
tui.need_render();
return true;
} else if (try m.match(.{ "B", event_type.RELEASE, key.BUTTON1, tp.any, tp.any, tp.any, tp.any, tp.any })) {
} else if (try m.match(.{ "B", input.event.release, @intFromEnum(input.mouse.BUTTON1), tp.any, tp.any, tp.any, tp.any, tp.any })) {
self.opts.on_click(self.opts.ctx, self);
self.active = false;
tui.need_render();
return true;
} else if (try m.match(.{ "D", event_type.RELEASE, key.BUTTON1, tp.any, tp.any, tp.any, tp.any, tp.any })) {
} else if (try m.match(.{ "D", input.event.release, @intFromEnum(input.mouse.BUTTON1), tp.any, tp.any, tp.any, tp.any, tp.any })) {
self.opts.on_click(self.opts.ctx, self);
self.active = false;
tui.need_render();

View file

@ -5,8 +5,7 @@ const EventHandler = @import("EventHandler");
const tui = @import("tui.zig");
const Widget = @import("Widget.zig");
const Plane = @import("renderer").Plane;
const key = @import("renderer").input.key;
const event_type = @import("renderer").input.event_type;
const input = @import("input");
pub fn Options(context: type) type {
return struct {
@ -95,16 +94,16 @@ pub fn State(ctx_type: type) type {
}
pub fn receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
var btn: u32 = 0;
if (try m.match(.{ "B", event_type.PRESS, tp.more })) {
var btn: input.MouseType = 0;
if (try m.match(.{ "B", input.event.press, tp.more })) {
return true;
} else if (try m.match(.{ "B", event_type.RELEASE, tp.extract(&btn), tp.more })) {
self.call_click_handler(btn);
} else if (try m.match(.{ "B", input.event.release, tp.extract(&btn), tp.more })) {
self.call_click_handler(@enumFromInt(btn));
return true;
} else if (try m.match(.{ "D", event_type.PRESS, tp.extract(&btn), tp.more })) {
} else if (try m.match(.{ "D", input.event.press, tp.extract(&btn), tp.more })) {
return true;
} else if (try m.match(.{ "D", event_type.RELEASE, tp.extract(&btn), tp.more })) {
self.call_click_handler(btn);
} else if (try m.match(.{ "D", input.event.release, tp.extract(&btn), tp.more })) {
self.call_click_handler(@enumFromInt(btn));
return true;
} else if (try m.match(.{ "H", tp.extract(&self.hover) })) {
tui.current().rdr.request_mouse_cursor_default(self.hover);
@ -113,14 +112,14 @@ pub fn State(ctx_type: type) type {
return false;
}
fn call_click_handler(self: *Self, btn: u32) void {
fn call_click_handler(self: *Self, btn: input.Mouse) void {
if (!self.hover) return;
switch (btn) {
key.BUTTON1 => self.opts.on_click(self.opts.ctx, self),
key.BUTTON2 => self.opts.on_click2(self.opts.ctx, self),
key.BUTTON3 => self.opts.on_click3(self.opts.ctx, self),
key.BUTTON4 => self.opts.on_click4(self.opts.ctx, self),
key.BUTTON5 => self.opts.on_click5(self.opts.ctx, self),
input.mouse.BUTTON1 => self.opts.on_click(self.opts.ctx, self),
input.mouse.BUTTON2 => self.opts.on_click2(self.opts.ctx, self),
input.mouse.BUTTON3 => self.opts.on_click3(self.opts.ctx, self),
input.mouse.BUTTON4 => self.opts.on_click4(self.opts.ctx, self),
input.mouse.BUTTON5 => self.opts.on_click5(self.opts.ctx, self),
else => {},
}
}

View file

@ -14,8 +14,7 @@ const root_mod = @import("root");
const Plane = @import("renderer").Plane;
const Cell = @import("renderer").Cell;
const key = @import("renderer").input.key;
const event_type = @import("renderer").input.event_type;
const input = @import("input");
const command = @import("command");
const EventHandler = @import("EventHandler");
@ -834,7 +833,7 @@ pub const Editor = struct {
mode.cursor_shape
else
.block;
tui.current().rdr.cursor_enable(y, x, shape) catch {};
tui.current().rdr.cursor_enable(y, x, tui.translate_cursor_shape(shape)) catch {};
} else {
tui.current().rdr.cursor_disable();
}
@ -4104,7 +4103,7 @@ pub const EditorWidget = struct {
editor: Editor,
commands: Commands = undefined,
last_btn: c_int = -1,
last_btn: input.Mouse = .none,
last_btn_time_ms: i64 = 0,
last_btn_count: usize = 0,
@ -4163,8 +4162,8 @@ pub const EditorWidget = struct {
}
fn receive_safe(self: *Self, m: tp.message) !bool {
var evtype: c_int = undefined;
var btn: c_int = undefined;
var event: input.Event = undefined;
var btn: input.MouseType = undefined;
var x: c_int = undefined;
var y: c_int = undefined;
var xpx: c_int = undefined;
@ -4179,10 +4178,10 @@ pub const EditorWidget = struct {
if (self.editor.jump_mode)
self.update_hover_timer(.init);
}
} else if (try m.match(.{ "B", tp.extract(&evtype), tp.extract(&btn), tp.any, tp.extract(&x), tp.extract(&y), tp.extract(&xpx), tp.extract(&ypx) })) {
try self.mouse_click_event(evtype, btn, y, x, ypx, xpx);
} else if (try m.match(.{ "D", tp.extract(&evtype), tp.extract(&btn), tp.any, tp.extract(&x), tp.extract(&y), tp.extract(&xpx), tp.extract(&ypx) })) {
try self.mouse_drag_event(evtype, btn, y, x, ypx, xpx);
} else if (try m.match(.{ "B", tp.extract(&event), tp.extract(&btn), tp.any, tp.extract(&x), tp.extract(&y), tp.extract(&xpx), tp.extract(&ypx) })) {
try self.mouse_click_event(event, @enumFromInt(btn), y, x, ypx, xpx);
} else if (try m.match(.{ "D", tp.extract(&event), tp.extract(&btn), tp.any, tp.extract(&x), tp.extract(&y), tp.extract(&xpx), tp.extract(&ypx) })) {
try self.mouse_drag_event(event, @enumFromInt(btn), y, x, ypx, xpx);
} else if (try m.match(.{ "scroll_to", tp.extract(&pos) })) {
self.editor.scroll_to(pos);
} else if (try m.match(.{ "filter", "stdout", tp.extract(&bytes) })) {
@ -4227,16 +4226,16 @@ pub const EditorWidget = struct {
const Result = command.Result;
fn mouse_click_event(self: *Self, evtype: c_int, btn: c_int, y: c_int, x: c_int, ypx: c_int, xpx: c_int) Result {
if (evtype != event_type.PRESS) return;
fn mouse_click_event(self: *Self, event: input.Event, btn: input.Mouse, y: c_int, x: c_int, ypx: c_int, xpx: c_int) Result {
if (event != input.event.press) return;
const ret = (switch (btn) {
key.BUTTON1 => &mouse_click_button1,
key.BUTTON2 => &mouse_click_button2,
key.BUTTON3 => &mouse_click_button3,
key.BUTTON4 => &mouse_click_button4,
key.BUTTON5 => &mouse_click_button5,
key.BUTTON8 => &mouse_click_button8, //back
key.BUTTON9 => &mouse_click_button9, //forward
input.mouse.BUTTON1 => &mouse_click_button1,
input.mouse.BUTTON2 => &mouse_click_button2,
input.mouse.BUTTON3 => &mouse_click_button3,
input.mouse.BUTTON4 => &mouse_click_button4,
input.mouse.BUTTON5 => &mouse_click_button5,
input.mouse.BUTTON8 => &mouse_click_button8, //back
input.mouse.BUTTON9 => &mouse_click_button9, //forward
else => return,
})(self, y, x, ypx, xpx);
self.last_btn = btn;
@ -4244,19 +4243,19 @@ pub const EditorWidget = struct {
return ret;
}
fn mouse_drag_event(self: *Self, evtype: c_int, btn: c_int, y: c_int, x: c_int, ypx: c_int, xpx: c_int) Result {
if (evtype != event_type.PRESS) return;
fn mouse_drag_event(self: *Self, event: input.Event, btn: input.Mouse, y: c_int, x: c_int, ypx: c_int, xpx: c_int) Result {
if (event != input.event.press) return;
return (switch (btn) {
key.BUTTON1 => &mouse_drag_button1,
key.BUTTON2 => &mouse_drag_button2,
key.BUTTON3 => &mouse_drag_button3,
input.mouse.BUTTON1 => &mouse_drag_button1,
input.mouse.BUTTON2 => &mouse_drag_button2,
input.mouse.BUTTON3 => &mouse_drag_button3,
else => return,
})(self, y, x, ypx, xpx);
}
fn mouse_click_button1(self: *Self, y: c_int, x: c_int, _: c_int, _: c_int) Result {
const y_, const x_ = self.editor.plane.abs_yx_to_rel(y, x);
if (self.last_btn == key.BUTTON1) {
if (self.last_btn == input.mouse.BUTTON1) {
const click_time_ms = time.milliTimestamp() - self.last_btn_time_ms;
if (click_time_ms <= double_click_time_ms) {
if (self.last_btn_count == 2) {

View file

@ -8,8 +8,7 @@ const root = @import("root");
const Plane = @import("renderer").Plane;
const style = @import("renderer").style;
const key = @import("renderer").input.key;
const event_type = @import("renderer").input.event_type;
const input = @import("input");
const command = @import("command");
const EventHandler = @import("EventHandler");
@ -90,15 +89,15 @@ pub fn receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
var y: i32 = undefined;
var ypx: i32 = undefined;
if (try m.match(.{ "B", event_type.PRESS, key.BUTTON1, tp.any, tp.any, tp.extract(&y), tp.any, tp.extract(&ypx) }))
if (try m.match(.{ "B", input.event.press, @intFromEnum(input.mouse.BUTTON1), tp.any, tp.any, tp.extract(&y), tp.any, tp.extract(&ypx) }))
return self.primary_click(y);
if (try m.match(.{ "B", event_type.PRESS, key.BUTTON3, tp.any, tp.any, tp.extract(&y), tp.any, tp.extract(&ypx) }))
if (try m.match(.{ "B", input.event.press, @intFromEnum(input.mouse.BUTTON3), tp.any, tp.any, tp.extract(&y), tp.any, tp.extract(&ypx) }))
return self.secondary_click();
if (try m.match(.{ "D", event_type.PRESS, key.BUTTON1, tp.any, tp.any, tp.extract(&y), tp.any, tp.extract(&ypx) }))
if (try m.match(.{ "D", input.event.press, @intFromEnum(input.mouse.BUTTON1), tp.any, tp.any, tp.extract(&y), tp.any, tp.extract(&ypx) }))
return self.primary_drag(y);
if (try m.match(.{ "B", event_type.PRESS, key.BUTTON4, tp.more }))
if (try m.match(.{ "B", input.event.press, @intFromEnum(input.mouse.BUTTON4), tp.more }))
return self.mouse_click_button4();
if (try m.match(.{ "B", event_type.PRESS, key.BUTTON5, tp.more }))
if (try m.match(.{ "B", input.event.press, @intFromEnum(input.mouse.BUTTON5), tp.more }))
return self.mouse_click_button5();
return false;

View file

@ -9,8 +9,7 @@ const project_manager = @import("project_manager");
const log = @import("log");
const Plane = @import("renderer").Plane;
const key = @import("renderer").input.key;
const event_type = @import("renderer").input.event_type;
const input = @import("input");
const command = @import("command");
const tui = @import("tui.zig");
@ -150,7 +149,7 @@ pub fn box(self: *const Self) Box {
fn handle_bottom_bar_event(self: *Self, _: tp.pid_ref, m: tp.message) tp.result {
var y: usize = undefined;
if (try m.match(.{ "D", event_type.PRESS, key.BUTTON1, tp.any, tp.any, tp.extract(&y), tp.any, tp.any }))
if (try m.match(.{ "D", input.event.press, @intFromEnum(input.mouse.BUTTON1), tp.any, tp.any, tp.extract(&y), tp.any, tp.any }))
return self.bottom_bar_primary_drag(y);
}

View file

@ -4,11 +4,8 @@ const cbor = @import("cbor");
const log = @import("log");
const root = @import("root");
const key = @import("renderer").input.key;
const mod = @import("renderer").input.modifier;
const event_type = @import("renderer").input.event_type;
const input = @import("input");
const keybind = @import("keybind");
const ucs32_to_utf8 = @import("renderer").ucs32_to_utf8;
const project_manager = @import("project_manager");
const command = @import("command");
const EventHandler = @import("EventHandler");
@ -310,7 +307,7 @@ pub fn Create(options: type) type {
return error.InvalidArgument;
self.complete_trigger_count = 0;
var buf: [32]u8 = undefined;
const bytes = try ucs32_to_utf8(&[_]u32{egc}, &buf);
const bytes = try input.ucs32_to_utf8(&[_]u32{egc}, &buf);
try self.file_path.appendSlice(buf[0..bytes]);
self.update_mini_mode_text();
}

View file

@ -1,10 +1,7 @@
const tp = @import("thespian");
const key = @import("renderer").input.key;
const mod = @import("renderer").input.modifier;
const event_type = @import("renderer").input.event_type;
const input = @import("input");
const keybind = @import("keybind");
const ucs32_to_utf8 = @import("renderer").ucs32_to_utf8;
const command = @import("command");
const EventHandler = @import("EventHandler");
@ -82,7 +79,7 @@ pub fn receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
fn insert_code_point(self: *Self, c: u32) !void {
var buf: [16]u8 = undefined;
const bytes = ucs32_to_utf8(&[_]u32{c}, &buf) catch |e| return tp.exit_error(e, @errorReturnTrace());
const bytes = input.ucs32_to_utf8(&[_]u32{c}, &buf) catch |e| return tp.exit_error(e, @errorReturnTrace());
try self.input.appendSlice(buf[0..bytes]);
}

View file

@ -1,10 +1,7 @@
const tp = @import("thespian");
const key = @import("renderer").input.key;
const mod = @import("renderer").input.modifier;
const event_type = @import("renderer").input.event_type;
const input = @import("input");
const keybind = @import("keybind");
const ucs32_to_utf8 = @import("renderer").ucs32_to_utf8;
const command = @import("command");
const EventHandler = @import("EventHandler");
@ -75,7 +72,7 @@ pub fn receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
fn insert_code_point(self: *Self, c: u32) !void {
if (self.input.len + 16 > self.buf.len)
try self.flush_input();
const bytes = try ucs32_to_utf8(&[_]u32{c}, self.buf[self.input.len..]);
const bytes = try input.ucs32_to_utf8(&[_]u32{c}, self.buf[self.input.len..]);
self.input = self.buf[0 .. self.input.len + bytes];
}

View file

@ -1,9 +1,6 @@
const tp = @import("thespian");
const key = @import("renderer").input.key;
const mod = @import("renderer").input.modifier;
const event_type = @import("renderer").input.event_type;
const ucs32_to_utf8 = @import("renderer").ucs32_to_utf8;
const input = @import("input");
const keybind = @import("keybind");
const command = @import("command");
const EventHandler = @import("EventHandler");
@ -89,7 +86,7 @@ fn execute_operation(self: *Self, c: u32) void {
},
};
var buf: [6]u8 = undefined;
const bytes = ucs32_to_utf8(&[_]u32{c}, &buf) catch return;
const bytes = input.ucs32_to_utf8(&[_]u32{c}, &buf) catch return;
command.executeName(cmd, command.fmt(.{buf[0..bytes]})) catch {};
command.executeName("exit_mini_mode", .{}) catch {};
}
@ -104,7 +101,7 @@ const cmds = struct {
if (!try ctx.args.match(.{tp.extract(&code_point)}))
return error.InvalidArgument;
var buf: [6]u8 = undefined;
const bytes = ucs32_to_utf8(&[_]u32{code_point}, &buf) catch return error.InvalidArgument;
const bytes = input.ucs32_to_utf8(&[_]u32{code_point}, &buf) catch return error.InvalidArgument;
const cmd = switch (self.direction) {
.left => switch (self.operation) {
.move => "move_to_char_left",

View file

@ -5,11 +5,8 @@ const cbor = @import("cbor");
const root = @import("root");
const Plane = @import("renderer").Plane;
const key = @import("renderer").input.key;
const mod = @import("renderer").input.modifier;
const event_type = @import("renderer").input.event_type;
const input = @import("input");
const keybind = @import("keybind");
const ucs32_to_utf8 = @import("renderer").ucs32_to_utf8;
const project_manager = @import("project_manager");
const command = @import("command");
const EventHandler = @import("EventHandler");
@ -243,7 +240,7 @@ fn delete_code_point(self: *Self) !void {
fn insert_code_point(self: *Self, c: u32) !void {
var buf: [6]u8 = undefined;
const bytes = try ucs32_to_utf8(&[_]u32{c}, &buf);
const bytes = try input.ucs32_to_utf8(&[_]u32{c}, &buf);
try self.inputbox.text.appendSlice(buf[0..bytes]);
self.inputbox.cursor = self.inputbox.text.items.len;
return self.start_query();

View file

@ -5,11 +5,8 @@ const cbor = @import("cbor");
const fuzzig = @import("fuzzig");
const Plane = @import("renderer").Plane;
const key = @import("renderer").input.key;
const mod = @import("renderer").input.modifier;
const event_type = @import("renderer").input.event_type;
const input = @import("input");
const keybind = @import("keybind");
const ucs32_to_utf8 = @import("renderer").ucs32_to_utf8;
const command = @import("command");
const EventHandler = @import("EventHandler");
@ -315,7 +312,7 @@ pub fn Create(options: type) type {
fn insert_code_point(self: *Self, c: u32) !void {
var buf: [6]u8 = undefined;
const bytes = try ucs32_to_utf8(&[_]u32{c}, &buf);
const bytes = try input.ucs32_to_utf8(&[_]u32{c}, &buf);
try self.inputbox.text.appendSlice(buf[0..bytes]);
self.inputbox.cursor = self.inputbox.text.items.len;
self.view_pos = 0;

View file

@ -3,8 +3,7 @@ const tp = @import("thespian");
const tracy = @import("tracy");
const Plane = @import("renderer").Plane;
const key = @import("renderer").input.key;
const event_type = @import("renderer").input.event_type;
const input = @import("input");
const EventHandler = @import("EventHandler");
const Widget = @import("Widget.zig");
@ -64,21 +63,21 @@ pub fn receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
var y: i32 = undefined;
var ypx: i32 = undefined;
if (try m.match(.{ "B", event_type.PRESS, key.BUTTON1, tp.any, tp.any, tp.extract(&y), tp.any, tp.extract(&ypx) })) {
if (try m.match(.{ "B", input.event.press, @intFromEnum(input.mouse.BUTTON1), tp.any, tp.any, tp.extract(&y), tp.any, tp.extract(&ypx) })) {
self.active = true;
self.move_to(y, ypx);
return true;
} else if (try m.match(.{ "B", event_type.RELEASE, tp.more })) {
} else if (try m.match(.{ "B", input.event.release, tp.more })) {
self.active = false;
return true;
} else if (try m.match(.{ "D", event_type.PRESS, key.BUTTON1, tp.any, tp.any, tp.extract(&y), tp.any, tp.extract(&ypx) })) {
} else if (try m.match(.{ "D", input.event.press, @intFromEnum(input.mouse.BUTTON1), tp.any, tp.any, tp.extract(&y), tp.any, tp.extract(&ypx) })) {
self.active = true;
self.move_to(y, ypx);
return true;
} else if (try m.match(.{ "B", event_type.RELEASE, tp.more })) {
} else if (try m.match(.{ "B", input.event.release, tp.more })) {
self.active = false;
return true;
} else if (try m.match(.{ "D", event_type.RELEASE, tp.more })) {
} else if (try m.match(.{ "D", input.event.release, tp.more })) {
self.active = false;
return true;
} else if (try m.match(.{ "H", tp.extract(&self.hover) })) {

View file

@ -4,9 +4,7 @@ const tp = @import("thespian");
const tracy = @import("tracy");
const Plane = @import("renderer").Plane;
const utils = @import("renderer").input.utils;
const key_ = @import("renderer").input.key;
const event_type = @import("renderer").input.event_type;
const input = @import("input");
const command = @import("command");
const EventHandler = @import("EventHandler");
@ -24,7 +22,7 @@ hover: bool = false,
keys: [history]Key = [_]Key{.{}} ** history,
const Key = struct { id: u32 = 0, mod: u32 = 0 };
const Key = struct { id: input.Key = 0, mod: input.ModSet = .{} };
const Self = @This();
@ -63,15 +61,15 @@ fn render_active(self: *Self) bool {
return true;
if (c > 0)
_ = self.plane.putstr(" ") catch {};
if (utils.isSuper(k.mod))
if (k.mod.super)
_ = self.plane.putstr("H-") catch {};
if (utils.isCtrl(k.mod))
if (k.mod.ctrl)
_ = self.plane.putstr("C-") catch {};
if (utils.isShift(k.mod))
if (k.mod.shift)
_ = self.plane.putstr("S-") catch {};
if (utils.isAlt(k.mod))
if (k.mod.alt)
_ = self.plane.putstr("A-") catch {};
_ = self.plane.print("{s}", .{utils.key_id_string(k.id)}) catch {};
_ = self.plane.print("{s}", .{input.utils.key_id_string(k.id)}) catch {};
c += 1;
}
return true;
@ -144,7 +142,7 @@ fn unset_nkey(self: *Self, key: Key) void {
fn unset_key_all(self: *Self) void {
for (0..self.keys.len) |i| {
self.keys[i].id = 0;
self.keys[i].mod = 0;
self.keys[i].mod = .{};
}
}
@ -155,17 +153,17 @@ fn set_key(self: *Self, key: Key, val: bool) void {
}
pub fn listen(self: *Self, _: tp.pid_ref, m: tp.message) tp.result {
var key: u32 = 0;
var mod: u32 = 0;
if (try m.match(.{ "I", event_type.PRESS, tp.extract(&key), tp.any, tp.any, tp.extract(&mod), tp.more })) {
self.set_key(.{ .id = key, .mod = mod }, true);
} else if (try m.match(.{ "I", event_type.RELEASE, tp.extract(&key), tp.any, tp.any, tp.extract(&mod), tp.more })) {
self.set_key(.{ .id = key, .mod = mod }, false);
var key: input.Key = 0;
var mod: input.Mods = 0;
if (try m.match(.{ "I", input.event.press, tp.extract(&key), tp.any, tp.any, tp.extract(&mod), tp.more })) {
self.set_key(.{ .id = key, .mod = @bitCast(mod) }, true);
} else if (try m.match(.{ "I", input.event.release, tp.extract(&key), tp.any, tp.any, tp.extract(&mod), tp.more })) {
self.set_key(.{ .id = key, .mod = @bitCast(mod) }, false);
}
}
pub fn receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
if (try m.match(.{ "B", event_type.PRESS, key_.BUTTON1, tp.any, tp.any, tp.any, tp.any, tp.any })) {
if (try m.match(.{ "B", input.event.press, @intFromEnum(input.mouse.BUTTON1), tp.any, tp.any, tp.any, tp.any, tp.any })) {
command.executeName("toggle_inputview", .{}) catch {};
return true;
}

View file

@ -4,9 +4,7 @@ const tp = @import("thespian");
const tracy = @import("tracy");
const Plane = @import("renderer").Plane;
const key = @import("renderer").input.key;
const event_type = @import("renderer").input.event_type;
const utils = @import("renderer").input.utils;
const input = @import("input");
const command = @import("command");
const EventHandler = @import("EventHandler");
@ -14,9 +12,7 @@ const Widget = @import("../Widget.zig");
const tui = @import("../tui.zig");
plane: Plane,
ctrl: bool = false,
shift: bool = false,
alt: bool = false,
mods: input.ModSet = .{},
hover: bool = false,
const Self = @This();
@ -54,9 +50,9 @@ pub fn render(self: *Self, theme: *const Widget.Theme) bool {
self.plane.home();
_ = self.plane.print(" {s}{s}{s} ", .{
mode(self.ctrl, "", "🅒 "),
mode(self.shift, "", "🅢 "),
mode(self.alt, "", "🅐 "),
mode(self.mods.ctrl, "", "🅒 "),
mode(self.mods.shift, "", "🅢 "),
mode(self.mods.alt, "", "🅐 "),
}) catch {};
return false;
}
@ -70,16 +66,14 @@ fn render_modifier(self: *Self, state: bool, off: [:0]const u8, on: [:0]const u8
}
pub fn listen(self: *Self, _: tp.pid_ref, m: tp.message) tp.result {
var mod: u32 = 0;
if (try m.match(.{ "I", tp.any, tp.any, tp.any, tp.any, tp.extract(&mod), tp.more })) {
self.ctrl = utils.isCtrl(mod);
self.shift = utils.isShift(mod);
self.alt = utils.isAlt(mod);
var mods: input.Mods = 0;
if (try m.match(.{ "I", tp.any, tp.any, tp.any, tp.any, tp.extract(&mods), tp.more })) {
self.mods = @bitCast(mods);
}
}
pub fn receive(self: *Self, _: tp.pid_ref, m: tp.message) error{Exit}!bool {
if (try m.match(.{ "B", event_type.PRESS, key.BUTTON1, tp.any, tp.any, tp.any, tp.any, tp.any })) {
if (try m.match(.{ "B", input.event.press, @intFromEnum(input.mouse.BUTTON1), tp.any, tp.any, tp.any, tp.any, tp.any })) {
command.executeName("toggle_inputview", .{}) catch {};
return true;
}

View file

@ -971,3 +971,15 @@ fn set_terminal_style(self: *Self) void {
self.rdr.set_terminal_cursor_color(self.theme.editor_cursor.bg.?);
}
}
pub fn translate_cursor_shape(in: keybind.CursorShape) renderer.CursorShape {
return switch (in) {
.default => .default,
.block_blink => .block_blink,
.block => .block,
.underline_blink => .underline_blink,
.underline => .underline,
.beam_blink => .beam_blink,
.beam => .beam,
};
}