casey / just

🤖 Just a command runner
https://just.systems
Creative Commons Zero v1.0 Universal
21.39k stars 476 forks source link

Modules and subcommands #383

Closed casey closed 10 months ago

casey commented 5 years ago

This is apropos of @valscion's comment in #208, where he talks about some of the annoyances of using just to emulate subcommands. This is also somewhat related to #237 and #367, where sub-justfiles are discussed.

I'd like to come up with something that enables all of these things. Some ideas:

A statement mod foo parses foo.just or foo/mod.just as a submodule. Recipes in foo.just / foo/mod.just can now be called on the command line with just foo RECIPE.

If the submodule source file is foo.just, the current working directory for recipes in that submodule will be the current directory. If the it is in foo/mod.just, the current working directory will be foo/.

Questions:


Notes for a first path for out-of-line modules only:


MadBomber commented 2 years ago

Interesting idea to make the include path glob'able. Current justprep the pre-processor stop-gap to modules feature only allows absolute or relative paths. I will look at adding a form of glob to the path.

MadBomber commented 2 years ago

@nickgarber I just released v1.2.2 of justprep a stop-gap pre-processor for just utility that adds the path globing capability. It works in both the Ruby gem and Crystal binary implementations.

I took this issue as the excuse to refactor the code base to extract common methods into their own files for use by both Ruby and Crystal. I added the file extension ".crb" to those files which can run under both implementations. I originally thought of ".crb" to meaning Crystal and Ruby; but, now I've come closer to thinking of it as "compiled ruby."

https://github.com/MadBomber/justprep

SteveChurch commented 1 year ago

Hi @casey, firstly this is an outstanding tool! Kudos. Secondly, is there any update on the progress or idea when this feature may be worked on? I appreciate you're busy and have a life outside of GH 😄 - but submodules would be a killer feature to have 😄

MadBomber commented 1 year ago

@SteveChurch There is a "fake module" convention that works in most circumstances. I documented in the wiki for the pre-processer justprep

https://github.com/MadBomber/justprep/wiki/Fake-Module-Convention

casey commented 1 year ago

HI @SteveChurch, thanks for checking in! I actually don't have a life outside of GH 😅 but I'm currently working on another project, ord, that's getting a huge amount of attention, so it's taking up all spare bandwidth.

No updates to report on modules, but check out include directives which, depending on your use-case, might be useful.

Splines commented 11 months ago

@SteveChurch There is a "fake module" convention that works in most circumstances. I documented in the wiki for the pre-processer justprep

https://github.com/MadBomber/justprep/wiki/Fake-Module-Convention

Thanks a lot for the link! However, I haven't found a solution yet to pass arguments, have you heard of any? E.g. I try to call

just myModule myRecipeInModule myArgument

// inside the module file:
myRecipeInModule myArgument="defaultValue":
  @echo {{myArgument}}

I've also tried to set positional-arguments in the root .justfile which didn't work.

Note I've also seen this Interactive Chooser section in the docs. Maybe it's useful for other solutions to implement "fake" modules?


Edit: To clarify my goal a bit: We have a big project and try to use just with command groups. The solution you provided here, allows us -- in principle -- to have a root .justfile and then a folder commands/ where we can put in more justfiles e.g. docker.justfile. The main justfile delegates to the module via

docker recipe="help":
    just -f ./commands/docker.justfile {{recipe}}

Right now, it's just passing the arguments that is problematic for us.

Splines commented 11 months ago

Ok, in the meantime, I found a solution for my "problem" using variadic parameters. You may find this helpful (or not ;)

# ./justfile

docker recipe *ARGS:
    just -f ./commands/docker.justfile {{recipe}} {{ARGS}}
# ./commands/docker.justfile

# List all available Docker commands.
help:
    @just --list --justfile {{justfile()}}

alias s := shell
# Puts you into a shell of your desired development docker container.
shell name="myDefaultContainer":
    docker exec -it $(docker ps -qf "name=development-{{name}}") bash
valscion commented 10 months ago

Ok, in the meantime, I found a solution for my "problem" using variadic parameters. You may find this helpful (or not ;)

Yeah this is basically the same solution we've been quite happy with since the beginning!

The only downside of this is that if you have special characters (such as whitespaces or quotes), then passing them down successfully to the downstream justfiles gets quite complex.

You might want to try the positional arguments as per the comment by @casey here:

I haven't tried that fully yet myself.

Splines commented 10 months ago

@valscion Thanks, will keep that in mind and come back to it if/once we encounter that situation 👍

casey commented 10 months ago

IT HAS BEEN NIGH ON FIVE YEARS, BUT JUST FINALLY HAS MODULES.

I just released 1.19.0, which includes modules.

See the readme for more information, but in short, modules can be defined using a mod statement, for example, mod foo, which will load a module from foo.just, foo/mod.just, or foo/justfile. Recipes in modules can then be called like subcommands. If the module foo has recipe bar, it can be called with just foo bar.

There are currently a bunch of limitations and missing features, so modules are unstable for now. See #929 for more details.

Thanks so much for everyone's copious patience! And special thanks to @neunenak, who laid a bunch of the ground work which enabled this.

If this doesn't work for your use case, please feel free to open an issue detailing what doesn't work.