feat(windows): parse escape seqences in windows input stream
This commit is contained in:
parent
ca85cbf3b2
commit
b82f4e14b4
2 changed files with 13 additions and 35 deletions
|
@ -113,8 +113,11 @@ pub fn Loop(comptime T: type) type {
|
||||||
|
|
||||||
switch (builtin.os.tag) {
|
switch (builtin.os.tag) {
|
||||||
.windows => {
|
.windows => {
|
||||||
|
var parser: Parser = .{
|
||||||
|
.grapheme_data = grapheme_data,
|
||||||
|
};
|
||||||
while (!self.should_quit) {
|
while (!self.should_quit) {
|
||||||
const event = try self.tty.nextEvent();
|
const event = try self.tty.nextEvent(&parser, paste_allocator);
|
||||||
try handleEventGeneric(self, self.vaxis, &cache, Event, event, null);
|
try handleEventGeneric(self, self.vaxis, &cache, Event, event, null);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -6,6 +6,7 @@ const std = @import("std");
|
||||||
const Event = @import("../event.zig").Event;
|
const Event = @import("../event.zig").Event;
|
||||||
const Key = @import("../Key.zig");
|
const Key = @import("../Key.zig");
|
||||||
const Mouse = @import("../Mouse.zig");
|
const Mouse = @import("../Mouse.zig");
|
||||||
|
const Parser = @import("../Parser.zig");
|
||||||
const windows = std.os.windows;
|
const windows = std.os.windows;
|
||||||
|
|
||||||
stdin: windows.HANDLE,
|
stdin: windows.HANDLE,
|
||||||
|
@ -117,7 +118,7 @@ pub fn bufferedWriter(self: *const Tty) std.io.BufferedWriter(4096, std.io.AnyWr
|
||||||
return std.io.bufferedWriter(self.anyWriter());
|
return std.io.bufferedWriter(self.anyWriter());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn nextEvent(self: *Tty) !Event {
|
pub fn nextEvent(self: *Tty, parser: *Parser, paste_allocator: ?std.mem.Allocator) !Event {
|
||||||
// We use a loop so we can ignore certain events
|
// We use a loop so we can ignore certain events
|
||||||
var state: EventState = .{};
|
var state: EventState = .{};
|
||||||
while (true) {
|
while (true) {
|
||||||
|
@ -126,7 +127,7 @@ pub fn nextEvent(self: *Tty) !Event {
|
||||||
if (ReadConsoleInputW(self.stdin, &input_record, 1, &event_count) == 0)
|
if (ReadConsoleInputW(self.stdin, &input_record, 1, &event_count) == 0)
|
||||||
return windows.unexpectedError(windows.kernel32.GetLastError());
|
return windows.unexpectedError(windows.kernel32.GetLastError());
|
||||||
|
|
||||||
if (try self.eventFromRecord(&input_record, &state)) |ev| {
|
if (try self.eventFromRecord(&input_record, &state, parser, paste_allocator)) |ev| {
|
||||||
return ev;
|
return ev;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -137,10 +138,9 @@ pub const EventState = struct {
|
||||||
ansi_idx: usize = 0,
|
ansi_idx: usize = 0,
|
||||||
utf16_buf: [2]u16 = undefined,
|
utf16_buf: [2]u16 = undefined,
|
||||||
utf16_half: bool = false,
|
utf16_half: bool = false,
|
||||||
escape_st: bool = false,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn eventFromRecord(self: *Tty, record: *const INPUT_RECORD, state: *EventState) !?Event {
|
pub fn eventFromRecord(self: *Tty, record: *const INPUT_RECORD, state: *EventState, parser: *Parser, paste_allocator: ?std.mem.Allocator) !?Event {
|
||||||
switch (record.EventType) {
|
switch (record.EventType) {
|
||||||
0x0001 => { // Key event
|
0x0001 => { // Key event
|
||||||
const event = record.Event.KeyEvent;
|
const event = record.Event.KeyEvent;
|
||||||
|
@ -171,36 +171,11 @@ pub fn eventFromRecord(self: *Tty, record: *const INPUT_RECORD, state: *EventSta
|
||||||
state.ansi_buf[state.ansi_idx] = event.uChar.AsciiChar;
|
state.ansi_buf[state.ansi_idx] = event.uChar.AsciiChar;
|
||||||
state.ansi_idx += 1;
|
state.ansi_idx += 1;
|
||||||
if (state.ansi_idx <= 2) return null;
|
if (state.ansi_idx <= 2) return null;
|
||||||
switch (state.ansi_buf[1]) {
|
const result = try parser.parse(state.ansi_buf[0..state.ansi_idx], paste_allocator);
|
||||||
'[' => { // CSI, read until 0x40 to 0xFF
|
return if (result.n == 0) null else evt: {
|
||||||
switch (event.uChar.UnicodeChar) {
|
state.ansi_idx = 0;
|
||||||
0x40...0xFF => {
|
break :evt result.event;
|
||||||
return .cap_da1;
|
};
|
||||||
},
|
|
||||||
else => return null,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
']' => { // OSC, read until ESC \ or BEL
|
|
||||||
if (state.ansi_idx <= 2) return null;
|
|
||||||
switch (event.uChar.UnicodeChar) {
|
|
||||||
0x07 => {
|
|
||||||
return .cap_da1;
|
|
||||||
},
|
|
||||||
0x1B => {
|
|
||||||
state.escape_st = true;
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
'\\' => {
|
|
||||||
if (state.escape_st) {
|
|
||||||
return .cap_da1;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
else => return null,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
else => return null,
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
0x08 => Key.backspace,
|
0x08 => Key.backspace,
|
||||||
0x09 => Key.tab,
|
0x09 => Key.tab,
|
||||||
|
|
Loading…
Reference in a new issue