feat: +notify CLI action for sending desktop notifications

Simple CLI action for sending a desktop notification using OSC 777.
This commit is contained in:
Jeffrey C. Ollie
2024-08-29 12:08:46 -05:00
parent fcb8b04049
commit 547f4ce371
2 changed files with 66 additions and 0 deletions

View File

@ -11,6 +11,7 @@ const list_colors = @import("list_colors.zig");
const list_actions = @import("list_actions.zig");
const show_config = @import("show_config.zig");
const validate_config = @import("validate_config.zig");
const notify = @import("notify.zig");
/// Special commands that can be invoked via CLI flags. These are all
/// invoked by using `+<action>` as a CLI flag. The only exception is
@ -43,6 +44,9 @@ pub const Action = enum {
// Validate passed config file
@"validate-config",
// Send a desktop notification
notify,
pub const Error = error{
/// Multiple actions were detected. You can specify at most one
/// action on the CLI otherwise the behavior desired is ambiguous.
@ -134,6 +138,7 @@ pub const Action = enum {
.@"list-actions" => try list_actions.run(alloc),
.@"show-config" => try show_config.run(alloc),
.@"validate-config" => try validate_config.run(alloc),
.notify => try notify.run(alloc),
};
}

61
src/cli/notify.zig Normal file
View File

@ -0,0 +1,61 @@
const std = @import("std");
const Allocator = std.mem.Allocator;
const ArenaAllocator = std.heap.ArenaAllocator;
const Action = @import("action.zig").Action;
const args = @import("args.zig");
const log = std.log.scoped(.notify);
pub const Config = struct {
/// This is set by the CLI parser for deinit.
_arena: ?ArenaAllocator = null,
/// The title of the notifiction.
title: [:0]const u8 = "Ghostty",
/// The body of the notification.
body: ?[:0]const u8 = null,
pub fn deinit(self: *Config) void {
if (self._arena) |arena| arena.deinit();
self.* = undefined;
}
/// Enables "-h" and "--help" to work.
pub fn help(self: Config) !void {
_ = self;
return Action.help_error;
}
};
/// The `notify` command is used to send a desktop notification to the user
/// using OSC 777.
///
/// The `--title` argument is used to set the title of the notification. If
/// unspecified, the default of "Ghostty" will be used.
///
/// The `--body` argument is used to set the body of the notification. This
/// argument is required.
pub fn run(alloc: Allocator) !u8 {
var iter = try std.process.argsWithAllocator(alloc);
defer iter.deinit();
return try runArgs(alloc, &iter);
}
fn runArgs(alloc_gpa: Allocator, argsIter: anytype) !u8 {
var config: Config = .{};
defer config.deinit();
try args.parse(Config, alloc_gpa, &config, argsIter);
const body = config.body orelse {
return Action.help_error;
};
var buffer: [2048]u8 = undefined;
const message = try std.fmt.bufPrint(&buffer, "\x1b]777;notify;{s};{s}\x1b\\", .{ config.title, body });
const stdout = std.io.getStdOut();
try stdout.writeAll(message);
return 0;
}