This is a bit annoying now, I have to dump them one by one and update
the repository url. But the format forces that. I could automate it
further, but for now it's okay to do by hand.
This adds some tools to keep external repositories in sync. They will
hold the Tree-sitter grammar and Zed extension. Perhaps in the future
I should move the Vim plugin out as well. Maybe the Zed extension and
Vim plugin can be submodules, but I quite like that I can update them
and see the diff in the same commit where I edit the grammar.
This has not been tested yet. Also, I may need to move it into a
separate repository, but we can do that in the same way as with the
Tree-sitter repo that I just extracted.
I want to make a Zed extension, and it looks like Zed does not support
Tree-sitter grammars that do not live at the repository root, so let's
just make a separate repository to dump a generated copy of the grammar
in. It will also make integration with other Tree-sitter consumers
easier.
In the expression `{ key: true }` (json syntax) `key` is interpreted as an
identifier whereas in `{ key = true }` (record syntax) `key` is a string literal.
This hint should highlight that possible syntax mixup.
I just encountered "Reduce Cognitive Load" in a comment on Hacker News
and it fits the acronym very well, I'm going to keep a list of possible
meanings of the name "RCL".
Ever since 8d4d61e2f1, I was unsure about
whether there should be a colon after else. It looks more natural in
the multi-line form for sure, but it looks weird in the single-line
form. But the single-line form looks a bit awkward anyway, and having
the colon feels more regular. It also creates more line noise though,
it is strictly not needed. Etc.
After having stared at RCL code for half a year now, my feeling is that
the colon should be there after all. Nim was right all along.
So support a colon after else, but make it optional for now. Do make it
the default, in the sense that the docs and autoformatter use it.
It means the fuzzer gets to explore less, actually, but we still have
the source-based fuzzer that will find the case where the colon is
missing, and which could hunt for non-idempotencies in the formatter and
such.
When I initially converted from the "if-then-else" keyword syntax to the
colon-based one, during development I put the colon in, then later I
removed it again, but I was still unsure. Now, after having used the
syntax for some time, my feeling is that there should be a colon after
all. Nim got it right. So put it back.
Because it's easy to stay backwards compatible here, make the colon
optional. We can make it mandatory at some point in the future, but even
making the autoformatter put it there is probably a strong enough push.
Background
I previously added support for depfiles to enable Ninja to update generated
files. But defining a build file like that has some overhead, and introduces
yet another tool. For small things like generating two GitHub Actions workflow
files, adding a build system seems overkill, so I just wrote a shell script.
But then I still needed to split the configuration into multiple files and add
a shell script.
Solution
Add some limited support for defining generated files in RCL itself. This is
not intended to replace a full-blown build tool, more as an intermediate step
to lower the barrier to rewriting configurations in RCL. For many small use
cases, like my two workflows above, we don’t need more than this.
Timeline
I started working on this in February and got it into a pretty good state, but
then never put in the finishing touches. Then I got sidetracked with the type
system blog post series. Now that all that is out of the way, let's integrate
this and make a new release.
Previously we named the file "build.rcl", but now that that is the
default name for "rcl build", let's name the Ninja meta build file
"ninja.rcl". Also, clarify that Make is able to use the depfiles too,
just in a way that I personally try to stay far away from.
Report errors properly. This is quite verbose, I should make some
shorthands for formatting paths. Also check the sandbox policy while
we create the output path.
This makes the golden tests for "rcl buidl" work with the Nix sandbox.
Instead of really writing to output files, we use the new --dry-run
option. This simplifies the test runner and clutters the repository
less. Splitting out IO is ususally a good thing.
As expected, the golden tests fail to run under Nix because the test
directory is not writable. And it's better to not write in my opinion,
let's not hack that and have a dry run output mode.
For now the output format is not structured, this is good enough for the
thests. It could be nice to do structured output in RCL format, but we
can do that later if needed.
I am a bit hesitant about making the tests write to the file system.
Maybe I should add a --dry-run mode to "rcl build" that instead prints
what files it would write to and what contents. But then we test less
of the real implementation, and there is something to say for testing
the real thing as much as possible, so let's do this for now. It may
cause trouble for the Nix flake checks, but outside of the Nix flake
it works.
I don't like this distinction that in the build file, we don't
implicitly add a newline, but on the command line we do. But making
users specify a trailing newline on the command line is annoying. So
then the RCL build spec will have to match the CLI, and append the
newline. But then empty string cannot be the default, so let's accept
null too.
I couldn't add a banner to the GitHub Actions yaml because the output
format is json which does not support comments. By making the banner
just a string that is up to the user to fill, everything becomes both
simpler and more general.
Classic Unix tools are silent on success, but I do like to know how much
it wrote. I can imagine the output would become verbose and I'd rather
have one status line like Ninja. But for now this is okay.
Wow, writing a proper deserializer for an RCL value is still a lot of
work, even in Rust! I should write a #[derive] macro for it. But having
record types would make this a lot easier already, so let's wait with
that. For now it's hand-written with a dozen error messages that I will
need to add goldens for ...