Skip to content

Instantly share code, notes, and snippets.

@MawKKe
Last active April 13, 2022 15:16
Show Gist options
  • Save MawKKe/485ad4ce21223309d2e90713f3b9b5ba to your computer and use it in GitHub Desktop.
Save MawKKe/485ad4ce21223309d2e90713f3b9b5ba to your computer and use it in GitHub Desktop.
A utility/wrapper script for launching go (golang) help topics | SEE ALSO https://github.com/MawKKe/golang-help-wrapper
#!/usr/bin/env sh
# A utility/wrapper script for launching go (golang) help topics
# Author: Markus H (MawKKe) <markus@mawkke.fi>
# What is this?
# -------------
# It annoys me greatly that none of the go subcommands have a help switch (-h
# or --help), requiring me to use "go help <subcommand>" instead. This is just
# annoying, adds more work than is necessary, and results in bad developer
# experience. I use shell history (ctrl-p, ctrl-r, ...) heavily, and this
# default mode of operation requires me to type much more than just adding '-h'
# at the end of previously executed command.
#
# This wrapper script attempts add the help flag to all the subcommands
# by reinterpreting the command line arguments: if '-h' or '--help' is passed
# in any position, the respective subcommand help is displayed (the subcommand
# is assumed to be the first argument passed, if any).
#
# So for example, this command
# $ go <subcommand> <whatever arguments> -h
# will launch
# $ go help <subcommand>
#
# Install
# -------
# - download the script, place it into a directory in your $PATH
# - make it executable: chmod +x golang-help-wrapper.sh
# - place 'alias go=golang-help-wrapper.sh' in your ~/.bashrc or similar
#
# Now you can run 'go' commands as usual, any '-h' or '--help' will be
# interpreted as 'go help ...' where it makes sense (see comments below).
#
# Bugs
# -----
# There can be bugs, due to mistakes in the bash script, and due to unforeseen
# edge cases in the 'go' CLI semantics. If you find such a case, let me know.
# My email is listed at the top of the file.
#
# In any case, you can always invoke the actual 'go' executable directly by
# prefixing the command name with a backslash. So, instead of:
#
# $ go ...
# run
# $ \go ...
#
# Note that this is generic behavior found in most(?) shells. You might need
# this hint in case of bugs in this wrapper :)
#
# Tips
# ----
# If you pass '-h' argument with 'go run ...', it will always be interpreted
# as "go help run", UNLESS you use the backslash escape trick OR you pass arguments
# using the double dash idiom:
#
# $ \go run my/run/target -h
# $ go run -- my/run/target -h
#
# both of these will pass '-h' to the target application, instead of being
# reintepreted by this script.
set -eu
for arg in "$@";
do
arg_idx=$(expr "${arg_idx:-0}" + 1)
if [ "$arg" = "--" ]; then
# if '--' appears before help flag, the help flag is not reinterpeted by this script.
# This is desirable behavior with various 'go' subcommands, such as 'go run':
# $ go run -- myapp.go foo bar baz -h # runs './myapp foo bar baz -h' (and '-h' has priority)
# $ go run myapp.go foo bar baz -h # runs 'go help run'
#
# WARNING: if you accidentally place '--' in the wrong position, for example:
# $ go run myapp.go -- foo bar baz -h
#
# then '--' will be handled by myapp.go instead of 'go run'. If myapp.go also
# uses a CLI parser (such as the stdlib 'flag' package), then the double dash
# interpreted to mean "the following arguments are not to be interpreted as flags",
# possibly causing confusion about missing flag values. Note: Note: this behavior
# has nothing to do with this script (I thought it would be useful knowledge for
# the interested)
break
fi
if [ "$arg" = "-h" ] || [ "$arg" = "--help" ]; then
help_idx="$arg_idx"
help_flag=1
help_arg="$arg"
break
fi
done
# Examples of help flag reinterpretation:
# (1) go help -> go help
# (2) go -h -> go help
# (3) go help -h -> go help
# (4) go help subcmd -> go help subcmd
# (5) go -h subcmd -> go help # !!! not subcommand help (easier this way)
# (6) go subcmd -h -> go help subcmd
# (7) go subcmd -h foo -> go help subcmd # basically same as (5)
# (8) go subcmd foo -h -> go help subcmd # interpreted as 'go subcmd -h'
# (9) go subcmd -- foo -h -> go subcmd -- foo -h # passthru, e.g case subcmd == run
# Help flag found (cases 2, 3, 5, 6, 7, 8 but NOT 9)
if [ ${help_flag:-0} -eq 1 ]; then
# let's user know that we grabbed the '-h'.
>&2 echo "@@@"
>&2 echo "@@@ WARNING: help flag ($help_arg) captured & reinterpreted by $(basename $0)"
>&2 echo "@@@"
if [ $help_idx -eq 1 ] || [ "${1:-}" = "help" ]; then
# cases 2, 3, 5
go help
else
# cases 6, 7, 8
go help "${1:-}"
fi
else
# no help flag given, pass arguments as-is
# cases 1 and 8.
go "$@"
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment