mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-15 00:06:09 +03:00
Merge branch 'main' of github.com:AlexJuca/ghostty into feature/display-memory-size-in-bytes-and-kb
This commit is contained in:
@ -1,10 +1,10 @@
|
|||||||
.{
|
.{
|
||||||
.name = "cimgui",
|
.name = "cimgui",
|
||||||
.version = "1.89.9",
|
.version = "1.90.6", // -docking branch
|
||||||
.paths = .{""},
|
.paths = .{""},
|
||||||
.dependencies = .{
|
.dependencies = .{
|
||||||
// This should be kept in sync with the submodule in the cimgui source
|
// This should be kept in sync with the submodule in the cimgui source
|
||||||
// code to be safe that they're compatible.
|
// code in ./vendor/ to be safe that they're compatible.
|
||||||
.imgui = .{
|
.imgui = .{
|
||||||
.url = "https://github.com/ocornut/imgui/archive/e391fe2e66eb1c96b1624ae8444dc64c23146ef4.tar.gz",
|
.url = "https://github.com/ocornut/imgui/archive/e391fe2e66eb1c96b1624ae8444dc64c23146ef4.tar.gz",
|
||||||
.hash = "1220bc6b9daceaf7c8c60f3c3998058045ba0c5c5f48ae255ff97776d9cd8bfc6402",
|
.hash = "1220bc6b9daceaf7c8c60f3c3998058045ba0c5c5f48ae255ff97776d9cd8bfc6402",
|
||||||
|
@ -13,7 +13,56 @@ pub fn build(b: *std.Build) !void {
|
|||||||
) orelse (target.result.os.tag != .windows);
|
) orelse (target.result.os.tag != .windows);
|
||||||
const freetype_enabled = b.option(bool, "enable-freetype", "Build freetype") orelse true;
|
const freetype_enabled = b.option(bool, "enable-freetype", "Build freetype") orelse true;
|
||||||
|
|
||||||
const module = b.addModule("fontconfig", .{ .root_source_file = b.path("main.zig") });
|
const module = b.addModule("fontconfig", .{
|
||||||
|
.root_source_file = b.path("main.zig"),
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
});
|
||||||
|
|
||||||
|
// For dynamic linking, we prefer dynamic linking and to search by
|
||||||
|
// mode first. Mode first will search all paths for a dynamic library
|
||||||
|
// before falling back to static.
|
||||||
|
const dynamic_link_opts: std.Build.Module.LinkSystemLibraryOptions = .{
|
||||||
|
.preferred_link_mode = .dynamic,
|
||||||
|
.search_strategy = .mode_first,
|
||||||
|
};
|
||||||
|
|
||||||
|
const test_exe = b.addTest(.{
|
||||||
|
.name = "test",
|
||||||
|
.root_source_file = b.path("main.zig"),
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
});
|
||||||
|
const tests_run = b.addRunArtifact(test_exe);
|
||||||
|
const test_step = b.step("test", "Run tests");
|
||||||
|
test_step.dependOn(&tests_run.step);
|
||||||
|
|
||||||
|
if (b.systemIntegrationOption("fontconfig", .{})) {
|
||||||
|
module.linkSystemLibrary("fontconfig", dynamic_link_opts);
|
||||||
|
test_exe.linkSystemLibrary2("fontconfig", dynamic_link_opts);
|
||||||
|
} else {
|
||||||
|
const lib = try buildLib(b, module, .{
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
|
||||||
|
.libxml2_enabled = libxml2_enabled,
|
||||||
|
.libxml2_iconv_enabled = libxml2_iconv_enabled,
|
||||||
|
.freetype_enabled = freetype_enabled,
|
||||||
|
|
||||||
|
.dynamic_link_opts = dynamic_link_opts,
|
||||||
|
});
|
||||||
|
|
||||||
|
test_exe.linkLibrary(lib);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn buildLib(b: *std.Build, module: *std.Build.Module, options: anytype) !*std.Build.Step.Compile {
|
||||||
|
const target = options.target;
|
||||||
|
const optimize = options.optimize;
|
||||||
|
|
||||||
|
const libxml2_enabled = options.libxml2_enabled;
|
||||||
|
const libxml2_iconv_enabled = options.libxml2_iconv_enabled;
|
||||||
|
const freetype_enabled = options.freetype_enabled;
|
||||||
|
|
||||||
const upstream = b.dependency("fontconfig", .{});
|
const upstream = b.dependency("fontconfig", .{});
|
||||||
const lib = b.addStaticLibrary(.{
|
const lib = b.addStaticLibrary(.{
|
||||||
@ -131,13 +180,7 @@ pub fn build(b: *std.Build) !void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// For dynamic linking, we prefer dynamic linking and to search by
|
const dynamic_link_opts = options.dynamic_link_opts;
|
||||||
// mode first. Mode first will search all paths for a dynamic library
|
|
||||||
// before falling back to static.
|
|
||||||
const dynamic_link_opts: std.Build.Module.LinkSystemLibraryOptions = .{
|
|
||||||
.preferred_link_mode = .dynamic,
|
|
||||||
.search_strategy = .mode_first,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Freetype2
|
// Freetype2
|
||||||
_ = b.systemIntegrationOption("freetype", .{}); // So it shows up in help
|
_ = b.systemIntegrationOption("freetype", .{}); // So it shows up in help
|
||||||
@ -194,16 +237,7 @@ pub fn build(b: *std.Build) !void {
|
|||||||
|
|
||||||
b.installArtifact(lib);
|
b.installArtifact(lib);
|
||||||
|
|
||||||
const test_exe = b.addTest(.{
|
return lib;
|
||||||
.name = "test",
|
|
||||||
.root_source_file = b.path("main.zig"),
|
|
||||||
.target = target,
|
|
||||||
.optimize = optimize,
|
|
||||||
});
|
|
||||||
test_exe.linkLibrary(lib);
|
|
||||||
const tests_run = b.addRunArtifact(test_exe);
|
|
||||||
const test_step = b.step("test", "Run tests");
|
|
||||||
test_step.dependOn(&tests_run.step);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const headers = &.{
|
const headers = &.{
|
||||||
|
@ -5,36 +5,59 @@ pub fn build(b: *std.Build) !void {
|
|||||||
const target = b.standardTargetOptions(.{});
|
const target = b.standardTargetOptions(.{});
|
||||||
const optimize = b.standardOptimizeOption(.{});
|
const optimize = b.standardOptimizeOption(.{});
|
||||||
|
|
||||||
const module = b.addModule("oniguruma", .{ .root_source_file = b.path("main.zig") });
|
const module = b.addModule("oniguruma", .{
|
||||||
|
.root_source_file = b.path("main.zig"),
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
});
|
||||||
|
|
||||||
const upstream = b.dependency("oniguruma", .{});
|
// For dynamic linking, we prefer dynamic linking and to search by
|
||||||
const lib = try buildOniguruma(b, upstream, target, optimize);
|
// mode first. Mode first will search all paths for a dynamic library
|
||||||
module.addIncludePath(upstream.path("src"));
|
// before falling back to static.
|
||||||
b.installArtifact(lib);
|
const dynamic_link_opts: std.Build.Module.LinkSystemLibraryOptions = .{
|
||||||
|
.preferred_link_mode = .dynamic,
|
||||||
|
.search_strategy = .mode_first,
|
||||||
|
};
|
||||||
|
|
||||||
|
var test_exe: ?*std.Build.Step.Compile = null;
|
||||||
if (target.query.isNative()) {
|
if (target.query.isNative()) {
|
||||||
const test_exe = b.addTest(.{
|
test_exe = b.addTest(.{
|
||||||
.name = "test",
|
.name = "test",
|
||||||
.root_source_file = b.path("main.zig"),
|
.root_source_file = b.path("main.zig"),
|
||||||
.target = target,
|
.target = target,
|
||||||
.optimize = optimize,
|
.optimize = optimize,
|
||||||
});
|
});
|
||||||
test_exe.linkLibrary(lib);
|
const tests_run = b.addRunArtifact(test_exe.?);
|
||||||
const tests_run = b.addRunArtifact(test_exe);
|
|
||||||
const test_step = b.step("test", "Run tests");
|
const test_step = b.step("test", "Run tests");
|
||||||
test_step.dependOn(&tests_run.step);
|
test_step.dependOn(&tests_run.step);
|
||||||
|
|
||||||
// Uncomment this if we're debugging tests
|
// Uncomment this if we're debugging tests
|
||||||
b.installArtifact(test_exe);
|
b.installArtifact(test_exe.?);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (b.systemIntegrationOption("oniguruma", .{})) {
|
||||||
|
module.linkSystemLibrary("oniguruma", dynamic_link_opts);
|
||||||
|
|
||||||
|
if (test_exe) |exe| {
|
||||||
|
exe.linkSystemLibrary2("oniguruma", dynamic_link_opts);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const lib = try buildLib(b, module, .{
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (test_exe) |exe| {
|
||||||
|
exe.linkLibrary(lib);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn buildOniguruma(
|
pub fn buildLib(b: *std.Build, module: *std.Build.Module, options: anytype) !*std.Build.Step.Compile {
|
||||||
b: *std.Build,
|
const target = options.target;
|
||||||
upstream: *std.Build.Dependency,
|
const optimize = options.optimize;
|
||||||
target: std.Build.ResolvedTarget,
|
|
||||||
optimize: std.builtin.OptimizeMode,
|
const upstream = b.dependency("oniguruma", .{});
|
||||||
) !*std.Build.Step.Compile {
|
|
||||||
const lib = b.addStaticLibrary(.{
|
const lib = b.addStaticLibrary(.{
|
||||||
.name = "oniguruma",
|
.name = "oniguruma",
|
||||||
.target = target,
|
.target = target,
|
||||||
@ -43,6 +66,7 @@ fn buildOniguruma(
|
|||||||
const t = target.result;
|
const t = target.result;
|
||||||
lib.linkLibC();
|
lib.linkLibC();
|
||||||
lib.addIncludePath(upstream.path("src"));
|
lib.addIncludePath(upstream.path("src"));
|
||||||
|
module.addIncludePath(upstream.path("src"));
|
||||||
|
|
||||||
if (target.result.isDarwin()) {
|
if (target.result.isDarwin()) {
|
||||||
const apple_sdk = @import("apple_sdk");
|
const apple_sdk = @import("apple_sdk");
|
||||||
@ -134,5 +158,7 @@ fn buildOniguruma(
|
|||||||
.{ .include_extensions = &.{".h"} },
|
.{ .include_extensions = &.{".h"} },
|
||||||
);
|
);
|
||||||
|
|
||||||
|
b.installArtifact(lib);
|
||||||
|
|
||||||
return lib;
|
return lib;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
.{
|
.{
|
||||||
.name = "simdutf",
|
.name = "simdutf",
|
||||||
.version = "4.0.9",
|
.version = "5.2.8",
|
||||||
.paths = .{""},
|
.paths = .{""},
|
||||||
.dependencies = .{
|
.dependencies = .{
|
||||||
.apple_sdk = .{ .path = "../apple-sdk" },
|
.apple_sdk = .{ .path = "../apple-sdk" },
|
||||||
|
@ -1644,7 +1644,7 @@ fn gtkActionPresentSurface(
|
|||||||
|
|
||||||
// Convert that u64 to pointer to a core surface. A value of zero
|
// Convert that u64 to pointer to a core surface. A value of zero
|
||||||
// means that there was no target surface for the notification so
|
// means that there was no target surface for the notification so
|
||||||
// we dont' focus any surface.
|
// we don't focus any surface.
|
||||||
const ptr_int: u64 = c.g_variant_get_uint64(parameter);
|
const ptr_int: u64 = c.g_variant_get_uint64(parameter);
|
||||||
if (ptr_int == 0) return;
|
if (ptr_int == 0) return;
|
||||||
const surface: *CoreSurface = @ptrFromInt(ptr_int);
|
const surface: *CoreSurface = @ptrFromInt(ptr_int);
|
||||||
|
@ -64,6 +64,7 @@ fn init(
|
|||||||
c.gtk_window_set_title(gtk_window, titleText(request));
|
c.gtk_window_set_title(gtk_window, titleText(request));
|
||||||
c.gtk_window_set_default_size(gtk_window, 550, 275);
|
c.gtk_window_set_default_size(gtk_window, 550, 275);
|
||||||
c.gtk_window_set_resizable(gtk_window, 0);
|
c.gtk_window_set_resizable(gtk_window, 0);
|
||||||
|
c.gtk_widget_add_css_class(@ptrCast(@alignCast(gtk_window)), "clipboard-confirmation-window");
|
||||||
_ = c.g_signal_connect_data(
|
_ = c.g_signal_connect_data(
|
||||||
window,
|
window,
|
||||||
"destroy",
|
"destroy",
|
||||||
|
@ -55,6 +55,7 @@ fn init(self: *ConfigErrors, app: *App) !void {
|
|||||||
c.gtk_window_set_default_size(gtk_window, 600, 275);
|
c.gtk_window_set_default_size(gtk_window, 600, 275);
|
||||||
c.gtk_window_set_resizable(gtk_window, 0);
|
c.gtk_window_set_resizable(gtk_window, 0);
|
||||||
c.gtk_window_set_icon_name(gtk_window, build_config.bundle_id);
|
c.gtk_window_set_icon_name(gtk_window, build_config.bundle_id);
|
||||||
|
c.gtk_widget_add_css_class(@ptrCast(@alignCast(gtk_window)), "config-errors-window");
|
||||||
_ = c.g_signal_connect_data(window, "destroy", c.G_CALLBACK(>kDestroy), self, null, c.G_CONNECT_DEFAULT);
|
_ = c.g_signal_connect_data(window, "destroy", c.G_CALLBACK(>kDestroy), self, null, c.G_CONNECT_DEFAULT);
|
||||||
|
|
||||||
// Set some state
|
// Set some state
|
||||||
|
@ -143,6 +143,7 @@ const Window = struct {
|
|||||||
c.gtk_window_set_title(gtk_window, "Ghostty: Terminal Inspector");
|
c.gtk_window_set_title(gtk_window, "Ghostty: Terminal Inspector");
|
||||||
c.gtk_window_set_default_size(gtk_window, 1000, 600);
|
c.gtk_window_set_default_size(gtk_window, 1000, 600);
|
||||||
c.gtk_window_set_icon_name(gtk_window, build_config.bundle_id);
|
c.gtk_window_set_icon_name(gtk_window, build_config.bundle_id);
|
||||||
|
c.gtk_widget_add_css_class(@ptrCast(@alignCast(gtk_window)), "inspector-window");
|
||||||
|
|
||||||
// Initialize our imgui widget
|
// Initialize our imgui widget
|
||||||
try self.imgui_widget.init();
|
try self.imgui_widget.init();
|
||||||
|
@ -129,7 +129,7 @@ pub fn eventMods(
|
|||||||
|
|
||||||
// On Wayland, we have to use the GDK device because the mods sent
|
// On Wayland, we have to use the GDK device because the mods sent
|
||||||
// to this event do not have the modifier key applied if it was
|
// to this event do not have the modifier key applied if it was
|
||||||
// presssed (i.e. left control).
|
// pressed (i.e. left control).
|
||||||
break :mods translateMods(c.gdk_device_get_modifier_state(device));
|
break :mods translateMods(c.gdk_device_get_modifier_state(device));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2916,7 +2916,7 @@ pub fn loadCliArgs(self: *Config, alloc_gpa: Allocator) !void {
|
|||||||
self.@"config-default-files" = true;
|
self.@"config-default-files" = true;
|
||||||
|
|
||||||
// Keep track of the replay steps up to this point so we
|
// Keep track of the replay steps up to this point so we
|
||||||
// can replay if we are disgarding the default files.
|
// can replay if we are discarding the default files.
|
||||||
const replay_len_start = self._replay_steps.items.len;
|
const replay_len_start = self._replay_steps.items.len;
|
||||||
|
|
||||||
// Keep track of font families because if they are set from the CLI
|
// Keep track of font families because if they are set from the CLI
|
||||||
|
@ -341,7 +341,7 @@ pub const Action = union(enum) {
|
|||||||
/// the direction given. For example `new_split:up`. Valid values are left, right, up, down and auto.
|
/// the direction given. For example `new_split:up`. Valid values are left, right, up, down and auto.
|
||||||
new_split: SplitDirection,
|
new_split: SplitDirection,
|
||||||
|
|
||||||
/// Focus on a split in a given direction. For example `goto_split:top`. Valid values are top, bottom, left, right, previous and next.
|
/// Focus on a split in a given direction. For example `goto_split:up`. Valid values are left, right, up, down, previous and next.
|
||||||
goto_split: SplitFocusDirection,
|
goto_split: SplitFocusDirection,
|
||||||
|
|
||||||
/// zoom/unzoom the current split.
|
/// zoom/unzoom the current split.
|
||||||
|
@ -282,7 +282,12 @@ fn legacy(
|
|||||||
// If we match a control sequence, we output that directly. For
|
// If we match a control sequence, we output that directly. For
|
||||||
// ctrlSeq we have to use all mods because we want it to only
|
// ctrlSeq we have to use all mods because we want it to only
|
||||||
// match ctrl+<char>.
|
// match ctrl+<char>.
|
||||||
if (ctrlSeq(self.event.utf8, self.event.unshifted_codepoint, all_mods)) |char| {
|
if (ctrlSeq(
|
||||||
|
self.event.key,
|
||||||
|
self.event.utf8,
|
||||||
|
self.event.unshifted_codepoint,
|
||||||
|
all_mods,
|
||||||
|
)) |char| {
|
||||||
// C0 sequences support alt-as-esc prefixing.
|
// C0 sequences support alt-as-esc prefixing.
|
||||||
if (binding_mods.alt) {
|
if (binding_mods.alt) {
|
||||||
if (buf.len < 2) return error.OutOfMemory;
|
if (buf.len < 2) return error.OutOfMemory;
|
||||||
@ -538,19 +543,17 @@ fn pcStyleFunctionKey(
|
|||||||
/// into a C0 byte. There are many cases for this and you should read
|
/// into a C0 byte. There are many cases for this and you should read
|
||||||
/// the source code to understand them.
|
/// the source code to understand them.
|
||||||
fn ctrlSeq(
|
fn ctrlSeq(
|
||||||
|
logical_key: key.Key,
|
||||||
utf8: []const u8,
|
utf8: []const u8,
|
||||||
unshifted_codepoint: u21,
|
unshifted_codepoint: u21,
|
||||||
mods: key.Mods,
|
mods: key.Mods,
|
||||||
) ?u8 {
|
) ?u8 {
|
||||||
|
const ctrl_only = comptime (key.Mods{ .ctrl = true }).int();
|
||||||
|
|
||||||
// If ctrl is not pressed then we never do anything.
|
// If ctrl is not pressed then we never do anything.
|
||||||
if (!mods.ctrl) return null;
|
if (!mods.ctrl) return null;
|
||||||
|
|
||||||
// If we don't have exactly one byte in our utf8 sequence, then
|
|
||||||
// we don't do anything, since all our ctrl keys are based on ASCII.
|
|
||||||
if (utf8.len != 1) return null;
|
|
||||||
|
|
||||||
const char, const unset_mods = unset_mods: {
|
const char, const unset_mods = unset_mods: {
|
||||||
var char = utf8[0];
|
|
||||||
var unset_mods = mods;
|
var unset_mods = mods;
|
||||||
|
|
||||||
// Remove alt from our modifiers because it does not impact whether
|
// Remove alt from our modifiers because it does not impact whether
|
||||||
@ -558,6 +561,34 @@ fn ctrlSeq(
|
|||||||
// logic separately.
|
// logic separately.
|
||||||
unset_mods.alt = false;
|
unset_mods.alt = false;
|
||||||
|
|
||||||
|
var char: u8 = char: {
|
||||||
|
// If we have exactly one UTF8 byte, we assume that is the
|
||||||
|
// character we want to convert to a C0 byte.
|
||||||
|
if (utf8.len == 1) break :char utf8[0];
|
||||||
|
|
||||||
|
// If we have a logical key that maps to a single byte
|
||||||
|
// printable character, we use that. History to explain this:
|
||||||
|
// this was added to support cyrillic keyboard layouts such
|
||||||
|
// as Russian and Mongolian. These layouts have a `c` key that
|
||||||
|
// maps to U+0441 (cyrillic small letter "c") but every
|
||||||
|
// terminal I've tested encodes this as ctrl+c.
|
||||||
|
if (logical_key.codepoint()) |cp| {
|
||||||
|
if (std.math.cast(u8, cp)) |byte| {
|
||||||
|
// For this specific case, we only map to the key if
|
||||||
|
// we have exactly ctrl pressed. This is because shift
|
||||||
|
// would modify the key and we don't know how to do that
|
||||||
|
// properly here (don't have the layout). And we want
|
||||||
|
// to encode shift as CSIu.
|
||||||
|
if (unset_mods.int() != ctrl_only) return null;
|
||||||
|
break :char byte;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise we don't have a character to convert that
|
||||||
|
// we can reliably map to a C0 byte.
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
// Remove shift if we have something outside of the US letter
|
// Remove shift if we have something outside of the US letter
|
||||||
// range. This is so that characters such as `ctrl+shift+-`
|
// range. This is so that characters such as `ctrl+shift+-`
|
||||||
// generate the correct ctrl-seq (used by emacs).
|
// generate the correct ctrl-seq (used by emacs).
|
||||||
@ -596,7 +627,6 @@ fn ctrlSeq(
|
|||||||
};
|
};
|
||||||
|
|
||||||
// After unsetting, we only continue if we have ONLY control set.
|
// After unsetting, we only continue if we have ONLY control set.
|
||||||
const ctrl_only = comptime (key.Mods{ .ctrl = true }).int();
|
|
||||||
if (unset_mods.int() != ctrl_only) return null;
|
if (unset_mods.int() != ctrl_only) return null;
|
||||||
|
|
||||||
// From Kitty's key encoding logic. I tried to discern the exact
|
// From Kitty's key encoding logic. I tried to discern the exact
|
||||||
@ -2132,36 +2162,52 @@ test "legacy: hu layout ctrl+ő sends proper codepoint" {
|
|||||||
const actual = try enc.legacy(&buf);
|
const actual = try enc.legacy(&buf);
|
||||||
try testing.expectEqualStrings("[337;5u", actual[1..]);
|
try testing.expectEqualStrings("[337;5u", actual[1..]);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "ctrlseq: normal ctrl c" {
|
test "ctrlseq: normal ctrl c" {
|
||||||
const seq = ctrlSeq("c", 'c', .{ .ctrl = true });
|
const seq = ctrlSeq(.invalid, "c", 'c', .{ .ctrl = true });
|
||||||
try testing.expectEqual(@as(u8, 0x03), seq.?);
|
try testing.expectEqual(@as(u8, 0x03), seq.?);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "ctrlseq: normal ctrl c, right control" {
|
test "ctrlseq: normal ctrl c, right control" {
|
||||||
const seq = ctrlSeq("c", 'c', .{ .ctrl = true, .sides = .{ .ctrl = .right } });
|
const seq = ctrlSeq(.invalid, "c", 'c', .{ .ctrl = true, .sides = .{ .ctrl = .right } });
|
||||||
try testing.expectEqual(@as(u8, 0x03), seq.?);
|
try testing.expectEqual(@as(u8, 0x03), seq.?);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "ctrlseq: alt should be allowed" {
|
test "ctrlseq: alt should be allowed" {
|
||||||
const seq = ctrlSeq("c", 'c', .{ .alt = true, .ctrl = true });
|
const seq = ctrlSeq(.invalid, "c", 'c', .{ .alt = true, .ctrl = true });
|
||||||
try testing.expectEqual(@as(u8, 0x03), seq.?);
|
try testing.expectEqual(@as(u8, 0x03), seq.?);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "ctrlseq: no ctrl does nothing" {
|
test "ctrlseq: no ctrl does nothing" {
|
||||||
try testing.expect(ctrlSeq("c", 'c', .{}) == null);
|
try testing.expect(ctrlSeq(.invalid, "c", 'c', .{}) == null);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "ctrlseq: shifted non-character" {
|
test "ctrlseq: shifted non-character" {
|
||||||
const seq = ctrlSeq("_", '-', .{ .ctrl = true, .shift = true });
|
const seq = ctrlSeq(.invalid, "_", '-', .{ .ctrl = true, .shift = true });
|
||||||
try testing.expectEqual(@as(u8, 0x1F), seq.?);
|
try testing.expectEqual(@as(u8, 0x1F), seq.?);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "ctrlseq: caps ascii letter" {
|
test "ctrlseq: caps ascii letter" {
|
||||||
const seq = ctrlSeq("C", 'c', .{ .ctrl = true, .caps_lock = true });
|
const seq = ctrlSeq(.invalid, "C", 'c', .{ .ctrl = true, .caps_lock = true });
|
||||||
try testing.expectEqual(@as(u8, 0x03), seq.?);
|
try testing.expectEqual(@as(u8, 0x03), seq.?);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "ctrlseq: shift does not generate ctrl seq" {
|
test "ctrlseq: shift does not generate ctrl seq" {
|
||||||
try testing.expect(ctrlSeq("C", 'c', .{ .shift = true }) == null);
|
try testing.expect(ctrlSeq(.invalid, "C", 'c', .{ .shift = true }) == null);
|
||||||
try testing.expect(ctrlSeq("C", 'c', .{ .shift = true, .ctrl = true }) == null);
|
try testing.expect(ctrlSeq(.invalid, "C", 'c', .{ .shift = true, .ctrl = true }) == null);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "ctrlseq: russian ctrl c" {
|
||||||
|
const seq = ctrlSeq(.c, "с", 0x0441, .{ .ctrl = true });
|
||||||
|
try testing.expectEqual(@as(u8, 0x03), seq.?);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "ctrlseq: russian shifted ctrl c" {
|
||||||
|
const seq = ctrlSeq(.c, "с", 0x0441, .{ .ctrl = true, .shift = true });
|
||||||
|
try testing.expect(seq == null);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "ctrlseq: russian alt ctrl c" {
|
||||||
|
const seq = ctrlSeq(.c, "с", 0x0441, .{ .ctrl = true, .alt = true });
|
||||||
|
try testing.expectEqual(@as(u8, 0x03), seq.?);
|
||||||
}
|
}
|
||||||
|
@ -295,7 +295,7 @@ pub const Key = enum(c_int) {
|
|||||||
eight,
|
eight,
|
||||||
nine,
|
nine,
|
||||||
|
|
||||||
// puncuation
|
// punctuation
|
||||||
semicolon,
|
semicolon,
|
||||||
space,
|
space,
|
||||||
apostrophe,
|
apostrophe,
|
||||||
@ -411,7 +411,7 @@ pub const Key = enum(c_int) {
|
|||||||
/// may be from the number row or the keypad, but it always maps
|
/// may be from the number row or the keypad, but it always maps
|
||||||
/// to '.zero'.
|
/// to '.zero'.
|
||||||
///
|
///
|
||||||
/// This is what we want, we awnt people to create keybindings that
|
/// This is what we want, we want people to create keybindings that
|
||||||
/// are independent of the physical key.
|
/// are independent of the physical key.
|
||||||
pub fn fromASCII(ch: u8) ?Key {
|
pub fn fromASCII(ch: u8) ?Key {
|
||||||
return switch (ch) {
|
return switch (ch) {
|
||||||
|
@ -35,7 +35,7 @@ pub const VTEvent = struct {
|
|||||||
const Kind = enum { print, execute, csi, esc, osc, dcs, apc };
|
const Kind = enum { print, execute, csi, esc, osc, dcs, apc };
|
||||||
const Metadata = std.StringHashMap([:0]const u8);
|
const Metadata = std.StringHashMap([:0]const u8);
|
||||||
|
|
||||||
/// Initiaze the event information for the given parser action.
|
/// Initialize the event information for the given parser action.
|
||||||
pub fn init(
|
pub fn init(
|
||||||
alloc: Allocator,
|
alloc: Allocator,
|
||||||
surface: *Surface,
|
surface: *Surface,
|
||||||
|
@ -58,6 +58,15 @@ fn dir(
|
|||||||
opts: Options,
|
opts: Options,
|
||||||
internal_opts: InternalOptions,
|
internal_opts: InternalOptions,
|
||||||
) ![]u8 {
|
) ![]u8 {
|
||||||
|
// If we have a cached home dir, use that.
|
||||||
|
if (opts.home) |home| {
|
||||||
|
return try std.fs.path.join(alloc, &[_][]const u8{
|
||||||
|
home,
|
||||||
|
internal_opts.default_subdir,
|
||||||
|
opts.subdir orelse "",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// First check the env var. On Windows we have to allocate so this tracks
|
// First check the env var. On Windows we have to allocate so this tracks
|
||||||
// both whether we have the env var and whether we own it.
|
// both whether we have the env var and whether we own it.
|
||||||
// on Windows we treat `LOCALAPPDATA` as a fallback for `XDG_CONFIG_HOME`
|
// on Windows we treat `LOCALAPPDATA` as a fallback for `XDG_CONFIG_HOME`
|
||||||
@ -93,15 +102,6 @@ fn dir(
|
|||||||
return try alloc.dupe(u8, env);
|
return try alloc.dupe(u8, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we have a cached home dir, use that.
|
|
||||||
if (opts.home) |home| {
|
|
||||||
return try std.fs.path.join(alloc, &[_][]const u8{
|
|
||||||
home,
|
|
||||||
internal_opts.default_subdir,
|
|
||||||
opts.subdir orelse "",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get our home dir
|
// Get our home dir
|
||||||
var buf: [1024]u8 = undefined;
|
var buf: [1024]u8 = undefined;
|
||||||
if (try homedir.home(&buf)) |home| {
|
if (try homedir.home(&buf)) |home| {
|
||||||
|
@ -764,7 +764,7 @@ pub fn updateFrame(
|
|||||||
|
|
||||||
// We used to share terminal state, but we've since learned through
|
// We used to share terminal state, but we've since learned through
|
||||||
// analysis that it is faster to copy the terminal state than to
|
// analysis that it is faster to copy the terminal state than to
|
||||||
// hold the lock wile rebuilding GPU cells.
|
// hold the lock while rebuilding GPU cells.
|
||||||
var screen_copy = try state.terminal.screen.clone(
|
var screen_copy = try state.terminal.screen.clone(
|
||||||
self.alloc,
|
self.alloc,
|
||||||
.{ .viewport = .{} },
|
.{ .viewport = .{} },
|
||||||
|
Reference in New Issue
Block a user