From 80376ce6da94e44d6d7e62ebc083ff32ae1b30ed Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Wed, 24 Aug 2022 11:08:39 -0700 Subject: [PATCH] hook up keybindings for copy/paste and arrow keys --- src/Window.zig | 101 ++++++++++++++++++++++------------------------ src/config.zig | 34 +++++++++++++++- src/input/key.zig | 6 +++ src/main.zig | 3 +- 4 files changed, 89 insertions(+), 55 deletions(-) diff --git a/src/Window.zig b/src/Window.zig index 6a91e9ccf..b2c98a30a 100644 --- a/src/Window.zig +++ b/src/Window.zig @@ -530,13 +530,59 @@ fn keyCallback( .x => .x, .y => .y, .z => .z, + .up => .up, + .down => .down, + .right => .right, + .left => .left, else => .invalid, }, }; if (win.config.keybind.set.get(trigger)) |binding_action| { - log.warn("BINDING ACTION={}", .{binding_action}); - _ = binding_action; + //log.warn("BINDING ACTION={}", .{binding_action}); + + switch (binding_action) { + .unbind => unreachable, + .ignore => {}, + + .csi => |data| { + win.queueWrite("\x1B[") catch |err| + log.err("error queueing write in keyCallback err={}", .{err}); + win.queueWrite(data) catch |err| + log.warn("error pasting clipboard: {}", .{err}); + }, + + .copy_to_clipboard => { + if (win.terminal.selection) |sel| { + var buf = win.terminal.screen.selectionString(win.alloc, sel) catch |err| { + log.err("error reading selection string err={}", .{err}); + return; + }; + defer win.alloc.free(buf); + + glfw.setClipboardString(buf) catch |err| { + log.err("error setting clipboard string err={}", .{err}); + return; + }; + } + }, + + .paste_from_clipboard => { + const data = glfw.getClipboardString() catch |err| { + log.warn("error reading clipboard: {}", .{err}); + return; + }; + + if (data.len > 0) { + if (win.bracketed_paste) win.queueWrite("\x1B[200~") catch |err| + log.err("error queueing write in keyCallback err={}", .{err}); + win.queueWrite(data) catch |err| + log.warn("error pasting clipboard: {}", .{err}); + if (win.bracketed_paste) win.queueWrite("\x1B[201~") catch |err| + log.err("error queueing write in keyCallback err={}", .{err}); + } + }, + } // Bindings always result in us ignoring the char if printable win.ignore_char = true; @@ -594,57 +640,6 @@ fn keyCallback( log.err("error queueing write in keyCallback err={}", .{err}); } } - - if (action == .press and mods.super) { - switch (key) { - // Copy - .c => { - // Ignore this character for writing - win.ignore_char = true; - - // If we have a selection, copy it. - if (win.terminal.selection) |sel| { - var buf = win.terminal.screen.selectionString(win.alloc, sel) catch |err| { - log.err("error reading selection string err={}", .{err}); - return; - }; - defer win.alloc.free(buf); - - glfw.setClipboardString(buf) catch |err| { - log.err("error setting clipboard string err={}", .{err}); - return; - }; - } - - return; - }, - - // Paste - .v => { - - // Ignore this character for writing - win.ignore_char = true; - - const data = glfw.getClipboardString() catch |err| { - log.warn("error reading clipboard: {}", .{err}); - return; - }; - - if (data.len > 0) { - if (win.bracketed_paste) win.queueWrite("\x1B[200~") catch |err| - log.err("error queueing write in keyCallback err={}", .{err}); - win.queueWrite(data) catch |err| - log.warn("error pasting clipboard: {}", .{err}); - if (win.bracketed_paste) win.queueWrite("\x1B[201~") catch |err| - log.err("error queueing write in keyCallback err={}", .{err}); - } - - return; - }, - - else => {}, - } - } } fn focusCallback(window: glfw.Window, focused: bool) void { diff --git a/src/config.zig b/src/config.zig index 8e24814f0..87f773d3f 100644 --- a/src/config.zig +++ b/src/config.zig @@ -20,7 +20,7 @@ pub const Config = struct { /// The command to run, usually a shell. If this is not an absolute path, /// it'll be looked up in the PATH. - command: ?[]const u8 = null, + command: ?[]const u8, /// Key bindings. The format is "trigger=action". Duplicate triggers /// will overwrite previously set values. @@ -63,6 +63,38 @@ pub const Config = struct { if (self._arena) |arena| arena.deinit(); self.* = undefined; } + + pub fn default(alloc_gpa: Allocator) Allocator.Error!Config { + var arena = ArenaAllocator.init(alloc_gpa); + errdefer arena.deinit(); + const alloc = arena.allocator(); + + // Build up our basic config + var result: Config = .{ + ._arena = arena, + .command = "sh", + }; + + // Add our default keybindings + try result.keybind.set.put( + alloc, + .{ .key = .c, .mods = .{ .super = true } }, + .{ .copy_to_clipboard = 0 }, + ); + + try result.keybind.set.put( + alloc, + .{ .key = .v, .mods = .{ .super = true } }, + .{ .paste_from_clipboard = 0 }, + ); + + try result.keybind.set.put(alloc, .{ .key = .up }, .{ .csi = "A" }); + try result.keybind.set.put(alloc, .{ .key = .down }, .{ .csi = "B" }); + try result.keybind.set.put(alloc, .{ .key = .right }, .{ .csi = "C" }); + try result.keybind.set.put(alloc, .{ .key = .left }, .{ .csi = "D" }); + + return result; + } }; /// Color represents a color using RGB. diff --git a/src/input/key.zig b/src/input/key.zig index dc03b72e1..940e7b570 100644 --- a/src/input/key.zig +++ b/src/input/key.zig @@ -49,6 +49,12 @@ pub const Key = enum { y, z, + // control + up, + down, + right, + left, + // To support more keys (there are obviously more!) add them here // and ensure the mapping is up to date in the Window key handler. }; diff --git a/src/main.zig b/src/main.zig index 282375cda..24fd0d8db 100644 --- a/src/main.zig +++ b/src/main.zig @@ -39,7 +39,8 @@ pub fn main() !void { // Parse the config from the CLI args var config = config: { - var result: Config = .{}; + var result = try Config.default(alloc); + errdefer result.deinit(); var iter = try std.process.argsWithAllocator(alloc); defer iter.deinit(); try cli_args.parse(Config, alloc, &result, &iter);