From 223accb4c8d09806fe4a155ea8d0a6b463c33cd0 Mon Sep 17 00:00:00 2001 From: Guillaume Wenzek Date: Fri, 24 Nov 2023 17:21:57 +0100 Subject: [PATCH] add "text" action --- src/Surface.zig | 42 ++++++++++++++++++++++++++++++++++++++++-- src/input/Binding.zig | 3 +++ 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/Surface.zig b/src/Surface.zig index 308e6e878..97129b0e5 100644 --- a/src/Surface.zig +++ b/src/Surface.zig @@ -2254,6 +2254,39 @@ fn showMouse(self: *Surface) void { self.rt_surface.setMouseVisibility(true); } +pub fn parseStringLiteral(out: []u8, bytes: []const u8) []u8 { + var offset: usize = 0; + var index: usize = 0; + while (true) { + if (index >= bytes.len or offset >= out.len) break; + const b = bytes[index]; + switch (b) { + '\\' => { + const escape_char_index = index + 1; + const result = std.zig.string_literal.parseEscapeSequence(bytes, &index); + switch (result) { + .success => |codepoint| { + if (bytes[escape_char_index] == 'u') { + const len = std.unicode.utf8Encode(codepoint, out[offset..]) catch break; + offset += len; + } else { + out[offset] = @as(u8, @intCast(codepoint)); + offset += 1; + } + }, + .failure => break, + } + }, + else => { + out[offset] = b; + offset += 1; + index += 1; + }, + } + } + return out[0..offset]; +} + /// Perform a binding action. A binding is a keybinding. This function /// must be called from the GUI thread. /// @@ -2271,12 +2304,17 @@ pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool .reload_config => try self.app.reloadConfig(self.rt_app), - .csi, .esc => |data| { + .csi, .esc, .text => |data| { // We need to send the CSI/ESC sequence as a single write request. // If you split it across two then the shell can interpret it // as two literals. var buf: [128]u8 = undefined; - const full_data = try std.fmt.bufPrint(&buf, "\x1b{s}{s}", .{ if (action == .csi) "[" else "", data }); + const full_data = switch (action) { + .csi => try std.fmt.bufPrint(&buf, "\x1b[{s}", .{data}), + .esc => try std.fmt.bufPrint(&buf, "\x1b{s}", .{data}), + .text => parseStringLiteral(&buf, data), + else => unreachable, + }; _ = self.io_thread.mailbox.push(try termio.Message.writeReq( self.alloc, full_data, diff --git a/src/input/Binding.zig b/src/input/Binding.zig index 6a66e1d6f..37e93ae3c 100644 --- a/src/input/Binding.zig +++ b/src/input/Binding.zig @@ -134,6 +134,9 @@ pub const Action = union(enum) { /// Send an ESC sequence. esc: []const u8, + // Send the given text. Uses Zig string literal syntax. + text: []const u8, + /// Send data to the pty depending on whether cursor key mode is /// enabled ("application") or disabled ("normal"). cursor_key: CursorKey,