mirror of
https://mzte.de/git/LordMZTE/dotfiles.git
synced 2024-12-13 09:42:58 +01:00
mzteinit: make entries configurable
This commit is contained in:
parent
9975a02051
commit
a8e140461a
6 changed files with 128 additions and 79 deletions
3
.config/mzteinit/entries.cfg.cgt
Normal file
3
.config/mzteinit/entries.cfg.cgt
Normal file
|
@ -0,0 +1,3 @@
|
|||
<! for _, v in ipairs(opt.mzteinit_entries) do !>
|
||||
<% v.key %> <% v.label %>: <% table.concat(v.cmd, ",") %><! if v.quit then !> :Q<! end !>
|
||||
<! end !>
|
|
@ -1,5 +1,13 @@
|
|||
local opts = {}
|
||||
|
||||
opts.mzteinit_entries = {
|
||||
{ key = "x", label = "startx", cmd = { "starx" } },
|
||||
{ key = "s", label = "shell", cmd = { "fish" } },
|
||||
{ key = "l", label = "logout", cmd = { "!quit" } },
|
||||
{ key = "p", label = "shutdown", cmd = { "systemctl", "poweroff" }, quit = true },
|
||||
{ key = "r", label = "reboot", cmd = { "systemctl", "reboot" }, quit = true },
|
||||
}
|
||||
|
||||
-- Enable if you have good internet, used for stuff like making
|
||||
-- streamlink use low-latency mode.
|
||||
opts.good_internet = true
|
||||
|
|
|
@ -11,9 +11,13 @@ cg.addFile ".vieterrc.cgt"
|
|||
|
||||
-- Recursively merge 2 tables
|
||||
local function merge(a, b)
|
||||
if b[1] then -- b is a list
|
||||
return b
|
||||
end
|
||||
|
||||
for k, v in pairs(b) do
|
||||
if type(v) == "table" and type(a[k]) == "table" then
|
||||
merge(a[k], v)
|
||||
a[k] = merge(a[k], v)
|
||||
else
|
||||
a[k] = v
|
||||
end
|
||||
|
|
77
scripts/mzteinit/src/command.zig
Normal file
77
scripts/mzteinit/src/command.zig
Normal file
|
@ -0,0 +1,77 @@
|
|||
const std = @import("std");
|
||||
const log = std.log.scoped(.command);
|
||||
|
||||
pub const Command = struct {
|
||||
key: u8,
|
||||
label: []const u8,
|
||||
command: [][]const u8,
|
||||
exit: bool,
|
||||
|
||||
pub fn deinit(self: Command, alloc: std.mem.Allocator) void {
|
||||
alloc.free(self.command);
|
||||
}
|
||||
|
||||
pub fn run(
|
||||
self: Command,
|
||||
alloc: std.mem.Allocator,
|
||||
exit: *@import("util.zig").ExitMode,
|
||||
env: *const std.process.EnvMap,
|
||||
) !void {
|
||||
if (std.mem.eql(u8, self.command[0], "!quit")) {
|
||||
exit.* = .delayed;
|
||||
log.info("user logged out", .{});
|
||||
return;
|
||||
}
|
||||
|
||||
if (self.exit) exit.* = .immediate;
|
||||
|
||||
log.info("run cmd: {s}", .{self.command});
|
||||
var child = std.ChildProcess.init(self.command, alloc);
|
||||
child.env_map = env;
|
||||
_ = try child.spawnAndWait();
|
||||
}
|
||||
};
|
||||
|
||||
pub fn parseEntriesConfig(alloc: std.mem.Allocator, data: []const u8) ![]Command {
|
||||
var entries = std.ArrayList(Command).init(alloc);
|
||||
errdefer entries.deinit();
|
||||
|
||||
var line_splits = std.mem.tokenizeScalar(u8, data, '\n');
|
||||
while (line_splits.next()) |line| {
|
||||
const line_without_comment = std.mem.sliceTo(line, '#');
|
||||
if (line_without_comment.len == 0)
|
||||
continue;
|
||||
|
||||
var seg_splits = std.mem.tokenizeScalar(u8, line_without_comment, ':');
|
||||
const labels = std.mem.trim(u8, seg_splits.next() orelse return error.InvalidConfig, &std.ascii.whitespace);
|
||||
const command = std.mem.trim(u8, seg_splits.next() orelse return error.InvalidConfig, &std.ascii.whitespace);
|
||||
var exit = false;
|
||||
if (seg_splits.next()) |extra| {
|
||||
if (std.mem.eql(u8, extra, "Q")) {
|
||||
exit = true;
|
||||
} else return error.InvalidConfig;
|
||||
}
|
||||
if (seg_splits.next()) |_| return error.InvalidConfig;
|
||||
|
||||
if (labels.len < 3 or labels[1] != ' ') return error.InvalidConfig;
|
||||
const key = std.ascii.toUpper(labels[0]);
|
||||
const label = labels[2..];
|
||||
|
||||
var argv = std.ArrayList([]const u8).init(alloc);
|
||||
errdefer argv.deinit();
|
||||
var command_splits = std.mem.splitScalar(u8, command, ',');
|
||||
while (command_splits.next()) |arg|
|
||||
try argv.append(arg);
|
||||
|
||||
if (argv.items.len == 0) return error.InvalidConfig;
|
||||
|
||||
try entries.append(.{
|
||||
.key = key,
|
||||
.label = label,
|
||||
.command = try argv.toOwnedSlice(),
|
||||
.exit = exit,
|
||||
});
|
||||
}
|
||||
|
||||
return try entries.toOwnedSlice();
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
const std = @import("std");
|
||||
const at = @import("ansi-term");
|
||||
const env = @import("env.zig");
|
||||
const run = @import("run.zig");
|
||||
const command = @import("command.zig");
|
||||
const util = @import("util.zig");
|
||||
|
||||
const msg = @import("message.zig").msg;
|
||||
|
@ -68,7 +68,7 @@ fn tryMain() !void {
|
|||
arg.* = std.mem.span(arg_in);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var env_map = try std.process.getEnvMap(alloc);
|
||||
defer env_map.deinit();
|
||||
|
||||
|
@ -94,10 +94,30 @@ fn tryMain() !void {
|
|||
return;
|
||||
}
|
||||
|
||||
const entries_config_path = try std.fs.path.join(alloc, &.{
|
||||
env_map.get("XDG_CONFIG_HOME") orelse @panic("bork"),
|
||||
"mzteinit",
|
||||
"entries.cfg",
|
||||
});
|
||||
defer alloc.free(entries_config_path);
|
||||
|
||||
var entries_config_file = try std.fs.cwd().openFile(entries_config_path, .{});
|
||||
defer entries_config_file.close();
|
||||
|
||||
const entries_config_data = try entries_config_file.readToEndAlloc(alloc, std.math.maxInt(usize));
|
||||
defer alloc.free(entries_config_data);
|
||||
|
||||
const entries = try command.parseEntriesConfig(alloc, entries_config_data);
|
||||
defer {
|
||||
for (entries) |entry|
|
||||
entry.deinit(alloc);
|
||||
alloc.free(entries);
|
||||
}
|
||||
|
||||
while (true) {
|
||||
try stdout.writer().writeAll(util.ansi_clear);
|
||||
|
||||
const cmd = ui(&stdout) catch |e| {
|
||||
const cmd = ui(&stdout, entries) catch |e| {
|
||||
std.debug.print("Error rendering the UI: {}\n", .{e});
|
||||
break;
|
||||
};
|
||||
|
@ -124,7 +144,7 @@ fn tryMain() !void {
|
|||
}
|
||||
}
|
||||
|
||||
fn ui(buf_writer: anytype) !run.Command {
|
||||
fn ui(buf_writer: anytype, entries: []command.Command) !command.Command {
|
||||
const w = buf_writer.writer();
|
||||
var style: ?at.style.Style = null;
|
||||
|
||||
|
@ -143,11 +163,11 @@ fn ui(buf_writer: anytype) !run.Command {
|
|||
try updateStyle(w, .{ .font_style = .{ .bold = true } }, &style);
|
||||
try w.writeAll(" What do you want to do?\n\n");
|
||||
|
||||
for (std.enums.values(run.Command)) |tag| {
|
||||
for (entries) |entry| {
|
||||
try updateStyle(w, .{ .foreground = .Cyan }, &style);
|
||||
try w.print("[{c}] ", .{tag.char()});
|
||||
try w.print("[{c}] ", .{entry.key});
|
||||
try updateStyle(w, .{ .foreground = .Green }, &style);
|
||||
try w.print("{s}\n", .{@tagName(tag)});
|
||||
try w.print("{s}\n", .{entry.label});
|
||||
}
|
||||
try at.format.resetStyle(w);
|
||||
style = .{};
|
||||
|
@ -160,12 +180,17 @@ fn ui(buf_writer: anytype) !run.Command {
|
|||
new_termios.lflag &= ~std.os.linux.ECHO; // No echoing stuff
|
||||
try std.os.tcsetattr(std.os.STDIN_FILENO, .NOW, new_termios);
|
||||
|
||||
var cmd: ?run.Command = null;
|
||||
var cmd: ?command.Command = null;
|
||||
var c: [1]u8 = undefined;
|
||||
while (cmd == null) {
|
||||
std.debug.assert(try std.io.getStdIn().read(&c) == 1);
|
||||
cmd = run.Command.fromChar(c[0]);
|
||||
if (cmd == null) {
|
||||
const key_upper = std.ascii.toUpper(c[0]);
|
||||
for (entries) |entry| {
|
||||
if (entry.key == key_upper) {
|
||||
cmd = entry;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
try w.print("Unknown command '{s}'\n", .{c});
|
||||
try buf_writer.flush();
|
||||
}
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
const std = @import("std");
|
||||
const log = std.log.scoped(.run);
|
||||
|
||||
pub const Command = enum {
|
||||
startx,
|
||||
shell,
|
||||
zellij,
|
||||
logout,
|
||||
shutdown,
|
||||
reboot,
|
||||
|
||||
pub fn fromChar(c: u8) ?Command {
|
||||
return switch (c) {
|
||||
'x', 'X' => .startx,
|
||||
's', 'S' => .shell,
|
||||
'z', 'Z' => .zellij,
|
||||
'l', 'L' => .logout,
|
||||
'p', 'P' => .shutdown,
|
||||
'r', 'R' => .reboot,
|
||||
else => null,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn char(self: Command) u8 {
|
||||
return switch (self) {
|
||||
.startx => 'X',
|
||||
.shell => 'S',
|
||||
.zellij => 'Z',
|
||||
.logout => 'L',
|
||||
.shutdown => 'P',
|
||||
.reboot => 'R',
|
||||
};
|
||||
}
|
||||
|
||||
pub fn run(
|
||||
self: Command,
|
||||
alloc: std.mem.Allocator,
|
||||
exit: *@import("util.zig").ExitMode,
|
||||
env: *const std.process.EnvMap,
|
||||
) !void {
|
||||
switch (self) {
|
||||
.logout => {
|
||||
exit.* = .delayed;
|
||||
log.info("user logged out", .{});
|
||||
return;
|
||||
},
|
||||
.shutdown, .reboot => exit.* = .immediate,
|
||||
else => {},
|
||||
}
|
||||
|
||||
const arg = self.argv();
|
||||
log.info("run cmd: {s}", .{arg});
|
||||
var child = std.ChildProcess.init(arg, alloc);
|
||||
child.env_map = env;
|
||||
_ = try child.spawnAndWait();
|
||||
}
|
||||
|
||||
fn argv(self: Command) []const []const u8 {
|
||||
return switch (self) {
|
||||
.startx => &.{"startx"},
|
||||
.shell => &.{"fish"},
|
||||
.zellij => &.{"zellij"},
|
||||
.logout => unreachable,
|
||||
.shutdown => &.{ "systemctl", "poweroff" },
|
||||
.reboot => &.{ "systemctl", "reboot" },
|
||||
};
|
||||
}
|
||||
};
|
Loading…
Reference in a new issue