argc

repository·main·Indexed 22 days ago

https://github.com/sigoden/argc

A Bash CLI framework and command runner (version 1.24.0) that allows developers to build feature-rich interfaces using comment tags. It provides argument parsing, validation, help text generation, and autocompletion. Key features include the ability to generate standalone scripts via --argc-build, man pages via --argc-mangen, and shell completions. It also includes Argcscript, a make-like command runner using Argcfile.sh to define recipes with support for environment variable management and external subcommands.

Tokens
11.8K
Snippets
47
Records
69
Agent score
78%

What's inside argc

  1. Explore Argc usage examples

    main

    The examples/ directory contains several shell scripts that demonstrate specific features and patterns in argc. You can use these scripts to understand how to implement various argument parsing behaviors.

    Core Features

    • Simple Demo: Basic usage in demo.sh.
    • Multiline Help: Using multiline text for help descriptions in multiline.sh.
    • Nested Commands: Implementing subcommands and command hierarchies in nested-commands.sh.
    • Hooks: Using argc hooks for custom logic in hooks.sh.
    • Strict Mode: Enabling strict mode for error handling in strict.sh.
    • Parallel Execution: Using the --argc-parallel flag in parallel.sh.

    Parameter Types

    • Positional Arguments: Exploring different @arg configurations in args.sh.
    • Flags and Options: Exploring different @option and @flag configurations in options.sh.
    • Environment Binding: Binding environment variables to parameters in bind-env.sh.
    • Environment Variables: Using the @env tag in envs.sh.

    Metadata and Advanced Configuration

    • Default Subcommands: Using @meta default-subcommand in default-subcommand.sh.
    • Tool Requirements: Using @meta require-tools to check for dependencies in require-tools.sh.
    • Flag Inheritance: Using @meta inherit-flag-options in inherit-flag-options.sh.
    • Short Flag Combination: Using @meta combine-shorts in combine-short.sh.
    • Symbols: Using @meta symbol in symbol.sh.
  2. Organize recipes into groups

    main

    You can group related recipes together for better organization and readability in the help output. Use a colon, dot, or at-sign to define group boundaries. Valid formats include foo:bar, foo.bar, and foo@bar.

    # @cmd
    test() { :; }
    # @cmd
    test-unit() { :; }
    # @cmd
    test-bin() { :; }
  3. Distinguish between ARGC_CWORD and ARGC_LAST_ARG

    main

    When writing completion logic, it is important to understand the difference between how the last word is captured:

    • ARGC_CWORD: Isolates the final word, regardless of preceding flags.
      • Example: In git --git-dir=git, ARGC_CWORD is git.
    • ARGC_LAST_ARG: Captures the entire last argument, including attached flags/options.
      • Example: In git --git-dir=git, ARGC_LAST_ARG is --git-dir=git.
  4. Use `ARGC_PARENT_ARGS` to access parent command context

    main

    When an external subcommand is dispatched, argc exports the ARGC_PARENT_ARGS environment variable. This variable contains the parent command and its flags (the arguments provided before the subcommand name).

    This is useful for preserving global options when the external script needs to re-invoke the parent command. You can implement this by defining a helper function that evaluates the exported variable.

    # Inside an external subcommand script
    
    _parent_cmd() {
      eval "$ARGC_PARENT_ARGS" "$@"
    }
    
    # Usage: calls the parent command with the original global flags preserved
    _parent_cmd log --oneline
  5. Use Argc-generated variables for options, flags, and arguments

    main

    When you define parameters using Argc directives, they are mapped to shell variables as follows:

    • @option --name: Becomes $argc_name.
    • @option --name* (Multi-occurs): Becomes an array ${argc_name[@]}.
    • @flag --name: Becomes $argc_name (typically 1 if present, 0 or empty if not).
    • @arg name: Becomes $argc_name.
    • @arg name*: Becomes an array ${argc_name[@]}.
    # Example mapping
    # @option --oa
    # @option --ob*
    # @flag   --fa
    # @arg va
    # @arg vb*
    
    # Running: ./script.sh --oa a --ob=b1 --ob=b2 --fa foo bar baz
    # Results:
    # $argc_oa     -> a
    # ${argc_ob[@]} -> b1 b2
    # $argc_fa     -> 1
    # $argc_va     -> foo
    # ${argc_vb[@]} -> bar baz
  6. Use Argcscript as a command runner

    main

    Argc includes Argcscript, a Bash-based command runner similar to make. It uses an Argcfile.sh to define "recipes" (commands).

    Key benefits include:

    • Leveraging existing Bash skills and GNU tools (awk, sed, grep, etc.).
    • Effortless environment variable management (loading, documenting, and validating .env files).
    • Built-in shell autocompletion for recipes.
    • Cross-platform compatibility.
  7. Understand project root directory behavior

    main

    Argc automatically cds into the directory containing the Argcfile.sh found in the parent hierarchy. This ensures recipes run relative to the project root.

    When running a command from a subdirectory:

    • $PWD: Points to the project root (where Argcfile.sh resides).
    • $ARGC_PWD: Points to the actual current working directory from which you invoked the command.
    # @cmd
    build() {
        echo $PWD      # Project root
        echo $ARGC_PWD # Current directory
    }
  8. Manage recipe dependencies

    main

    Since recipes are shell functions, you can manage dependencies by calling one recipe from within another. This allows for sequential execution of setup or teardown tasks.

    # @cmd
    current() {
      before
      echo current
      after
    }
    
    # @cmd
    before() {
      echo before
    }
    
    # @cmd
    after() {
      echo after
    }
  9. Set a default recipe

    main

    By default, running argc without arguments displays a list of available recipes. You can override this behavior to run a specific recipe automatically using one of two methods:

    1. Define a main() function in your Argcfile.sh.
    2. Use the # @meta default-subcommand tag above a recipe.
    # Method 1: Using main()
    # @cmd
    build() { :; }
    
    main() {
      build
    }
    
    # Method 2: Using @meta
    # @meta default-subcommand
    # @cmd
    build() { :; }
  10. Initialize Argc-generated variables

    main

    Argc automatically creates shell variables for every @option, @flag, and @arg directive defined in your script. To populate these variables, you must initialize them by evaluating the output of the argc --argc-eval command with your script name and the passed arguments.

    Variables follow the naming convention argc_<name>, where <name> is the name of the option, flag, or argument (stripping leading dashes).

    # @option --oa
    # @option --ob*
    # @flag   --fa
    # @arg va
    # @arg vb*
    
    eval "$(argc --argc-eval "$0" "$@")"  # Initializes Argc variables
    
    echo '--oa:' $argc_oa
    echo '--ob:' ${argc_ob[@]}  # Accessing multiple values as an array
    echo '--fa:' $argc_fa
    echo '  va:' $argc_va
    echo '  vb:' ${argc_vb[@]}
  11. Create an Argcfile.sh

    main

    Argc uses a file named Argcfile.sh to store commands, which are referred to as recipes. A recipe is a standard shell function preceded by a # @cmd comment tag. You can quickly scaffold a new Argcfile.sh with sample recipes using the --argc-create flag.

    argc --argc-create build test