From 617a2ea0a7ca4cb1300d2e60e3e51c15828ad59a Mon Sep 17 00:00:00 2001 From: Rylan Polster Date: Thu, 14 Jan 2021 20:34:46 -0500 Subject: [PATCH 1/3] docs: update external command documentation --- docs/External-Commands.md | 86 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/docs/External-Commands.md b/docs/External-Commands.md index 0a2c6e69d3..15c746e142 100644 --- a/docs/External-Commands.md +++ b/docs/External-Commands.md @@ -13,6 +13,8 @@ External commands come in two flavours: Ruby commands and shell scripts. In both cases, the command file should be executable (`chmod +x`) and live somewhere in `PATH`. +External commands can be added to a tap to allow easy distribution. See [below](#external-commands-in-taps) for more details. + ### Ruby commands An external command `extcmd` implemented as a Ruby command should be named `brew-extcmd.rb`. The command is executed by doing a `require` on the full pathname. As the command is `require`d, it has full access to the Homebrew "environment", i.e. all global variables and modules that any internal command has access to. Be wary of using Homebrew internals; they may change at any time without warning. @@ -66,3 +68,87 @@ Note they are largely untested, and as always, be careful about running untested Install any `gem` package into a self-contained Homebrew Cellar location: Note this can also be installed with `brew install brew-gem`. + +## External commands in taps +External commands can be hosted in a [tap](Taps.md) to allow users to easy install and use the command. See [How to Create and Maintain a Tap](How-to-Create-and-Maintain-a-Tap.md) for more details about creating and maintaining a tap. + +External commands should be added to a `cmd` directory in the tap. An external command `extcmd` implemented as a Ruby command should live in `cmd/extcmd.rb` (don't forget to `chmod +x`). + +To easily use Homebrew's argument parser, follow the following Ruby template for external commands (replacing all instances of `foo` with the name of the command): + +```ruby +# frozen_string_literal: true + +module Homebrew + module_function + + def foo_args + Homebrew::CLI::Parser.new do + usage_banner <<~EOS + `foo` [] + + Do something. Place a description here. + EOS + switch "-f", "--force", + description: "Force doing something in the command." + flag "--file=", + description: "Specify a file to do something with in the command." + comma_array "--names", + description: "Add a list of names to the command." + + named_args [:formula, :cask], min: 1 + end + end + + def foo + args = foo_args.parse + + something if args.force? + something_else if args.file == "file.txt" + end +end +``` + +Using the above will generate the appropriate help text: + +```console +$ brew foo --help +Usage: brew foo [options] formula|cask + +Do something. Place a description here. + + -f, --force Force doing something in the command. + --file Specify a file to do something with in the + command. + --names Add a list of names to the command. + -d, --debug Display any debugging information. + -q, --quiet Make some output more quiet. + -v, --verbose Make some output more verbose. + -h, --help Show this message. +``` + +Use the `named_args` method to specify the type and number of named arguments that are expected. Pass a symbol to indicate the type of argument expected. Pass an array of symbols to indicate that multiple types should be expected. Pass an array of strings to specify the specific options that should be expected (see the [`brew analytics`](https://github.com/Homebrew/brew/blob/HEAD/Library/Homebrew/cmd/analytics.rb) command for an example of this). + +Pass an integer to the `number`, `min`, or `max` parameter of `named_args` to specify the number of named arguments that are expected. See the following examples: + +```ruby +# Accept no named args +named_args :none + +# Accept any number (including none) of formula arguments +named_args :formula + +# Accept exactly one of the specified options as an argument +named_args %w[state off on], number: 1 + +# Accept at least one argument that is either a formula or a cask +named_args [:formula, :cask], min: 1 + +# Accept no more than one argument that is a tap +named_args :tap, max: 1 + +# Accept between one and two named args +named_args min: 1, max: 2 +``` + +Named arguments can be accessed by calling `args.named`. Check out the internal [commands](https://github.com/Homebrew/brew/tree/HEAD/Library/Homebrew/cmd) and [developer commands](https://github.com/Homebrew/brew/tree/HEAD/Library/Homebrew/dev-cmd) for more usage examples. From 6d3d88d33e4c0ee16b1e955f05adf889f221f8dc Mon Sep 17 00:00:00 2001 From: Rylan Polster Date: Fri, 15 Jan 2021 10:11:27 -0500 Subject: [PATCH 2/3] Apply suggestions from code review Co-authored-by: Eric Knibbe --- docs/External-Commands.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/External-Commands.md b/docs/External-Commands.md index 15c746e142..fb982bfca7 100644 --- a/docs/External-Commands.md +++ b/docs/External-Commands.md @@ -70,7 +70,7 @@ Install any `gem` package into a self-contained Homebrew Cellar location: Date: Mon, 18 Jan 2021 12:09:16 -0500 Subject: [PATCH 3/3] docs: update external command usage string instructions --- docs/External-Commands.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/External-Commands.md b/docs/External-Commands.md index fb982bfca7..a6696e7699 100644 --- a/docs/External-Commands.md +++ b/docs/External-Commands.md @@ -84,9 +84,7 @@ module Homebrew def foo_args Homebrew::CLI::Parser.new do - usage_banner <<~EOS - `foo` [] - + description <<~EOS Do something. Place a description here. EOS switch "-f", "--force", @@ -113,7 +111,7 @@ Using the above will generate appropriate help text: ```console $ brew foo --help -Usage: brew foo [options] formula|cask +Usage: brew foo [options] formula|cask [...] Do something. Place a description here. @@ -127,6 +125,8 @@ Do something. Place a description here. -h, --help Show this message. ``` +The usage string is automatically generated based on the specified number and type of named arguments (see below for more details on specifying named arguments). The generated usage string can be overridden by passing the correct usage string to the `usage_banner` method (placed just before the `description` method). See the [`brew tap` command](https://github.com/Homebrew/brew/blob/HEAD/Library/Homebrew/cmd/tap.rb) for an example. + Use the `named_args` method to specify the type and number of named arguments that are expected. Pass either a symbol to indicate the type of argument expected, an array of symbols to indicate that multiple types should be expected, or an array of strings to specify which specific options should be expected (see the [`brew analytics`](https://github.com/Homebrew/brew/blob/HEAD/Library/Homebrew/cmd/analytics.rb) command for an example of this). Pass an integer to the `number`, `min`, or `max` parameter of `named_args` to specify the number of named arguments that are expected. See the following examples: