111 lines
3.6 KiB
Zig
111 lines
3.6 KiB
Zig
const std = @import("std");
|
|
const builtin = @import("builtin");
|
|
const eql = @import("std").mem.eql;
|
|
|
|
const stdout = std.io.getStdOut().writer();
|
|
const stderr = std.io.getStdErr().writer();
|
|
const stdin = std.io.getStdIn().reader();
|
|
|
|
const Target = enum {
|
|
Stdout,
|
|
Stderr,
|
|
};
|
|
|
|
pub fn write(target: Target, comptime format: []const u8, args: anytype) void {
|
|
switch (target) {
|
|
Target.Stdout => stdout.print(format, args) catch |err| {
|
|
std.debug.panic("unable to write to output: {any}\n", .{err});
|
|
},
|
|
Target.Stderr => stderr.print(format, args) catch |err| {
|
|
std.debug.panic("unable to write to output: {any}\n", .{err});
|
|
},
|
|
}
|
|
}
|
|
|
|
pub fn main() !void {
|
|
// Read the first argument to determine the subcommand
|
|
const allocator = std.heap.page_allocator;
|
|
var args = std.process.argsWithAllocator(allocator) catch |err| {
|
|
write(Target.Stderr, "out of memory: {any}\n", .{err});
|
|
};
|
|
defer args.deinit();
|
|
|
|
_ = args.next(); // Skip the first argument, which is the program name
|
|
|
|
const firstArg = args.next() orelse {
|
|
write(Target.Stderr, "no subcommand provided\n", .{});
|
|
return;
|
|
};
|
|
|
|
if (eql(u8, firstArg, "list")) {
|
|
listEntries();
|
|
} else if (eql(u8, firstArg, "create")) {
|
|
createNewEntry() catch |err| {
|
|
write(Target.Stderr, "error while creating new entry: {any}\n", .{err});
|
|
};
|
|
} else {
|
|
write(Target.Stderr, "Unknown subcommand: {any}\n", .{firstArg});
|
|
}
|
|
}
|
|
|
|
fn createNewEntry() !void {
|
|
// Open the file in append mode
|
|
const file = std.fs.cwd().openFile("entries.log.gmi", .{
|
|
.mode = .read_write
|
|
}) catch |err| {
|
|
write(Target.Stderr, "unable to open file: {any}\n", .{err});
|
|
return;
|
|
};
|
|
defer file.close();
|
|
try file.seekFromEnd(0);
|
|
|
|
//const date = try std.time.Time.nowUTC().format("yyyy-MM-dd HH:mm UTC");
|
|
const es = std.time.epoch.EpochSeconds{ .secs = @intCast(std.time.timestamp()) };
|
|
const ed = std.time.epoch.EpochDay{ .day = es.getEpochDay().day };
|
|
var buf2: [256]u8 = undefined;
|
|
const date = try std.fmt.bufPrint(&buf2, "## {d}-{d:0>2}-{d:0>2} {d:0>2}:{d:0>2} UTC\n", .{
|
|
ed.calculateYearDay().year,
|
|
std.time.epoch.YearAndDay.calculateMonthDay(ed.calculateYearDay()).month.numeric(),
|
|
std.time.epoch.YearAndDay.calculateMonthDay(ed.calculateYearDay()).day_index,
|
|
es.getDaySeconds().getHoursIntoDay(),
|
|
es.getDaySeconds().getMinutesIntoHour(),});
|
|
|
|
// Read the input content from STDIN and append it to the file
|
|
var buf: [1024]u8 = undefined;
|
|
|
|
try file.writeAll(date);
|
|
|
|
while (stdin.readUntilDelimiterOrEof(&buf, '\n')) |line| {
|
|
try file.writeAll(line orelse break);
|
|
try file.writeAll("\n");
|
|
} else |err| {
|
|
write(Target.Stderr, "error while reading from stdin: {any}\n", .{err});
|
|
return;
|
|
}
|
|
|
|
try file.writeAll("\n");
|
|
|
|
// Print some success message and the back link to STDOUT
|
|
try stdout.print("Entry added successfully\n", .{});
|
|
try stdout.print("=> / Back to the log entries", .{});
|
|
}
|
|
|
|
fn listEntries() void {
|
|
const file = std.fs.cwd().openFile("entries.log.gmi", .{}) catch |err| {
|
|
write(Target.Stderr, "unable to open file: {any}\n", .{err});
|
|
return;
|
|
};
|
|
defer file.close();
|
|
|
|
var bufReader = std.io.bufferedReader(file.reader());
|
|
var inStream = bufReader.reader();
|
|
|
|
var buf: [1024]u8 = undefined;
|
|
|
|
while (inStream.readUntilDelimiterOrEof(&buf, '\n')) |line| {
|
|
write(Target.Stdout, "{s}\n", .{ line orelse break });
|
|
} else |err| {
|
|
write(Target.Stderr, "error while reading the file: {!}\n", .{err});
|
|
}
|
|
}
|
|
|