M src/cmd.zig => src/cmd.zig +26 -2
@@ 1,4 1,5 @@
const std = @import("std");
+const stdout = std.io.getStdOut().outStream();
const zettel = @import("zettel.zig");
@@ 19,7 20,7 @@ pub const Command = enum {
Show,
Tags,
- pub fn usage(comptime self: Command) []const u8 {
+ pub fn usage(self: Command) []const u8 {
return switch (self) {
.List => list.usage,
.New => new.usage,
@@ 31,7 32,7 @@ pub const Command = enum {
};
}
- pub fn desc(comptime self: Command) []const u8 {
+ pub fn desc(self: Command) []const u8 {
return switch (self) {
.List => list.desc,
.New => new.desc,
@@ 44,7 45,30 @@ pub const Command = enum {
}
};
+pub fn printUsage(cmd: ?Command) void {
+ stdout.print("Usage: zet {}\n\n", .{if (cmd != null) cmd.?.usage() else "COMMAND"}) catch return;
+
+ if (cmd) |_| {
+ stdout.print("{}\n", .{cmd.?.desc()}) catch return;
+ } else {
+ stdout.print("Available commands:\n", .{}) catch return;
+ inline for (@typeInfo(Command).Enum.fields) |command| {
+ stdout.print(" ", .{}) catch return;
+ inline for (command.name) |char| stdout.print("{c}", .{std.ascii.toLower(char)}) catch return;
+ stdout.print("\n", .{}) catch return;
+ }
+ stdout.print("\n", .{}) catch return;
+ stdout.print("Use \"zet help COMMAND\" for more information about a command.\n", .{}) catch return;
+ }
+}
+
pub fn handleCommand(allocator: *std.mem.Allocator, command: []const u8, args: ?[][]const u8) !void {
+ if (std.mem.eql(u8, command, "help")) {
+ const subcmd = if (args != null) try parseCommand(args.?[0]) else null;
+ printUsage(subcmd);
+ return;
+ }
+
const zettels = try zettel.getZettels(allocator);
defer allocator.free(zettels);
M src/cmd/list.zig => src/cmd/list.zig +1 -1
@@ 4,7 4,7 @@ const stdout = std.io.getStdOut().outStream();
const Zettel = @import("../zettel.zig").Zettel;
pub const usage = "l|list [PATTERN [PATTERN ...]]";
-pub const desc = "With no argument, list all notes. Otherwise list notes matching any of the given patterns";
+pub const desc = "With no argument, list all notes. Otherwise list notes matching any of the given patterns.";
pub fn run(allocator: *std.mem.Allocator, patterns: ?[][]const u8, zettels: []const Zettel) !void {
for (zettels) |zet| {
M src/cmd/new.zig => src/cmd/new.zig +1 -1
@@ 6,7 6,7 @@ const Zettel = @import("../zettel.zig").Zettel;
const util = @import("../util.zig");
pub const usage = "n|new <TITLE>";
-pub const desc = "Create a new note with the given title";
+pub const desc = "Create a new note with the given title.";
pub fn run(allocator: *std.mem.Allocator, title: []const u8) !void {
const new_zettel = try Zettel.new(allocator, title);
M src/cmd/open.zig => src/cmd/open.zig +1 -1
@@ 4,7 4,7 @@ const stderr = std.io.getStdErr().outStream();
const Zettel = @import("../zettel.zig").Zettel;
pub const usage = "o|open [NOTE [NOTE ...]]";
-pub const desc = "Open the given notes in your $EDITOR";
+pub const desc = "Open the given notes in your $EDITOR.";
pub fn run(allocator: *std.mem.Allocator, zettels: ?[]const Zettel) !void {
var args = std.ArrayList([]const u8).init(allocator);
M src/cmd/preview.zig => src/cmd/preview.zig +1 -1
@@ 5,7 5,7 @@ const Zettel = @import("../zettel.zig").Zettel;
const util = @import("../util.zig");
pub const usage = "p|preview <NOTE> [NOTE ...]";
-pub const desc = "View notes as HTML";
+pub const desc = "View notes as HTML.";
pub fn run(allocator: *std.mem.Allocator, zettels: []const Zettel) !void {
const pandoc = util.expandPath(allocator, "pandoc") orelse {
M src/cmd/search.zig => src/cmd/search.zig +1 -1
@@ 4,7 4,7 @@ const stdout = std.io.getStdOut().outStream();
const Zettel = @import("../zettel.zig").Zettel;
pub const usage = "s|search <PATTERN> [PATTERN ...]";
-pub const desc = "Search for notes whose contents match any of the given patterns";
+pub const desc = "Search for notes whose contents match any of the given patterns.";
pub fn run(allocator: *std.mem.Allocator, patterns: [][]const u8, zettels: []const Zettel) !void {
var matches = std.ArrayList(Zettel).init(allocator);
M src/cmd/show.zig => src/cmd/show.zig +1 -2
@@ 1,11 1,10 @@
const std = @import("std");
const stdout = std.io.getStdOut().outStream();
-const stderr = std.io.getStdErr().outStream();
const Zettel = @import("../zettel.zig").Zettel;
pub const usage = "sh|show <NOTE> [NOTE ...]";
-pub const desc = "Display contents of notes to stdout";
+pub const desc = "Display contents of notes to stdout.";
pub fn run(allocator: *std.mem.Allocator, zettels: []const Zettel) !void {
for (zettels) |zet| {
M src/cmd/tags.zig => src/cmd/tags.zig +1 -1
@@ 4,7 4,7 @@ const stdout = std.io.getStdOut().outStream();
const Zettel = @import("../zettel.zig").Zettel;
pub const usage = "t|tags [TAG [TAG ...]]";
-pub const desc = "With no argument, list all tags found in notes. Otherwise list all notes containing any of the given tags";
+pub const desc = "With no argument, list all tags found in notes. Otherwise list all notes containing any of the given tags.";
pub fn run(allocator: *std.mem.Allocator, tags: ?[][]const u8, zettels: []const Zettel) !void {
if (tags == null) {
M src/main.zig => src/main.zig +6 -17
@@ 4,17 4,6 @@ const stderr = std.io.getStdErr().outStream();
const cmd = @import("cmd.zig");
-fn printUsage(exe: []const u8) void {
- stdout.print("Usage: {} COMMAND\n", .{std.fs.path.basename(exe)}) catch return;
- stdout.print("\n", .{}) catch return;
- stdout.print("Available commands:\n", .{}) catch return;
- inline for (@typeInfo(cmd.Command).Enum.fields) |command| {
- comptime var usage = @field(cmd.Command, command.name).usage();
- stdout.print(" {}", .{usage}) catch return;
- stdout.print("{}{}\n", .{ " " ** (36 - usage.len), @field(cmd.Command, command.name).desc() }) catch return;
- }
-}
-
fn zettelDir(allocator: *std.mem.Allocator) ![]const u8 {
var path: []u8 = undefined;
if (std.os.getenv("ZETTEL_DIR")) |dir| {
@@ 54,7 43,7 @@ pub fn main() anyerror!void {
const exe = arglist[0];
if (arglist.len == 1) {
- printUsage(exe);
+ cmd.printUsage(null);
return;
}
@@ 69,17 58,17 @@ pub fn main() anyerror!void {
cmd.handleCommand(allocator, command, args) catch |err| return switch (err) {
error.UnknownCommand => {
- try stderr.print("Unknown command: {}\n", .{command});
- printUsage(exe);
+ try stderr.print("Error: unknown command: {}\n", .{command});
+ try stderr.print("Use \"zet help\" for usage.\n", .{});
std.process.exit(1);
},
error.MissingRequiredArgument => {
- try stderr.print("Missing required argument\n", .{});
- printUsage(exe);
+ try stderr.print("Error: missing required argument\n\n", .{});
+ try stderr.print("Use \"zet help\" for usage.\n", .{});
std.process.exit(1);
},
error.NoAvailableBrowser => {
- try stderr.print("Couldn't find a way to open compiled notes\n", .{});
+ try stderr.print("Error: couldn't find a way to open compiled notes\n", .{});
std.process.exit(1);
},
error.NoMatches => {