mirror of https://github.com/fairyglade/ly.git
moved ini to a lib, fixed alternative langs
This commit is contained in:
parent
17e87cb6f6
commit
0aa400383a
11
build.zig
11
build.zig
|
@ -1,10 +1,15 @@
|
|||
const std = @import("std");
|
||||
|
||||
const ly_version = std.SemanticVersion{ .major = 1, .minor = 0, .patch = 0 };
|
||||
|
||||
pub fn build(b: *std.Build) void {
|
||||
const data_directory = b.option([]const u8, "data_directory", "Specify a default data directory (default is /etc/ly)");
|
||||
|
||||
const build_options = b.addOptions();
|
||||
build_options.addOption([]const u8, "data_directory", data_directory orelse "/etc/ly");
|
||||
var version_str = b.fmt("{d}.{d}.{d}", .{ ly_version.major, ly_version.minor, ly_version.patch });
|
||||
|
||||
build_options.addOption([]const u8, "version", version_str);
|
||||
|
||||
const target = b.standardTargetOptions(.{});
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
@ -29,10 +34,10 @@ pub fn build(b: *std.Build) void {
|
|||
.optimize = optimize,
|
||||
});
|
||||
|
||||
exe.addOptions("build_options", build_options);
|
||||
const zigini = b.dependency("zigini", .{ .target = target, .optimize = optimize });
|
||||
exe.addModule("zigini", zigini.module("zigini"));
|
||||
|
||||
const ini = b.dependency("ini", .{});
|
||||
exe.addModule("ini", ini.module("ini"));
|
||||
exe.addOptions("build_options", build_options);
|
||||
|
||||
const clap = b.dependency("clap", .{ .target = target, .optimize = optimize });
|
||||
exe.addModule("clap", clap.module("clap"));
|
||||
|
|
|
@ -2,13 +2,13 @@
|
|||
.name = "ly",
|
||||
.version = "1.0.0",
|
||||
.dependencies = .{
|
||||
.ini = .{
|
||||
.url = "https://github.com/ziglibs/ini/archive/2b11e8fef86d0eefb225156e695be1c1d5c35cbc.tar.gz",
|
||||
.hash = "1220ed24f7dda09121a175601ddd5c86c1cc937d061a97d38aef049ee4af76e2f594",
|
||||
},
|
||||
.clap = .{
|
||||
.url = "https://github.com/Hejsil/zig-clap/archive/f49b94700e0761b7514abdca0e4f0e7f3f938a93.tar.gz",
|
||||
.hash = "1220f48518ce22882e102255ed3bcdb7aeeb4891f50b2cdd3bd74b5b2e24d3149ba2",
|
||||
},
|
||||
.zigini = .{
|
||||
.url = "https://github.com/Kawaii-Ash/zigini/archive/91f47e46591982fc559afa3248749c1d29a0fa2a.tar.gz",
|
||||
.hash = "12209908f2773f730fbca024c80dc7f48dce15a6527b2387f3768968f5bae0d3931e",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
[ly]
|
||||
capslock = Bloq Majús
|
||||
err_alloc = falla d'assignació de memòria
|
||||
err_bounds = índex fora de límit
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
[ly]
|
||||
capslock = capslock
|
||||
err_alloc = alokace paměti selhala
|
||||
err_bounds = index je mimo hranice pole
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
[ly]
|
||||
capslock = Feststelltaste
|
||||
err_alloc = Speicherzuweisung fehlgeschlagen
|
||||
err_bounds = Listenindex ist außerhalb des Bereichs
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
[ly]
|
||||
capslock = capslock
|
||||
err_alloc = failed memory allocation
|
||||
err_bounds = out-of-bounds index
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
[ly]
|
||||
capslock = Bloq Mayús
|
||||
err_alloc = asignación de memoria fallida
|
||||
err_bounds = índice fuera de límites
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
[ly]
|
||||
capslock = verr.maj
|
||||
capslock = verr.maj
|
||||
err_alloc = échec d'allocation mémoire
|
||||
err_bounds = indice hors-limite
|
||||
err_chdir = échec de l'ouverture du répertoire home
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
[ly]
|
||||
capslock = capslock
|
||||
err_alloc = impossibile allocare memoria
|
||||
err_bounds = indice fuori limite
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
[ly]
|
||||
capslock = capslock
|
||||
err_alloc = nieudana alokacja pamięci
|
||||
err_bounds = indeks poza granicami
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
[ly]
|
||||
capslock = capslock
|
||||
err_alloc = erro na atribuição de memória
|
||||
err_bounds = índice fora de limites
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
[ly]
|
||||
capslock = caixa alta
|
||||
err_alloc = alocação de memória malsucedida
|
||||
err_bounds = índice fora de limites
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
[ly]
|
||||
capslock = capslock
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
[ly]
|
||||
capslock = capslock
|
||||
err_alloc = не удалось выделить память
|
||||
err_bounds = за пределами индекса
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
[ly]
|
||||
capslock = capslock
|
||||
err_alloc = neuspijesna alokacija memorije
|
||||
err_bounds = izvan granica indeksa
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
[ly]
|
||||
capslock = capslock
|
||||
err_alloc = misslyckad minnesallokering
|
||||
err_bounds = utanför banan index
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
[ly]
|
||||
capslock = capslock
|
||||
err_alloc = basarisiz bellek ayirma
|
||||
err_bounds = sinirlarin disinda dizin
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
[ly]
|
||||
capslock = capslock
|
||||
err_alloc = невдале виділення пам'яті
|
||||
err_bounds = поза межами індексу
|
||||
|
|
|
@ -13,8 +13,8 @@ bigclock: bool = false,
|
|||
blank_box: bool = true,
|
||||
border_fg: u8 = 8,
|
||||
clear_password: bool = false,
|
||||
clock: ?[]const u8 = null,
|
||||
console_dev: []const u8 = "/dev/console",
|
||||
clock: ?[:0]const u8 = null,
|
||||
console_dev: [:0]const u8 = "/dev/console",
|
||||
default_input: Input = .login,
|
||||
fg: u8 = 8,
|
||||
hide_borders: bool = false,
|
||||
|
|
|
@ -1,194 +0,0 @@
|
|||
const std = @import("std");
|
||||
const ini = @import("ini");
|
||||
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
const trueOrFalse = std.ComptimeStringMap(bool, .{ .{ "true", true }, .{ "false", false }, .{ "1", true }, .{ "0", false } });
|
||||
|
||||
pub fn Ini(comptime T: type) type {
|
||||
return struct {
|
||||
const Self = @This();
|
||||
|
||||
data: T,
|
||||
allocator: std.mem.Allocator,
|
||||
list: std.ArrayList([]u8),
|
||||
|
||||
pub fn init(allocator: std.mem.Allocator) Self {
|
||||
return .{
|
||||
.data = T{},
|
||||
.allocator = allocator,
|
||||
.list = std.ArrayList([]u8).init(allocator),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Self) void {
|
||||
for (self.list.items) |item| {
|
||||
self.allocator.free(item);
|
||||
}
|
||||
self.list.deinit();
|
||||
}
|
||||
|
||||
pub fn readToStruct(self: *Self, path: []const u8) !T {
|
||||
const file = try std.fs.cwd().openFile(path, .{});
|
||||
defer file.close();
|
||||
var parser = ini.parse(self.allocator, file.reader());
|
||||
defer parser.deinit();
|
||||
|
||||
var ns: []u8 = &.{};
|
||||
defer self.allocator.free(ns);
|
||||
|
||||
while (try parser.next()) |record| {
|
||||
switch (record) {
|
||||
.section => |heading| {
|
||||
ns = try self.allocator.realloc(ns, heading.len);
|
||||
@memcpy(ns, heading);
|
||||
std.mem.replaceScalar(u8, ns, ' ', '_');
|
||||
},
|
||||
.property => |kv| {
|
||||
inline for (std.meta.fields(T)) |field| {
|
||||
const field_info = @typeInfo(field.type);
|
||||
if (field_info == .Struct or (field_info == .Optional and @typeInfo(field_info.Optional.child) == .Struct)) {
|
||||
if (ns.len != 0 and std.mem.eql(u8, field.name, ns)) {
|
||||
inline for (std.meta.fields(@TypeOf(@field(self.data, field.name)))) |inner_field| {
|
||||
if (std.mem.eql(u8, inner_field.name, kv.key)) {
|
||||
@field(@field(self.data, field.name), inner_field.name) = try self.convert(inner_field.type, kv.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (ns.len == 0 and std.mem.eql(u8, field.name, kv.key)) {
|
||||
@field(self.data, field.name) = try self.convert(field.type, kv.value);
|
||||
}
|
||||
}
|
||||
},
|
||||
.enumeration => {},
|
||||
}
|
||||
}
|
||||
|
||||
return self.data;
|
||||
}
|
||||
|
||||
fn convert(self: *Self, comptime T1: type, val: []const u8) !T1 {
|
||||
return switch (@typeInfo(T1)) {
|
||||
.Int, .ComptimeInt => try std.fmt.parseInt(T1, val, 0),
|
||||
.Float, .ComptimeFloat => try std.fmt.parseFloat(T1, val),
|
||||
.Bool => trueOrFalse.get(val).?,
|
||||
.Enum => std.meta.stringToEnum(T1, val).?,
|
||||
.Optional => |opt| {
|
||||
if (val.len == 0 or std.mem.eql(u8, val, "null")) return null;
|
||||
return try self.convert(opt.child, val);
|
||||
},
|
||||
else => {
|
||||
const a_val = try self.allocator.alloc(u8, val.len);
|
||||
@memcpy(a_val, val);
|
||||
try self.list.append(a_val);
|
||||
return @as(T1, a_val);
|
||||
},
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn writeProperty(writer: anytype, field_name: []const u8, val: anytype) !void {
|
||||
switch (@typeInfo(@TypeOf(val))) {
|
||||
.Bool => {
|
||||
try writer.print("{s}={d}\n", .{ field_name, @intFromBool(val) });
|
||||
},
|
||||
.Int, .ComptimeInt, .Float, .ComptimeFloat => {
|
||||
try writer.print("{s}={d}\n", .{ field_name, val });
|
||||
},
|
||||
.Enum => {
|
||||
try writer.print("{s}={s}\n", .{ field_name, @tagName(val) });
|
||||
},
|
||||
else => {
|
||||
try writer.print("{s}={s}\n", .{ field_name, val });
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn isDefaultValue(field: anytype, field_value: field.type) bool {
|
||||
if (field.default_value) |default_value_ao| {
|
||||
const def_val: *align(field.alignment) const anyopaque = @alignCast(default_value_ao);
|
||||
const default_value = @as(*const field.type, @ptrCast(def_val)).*;
|
||||
const field_t_info = @typeInfo(field.type);
|
||||
if (field_t_info == .Optional) {
|
||||
if (default_value != null) {
|
||||
if (field_value != null) {
|
||||
if (field_t_info == .Pointer) {
|
||||
return std.mem.eql(field_t_info.Pointer.child, default_value.?, field_value.?);
|
||||
} else {
|
||||
return default_value.? == field_value.?;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return field_value == null;
|
||||
}
|
||||
|
||||
if (field_t_info == .Pointer) {
|
||||
return std.mem.eql(field_t_info.Pointer.child, default_value, field_value);
|
||||
} else {
|
||||
return default_value == field_value;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
pub fn writeFromStruct(data: anytype, writer: anytype, ns: ?[]const u8) !void {
|
||||
if (@typeInfo(@TypeOf(data)) != .Struct) @compileError("writeFromStruct() requires a struct");
|
||||
|
||||
var should_write_ns = ns != null;
|
||||
|
||||
inline for (std.meta.fields(@TypeOf(data))) |field| {
|
||||
switch (@typeInfo(field.type)) {
|
||||
.Struct => continue,
|
||||
.Optional => |opt| {
|
||||
if (@typeInfo(opt.child) != .Struct) {
|
||||
const val = @field(data, field.name);
|
||||
if (val) |field_val| {
|
||||
if (!isDefaultValue(field, @field(data, field.name))) {
|
||||
if (should_write_ns) {
|
||||
try writer.print("[{s}]\n", .{ns.?});
|
||||
should_write_ns = false;
|
||||
}
|
||||
try writeProperty(writer, field.name, field_val);
|
||||
}
|
||||
} else if (!isDefaultValue(field, @field(data, field.name))) {
|
||||
if (should_write_ns) {
|
||||
try writer.print("[{s}]\n", .{ns.?});
|
||||
should_write_ns = false;
|
||||
}
|
||||
try writeProperty(writer, field.name, "");
|
||||
}
|
||||
} else continue;
|
||||
},
|
||||
else => {
|
||||
if (!isDefaultValue(field, @field(data, field.name))) {
|
||||
if (should_write_ns) {
|
||||
try writer.print("[{s}]\n", .{ns.?});
|
||||
should_write_ns = false;
|
||||
}
|
||||
try writeProperty(writer, field.name, @field(data, field.name));
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if (ns == null) {
|
||||
inline for (std.meta.fields(@TypeOf(data))) |field| {
|
||||
switch (@typeInfo(field.type)) {
|
||||
.Struct => {
|
||||
try writeFromStruct(@field(data, field.name), writer, field.name);
|
||||
},
|
||||
.Optional => |opt| {
|
||||
if (@typeInfo(opt.child) == .Struct) {
|
||||
if (@field(data, field.name)) |inner_data| {
|
||||
try writeFromStruct(inner_data, writer, field.name);
|
||||
}
|
||||
} else continue;
|
||||
},
|
||||
else => continue,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -18,10 +18,6 @@ pub const xcb = @cImport({
|
|||
@cInclude("xcb/xcb.h");
|
||||
});
|
||||
|
||||
pub const c_size = u64;
|
||||
pub const c_uid = u32;
|
||||
pub const c_gid = u32;
|
||||
pub const c_time = c_long;
|
||||
pub const tm = extern struct {
|
||||
tm_sec: c_int,
|
||||
tm_min: c_int,
|
||||
|
@ -37,8 +33,8 @@ pub const passwd = extern struct {
|
|||
pw_name: [*:0]u8,
|
||||
pw_passwd: [*:0]u8,
|
||||
|
||||
pw_uid: c_uid,
|
||||
pw_gid: c_gid,
|
||||
pw_uid: u32,
|
||||
pw_gid: u32,
|
||||
pw_gecos: [*:0]u8,
|
||||
pw_dir: [*:0]u8,
|
||||
pw_shell: [*:0]u8,
|
||||
|
@ -68,20 +64,20 @@ pub const O_RDWR: c_uint = 0x02;
|
|||
|
||||
pub extern "c" fn fileno(stream: *std.c.FILE) c_int;
|
||||
pub extern "c" fn sysconf(name: c_int) c_long;
|
||||
pub extern "c" fn time(second: ?*c_time) c_time;
|
||||
pub extern "c" fn localtime(timer: *const c_time) *tm;
|
||||
pub extern "c" fn strftime(str: [*:0]u8, maxsize: c_size, format: [*:0]const u8, timeptr: *const tm) c_size;
|
||||
pub extern "c" fn time(second: ?*c_long) c_long;
|
||||
pub extern "c" fn localtime(timer: *const c_long) *tm;
|
||||
pub extern "c" fn strftime(str: [*:0]u8, maxsize: u64, format: [*:0]const u8, timeptr: *const tm) u64;
|
||||
pub extern "c" fn setenv(name: [*:0]const u8, value: [*:0]const u8, overwrite: c_int) c_int;
|
||||
pub extern "c" fn getenv(name: [*:0]const u8) [*:0]u8;
|
||||
pub extern "c" fn putenv(name: [*:0]u8) c_int;
|
||||
pub extern "c" fn clearenv() c_int;
|
||||
pub extern "c" fn getuid() c_uid;
|
||||
pub extern "c" fn getuid() u32;
|
||||
pub extern "c" fn getpwnam(name: [*:0]const u8) ?*passwd;
|
||||
pub extern "c" fn endpwent() void;
|
||||
pub extern "c" fn setusershell() void;
|
||||
pub extern "c" fn getusershell() [*:0]u8;
|
||||
pub extern "c" fn endusershell() void;
|
||||
pub extern "c" fn initgroups(user: [*:0]const u8, group: c_gid) c_int;
|
||||
pub extern "c" fn initgroups(user: [*:0]const u8, group: u32) c_int;
|
||||
pub extern "c" fn chdir(path: [*:0]const u8) c_int;
|
||||
pub extern "c" fn execl(path: [*:0]const u8, arg: [*:0]const u8, ...) c_int;
|
||||
|
||||
|
@ -93,6 +89,7 @@ pub fn getHostName(allocator: Allocator) !struct {
|
|||
const hostname_max_length: u64 = if (hostname_sysconf < 0) @intCast(_POSIX_HOST_NAME_MAX) else @intCast(hostname_sysconf);
|
||||
|
||||
const buffer = try allocator.alloc(u8, hostname_max_length);
|
||||
errdefer allocator.free(buffer);
|
||||
|
||||
const error_code = std.c.gethostname(buffer.ptr, hostname_max_length);
|
||||
if (error_code < 0) return error.CannotGetHostName;
|
||||
|
@ -111,27 +108,21 @@ pub fn getHostName(allocator: Allocator) !struct {
|
|||
};
|
||||
}
|
||||
|
||||
pub fn timeAsString(allocator: Allocator, format: []const u8, max_length: u64) ![:0]u8 {
|
||||
pub fn timeAsString(allocator: Allocator, format: [:0]const u8, max_length: u64) ![:0]u8 {
|
||||
const timer = time(null);
|
||||
const tm_info = localtime(&timer);
|
||||
const buffer = try allocator.allocSentinel(u8, max_length, 0);
|
||||
|
||||
const format_z = try allocator.dupeZ(u8, format);
|
||||
defer allocator.free(format_z);
|
||||
|
||||
if (strftime(buffer, max_length, format_z, tm_info) < 0) return error.CannotGetFormattedTime;
|
||||
if (strftime(buffer, max_length, format, tm_info) < 0) return error.CannotGetFormattedTime;
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
pub fn getLockState(allocator: Allocator, console_dev: []const u8) !struct {
|
||||
pub fn getLockState(console_dev: [:0]const u8) !struct {
|
||||
numlock: bool,
|
||||
capslock: bool,
|
||||
} {
|
||||
const console_dev_z = try allocator.dupeZ(u8, console_dev);
|
||||
defer allocator.free(console_dev_z);
|
||||
|
||||
const fd = std.c.open(console_dev_z, O_RDONLY);
|
||||
const fd = std.c.open(console_dev, O_RDONLY);
|
||||
if (fd < 0) return error.CannotOpenConsoleDev;
|
||||
|
||||
var numlock = false;
|
||||
|
|
22
src/main.zig
22
src/main.zig
|
@ -11,17 +11,16 @@ const TerminalBuffer = @import("tui/TerminalBuffer.zig");
|
|||
const Desktop = @import("tui/components/Desktop.zig");
|
||||
const Text = @import("tui/components/Text.zig");
|
||||
const Config = @import("config/Config.zig");
|
||||
const ini = @import("config/ini.zig");
|
||||
const ini = @import("zigini");
|
||||
const Lang = @import("config/Lang.zig");
|
||||
const Save = @import("config/Save.zig");
|
||||
const ViMode = @import("enums.zig").ViMode;
|
||||
const SharedError = @import("SharedError.zig");
|
||||
const utils = @import("tui/utils.zig");
|
||||
|
||||
const Ini = ini.Ini;
|
||||
const termbox = interop.termbox;
|
||||
|
||||
const LY_VERSION = "1.0.0";
|
||||
|
||||
pub fn signalHandler(i: c_int) callconv(.C) void {
|
||||
termbox.tb_shutdown();
|
||||
std.c.exit(i);
|
||||
|
@ -59,7 +58,7 @@ pub fn main() !void {
|
|||
std.os.exit(0);
|
||||
}
|
||||
if (res.args.version != 0) {
|
||||
_ = try stderr.write("Ly version " ++ LY_VERSION ++ "\n");
|
||||
_ = try stderr.write("Ly version " ++ build_options.version ++ "\n");
|
||||
std.os.exit(0);
|
||||
}
|
||||
|
||||
|
@ -352,8 +351,11 @@ pub fn main() !void {
|
|||
buffer.drawLabel(lang.password, label_x, label_y + 6);
|
||||
|
||||
if (info_line.len > 0) {
|
||||
const x = buffer.box_x + ((buffer.box_width - info_line.len) / 2);
|
||||
buffer.drawLabel(info_line, x, label_y);
|
||||
const info_line_width = try utils.strWidth(info_line);
|
||||
if (buffer.box_width > info_line_width) {
|
||||
const x = buffer.box_x + ((buffer.box_width - info_line_width) / 2);
|
||||
buffer.drawLabel(info_line, x, label_y);
|
||||
}
|
||||
}
|
||||
|
||||
if (!config.hide_key_hints) {
|
||||
|
@ -364,14 +366,16 @@ pub fn main() !void {
|
|||
buffer.drawLabel(" ", length - 1, 0);
|
||||
|
||||
buffer.drawLabel(lang.shutdown, length, 0);
|
||||
length += lang.shutdown.len + 1;
|
||||
const shutdown_len = try utils.strWidth(lang.shutdown);
|
||||
length += shutdown_len + 1;
|
||||
|
||||
buffer.drawLabel(config.restart_key, length, 0);
|
||||
length += config.restart_key.len + 1;
|
||||
buffer.drawLabel(" ", length - 1, 0);
|
||||
|
||||
buffer.drawLabel(lang.restart, length, 0);
|
||||
length += lang.restart.len + 1;
|
||||
const restart_len = try utils.strWidth(lang.restart);
|
||||
length += restart_len + 1;
|
||||
|
||||
if (config.sleep_cmd != null) {
|
||||
buffer.drawLabel(config.sleep_key, length, 0);
|
||||
|
@ -388,7 +392,7 @@ pub fn main() !void {
|
|||
}
|
||||
|
||||
draw_lock_state: {
|
||||
const lock_state = interop.getLockState(allocator, config.console_dev) catch |err| {
|
||||
const lock_state = interop.getLockState(config.console_dev) catch |err| {
|
||||
if (err == error.CannotOpenConsoleDev) {
|
||||
info_line = lang.err_console_dev;
|
||||
} else {
|
||||
|
|
|
@ -161,7 +161,13 @@ pub fn calculateComponentCoordinates(self: TerminalBuffer) struct {
|
|||
|
||||
pub fn drawLabel(self: TerminalBuffer, text: []const u8, x: u64, y: u64) void {
|
||||
const yc: c_int = @intCast(y);
|
||||
for (0..text.len) |xx| termbox.tb_change_cell(@intCast(x + xx), yc, text[xx], self.fg, self.bg);
|
||||
const utf8view = std.unicode.Utf8View.init(text) catch return;
|
||||
var utf8 = utf8view.iterator();
|
||||
|
||||
var i = x;
|
||||
while (utf8.nextCodepoint()) |codepoint| : (i += 1) {
|
||||
termbox.tb_change_cell(@intCast(i), yc, codepoint, self.fg, self.bg);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn drawCharMultiple(self: TerminalBuffer, char: u8, x: u64, y: u64, length: u64) void {
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
const std = @import("std");
|
||||
const ini = @import("ini");
|
||||
const enums = @import("../../enums.zig");
|
||||
const interop = @import("../../interop.zig");
|
||||
const TerminalBuffer = @import("../TerminalBuffer.zig");
|
||||
const Ini = @import("../../config/ini.zig").Ini;
|
||||
const Ini = @import("zigini").Ini;
|
||||
|
||||
const Allocator = std.mem.Allocator;
|
||||
const EnvironmentList = std.ArrayList(Environment);
|
||||
|
@ -74,7 +73,7 @@ pub fn addEnvironment(self: *Desktop, name: []const u8, cmd: []const u8, display
|
|||
.specifier = switch (display_server) {
|
||||
.wayland => "wayland",
|
||||
.x11 => "x11",
|
||||
else => "other",
|
||||
else => "",
|
||||
},
|
||||
.display_server = display_server,
|
||||
});
|
||||
|
@ -91,7 +90,7 @@ pub fn addEnvironmentWithIni(self: *Desktop, entry_ini: Ini(Entry), name: []cons
|
|||
.specifier = switch (display_server) {
|
||||
.wayland => "wayland",
|
||||
.x11 => "x11",
|
||||
else => "other",
|
||||
else => "",
|
||||
},
|
||||
.display_server = display_server,
|
||||
});
|
||||
|
|
|
@ -3,10 +3,20 @@ const interop = @import("../interop.zig");
|
|||
|
||||
const termbox = interop.termbox;
|
||||
|
||||
pub inline fn initCell(ch: u32, fg: u32, bg: u32) termbox.tb_cell {
|
||||
pub fn initCell(ch: u32, fg: u32, bg: u32) termbox.tb_cell {
|
||||
return .{
|
||||
.ch = ch,
|
||||
.fg = fg,
|
||||
.bg = bg,
|
||||
};
|
||||
}
|
||||
|
||||
// Every codepoint is assumed to have a width of 1.
|
||||
// Since ly should be running in a tty, this should be fine.
|
||||
pub fn strWidth(str: []const u8) !u8 {
|
||||
const utf8view = try std.unicode.Utf8View.init(str);
|
||||
var utf8 = utf8view.iterator();
|
||||
var i: u8 = 0;
|
||||
while (utf8.nextCodepoint()) |_| i += 1;
|
||||
return i;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue