mirror of
https://github.com/fairyglade/ly.git
synced 2026-05-06 15:20:36 +00:00
Feature: Add custom command & label support (#945)
## What are the changes about? Adds customizable commands and labels to ly. Solves https://codeberg.org/fairyglade/ly/issues/905. Since Ly doesn't use INI headers. I use them exclusively for declarations of custom commands and labels. ### Commands Bind a keybind to a command, and add a hint to the HUD. Useful for use cases like display brightness, switching between GPUs, etc. Supports localization in the `name` field only. ex: where `lang = es`: `$brightness_up` => `bajar brillo` Declared in config.ini with the following: ```ini [cmd:F8] name = custom command 2 cmd = touch /tmp/ly.gaming ``` ### Labels Add a label to the HUD. As specified in #905. The text of the label corresponds to the output of the command specified in `[lbl:NAME]`. Only shows the first line of the output. Declared in config.ini with the following: ```ini [lbl:kernel] cmd = uname -srn refresh = 0 ``` Example to add to the config.ini: ```ini # Declare a command with the F8 binding. [cmd:F8] #The name of the command to show up in Ly. name = custom command cmd = touch /tmp/ly.gaming # Declare a label with an ID. This ID should be unique across all labels. [lbl:kernel] cmd = uname -srn # In frames, the time to re-run the command and update the label. If 0, only run once- do not refresh. refresh = 0 # Once you're done setting up labels and commands, add an empty header # below to continue configurating the rest of Ly. # Put other settings not belonging to custom commands/labels below here. [] ``` ## Pre-requisites - [x] I have tested & confirmed the changes work locally  Reviewed-on: https://codeberg.org/fairyglade/ly/pulls/945 Reviewed-by: AnErrupTion <anerruption+codeberg@disroot.org> Co-authored-by: RadsammyT <radsammyt@gmail.com> Co-committed-by: RadsammyT <radsammyt@gmail.com>
This commit is contained in:
@@ -37,6 +37,7 @@ cmatrix_max_codepoint: u16 = 0x7B,
|
||||
colormix_col1: u32 = 0x00FF0000,
|
||||
colormix_col2: u32 = 0x000000FF,
|
||||
colormix_col3: u32 = 0x20000000,
|
||||
custom_bind_width: ?u32 = null,
|
||||
custom_sessions: []const u8 = build_options.config_directory ++ "/ly/custom-sessions",
|
||||
default_input: Input = .login,
|
||||
doom_fire_height: u8 = 6,
|
||||
|
||||
@@ -8,6 +8,9 @@ brightness_down: []const u8 = "decrease brightness",
|
||||
brightness_up: []const u8 = "increase brightness",
|
||||
capslock: []const u8 = "capslock",
|
||||
custom: []const u8 = "custom",
|
||||
custom_info_err_output_long: []const u8 = "output too long",
|
||||
custom_info_err_no_output: []const u8 = "no output",
|
||||
custom_info_err_no_output_error: []const u8 = ", possible error",
|
||||
err_alloc: []const u8 = "failed memory allocation",
|
||||
err_args: []const u8 = "unable to parse command line arguments",
|
||||
err_autologin_session: []const u8 = "autologin session not found",
|
||||
|
||||
25
src/config/custom.zig
Normal file
25
src/config/custom.zig
Normal file
@@ -0,0 +1,25 @@
|
||||
const std = @import("std");
|
||||
|
||||
const custom = @This();
|
||||
|
||||
pub const CustomCommandBind = struct {
|
||||
name: []const u8 = "",
|
||||
cmd: []const u8 = "",
|
||||
};
|
||||
|
||||
pub const UNDEFINED_CMD: []const u8 = "echo \"You forgot to define 'cmd'!\"";
|
||||
|
||||
pub const CustomCommandInfo = struct {
|
||||
name: []const u8 = "",
|
||||
cmd: ?[]const u8 = null,
|
||||
/// To be set to the label's widget ID
|
||||
id: u64 = 0,
|
||||
|
||||
/// In frames, the refresh rate for the `cmd` to run again
|
||||
/// If 0, only run once.
|
||||
refresh: u32 = 0,
|
||||
counter: u32 = 0,
|
||||
};
|
||||
|
||||
pub var binds: std.StringHashMap(CustomCommandBind) = undefined;
|
||||
pub var labels: std.StringHashMap(CustomCommandInfo) = undefined;
|
||||
@@ -16,6 +16,7 @@ const ini = ly_core.ini;
|
||||
const Config = @import("Config.zig");
|
||||
const OldSave = @import("OldSave.zig");
|
||||
const SavedUsers = @import("SavedUsers.zig");
|
||||
const custom = @import("custom.zig");
|
||||
|
||||
const color_properties = [_][]const u8{
|
||||
"bg",
|
||||
@@ -162,6 +163,61 @@ pub fn configFieldHandler(_: std.mem.Allocator, field: ini.IniField) ?ini.IniFie
|
||||
return mapped_field;
|
||||
}
|
||||
|
||||
// TODO: Dearest Melpert,
|
||||
// I pray this message finds you well, as daylight dwindles and the witching hour
|
||||
// approaches, I find it more and more imperative as time continues that I place
|
||||
// this reminder here in such a format that you cannot ignore.
|
||||
// Do you know how long I have been waiting for this petition to be authorized
|
||||
// in regards to this particular segment of computerized instructions?
|
||||
// It has been many a moon since this particular audit has been
|
||||
// posted regarding the position of handling configurable literature
|
||||
// apparatuses and plans for a new feature to the configuration
|
||||
// interface and as time continues onwards I grow more restless
|
||||
// on the progress of said interface, only to find out afterwards
|
||||
// that you have PROCRASTINATED on the efforts meant to enhance
|
||||
// configuration. Thus the requirement for this reminder larger
|
||||
// compared to the two reminders regarding better methods of
|
||||
// X termination detection and new usernames with existing
|
||||
// save files.
|
||||
//
|
||||
// Thus is my que to leave this TODO at thy request,
|
||||
//
|
||||
// Forever Sullied,
|
||||
//
|
||||
// Ly Contributor.
|
||||
//
|
||||
if (std.mem.startsWith(u8, field.header, "cmd:")) {
|
||||
const key = field.header["cmd:".len..];
|
||||
const keyZ = temporary_allocator.dupe(u8, key) catch "";
|
||||
if (!custom.binds.contains(key)) {
|
||||
custom.binds.put(keyZ, .{}) catch {};
|
||||
}
|
||||
if (custom.binds.getPtr(keyZ)) |command| {
|
||||
if (std.mem.eql(u8, field.key, "name")) {
|
||||
command.name = temporary_allocator.dupe(u8, field.value) catch "";
|
||||
}
|
||||
if (std.mem.eql(u8, field.key, "cmd")) {
|
||||
command.cmd = temporary_allocator.dupe(u8, field.value) catch "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (std.mem.startsWith(u8, field.header, "lbl:")) {
|
||||
const key = field.header["lbl:".len..];
|
||||
const keyZ = temporary_allocator.dupe(u8, key) catch "";
|
||||
if (!custom.labels.contains(keyZ)) {
|
||||
custom.labels.put(keyZ, .{ .name = keyZ }) catch {};
|
||||
}
|
||||
if (custom.labels.getPtr(keyZ)) |label| {
|
||||
if (std.mem.eql(u8, field.key, "cmd")) {
|
||||
label.cmd = temporary_allocator.dupe(u8, field.value) catch "";
|
||||
}
|
||||
if (std.mem.eql(u8, field.key, "refresh")) {
|
||||
label.refresh = std.fmt.parseInt(u32, field.value, 10) catch 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return field;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user