first
This commit is contained in:
commit
8b8dcce24e
9 changed files with 836 additions and 0 deletions
108
src/main.zig
Normal file
108
src/main.zig
Normal file
|
@ -0,0 +1,108 @@
|
|||
const std = @import("std");
|
||||
const os = std.os;
|
||||
const io = std.io;
|
||||
const fs = std.fs;
|
||||
const mem = std.mem;
|
||||
const heap = std.heap;
|
||||
const fmt = std.fmt;
|
||||
|
||||
pub fn main() !void {
|
||||
var gpa = heap.GeneralPurposeAllocator(.{}){};
|
||||
defer _ = gpa.deinit();
|
||||
const allocator = gpa.allocator();
|
||||
|
||||
var term = try Terminal.init(allocator);
|
||||
defer term.deinit();
|
||||
|
||||
// var info = try Terminal.Info.init(allocator);
|
||||
// defer info.deinit();
|
||||
|
||||
// var seq = Terminal.Info.Sequence.init(allocator, &info);
|
||||
// defer seq.deinit();
|
||||
// try seq.cursorLeft();
|
||||
try term.print("poopoo", .{});
|
||||
try term.cursorLeft();
|
||||
try term.cursorLeft();
|
||||
try term.print("ee", .{});
|
||||
// try seq.writeOut(term.tty.writer()); //io.AnyWriter{ .context = &term.tty, .writeFn = &fs.File.write });
|
||||
}
|
||||
|
||||
pub const Terminal = struct {
|
||||
tty: fs.File,
|
||||
original_termios: os.linux.termios,
|
||||
info: Info,
|
||||
allocator: mem.Allocator,
|
||||
|
||||
pub fn init(allocator: mem.Allocator) !Terminal {
|
||||
var term = Terminal{
|
||||
.tty = try fs.openFileAbsolute("/dev/tty", .{ .mode = .read_write }),
|
||||
.original_termios = undefined,
|
||||
.info = try Info.init(allocator),
|
||||
.allocator = allocator,
|
||||
};
|
||||
errdefer term.tty.close();
|
||||
errdefer term.info.deinit();
|
||||
term.uncook();
|
||||
return term;
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Terminal) void {
|
||||
self.cook();
|
||||
self.tty.close();
|
||||
self.info.deinit();
|
||||
}
|
||||
|
||||
// pub fn poll(self: *Terminal) void {}
|
||||
|
||||
fn uncook(self: *Terminal) void {
|
||||
_ = os.linux.tcgetattr(self.tty.handle, &self.original_termios);
|
||||
var raw = self.original_termios;
|
||||
|
||||
raw.lflag.ECHO = false;
|
||||
raw.lflag.ICANON = false;
|
||||
raw.lflag.ISIG = false;
|
||||
raw.lflag.IEXTEN = false;
|
||||
|
||||
raw.iflag.IXON = false;
|
||||
raw.iflag.ICRNL = false;
|
||||
raw.iflag.BRKINT = false;
|
||||
raw.iflag.INPCK = false;
|
||||
raw.iflag.ISTRIP = false;
|
||||
|
||||
raw.oflag.OPOST = false;
|
||||
|
||||
raw.cc[@intFromEnum(os.linux.V.TIME)] = 0;
|
||||
raw.cc[@intFromEnum(os.linux.V.MIN)] = 1;
|
||||
|
||||
_ = os.linux.tcsetattr(self.tty.handle, .FLUSH, &raw);
|
||||
}
|
||||
|
||||
fn cook(self: *Terminal) void {
|
||||
_ = os.linux.tcsetattr(self.tty.handle, .FLUSH, &self.original_termios);
|
||||
}
|
||||
|
||||
pub fn print(self: *Terminal, comptime format: []const u8, args: anytype) !void {
|
||||
const formatted = try fmt.allocPrint(self.allocator, format, args);
|
||||
defer self.allocator.free(formatted);
|
||||
try self.tty.writeAll(formatted);
|
||||
}
|
||||
|
||||
pub fn cursorLeft(self: *Terminal) !void {
|
||||
try self.info.cursorLeft(self.tty.writer());
|
||||
}
|
||||
|
||||
pub const Info = @import("terminfo.zig");
|
||||
|
||||
pub const SpecialKey = enum(u16) {
|
||||
home,
|
||||
end,
|
||||
page_up,
|
||||
page_down,
|
||||
delete,
|
||||
backspace,
|
||||
arrow_left,
|
||||
arrow_right,
|
||||
arrow_up,
|
||||
arrow_down,
|
||||
};
|
||||
};
|
10
src/root.zig
Normal file
10
src/root.zig
Normal file
|
@ -0,0 +1,10 @@
|
|||
const std = @import("std");
|
||||
const testing = std.testing;
|
||||
|
||||
export fn add(a: i32, b: i32) i32 {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
test "basic add functionality" {
|
||||
try testing.expect(add(3, 7) == 10);
|
||||
}
|
386
src/terminfo.zig
Normal file
386
src/terminfo.zig
Normal file
|
@ -0,0 +1,386 @@
|
|||
const std = @import("std");
|
||||
const mem = std.mem;
|
||||
const fmt = std.fmt;
|
||||
const io = std.io;
|
||||
|
||||
const Self = @This();
|
||||
|
||||
pub fn init(allocator: mem.Allocator) !Self {
|
||||
const result = try std.ChildProcess.run(.{
|
||||
.allocator = allocator,
|
||||
.argv = &[_][]const u8{ "infocmp", "-x" },
|
||||
});
|
||||
defer allocator.free(result.stdout);
|
||||
defer allocator.free(result.stderr);
|
||||
return parse(allocator, result.stdout);
|
||||
}
|
||||
|
||||
pub fn parse(allocator: mem.Allocator, entry: []const u8) !Self {
|
||||
var self = Self{
|
||||
.allocator = allocator,
|
||||
.entry = try allocator.dupe(u8, entry),
|
||||
.names = undefined,
|
||||
.bools = std.StringHashMap(bool).init(allocator),
|
||||
.ints = std.StringHashMap(u32).init(allocator),
|
||||
.strings = std.StringHashMap([]const u8).init(allocator),
|
||||
};
|
||||
|
||||
var num_fields: usize = 0;
|
||||
var line_it = mem.splitScalar(u8, self.entry, '\n');
|
||||
while (line_it.next()) |line| {
|
||||
if (mem.startsWith(u8, line, "#")) continue;
|
||||
|
||||
var field_it = FieldIterator{ .buffer = line, .index = 0 };
|
||||
while (field_it.next()) |field| : (num_fields += 1) {
|
||||
if (num_fields == 0) {
|
||||
self.names = field;
|
||||
continue;
|
||||
}
|
||||
// std.debug.print("'{s}' (len {d}): ", .{ arg, arg.len });
|
||||
if (mem.indexOfScalar(u8, field, '=')) |idx| {
|
||||
// string
|
||||
try self.strings.put(field[0..idx], try unescapeString(allocator, field[idx + 1 ..]));
|
||||
// std.debug.print("string {s} {s}\n", .{ field[0..idx], field[idx + 1 ..] });
|
||||
} else if (mem.indexOfScalar(u8, field, '#')) |idx| {
|
||||
// int
|
||||
try self.ints.put(field[0..idx], try fmt.parseInt(u32, field[idx + 1 ..], 0));
|
||||
// std.debug.print("int {s} {s}\n", .{ field[0..idx], field[idx + 1 ..] });
|
||||
} else {
|
||||
// bool
|
||||
// std.debug.print("bool {s}\n", .{field});
|
||||
try self.bools.put(field, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// var it = self.bools.keyIterator();
|
||||
// while (it.next()) |k| std.debug.print("{s}\n", .{k.*});
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
fn unescapeString(allocator: mem.Allocator, input: []const u8) ![]u8 {
|
||||
var output = try allocator.alloc(u8, input.len);
|
||||
errdefer allocator.free(output);
|
||||
|
||||
var i: usize = 0;
|
||||
var slide: usize = 0;
|
||||
var size = input.len;
|
||||
while (slide < input.len) {
|
||||
if (startsWithNoEscape(input, slide, "\\E") or startsWithNoEscape(input, slide, "\\e")) {
|
||||
output[i] = '\x1b';
|
||||
i += 1;
|
||||
slide += 2;
|
||||
size -= 1;
|
||||
} else if (input[slide] == '^' and (slide == 0 or input[slide - 1] != '\\') and std.ascii.isUpper(input[slide + 1])) {
|
||||
output[i] = input[slide + 1] - 64; // convert to control character
|
||||
i += 1;
|
||||
slide += 2;
|
||||
size -= 1;
|
||||
} else if (startsWithNoEscape(input, slide, "\\n")) {
|
||||
output[i] = '\n';
|
||||
i += 1;
|
||||
slide += 2;
|
||||
size -= 1;
|
||||
} else if (startsWithNoEscape(input, slide, "\\l")) {
|
||||
output[i] = '\x0a';
|
||||
i += 1;
|
||||
slide += 2;
|
||||
size -= 1;
|
||||
} else if (startsWithNoEscape(input, slide, "\\r")) {
|
||||
output[i] = '\r';
|
||||
i += 1;
|
||||
slide += 2;
|
||||
size -= 1;
|
||||
} else if (startsWithNoEscape(input, slide, "\\t")) {
|
||||
output[i] = '\t';
|
||||
i += 1;
|
||||
slide += 2;
|
||||
size -= 1;
|
||||
} else if (startsWithNoEscape(input, slide, "\\b")) {
|
||||
output[i] = '\x08';
|
||||
i += 1;
|
||||
slide += 2;
|
||||
size -= 1;
|
||||
} else if (startsWithNoEscape(input, slide, "\\f")) {
|
||||
output[i] = '\x0c';
|
||||
i += 1;
|
||||
slide += 2;
|
||||
size -= 1;
|
||||
} else if (startsWithNoEscape(input, slide, "\\s")) {
|
||||
output[i] = ' ';
|
||||
i += 1;
|
||||
slide += 2;
|
||||
size -= 1;
|
||||
} else {
|
||||
output[i] = input[slide];
|
||||
i += 1;
|
||||
slide += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: now do the reverse and make a startsWithEscape
|
||||
|
||||
// const in = try allocator.dupe(u8, output);
|
||||
// defer allocator.free(in);
|
||||
// i = 0;
|
||||
// slide = 0;
|
||||
// while (slide < in.len) {
|
||||
// if (in[slide] == '^' and (slide == 0 or in[slide - 1] != '\\') and std.ascii.isUpper(in[slide + 1])) {
|
||||
// output[i] = in[slide + 1] - 64; // convert to control character
|
||||
// i += 1;
|
||||
// slide += 2;
|
||||
// size -= 1;
|
||||
// } else {
|
||||
// output[i] = in[slide];
|
||||
// i += 1;
|
||||
// slide += 1;
|
||||
// }
|
||||
// }
|
||||
|
||||
return try allocator.realloc(output, size);
|
||||
}
|
||||
|
||||
fn startsWithNoEscape(haystack: []const u8, index: usize, needle: []const u8) bool {
|
||||
return mem.startsWith(u8, haystack[index..], needle) and (index == 0 or haystack[index - 1] != '\\');
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Self) void {
|
||||
self.bools.deinit();
|
||||
self.ints.deinit();
|
||||
var sit = self.strings.valueIterator();
|
||||
while (sit.next()) |s| self.allocator.free(s.*);
|
||||
self.strings.deinit();
|
||||
self.allocator.free(self.entry);
|
||||
}
|
||||
|
||||
/// Iterates over terminfo fields, ignoring backslash-escaped commas
|
||||
/// NOTE: Does not follow full iterator pattern!
|
||||
const FieldIterator = struct {
|
||||
buffer: []const u8,
|
||||
index: ?usize,
|
||||
|
||||
pub fn next(self: *FieldIterator) ?[]const u8 {
|
||||
const start = self.index orelse return null;
|
||||
const end = if (getEnd(self.buffer, start)) |delim_start| blk: {
|
||||
self.index = delim_start + 1;
|
||||
break :blk delim_start;
|
||||
} else blk: {
|
||||
self.index = null;
|
||||
break :blk self.buffer.len;
|
||||
};
|
||||
const trimmed = mem.trim(u8, self.buffer[start..end], &std.ascii.whitespace);
|
||||
if (trimmed.len == 0) return null;
|
||||
return trimmed;
|
||||
}
|
||||
|
||||
fn getEnd(buf: []const u8, start: usize) ?usize {
|
||||
var comma = mem.indexOfScalarPos(u8, buf, start, ',') orelse return null;
|
||||
while (buf[comma - 1] == '\\') comma = mem.indexOfScalarPos(u8, buf, comma + 1, ',') orelse return null;
|
||||
return comma;
|
||||
}
|
||||
};
|
||||
|
||||
allocator: mem.Allocator,
|
||||
entry: []u8,
|
||||
names: []const u8,
|
||||
bools: std.StringHashMap(bool),
|
||||
ints: std.StringHashMap(u32),
|
||||
strings: std.StringHashMap([]const u8),
|
||||
|
||||
pub fn cursorLeft(self: *Self, writer: anytype) !void {
|
||||
try writer.writeAll(self.strings.get("cub1") orelse "\x08");
|
||||
}
|
||||
|
||||
// pub const Sequence = struct {
|
||||
// info: *Self,
|
||||
// bytes: std.ArrayList(u8),
|
||||
|
||||
// pub fn init(allocator: mem.Allocator, info: *Self) Sequence {
|
||||
// return .{ .info = info, .bytes = std.ArrayList(u8).init(allocator) };
|
||||
// }
|
||||
|
||||
// pub fn deinit(self: *Sequence) void {
|
||||
// self.bytes.deinit();
|
||||
// }
|
||||
|
||||
// pub fn writeOut(self: *Sequence, writer: anytype) !void {
|
||||
// try writer.writeAll(self.bytes.items);
|
||||
// }
|
||||
|
||||
// pub fn cursorLeft(self: *Sequence) !void {
|
||||
// try self.bytes.appendSlice(self.info.strings.get("cub1") orelse "\x08");
|
||||
// }
|
||||
// };
|
||||
|
||||
pub const Bool = enum {
|
||||
auto_left_margin,
|
||||
auto_right_margin,
|
||||
back_color_erase,
|
||||
can_change,
|
||||
ceol_standout_glitch,
|
||||
col_addr_glitch,
|
||||
cpi_changes_res,
|
||||
cr_cancels_micro_mode,
|
||||
dest_tabs_magic_smso,
|
||||
eat_newline_glitch,
|
||||
erase_overstrike,
|
||||
generic_type,
|
||||
hard_copy,
|
||||
hard_cursor,
|
||||
has_meta_key,
|
||||
has_print_wheel,
|
||||
has_status_line,
|
||||
hue_lightness_saturation,
|
||||
insert_null_glitch,
|
||||
lpi_changes_res,
|
||||
memory_above,
|
||||
memory_below,
|
||||
move_insert_mode,
|
||||
move_standout_mode,
|
||||
needs_xon_xoff,
|
||||
no_esc_ctlc,
|
||||
no_pad_char,
|
||||
non_dest_scroll_region,
|
||||
non_rev_rmcup,
|
||||
over_strike,
|
||||
prtr_silent,
|
||||
row_addr_glitch,
|
||||
semi_auto_right_margin,
|
||||
status_line_esc_ok,
|
||||
tilde_glitch,
|
||||
transparent_underline,
|
||||
xon_xoff,
|
||||
|
||||
pub fn toCapName(self: Bool) []const u8 {
|
||||
return switch (self) {
|
||||
.auto_left_margin => "bw",
|
||||
.auto_right_margin => "am",
|
||||
.back_color_erase => "bce",
|
||||
.can_change => "ccc",
|
||||
.ceol_standout_glitch => "xhp",
|
||||
.col_addr_glitch => "xhpa",
|
||||
.cpi_changes_res => "cpix",
|
||||
.cr_cancels_micro_mode => "crxm",
|
||||
.dest_tabs_magic_smso => "xt",
|
||||
.eat_newline_glitch => "xenl",
|
||||
.erase_overstrike => "eo",
|
||||
.generic_type => "gn",
|
||||
.hard_copy => "hc",
|
||||
.hard_cursor => "chts",
|
||||
.has_meta_key => "km",
|
||||
.has_print_wheel => "daisy",
|
||||
.has_status_line => "hs",
|
||||
.hue_lightness_saturation => "hls",
|
||||
.insert_null_glitch => "in",
|
||||
.lpi_changes_res => "lpix",
|
||||
.memory_above => "da",
|
||||
.memory_below => "db",
|
||||
.move_insert_mode => "mir",
|
||||
.move_standout_mode => "msgr",
|
||||
.needs_xon_xoff => "nxon",
|
||||
.no_esc_ctlc => "xsb",
|
||||
.no_pad_char => "npc",
|
||||
.non_dest_scroll_region => "ndscr",
|
||||
.non_rev_rmcup => "nrrmc",
|
||||
.over_strike => "os",
|
||||
.prtr_silent => "mc5i",
|
||||
.row_addr_glitch => "xvpa",
|
||||
.semi_auto_right_margin => "sam",
|
||||
.status_line_esc_ok => "eslok",
|
||||
.tilde_glitch => "hz",
|
||||
.transparent_underline => "ul",
|
||||
.xon_xoff => "xon",
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub const Ints = enum {
|
||||
columns,
|
||||
init_tabs,
|
||||
label_height,
|
||||
label_width,
|
||||
lines,
|
||||
lines_of_memory,
|
||||
magic_cookie_glitch,
|
||||
max_attributes,
|
||||
max_colors,
|
||||
max_pairs,
|
||||
maximum_windows,
|
||||
no_color_video,
|
||||
num_labels,
|
||||
padding_baud_rate,
|
||||
virtual_terminal,
|
||||
width_status_line,
|
||||
};
|
||||
|
||||
pub const Strings = enum {
|
||||
acs_chars,
|
||||
back_tab_bell,
|
||||
carriage_return,
|
||||
change_char_pitch,
|
||||
change_line_pitch,
|
||||
change_res_horz,
|
||||
change_res_vert,
|
||||
change_scroll_region,
|
||||
char_padding,
|
||||
clear_all_tabs,
|
||||
};
|
||||
|
||||
test "parse terminfo" {
|
||||
var terminfo = try parse(std.testing.allocator,
|
||||
\\# Reconstructed via infocmp from file: /nix/store/c1d0bgq6whz4khqxncmqikpdsxmr1szw-kitty-0.32.2/lib/kitty/terminfo/x/xterm-kitty
|
||||
\\xterm-kitty|KovIdTTY,
|
||||
\\ am, ccc, hs, km, mc5i, mir, msgr, npc, xenl,
|
||||
\\ colors#0x100, cols#80, it#8, lines#24, pairs#0x7fff,
|
||||
\\ acsc=++\,\,--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~,
|
||||
\\ bel=^G, bold=\E[1m, cbt=\E[Z, civis=\E[?25l,
|
||||
\\ clear=\E[H\E[2J, cnorm=\E[?12h\E[?25h, cr=\r,
|
||||
\\ csr=\E[%i%p1%d;%p2%dr, cub=\E[%p1%dD, cub1=^H,
|
||||
\\ cud=\E[%p1%dB, cud1=\n, cuf=\E[%p1%dC, cuf1=\E[C,
|
||||
\\ cup=\E[%i%p1%d;%p2%dH, cuu=\E[%p1%dA, cuu1=\E[A,
|
||||
\\ cvvis=\E[?12;25h, dch=\E[%p1%dP, dch1=\E[P, dim=\E[2m,
|
||||
\\ dl=\E[%p1%dM, dl1=\E[M, dsl=\E]2;\E\\, ech=\E[%p1%dX,
|
||||
\\ ed=\E[J, el=\E[K, el1=\E[1K, flash=\E[?5h$<100/>\E[?5l,
|
||||
\\ fsl=^G, home=\E[H, hpa=\E[%i%p1%dG, ht=^I, hts=\EH,
|
||||
\\ ich=\E[%p1%d@, il=\E[%p1%dL, il1=\E[L, ind=\n,
|
||||
\\ indn=\E[%p1%dS,
|
||||
\\ initc=\E]4;%p1%d;rgb:%p2%{255}%*%{1000}%/%2.2X/%p3%{255}%*%{1000}%/%2.2X/%p4%{255}%*%{1000}%/%2.2X\E\\,
|
||||
\\ kBEG=\E[1;2E, kDC=\E[3;2~, kEND=\E[1;2F, kHOM=\E[1;2H,
|
||||
\\ kIC=\E[2;2~, kLFT=\E[1;2D, kNXT=\E[6;2~, kPRV=\E[5;2~,
|
||||
\\ kRIT=\E[1;2C, ka1=, ka3=, kbeg=\EOE, kbs=^?, kc1=, kc3=,
|
||||
\\ kcbt=\E[Z, kcub1=\EOD, kcud1=\EOB, kcuf1=\EOC, kcuu1=\EOA,
|
||||
\\ kdch1=\E[3~, kend=\EOF, kf1=\EOP, kf10=\E[21~, kf11=\E[23~,
|
||||
\\ kf12=\E[24~, kf13=\E[1;2P, kf14=\E[1;2Q, kf15=\E[13;2~,
|
||||
\\ kf16=\E[1;2S, kf17=\E[15;2~, kf18=\E[17;2~,
|
||||
\\ kf19=\E[18;2~, kf2=\EOQ, kf20=\E[19;2~, kf21=\E[20;2~,
|
||||
\\ kf22=\E[21;2~, kf23=\E[23;2~, kf24=\E[24;2~,
|
||||
\\ kf25=\E[1;5P, kf26=\E[1;5Q, kf27=\E[13;5~, kf28=\E[1;5S,
|
||||
\\ kf29=\E[15;5~, kf3=\EOR, kf30=\E[17;5~, kf31=\E[18;5~,
|
||||
\\ kf32=\E[19;5~, kf33=\E[20;5~, kf34=\E[21;5~,
|
||||
\\ kf35=\E[23;5~, kf36=\E[24;5~, kf37=\E[1;6P, kf38=\E[1;6Q,
|
||||
\\ kf39=\E[13;6~, kf4=\EOS, kf40=\E[1;6S, kf41=\E[15;6~,
|
||||
\\ kf42=\E[17;6~, kf43=\E[18;6~, kf44=\E[19;6~,
|
||||
\\ kf45=\E[20;6~, kf46=\E[21;6~, kf47=\E[23;6~,
|
||||
\\ kf48=\E[24;6~, kf49=\E[1;3P, kf5=\E[15~, kf50=\E[1;3Q,
|
||||
\\ kf51=\E[13;3~, kf52=\E[1;3S, kf53=\E[15;3~,
|
||||
\\ kf54=\E[17;3~, kf55=\E[18;3~, kf56=\E[19;3~,
|
||||
\\ kf57=\E[20;3~, kf58=\E[21;3~, kf59=\E[23;3~, kf6=\E[17~,
|
||||
\\ kf60=\E[24;3~, kf61=\E[1;4P, kf62=\E[1;4Q, kf63=\E[13;4~,
|
||||
\\ kf7=\E[18~, kf8=\E[19~, kf9=\E[20~, khlp=, khome=\EOH,
|
||||
\\ kich1=\E[2~, kind=\E[1;2B, kmous=\E[M, knp=\E[6~,
|
||||
\\ kpp=\E[5~, kri=\E[1;2A, kund=, oc=\E]104\007, op=\E[39;49m,
|
||||
\\ rc=\E8, rep=%p1%c\E[%p2%{1}%-%db, rev=\E[7m, ri=\EM,
|
||||
\\ rin=\E[%p1%dT, ritm=\E[23m, rmacs=\E(B, rmam=\E[?7l,
|
||||
\\ rmcup=\E[?1049l, rmir=\E[4l, rmkx=\E[?1l, rmso=\E[27m,
|
||||
\\ rmul=\E[24m, rs1=\E]\E\\\Ec, sc=\E7,
|
||||
\\ setab=\E[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m,
|
||||
\\ setaf=\E[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m,
|
||||
\\ sgr=%?%p9%t\E(0%e\E(B%;\E[0%?%p6%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;%?%p7%t;8%;m,
|
||||
\\ sgr0=\E(B\E[m, sitm=\E[3m, smacs=\E(0, smam=\E[?7h,
|
||||
\\ smcup=\E[?1049h, smir=\E[4h, smkx=\E[?1h, smso=\E[7m,
|
||||
\\ smul=\E[4m, tbc=\E[3g, tsl=\E]2;, u6=\E[%i%d;%dR, u7=\E[6n,
|
||||
\\ u8=\E[?%[;0123456789]c, u9=\E[c, vpa=\E[%i%p1%dd,
|
||||
);
|
||||
defer terminfo.deinit();
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue