From b2d02a77cd022870c6009f702e0e956f625751f8 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Wed, 11 May 2022 10:02:32 -0700 Subject: [PATCH] terminal stream set mode and reset mode --- src/terminal/ansi.zig | 13 +++++++++++++ src/terminal/stream.zig | 30 ++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/src/terminal/ansi.zig b/src/terminal/ansi.zig index 0665bbb06..eb77b49da 100644 --- a/src/terminal/ansi.zig +++ b/src/terminal/ansi.zig @@ -29,3 +29,16 @@ pub const RenditionAspect = enum(u16) { // user-generated. _, }; + +/// Modes that can be set with with Set Mode (SM) (ESC [ h). The enum +/// values correspond to the `?`-prefixed modes, since those are the ones +/// of primary interest. The enum value is the mode value. +pub const Mode = enum(u16) { + /// If set, the origin of the coordinate system is relative to the + /// current scroll region. If set the cursor is moved to the top left of + /// the current scroll region. + origin = 6, + + // Non-exhaustive so that @intToEnum never fails for unsupported modes. + _, +}; diff --git a/src/terminal/stream.zig b/src/terminal/stream.zig index f9f6d7c3d..321bc58ac 100644 --- a/src/terminal/stream.zig +++ b/src/terminal/stream.zig @@ -230,6 +230,18 @@ pub fn Stream(comptime Handler: type) type { }, ) else log.warn("unimplemented CSI callback: {}", .{action}), + // SM - Set Mode + 'h' => if (@hasDecl(T, "setMode")) { + for (action.params) |mode| + try self.handler.setMode(@intToEnum(ansi.Mode, mode), true); + } else log.warn("unimplemented CSI callback: {}", .{action}), + + // RM - Reset Mode + 'l' => if (@hasDecl(T, "setMode")) { + for (action.params) |mode| + try self.handler.setMode(@intToEnum(ansi.Mode, mode), false); + } else log.warn("unimplemented CSI callback: {}", .{action}), + // SGR - Select Graphic Rendition 'm' => if (@hasDecl(T, "selectGraphicRendition")) { if (action.params.len == 0) { @@ -310,3 +322,21 @@ test "stream: cursor right (CUF)" { try s.nextSlice("\x1B[5;4C"); try testing.expectEqual(@as(u16, 0), s.handler.amount); } + +test "stream: set mode (SM) and reset mode (RM)" { + const H = struct { + mode: ansi.Mode = @intToEnum(ansi.Mode, 0), + + pub fn setMode(self: *@This(), mode: ansi.Mode, v: bool) !void { + self.mode = @intToEnum(ansi.Mode, 0); + if (v) self.mode = mode; + } + }; + + var s: Stream(H) = .{ .handler = .{} }; + try s.nextSlice("\x1B[?6h"); + try testing.expectEqual(@as(ansi.Mode, .origin), s.handler.mode); + + try s.nextSlice("\x1B[?6l"); + try testing.expectEqual(@intToEnum(ansi.Mode, 0), s.handler.mode); +}