Skip to content

Chooser - support recipes with arguments and broader shell support #3272

@duncanawoods

Description

@duncanawoods

--choose doesn't show recipes if they have arguments because they can't be immediately invoked.

This is a problem because:

  • the chooser is helpful way to search and browse recipes
  • recipes with arguments are exactly the ones where I need to remind myself of the arguments and how they are used

Background

Just has changed my approach to scripting and I now rely on a library of 100s of admin/utility recipes. Previously, my small shell scripts would die unused, either forgotten or untrusted as I dare not run something too old without checking what it does first. Just changed that because --choose is a killer feature that lets me easily manage far more scripts than I can learn by rote by fuzzy-finding and browsing related recipes and then checking what they do before execution.

After some confusion with missing recipes, I recreated the chooser as a fish function to support what I wanted which is to see all the recipes and if they take arguments, don't invoke but stage a command line so I can supply them. I use it daily from a 'jc' alias:

# Usage: just_choose [just options]
#   Allows choosing recipes that take params by populating the prompt
#   Passes all args straight through to just.
#   Requires fzf and jq
function just_choose
    set -l just_args $argv

    # Select recipe
    set -l recipe (just $just_args --summary \
        | string split ' ' \
        | string trim \
        | fzf --prompt="just> " --preview="just $just_args -s {}" --preview-window=right:70%)
    
    test -z "$recipe"; and return 1

    # Check if recipe has parameters
    just $just_args --dump --dump-format json \
        | jq -e --arg r "$recipe" '.recipes[$r] and ((.recipes[$r].parameters // []) | length > 0)' >/dev/null
    set -l has_params $status

    # echo "$recipe"
    j -s $recipe

    argparse --ignore-unknown 'justfile=' 'f=' -- $argv
    argparse --ignore-unknown 'working-directory=' 'd=' -- $argv
    set -l just_args $argv

    if test $has_params -ne 0
        # No params: run immediately
        echo "no params: just $just_args $recipe"
        j $just_args $recipe
    else
        # Has params: stage command line
        set -l cmd "j $just_args $recipe"
        commandline -r -- $cmd' '
    end
end

Suggestion

I don't believe it's possible to stage a command line from within the just binary as it's a feature of the shell.

If designed with shell support in mind, the current --choose implementation would support showing all recipes and if the choice takes an argument, exit with a result appropriate for a thin shell wrapper to stage the command line.

The ideal path to great terminal ergonomics and features that can't be achieved as a binary alone would be to create an optional plug-in for popular shells. I'm aware this is likely be considered out-of-scope but there can be big usability wins from something very minimal i.e. a couple of lines invoking the binary.

It would allow resolving the frequent question of "how to execute recipe within the current shell?". A shell wrapper can use the just binary to generate the temp file for the recipe and execute it within the same process. It would enable support for recipes that currently aren't possible e.g. to manipulate the shell environment.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions