~gpanders/wk

ref: 4f358b1aca29c3f19357695a8d0ea1338b4c1423 wk/src/main.zig -rw-r--r-- 2.2 KiB
4f358b1a — Gregory Anders 2 months ago
Import std.io in main.zig
Rename project to wk
Refactor common functions

Most of the heavy lifting now happens in the zettel.zig file itself and
most of the cmd/*.zig files just act as front-ends to these functions
(e.g. backlinks, reading, opening, etc.). This allows most of the
complexity to exist in a single place and the command functions
themselves to be nicely isolated.
Don't free memory allocated by arena allocator

Memory allocated by the arena allocator doesn't need to be freed (in
fact, the 'free' function of the ArenaAllocator doesn't actually do
anything except set the memory to 'undefined') and since zet is only a
short lived command line tool, there's no worry about memory leaks.
Import subnamespaces from standard lib

This helps reduce some code noise and shorten line length (just a bit).
Only commit files that were actually modified

This involves a few significant changes:

- Hash file contents and check file modification times to see if a file
  was changed
- Dynamically create the git commit message based on both the command
  and the number of actually modified files
- Re-write the backlinks function to be more efficient. Now, each file
  will be read at most twice (whereas before each file could be read up
  to N times, where N = total number of zettels!)
- Update backlinks after every `open` or `new` command. This should
  ensure that backlinks are always up to date.
Simplify error handling
Print unknown command error from parseCommand function

parseCommand is the only function that actually knows what the command
that's being parsed is, since the command could be the first argument,
i.e.

    zet CMD

or the second, when using `help`:

    zet help CMD
Read arguments from stdin if stdin is not a TTY

This means commands can be composed using

    zet tag TAG | zet open

With fish, the former method still works too:

    zet open (zet tag TAG)

fish handles spaces and line separators in command output much better
than bash.
Split newline delimited argument into separate lines

When composing commands together, e.g.

    zet open "$(zet tags foobar)"

The command used as the argument must be quoted to prevent the shell
from splitting the output on spaces. However, this causes `zet open` to
have a single argument which is just a long newline-delimited string of
the output of `zet tags foobar`. In these cases manually split the
string on the newlines and treat each line as a separate argument.

This is a total hack: I'm basically doing the shell's job for it, but
it's an important feature to be able to chain commands together in this
way. To do it the bash way, you'd have to use

    readarray -t lines < <(zet tags foobar)
    zet open "${lines[@]}"

Bash sucks sometimes.
Clean up zettel dir discovery

The chained if statement accomplishes the same thing, but has fewer
braces and no `break :blk` statements.
Define zettel dir with eval block
Use argsAlloc from standard library over custom func
Add help subcommand and improve help output
Allow subcommands to take multiple arguments
Add command descriptions to usage output
Remove unreachable statements when using stdout

Unreachable statements cause UB when used in unsafe build modes, so they
should only be used in cases that are *actually* unreachable.
Considering there are realistic cases where stdout could fail, this is
not a good use of unreachable, so instead just prematurely exit the
function.
Refactor to parse items into structs

The `getZettels` method now opens and reads the metadata from each file
to create a `Zettel` struct that contains the Zettel's ID, title, and
filename. This makes it much easier to decouple the filename, ID, and
title and also allows more information to be abstracted away into the
common `Zettel` interface. The only "downside" is that collecting the
Zettels is now (slightly) slower as each one has to be opened and the
first few lines read.
Use Dir.makePath instead of std.fs.makeDirAbsolute

`makePath` recursively creates all directories in the hierarchy and
doesn't return an error if the directory already exists.
Remove Commands array

The Commands array was solely being used as a reference of all possible
values of the Command enum. This was solely being used in the printUsage
function which iterated through each possible value and called the
`.usage()` method. Instead, use some Zig builtin functions to access the
enum fields at compile time.
Plug a few memory leaks
Next