/* * Copyright (c) 2013 Dario Castañé. * This file is part of Zas. * * Zas is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Zas is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Zas. If not, see . */ package zas import ( "flag" "strings" ) // Subcommand is a Zas internal subcommand, inspired by the go command. type Subcommand struct { // Run runs the subcommand. It takes no arguments - flags are package // globals wired up in init() - and returns an error instead of // panicking or exiting directly. Run func() error // UsageLine is the one-line usage message. // The first word in the line is taken to be the subcommand name. UsageLine string // Name is the name of the subcommand. Name string // Flag is a set of flags specific to this command. Flag flag.FlagSet } // NewSubcommand builds a Subcommand from a usage line and its run function. func NewSubcommand(usageLine string, run func() error) *Subcommand { data := strings.SplitN(usageLine, " ", 2) name := strings.ToLower(data[0]) // Named (rather than the zero value) so that Go's own flag-parsing // error/usage output - e.g. from an unrecognized flag, or -h/-help on a // subcommand with no Usage func set - reports "Usage of :" // instead of "Usage of :". fs := flag.NewFlagSet(name, flag.ContinueOnError) // flag.NewFlagSet points fs.Usage at fs.defaultUsage, a method value // bound to the *flag.FlagSet it returns. Subcommand.Flag stores a // flag.FlagSet by value, so fs gets copied below; a bound Usage would // keep referring to this now-orphaned fs instead of the copy that // callers actually register flags on and parse with, so it would // print an empty flag list. Clearing it here restores the ordinary // (nil-Usage) behavior, where usage() calls defaultUsage() on // whichever FlagSet it's actually invoked on. fs.Usage = nil return &Subcommand{ UsageLine: usageLine, Name: name, Run: run, Flag: *fs, } }