How to Extract the homepage Field from shard.yml

Hi, I have a question about parsing shard.yml files in Crystal.

I know that many people use macros to get the version from shard.yml, although I understand that not everyone likes using this idiom:

VERSION = {{ `shards version #{__DIR__}`.chomp.stringify }}

Could anyone share a simple and effective way to extract the homepage field from shard.yml?

HOMEPAGE = ??

Thanks!

YAML.parse("./shard.yml")["homepage"].as_s? I think it’s also possible to install the shards shard and use its types via .from_yaml but this is simpler. Of if you want to stick with a shell command, could do like oq -i yaml '.homepage' shard.yml.

1 Like

This makes me think how useful would be for the run macro to accept a block of crystal code too. But maybe the code would become too messy.

1 Like

Could just use crystal eval with the system or backtick macro method to get the same outcome.

1 Like

This works, but it’s a bit long.

HOMEPAGE = {{ `crystal eval 'require "yaml"; File.open("shard.yml"){|f| puts YAML.parse(f)["homepage"]}'`.chomp.stringify }}

Can’t we make it a little shorter?

This is super inefficient because crystal eval needs to build the parser program on every compilation.
macro run would be better because it caches the macro program.

However, there is no need to use a custom program for this in the first place. You can use an existing YAML parser tool like oq or yq.

Since the YAML format is pretty simple, some shell tools without syntax support could also get you there. For example:

grep -o '^homepage:[[:space:]]*.*' shard.yml | sed 's/^homepage:[[:space:]]*//'

This could even be simplified with GNU extensions:

grep -Po '^homepage:[[:space:]]*\K.*' shard.yml
1 Like

Yes, crystal eval is inefficient, so using tools like oq, grep, or sed is a practical way.
Still, it’s a bit sad that Crystal doesn’t have a built-in way to read shard.yml at compile time.
Also, grep or sed may not work on Windows by default.

1 Like

You can create a small shard for this. Returning everything at compile time with a nice API without depending on external tools. Just a run macro that populate a struct or some constants.

1 Like

You mean a macro-only library that reads shard.yml at compile time? That’s an interesting idea.

1 Like