Compare commits

..

4 commits

6 changed files with 73 additions and 21 deletions

View file

@ -509,6 +509,7 @@ pub fn build_exe(
.{ .name = "thespian", .module = thespian_mod },
.{ .name = "log", .module = log_mod },
.{ .name = "Buffer", .module = Buffer_mod },
.{ .name = "config", .module = config_mod },
},
});
@ -527,6 +528,7 @@ pub fn build_exe(
tests.root_module.addImport("thespian", thespian_mod);
tests.root_module.addImport("log", log_mod);
tests.root_module.addImport("Buffer", Buffer_mod);
tests.root_module.addImport("config", config_mod);
// b.installArtifact(tests);
break :blk b.addRunArtifact(tests);
};

View file

@ -24,7 +24,7 @@ idle_actions: []const IdleAction = &default_actions,
enable_format_on_save: bool = false,
restore_last_cursor_position: bool = true,
follow_cursor_on_buffer_switch: bool = false, //scroll cursor into view on buffer switch
default_cursor: []const u8 = "default",
default_cursor: CursorShape = .default,
enable_auto_save: bool = false,
limit_auto_save_file_types: ?[]const []const u8 = null, // null means *all*
@ -114,3 +114,13 @@ pub const WhitespaceMode = enum {
full,
none,
};
pub const CursorShape = enum {
default,
block_blink,
block,
underline_blink,
underline,
beam_blink,
beam,
};

View file

@ -27,10 +27,12 @@
["ctrl+^", "open_previous_file"],
["ctrl+w v", "add_split"],
["ctrl+w c", "toggle_centered_view"],
["ctrl+w h", "goto_left_split"],
["ctrl+w l", "goto_right_split"],
["ctrl+w H", "swap_left_split"],
["ctrl+w L", "swap_right_split"],
["ctrl+w F", "goto_file_split"],
["ctrl+w q", "close_split"],
["ctrl+w o", "close_other_splits"],

View file

@ -14,6 +14,7 @@ const command = @import("command");
const EventHandler = @import("EventHandler");
const KeyEvent = input.KeyEvent;
const SelectionStyle = @import("Buffer").Selection.Style;
pub const CursorShape = @import("config").CursorShape;
const parse_flow = @import("parse_flow.zig");
const parse_vim = @import("parse_vim.zig");
@ -743,16 +744,6 @@ pub const LineNumbers = enum {
relative,
};
pub const CursorShape = enum {
default,
block_blink,
block,
underline_blink,
underline,
beam_blink,
beam,
};
pub fn get_or_create_namespace_config_file(allocator: std.mem.Allocator, namespace_name: []const u8) ![]const u8 {
if (root.read_keybind_namespace(allocator, namespace_name)) |content| {
allocator.free(content);

View file

@ -698,6 +698,7 @@ pub fn write_config_to_writer(comptime T: type, data: T, writer: *std.Io.Writer)
const default: T = .{};
inline for (@typeInfo(T).@"struct".fields) |field_info| {
if (config_eql(
T,
field_info.type,
@field(data, field_info.name),
@field(default, field_info.name),
@ -718,9 +719,57 @@ pub fn write_config_to_writer(comptime T: type, data: T, writer: *std.Io.Writer)
},
}
try writer.print("\n", .{});
try writer.print("# value type: ", .{});
try write_config_value_description(T, field_info.type, writer);
try writer.print("\n", .{});
try writer.print("\n", .{});
}
}
fn write_config_value_description(T: type, field_type: type, writer: *std.Io.Writer) !void {
switch (@typeInfo(field_type)) {
.int => switch (field_type) {
u24 => try writer.print("24 bit hex color value in quotes", .{}),
usize => try writer.print("positive integer", .{}),
u8 => try writer.print("positive integer up to 255", .{}),
else => unsupported_error(T, field_type),
},
.bool => try writer.print("true or false", .{}),
.@"enum" => {
var first = true;
try writer.print("one of ", .{});
for (std.meta.tags(field_type)) |tag| {
if (first) first = false else try writer.print(", ", .{});
try writer.print("\"{s}\"", .{@tagName(tag)});
}
},
.optional => |info| switch (@typeInfo(info.child)) {
else => {
try write_config_value_description(T, info.child, writer);
try writer.print(" or null", .{});
},
},
.pointer => |info| switch (info.size) {
.slice => if (info.child == u8)
try writer.print("quoted string", .{})
else if (info.child == u16)
try writer.print("quoted string (u16)", .{})
else if (info.child == []const u8)
try writer.print("list of quoted strings", .{})
else if (info.child == @import("config").IdleAction)
try writer.print("list of idle actions", .{})
else
unsupported_error(T, info.child),
else => unsupported_error(T, info.child),
},
else => unsupported_error(T, field_type),
}
}
fn unsupported_error(config_type: type, value_type: type) void {
@compileError("unsupported config type in " ++ @typeName(config_type) ++ ": " ++ @typeName(value_type));
}
fn write_color_value(value: u24, writer: *std.Io.Writer) std.Io.Writer.Error!void {
var hex: [7]u8 = undefined;
try writer.writeByte('"');
@ -728,12 +777,12 @@ fn write_color_value(value: u24, writer: *std.Io.Writer) std.Io.Writer.Error!voi
try writer.writeByte('"');
}
fn config_eql(comptime T: type, a: T, b: T) bool {
fn config_eql(config_type: type, T: type, a: T, b: T) bool {
switch (T) {
[]const u8 => return std.mem.eql(u8, a, b),
[]const []const u8 => {
if (a.len != b.len) return false;
for (a, 0..) |x, i| if (!config_eql([]const u8, x, b[i])) return false;
for (a, 0..) |x, i| if (!config_eql(config_type, []const u8, x, b[i])) return false;
return true;
},
else => {},
@ -745,19 +794,19 @@ fn config_eql(comptime T: type, a: T, b: T) bool {
return true;
if (a == null or b == null)
return false;
return config_eql(info.child, a.?, b.?);
return config_eql(config_type, info.child, a.?, b.?);
},
.pointer => |info| switch (info.size) {
.slice => {
if (a.len != b.len) return false;
for (a, 0..) |x, i| if (!config_eql(info.child, x, b[i])) return false;
for (a, 0..) |x, i| if (!config_eql(config_type, info.child, x, b[i])) return false;
return true;
},
else => @compileError("unsupported config type " ++ @typeName(T)),
else => unsupported_error(config_type, T),
},
else => {},
}
@compileError("unsupported config type " ++ @typeName(T));
unsupported_error(config_type, T);
}
fn write_json_file(comptime T: type, data: T, allocator: std.mem.Allocator, file_name: []const u8) !void {

View file

@ -73,7 +73,6 @@ render_pending: bool = false,
keepalive_timer: ?tp.Cancellable = null,
input_idle_timer: ?tp.Cancellable = null,
mouse_idle_timer: ?tp.Cancellable = null,
default_cursor: keybind.CursorShape = .default,
fontface_: []const u8 = "",
fontfaces_: std.ArrayListUnmanaged([]const u8) = .{},
input_is_idle: bool = false,
@ -183,8 +182,6 @@ fn init(allocator: Allocator) InitError!*Self {
instance_ = self;
defer instance_ = null;
self.default_cursor = std.meta.stringToEnum(keybind.CursorShape, conf.default_cursor) orelse .default;
self.config_.default_cursor = @tagName(self.default_cursor);
self.rdr_.handler_ctx = self;
self.rdr_.dispatch_input = dispatch_input;
self.rdr_.dispatch_mouse = dispatch_mouse;
@ -1745,7 +1742,8 @@ fn set_terminal_style(self: *Self, theme_: *const Widget.Theme) void {
pub fn get_cursor_shape() renderer.CursorShape {
const self = current();
const shape_ = if (self.input_mode_) |mode| mode.cursor_shape orelse self.default_cursor else self.default_cursor;
const default_cursor = self.config_.default_cursor;
const shape_ = if (self.input_mode_) |mode| mode.cursor_shape orelse default_cursor else default_cursor;
const shape = if (self.rdr_.vx.caps.multi_cursor and shape_ == .default) .beam_blink else shape_;
return switch (shape) {
.default => .default,