diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 7c049124..c104ead6 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -1,22 +1,22 @@ { "ImportPath": "github.com/aybabtme/humanlog", - "GoVersion": "devel +bb82d18ac07a Thu Oct 30 13:20:43 2014 -0700", + "GoVersion": "go1.4.2", "Packages": [ "./..." ], "Deps": [ { "ImportPath": "github.com/aybabtme/rgbterm", - "Rev": "9e3d038e1b8341ed7416c841a884cab4a3487941" + "Rev": "c07e2f009ed2311e9c35bca12ec00b38ccd48283" }, { "ImportPath": "github.com/codegangsta/cli", - "Comment": "1.2.0-24-g7381bc4", - "Rev": "7381bc4e62942763475703c7edd405f1e42adf4f" + "Comment": "1.2.0-95-g9b2bd2b", + "Rev": "9b2bd2b3489748d4d0a204fa4eb2ee9e89e0ebc6" }, { "ImportPath": "github.com/kr/logfmt", - "Rev": "d08c20444daa49c1f4d4c171c81f36178e5f625d" + "Rev": "b84e30acd515aadc4b783ad4ff83aff3299bdfe0" } ] } diff --git a/Godeps/_workspace/src/github.com/aybabtme/rgbterm/codes.go b/Godeps/_workspace/src/github.com/aybabtme/rgbterm/codes.go index e8446a85..30e76b00 100644 --- a/Godeps/_workspace/src/github.com/aybabtme/rgbterm/codes.go +++ b/Godeps/_workspace/src/github.com/aybabtme/rgbterm/codes.go @@ -1,519 +1,521 @@ package rgbterm +// \033[ + var fgTermRGB = [...][]byte{ - []byte("\033[38;5;0m"), - []byte("\033[38;5;1m"), - []byte("\033[38;5;2m"), - []byte("\033[38;5;3m"), - []byte("\033[38;5;4m"), - []byte("\033[38;5;5m"), - []byte("\033[38;5;6m"), - []byte("\033[38;5;7m"), - []byte("\033[38;5;8m"), - []byte("\033[38;5;9m"), - []byte("\033[38;5;10m"), - []byte("\033[38;5;11m"), - []byte("\033[38;5;12m"), - []byte("\033[38;5;13m"), - []byte("\033[38;5;14m"), - []byte("\033[38;5;15m"), - []byte("\033[38;5;16m"), - []byte("\033[38;5;17m"), - []byte("\033[38;5;18m"), - []byte("\033[38;5;19m"), - []byte("\033[38;5;20m"), - []byte("\033[38;5;21m"), - []byte("\033[38;5;22m"), - []byte("\033[38;5;23m"), - []byte("\033[38;5;24m"), - []byte("\033[38;5;25m"), - []byte("\033[38;5;26m"), - []byte("\033[38;5;27m"), - []byte("\033[38;5;28m"), - []byte("\033[38;5;29m"), - []byte("\033[38;5;30m"), - []byte("\033[38;5;31m"), - []byte("\033[38;5;32m"), - []byte("\033[38;5;33m"), - []byte("\033[38;5;34m"), - []byte("\033[38;5;35m"), - []byte("\033[38;5;36m"), - []byte("\033[38;5;37m"), - []byte("\033[38;5;38m"), - []byte("\033[38;5;39m"), - []byte("\033[38;5;40m"), - []byte("\033[38;5;41m"), - []byte("\033[38;5;42m"), - []byte("\033[38;5;43m"), - []byte("\033[38;5;44m"), - []byte("\033[38;5;45m"), - []byte("\033[38;5;46m"), - []byte("\033[38;5;47m"), - []byte("\033[38;5;48m"), - []byte("\033[38;5;49m"), - []byte("\033[38;5;50m"), - []byte("\033[38;5;51m"), - []byte("\033[38;5;52m"), - []byte("\033[38;5;53m"), - []byte("\033[38;5;54m"), - []byte("\033[38;5;55m"), - []byte("\033[38;5;56m"), - []byte("\033[38;5;57m"), - []byte("\033[38;5;58m"), - []byte("\033[38;5;59m"), - []byte("\033[38;5;60m"), - []byte("\033[38;5;61m"), - []byte("\033[38;5;62m"), - []byte("\033[38;5;63m"), - []byte("\033[38;5;64m"), - []byte("\033[38;5;65m"), - []byte("\033[38;5;66m"), - []byte("\033[38;5;67m"), - []byte("\033[38;5;68m"), - []byte("\033[38;5;69m"), - []byte("\033[38;5;70m"), - []byte("\033[38;5;71m"), - []byte("\033[38;5;72m"), - []byte("\033[38;5;73m"), - []byte("\033[38;5;74m"), - []byte("\033[38;5;75m"), - []byte("\033[38;5;76m"), - []byte("\033[38;5;77m"), - []byte("\033[38;5;78m"), - []byte("\033[38;5;79m"), - []byte("\033[38;5;80m"), - []byte("\033[38;5;81m"), - []byte("\033[38;5;82m"), - []byte("\033[38;5;83m"), - []byte("\033[38;5;84m"), - []byte("\033[38;5;85m"), - []byte("\033[38;5;86m"), - []byte("\033[38;5;87m"), - []byte("\033[38;5;88m"), - []byte("\033[38;5;89m"), - []byte("\033[38;5;90m"), - []byte("\033[38;5;91m"), - []byte("\033[38;5;92m"), - []byte("\033[38;5;93m"), - []byte("\033[38;5;94m"), - []byte("\033[38;5;95m"), - []byte("\033[38;5;96m"), - []byte("\033[38;5;97m"), - []byte("\033[38;5;98m"), - []byte("\033[38;5;99m"), - []byte("\033[38;5;100m"), - []byte("\033[38;5;101m"), - []byte("\033[38;5;102m"), - []byte("\033[38;5;103m"), - []byte("\033[38;5;104m"), - []byte("\033[38;5;105m"), - []byte("\033[38;5;106m"), - []byte("\033[38;5;107m"), - []byte("\033[38;5;108m"), - []byte("\033[38;5;109m"), - []byte("\033[38;5;110m"), - []byte("\033[38;5;111m"), - []byte("\033[38;5;112m"), - []byte("\033[38;5;113m"), - []byte("\033[38;5;114m"), - []byte("\033[38;5;115m"), - []byte("\033[38;5;116m"), - []byte("\033[38;5;117m"), - []byte("\033[38;5;118m"), - []byte("\033[38;5;119m"), - []byte("\033[38;5;120m"), - []byte("\033[38;5;121m"), - []byte("\033[38;5;122m"), - []byte("\033[38;5;123m"), - []byte("\033[38;5;124m"), - []byte("\033[38;5;125m"), - []byte("\033[38;5;126m"), - []byte("\033[38;5;127m"), - []byte("\033[38;5;128m"), - []byte("\033[38;5;129m"), - []byte("\033[38;5;130m"), - []byte("\033[38;5;131m"), - []byte("\033[38;5;132m"), - []byte("\033[38;5;133m"), - []byte("\033[38;5;134m"), - []byte("\033[38;5;135m"), - []byte("\033[38;5;136m"), - []byte("\033[38;5;137m"), - []byte("\033[38;5;138m"), - []byte("\033[38;5;139m"), - []byte("\033[38;5;140m"), - []byte("\033[38;5;141m"), - []byte("\033[38;5;142m"), - []byte("\033[38;5;143m"), - []byte("\033[38;5;144m"), - []byte("\033[38;5;145m"), - []byte("\033[38;5;146m"), - []byte("\033[38;5;147m"), - []byte("\033[38;5;148m"), - []byte("\033[38;5;149m"), - []byte("\033[38;5;150m"), - []byte("\033[38;5;151m"), - []byte("\033[38;5;152m"), - []byte("\033[38;5;153m"), - []byte("\033[38;5;154m"), - []byte("\033[38;5;155m"), - []byte("\033[38;5;156m"), - []byte("\033[38;5;157m"), - []byte("\033[38;5;158m"), - []byte("\033[38;5;159m"), - []byte("\033[38;5;160m"), - []byte("\033[38;5;161m"), - []byte("\033[38;5;162m"), - []byte("\033[38;5;163m"), - []byte("\033[38;5;164m"), - []byte("\033[38;5;165m"), - []byte("\033[38;5;166m"), - []byte("\033[38;5;167m"), - []byte("\033[38;5;168m"), - []byte("\033[38;5;169m"), - []byte("\033[38;5;170m"), - []byte("\033[38;5;171m"), - []byte("\033[38;5;172m"), - []byte("\033[38;5;173m"), - []byte("\033[38;5;174m"), - []byte("\033[38;5;175m"), - []byte("\033[38;5;176m"), - []byte("\033[38;5;177m"), - []byte("\033[38;5;178m"), - []byte("\033[38;5;179m"), - []byte("\033[38;5;180m"), - []byte("\033[38;5;181m"), - []byte("\033[38;5;182m"), - []byte("\033[38;5;183m"), - []byte("\033[38;5;184m"), - []byte("\033[38;5;185m"), - []byte("\033[38;5;186m"), - []byte("\033[38;5;187m"), - []byte("\033[38;5;188m"), - []byte("\033[38;5;189m"), - []byte("\033[38;5;190m"), - []byte("\033[38;5;191m"), - []byte("\033[38;5;192m"), - []byte("\033[38;5;193m"), - []byte("\033[38;5;194m"), - []byte("\033[38;5;195m"), - []byte("\033[38;5;196m"), - []byte("\033[38;5;197m"), - []byte("\033[38;5;198m"), - []byte("\033[38;5;199m"), - []byte("\033[38;5;200m"), - []byte("\033[38;5;201m"), - []byte("\033[38;5;202m"), - []byte("\033[38;5;203m"), - []byte("\033[38;5;204m"), - []byte("\033[38;5;205m"), - []byte("\033[38;5;206m"), - []byte("\033[38;5;207m"), - []byte("\033[38;5;208m"), - []byte("\033[38;5;209m"), - []byte("\033[38;5;210m"), - []byte("\033[38;5;211m"), - []byte("\033[38;5;212m"), - []byte("\033[38;5;213m"), - []byte("\033[38;5;214m"), - []byte("\033[38;5;215m"), - []byte("\033[38;5;216m"), - []byte("\033[38;5;217m"), - []byte("\033[38;5;218m"), - []byte("\033[38;5;219m"), - []byte("\033[38;5;220m"), - []byte("\033[38;5;221m"), - []byte("\033[38;5;222m"), - []byte("\033[38;5;223m"), - []byte("\033[38;5;224m"), - []byte("\033[38;5;225m"), - []byte("\033[38;5;226m"), - []byte("\033[38;5;227m"), - []byte("\033[38;5;228m"), - []byte("\033[38;5;229m"), - []byte("\033[38;5;230m"), - []byte("\033[38;5;231m"), - []byte("\033[38;5;232m"), - []byte("\033[38;5;233m"), - []byte("\033[38;5;234m"), - []byte("\033[38;5;235m"), - []byte("\033[38;5;236m"), - []byte("\033[38;5;237m"), - []byte("\033[38;5;238m"), - []byte("\033[38;5;239m"), - []byte("\033[38;5;240m"), - []byte("\033[38;5;241m"), - []byte("\033[38;5;242m"), - []byte("\033[38;5;243m"), - []byte("\033[38;5;244m"), - []byte("\033[38;5;245m"), - []byte("\033[38;5;246m"), - []byte("\033[38;5;247m"), - []byte("\033[38;5;248m"), - []byte("\033[38;5;249m"), - []byte("\033[38;5;250m"), - []byte("\033[38;5;251m"), - []byte("\033[38;5;252m"), - []byte("\033[38;5;253m"), - []byte("\033[38;5;254m"), - []byte("\033[38;5;255m"), + []byte("38;5;0"), + []byte("38;5;1"), + []byte("38;5;2"), + []byte("38;5;3"), + []byte("38;5;4"), + []byte("38;5;5"), + []byte("38;5;6"), + []byte("38;5;7"), + []byte("38;5;8"), + []byte("38;5;9"), + []byte("38;5;10"), + []byte("38;5;11"), + []byte("38;5;12"), + []byte("38;5;13"), + []byte("38;5;14"), + []byte("38;5;15"), + []byte("38;5;16"), + []byte("38;5;17"), + []byte("38;5;18"), + []byte("38;5;19"), + []byte("38;5;20"), + []byte("38;5;21"), + []byte("38;5;22"), + []byte("38;5;23"), + []byte("38;5;24"), + []byte("38;5;25"), + []byte("38;5;26"), + []byte("38;5;27"), + []byte("38;5;28"), + []byte("38;5;29"), + []byte("38;5;30"), + []byte("38;5;31"), + []byte("38;5;32"), + []byte("38;5;33"), + []byte("38;5;34"), + []byte("38;5;35"), + []byte("38;5;36"), + []byte("38;5;37"), + []byte("38;5;38"), + []byte("38;5;39"), + []byte("38;5;40"), + []byte("38;5;41"), + []byte("38;5;42"), + []byte("38;5;43"), + []byte("38;5;44"), + []byte("38;5;45"), + []byte("38;5;46"), + []byte("38;5;47"), + []byte("38;5;48"), + []byte("38;5;49"), + []byte("38;5;50"), + []byte("38;5;51"), + []byte("38;5;52"), + []byte("38;5;53"), + []byte("38;5;54"), + []byte("38;5;55"), + []byte("38;5;56"), + []byte("38;5;57"), + []byte("38;5;58"), + []byte("38;5;59"), + []byte("38;5;60"), + []byte("38;5;61"), + []byte("38;5;62"), + []byte("38;5;63"), + []byte("38;5;64"), + []byte("38;5;65"), + []byte("38;5;66"), + []byte("38;5;67"), + []byte("38;5;68"), + []byte("38;5;69"), + []byte("38;5;70"), + []byte("38;5;71"), + []byte("38;5;72"), + []byte("38;5;73"), + []byte("38;5;74"), + []byte("38;5;75"), + []byte("38;5;76"), + []byte("38;5;77"), + []byte("38;5;78"), + []byte("38;5;79"), + []byte("38;5;80"), + []byte("38;5;81"), + []byte("38;5;82"), + []byte("38;5;83"), + []byte("38;5;84"), + []byte("38;5;85"), + []byte("38;5;86"), + []byte("38;5;87"), + []byte("38;5;88"), + []byte("38;5;89"), + []byte("38;5;90"), + []byte("38;5;91"), + []byte("38;5;92"), + []byte("38;5;93"), + []byte("38;5;94"), + []byte("38;5;95"), + []byte("38;5;96"), + []byte("38;5;97"), + []byte("38;5;98"), + []byte("38;5;99"), + []byte("38;5;100"), + []byte("38;5;101"), + []byte("38;5;102"), + []byte("38;5;103"), + []byte("38;5;104"), + []byte("38;5;105"), + []byte("38;5;106"), + []byte("38;5;107"), + []byte("38;5;108"), + []byte("38;5;109"), + []byte("38;5;110"), + []byte("38;5;111"), + []byte("38;5;112"), + []byte("38;5;113"), + []byte("38;5;114"), + []byte("38;5;115"), + []byte("38;5;116"), + []byte("38;5;117"), + []byte("38;5;118"), + []byte("38;5;119"), + []byte("38;5;120"), + []byte("38;5;121"), + []byte("38;5;122"), + []byte("38;5;123"), + []byte("38;5;124"), + []byte("38;5;125"), + []byte("38;5;126"), + []byte("38;5;127"), + []byte("38;5;128"), + []byte("38;5;129"), + []byte("38;5;130"), + []byte("38;5;131"), + []byte("38;5;132"), + []byte("38;5;133"), + []byte("38;5;134"), + []byte("38;5;135"), + []byte("38;5;136"), + []byte("38;5;137"), + []byte("38;5;138"), + []byte("38;5;139"), + []byte("38;5;140"), + []byte("38;5;141"), + []byte("38;5;142"), + []byte("38;5;143"), + []byte("38;5;144"), + []byte("38;5;145"), + []byte("38;5;146"), + []byte("38;5;147"), + []byte("38;5;148"), + []byte("38;5;149"), + []byte("38;5;150"), + []byte("38;5;151"), + []byte("38;5;152"), + []byte("38;5;153"), + []byte("38;5;154"), + []byte("38;5;155"), + []byte("38;5;156"), + []byte("38;5;157"), + []byte("38;5;158"), + []byte("38;5;159"), + []byte("38;5;160"), + []byte("38;5;161"), + []byte("38;5;162"), + []byte("38;5;163"), + []byte("38;5;164"), + []byte("38;5;165"), + []byte("38;5;166"), + []byte("38;5;167"), + []byte("38;5;168"), + []byte("38;5;169"), + []byte("38;5;170"), + []byte("38;5;171"), + []byte("38;5;172"), + []byte("38;5;173"), + []byte("38;5;174"), + []byte("38;5;175"), + []byte("38;5;176"), + []byte("38;5;177"), + []byte("38;5;178"), + []byte("38;5;179"), + []byte("38;5;180"), + []byte("38;5;181"), + []byte("38;5;182"), + []byte("38;5;183"), + []byte("38;5;184"), + []byte("38;5;185"), + []byte("38;5;186"), + []byte("38;5;187"), + []byte("38;5;188"), + []byte("38;5;189"), + []byte("38;5;190"), + []byte("38;5;191"), + []byte("38;5;192"), + []byte("38;5;193"), + []byte("38;5;194"), + []byte("38;5;195"), + []byte("38;5;196"), + []byte("38;5;197"), + []byte("38;5;198"), + []byte("38;5;199"), + []byte("38;5;200"), + []byte("38;5;201"), + []byte("38;5;202"), + []byte("38;5;203"), + []byte("38;5;204"), + []byte("38;5;205"), + []byte("38;5;206"), + []byte("38;5;207"), + []byte("38;5;208"), + []byte("38;5;209"), + []byte("38;5;210"), + []byte("38;5;211"), + []byte("38;5;212"), + []byte("38;5;213"), + []byte("38;5;214"), + []byte("38;5;215"), + []byte("38;5;216"), + []byte("38;5;217"), + []byte("38;5;218"), + []byte("38;5;219"), + []byte("38;5;220"), + []byte("38;5;221"), + []byte("38;5;222"), + []byte("38;5;223"), + []byte("38;5;224"), + []byte("38;5;225"), + []byte("38;5;226"), + []byte("38;5;227"), + []byte("38;5;228"), + []byte("38;5;229"), + []byte("38;5;230"), + []byte("38;5;231"), + []byte("38;5;232"), + []byte("38;5;233"), + []byte("38;5;234"), + []byte("38;5;235"), + []byte("38;5;236"), + []byte("38;5;237"), + []byte("38;5;238"), + []byte("38;5;239"), + []byte("38;5;240"), + []byte("38;5;241"), + []byte("38;5;242"), + []byte("38;5;243"), + []byte("38;5;244"), + []byte("38;5;245"), + []byte("38;5;246"), + []byte("38;5;247"), + []byte("38;5;248"), + []byte("38;5;249"), + []byte("38;5;250"), + []byte("38;5;251"), + []byte("38;5;252"), + []byte("38;5;253"), + []byte("38;5;254"), + []byte("38;5;255"), } var bgTermRGB = [...][]byte{ - []byte("\033[48;5;0m"), - []byte("\033[48;5;1m"), - []byte("\033[48;5;2m"), - []byte("\033[48;5;3m"), - []byte("\033[48;5;4m"), - []byte("\033[48;5;5m"), - []byte("\033[48;5;6m"), - []byte("\033[48;5;7m"), - []byte("\033[48;5;8m"), - []byte("\033[48;5;9m"), - []byte("\033[48;5;10m"), - []byte("\033[48;5;11m"), - []byte("\033[48;5;12m"), - []byte("\033[48;5;13m"), - []byte("\033[48;5;14m"), - []byte("\033[48;5;15m"), - []byte("\033[48;5;16m"), - []byte("\033[48;5;17m"), - []byte("\033[48;5;18m"), - []byte("\033[48;5;19m"), - []byte("\033[48;5;20m"), - []byte("\033[48;5;21m"), - []byte("\033[48;5;22m"), - []byte("\033[48;5;23m"), - []byte("\033[48;5;24m"), - []byte("\033[48;5;25m"), - []byte("\033[48;5;26m"), - []byte("\033[48;5;27m"), - []byte("\033[48;5;28m"), - []byte("\033[48;5;29m"), - []byte("\033[48;5;30m"), - []byte("\033[48;5;31m"), - []byte("\033[48;5;32m"), - []byte("\033[48;5;33m"), - []byte("\033[48;5;34m"), - []byte("\033[48;5;35m"), - []byte("\033[48;5;36m"), - []byte("\033[48;5;37m"), - []byte("\033[48;5;38m"), - []byte("\033[48;5;39m"), - []byte("\033[48;5;40m"), - []byte("\033[48;5;41m"), - []byte("\033[48;5;42m"), - []byte("\033[48;5;43m"), - []byte("\033[48;5;44m"), - []byte("\033[48;5;45m"), - []byte("\033[48;5;46m"), - []byte("\033[48;5;47m"), - []byte("\033[48;5;48m"), - []byte("\033[48;5;49m"), - []byte("\033[48;5;50m"), - []byte("\033[48;5;51m"), - []byte("\033[48;5;52m"), - []byte("\033[48;5;53m"), - []byte("\033[48;5;54m"), - []byte("\033[48;5;55m"), - []byte("\033[48;5;56m"), - []byte("\033[48;5;57m"), - []byte("\033[48;5;58m"), - []byte("\033[48;5;59m"), - []byte("\033[48;5;60m"), - []byte("\033[48;5;61m"), - []byte("\033[48;5;62m"), - []byte("\033[48;5;63m"), - []byte("\033[48;5;64m"), - []byte("\033[48;5;65m"), - []byte("\033[48;5;66m"), - []byte("\033[48;5;67m"), - []byte("\033[48;5;68m"), - []byte("\033[48;5;69m"), - []byte("\033[48;5;70m"), - []byte("\033[48;5;71m"), - []byte("\033[48;5;72m"), - []byte("\033[48;5;73m"), - []byte("\033[48;5;74m"), - []byte("\033[48;5;75m"), - []byte("\033[48;5;76m"), - []byte("\033[48;5;77m"), - []byte("\033[48;5;78m"), - []byte("\033[48;5;79m"), - []byte("\033[48;5;80m"), - []byte("\033[48;5;81m"), - []byte("\033[48;5;82m"), - []byte("\033[48;5;83m"), - []byte("\033[48;5;84m"), - []byte("\033[48;5;85m"), - []byte("\033[48;5;86m"), - []byte("\033[48;5;87m"), - []byte("\033[48;5;88m"), - []byte("\033[48;5;89m"), - []byte("\033[48;5;90m"), - []byte("\033[48;5;91m"), - []byte("\033[48;5;92m"), - []byte("\033[48;5;93m"), - []byte("\033[48;5;94m"), - []byte("\033[48;5;95m"), - []byte("\033[48;5;96m"), - []byte("\033[48;5;97m"), - []byte("\033[48;5;98m"), - []byte("\033[48;5;99m"), - []byte("\033[48;5;100m"), - []byte("\033[48;5;101m"), - []byte("\033[48;5;102m"), - []byte("\033[48;5;103m"), - []byte("\033[48;5;104m"), - []byte("\033[48;5;105m"), - []byte("\033[48;5;106m"), - []byte("\033[48;5;107m"), - []byte("\033[48;5;108m"), - []byte("\033[48;5;109m"), - []byte("\033[48;5;110m"), - []byte("\033[48;5;111m"), - []byte("\033[48;5;112m"), - []byte("\033[48;5;113m"), - []byte("\033[48;5;114m"), - []byte("\033[48;5;115m"), - []byte("\033[48;5;116m"), - []byte("\033[48;5;117m"), - []byte("\033[48;5;118m"), - []byte("\033[48;5;119m"), - []byte("\033[48;5;120m"), - []byte("\033[48;5;121m"), - []byte("\033[48;5;122m"), - []byte("\033[48;5;123m"), - []byte("\033[48;5;124m"), - []byte("\033[48;5;125m"), - []byte("\033[48;5;126m"), - []byte("\033[48;5;127m"), - []byte("\033[48;5;128m"), - []byte("\033[48;5;129m"), - []byte("\033[48;5;130m"), - []byte("\033[48;5;131m"), - []byte("\033[48;5;132m"), - []byte("\033[48;5;133m"), - []byte("\033[48;5;134m"), - []byte("\033[48;5;135m"), - []byte("\033[48;5;136m"), - []byte("\033[48;5;137m"), - []byte("\033[48;5;138m"), - []byte("\033[48;5;139m"), - []byte("\033[48;5;140m"), - []byte("\033[48;5;141m"), - []byte("\033[48;5;142m"), - []byte("\033[48;5;143m"), - []byte("\033[48;5;144m"), - []byte("\033[48;5;145m"), - []byte("\033[48;5;146m"), - []byte("\033[48;5;147m"), - []byte("\033[48;5;148m"), - []byte("\033[48;5;149m"), - []byte("\033[48;5;150m"), - []byte("\033[48;5;151m"), - []byte("\033[48;5;152m"), - []byte("\033[48;5;153m"), - []byte("\033[48;5;154m"), - []byte("\033[48;5;155m"), - []byte("\033[48;5;156m"), - []byte("\033[48;5;157m"), - []byte("\033[48;5;158m"), - []byte("\033[48;5;159m"), - []byte("\033[48;5;160m"), - []byte("\033[48;5;161m"), - []byte("\033[48;5;162m"), - []byte("\033[48;5;163m"), - []byte("\033[48;5;164m"), - []byte("\033[48;5;165m"), - []byte("\033[48;5;166m"), - []byte("\033[48;5;167m"), - []byte("\033[48;5;168m"), - []byte("\033[48;5;169m"), - []byte("\033[48;5;170m"), - []byte("\033[48;5;171m"), - []byte("\033[48;5;172m"), - []byte("\033[48;5;173m"), - []byte("\033[48;5;174m"), - []byte("\033[48;5;175m"), - []byte("\033[48;5;176m"), - []byte("\033[48;5;177m"), - []byte("\033[48;5;178m"), - []byte("\033[48;5;179m"), - []byte("\033[48;5;180m"), - []byte("\033[48;5;181m"), - []byte("\033[48;5;182m"), - []byte("\033[48;5;183m"), - []byte("\033[48;5;184m"), - []byte("\033[48;5;185m"), - []byte("\033[48;5;186m"), - []byte("\033[48;5;187m"), - []byte("\033[48;5;188m"), - []byte("\033[48;5;189m"), - []byte("\033[48;5;190m"), - []byte("\033[48;5;191m"), - []byte("\033[48;5;192m"), - []byte("\033[48;5;193m"), - []byte("\033[48;5;194m"), - []byte("\033[48;5;195m"), - []byte("\033[48;5;196m"), - []byte("\033[48;5;197m"), - []byte("\033[48;5;198m"), - []byte("\033[48;5;199m"), - []byte("\033[48;5;200m"), - []byte("\033[48;5;201m"), - []byte("\033[48;5;202m"), - []byte("\033[48;5;203m"), - []byte("\033[48;5;204m"), - []byte("\033[48;5;205m"), - []byte("\033[48;5;206m"), - []byte("\033[48;5;207m"), - []byte("\033[48;5;208m"), - []byte("\033[48;5;209m"), - []byte("\033[48;5;210m"), - []byte("\033[48;5;211m"), - []byte("\033[48;5;212m"), - []byte("\033[48;5;213m"), - []byte("\033[48;5;214m"), - []byte("\033[48;5;215m"), - []byte("\033[48;5;216m"), - []byte("\033[48;5;217m"), - []byte("\033[48;5;218m"), - []byte("\033[48;5;219m"), - []byte("\033[48;5;220m"), - []byte("\033[48;5;221m"), - []byte("\033[48;5;222m"), - []byte("\033[48;5;223m"), - []byte("\033[48;5;224m"), - []byte("\033[48;5;225m"), - []byte("\033[48;5;226m"), - []byte("\033[48;5;227m"), - []byte("\033[48;5;228m"), - []byte("\033[48;5;229m"), - []byte("\033[48;5;230m"), - []byte("\033[48;5;231m"), - []byte("\033[48;5;232m"), - []byte("\033[48;5;233m"), - []byte("\033[48;5;234m"), - []byte("\033[48;5;235m"), - []byte("\033[48;5;236m"), - []byte("\033[48;5;237m"), - []byte("\033[48;5;238m"), - []byte("\033[48;5;239m"), - []byte("\033[48;5;240m"), - []byte("\033[48;5;241m"), - []byte("\033[48;5;242m"), - []byte("\033[48;5;243m"), - []byte("\033[48;5;244m"), - []byte("\033[48;5;245m"), - []byte("\033[48;5;246m"), - []byte("\033[48;5;247m"), - []byte("\033[48;5;248m"), - []byte("\033[48;5;249m"), - []byte("\033[48;5;250m"), - []byte("\033[48;5;251m"), - []byte("\033[48;5;252m"), - []byte("\033[48;5;253m"), - []byte("\033[48;5;254m"), - []byte("\033[48;5;255m"), + []byte("48;5;0"), + []byte("48;5;1"), + []byte("48;5;2"), + []byte("48;5;3"), + []byte("48;5;4"), + []byte("48;5;5"), + []byte("48;5;6"), + []byte("48;5;7"), + []byte("48;5;8"), + []byte("48;5;9"), + []byte("48;5;10"), + []byte("48;5;11"), + []byte("48;5;12"), + []byte("48;5;13"), + []byte("48;5;14"), + []byte("48;5;15"), + []byte("48;5;16"), + []byte("48;5;17"), + []byte("48;5;18"), + []byte("48;5;19"), + []byte("48;5;20"), + []byte("48;5;21"), + []byte("48;5;22"), + []byte("48;5;23"), + []byte("48;5;24"), + []byte("48;5;25"), + []byte("48;5;26"), + []byte("48;5;27"), + []byte("48;5;28"), + []byte("48;5;29"), + []byte("48;5;30"), + []byte("48;5;31"), + []byte("48;5;32"), + []byte("48;5;33"), + []byte("48;5;34"), + []byte("48;5;35"), + []byte("48;5;36"), + []byte("48;5;37"), + []byte("48;5;38"), + []byte("48;5;39"), + []byte("48;5;40"), + []byte("48;5;41"), + []byte("48;5;42"), + []byte("48;5;43"), + []byte("48;5;44"), + []byte("48;5;45"), + []byte("48;5;46"), + []byte("48;5;47"), + []byte("48;5;48"), + []byte("48;5;49"), + []byte("48;5;50"), + []byte("48;5;51"), + []byte("48;5;52"), + []byte("48;5;53"), + []byte("48;5;54"), + []byte("48;5;55"), + []byte("48;5;56"), + []byte("48;5;57"), + []byte("48;5;58"), + []byte("48;5;59"), + []byte("48;5;60"), + []byte("48;5;61"), + []byte("48;5;62"), + []byte("48;5;63"), + []byte("48;5;64"), + []byte("48;5;65"), + []byte("48;5;66"), + []byte("48;5;67"), + []byte("48;5;68"), + []byte("48;5;69"), + []byte("48;5;70"), + []byte("48;5;71"), + []byte("48;5;72"), + []byte("48;5;73"), + []byte("48;5;74"), + []byte("48;5;75"), + []byte("48;5;76"), + []byte("48;5;77"), + []byte("48;5;78"), + []byte("48;5;79"), + []byte("48;5;80"), + []byte("48;5;81"), + []byte("48;5;82"), + []byte("48;5;83"), + []byte("48;5;84"), + []byte("48;5;85"), + []byte("48;5;86"), + []byte("48;5;87"), + []byte("48;5;88"), + []byte("48;5;89"), + []byte("48;5;90"), + []byte("48;5;91"), + []byte("48;5;92"), + []byte("48;5;93"), + []byte("48;5;94"), + []byte("48;5;95"), + []byte("48;5;96"), + []byte("48;5;97"), + []byte("48;5;98"), + []byte("48;5;99"), + []byte("48;5;100"), + []byte("48;5;101"), + []byte("48;5;102"), + []byte("48;5;103"), + []byte("48;5;104"), + []byte("48;5;105"), + []byte("48;5;106"), + []byte("48;5;107"), + []byte("48;5;108"), + []byte("48;5;109"), + []byte("48;5;110"), + []byte("48;5;111"), + []byte("48;5;112"), + []byte("48;5;113"), + []byte("48;5;114"), + []byte("48;5;115"), + []byte("48;5;116"), + []byte("48;5;117"), + []byte("48;5;118"), + []byte("48;5;119"), + []byte("48;5;120"), + []byte("48;5;121"), + []byte("48;5;122"), + []byte("48;5;123"), + []byte("48;5;124"), + []byte("48;5;125"), + []byte("48;5;126"), + []byte("48;5;127"), + []byte("48;5;128"), + []byte("48;5;129"), + []byte("48;5;130"), + []byte("48;5;131"), + []byte("48;5;132"), + []byte("48;5;133"), + []byte("48;5;134"), + []byte("48;5;135"), + []byte("48;5;136"), + []byte("48;5;137"), + []byte("48;5;138"), + []byte("48;5;139"), + []byte("48;5;140"), + []byte("48;5;141"), + []byte("48;5;142"), + []byte("48;5;143"), + []byte("48;5;144"), + []byte("48;5;145"), + []byte("48;5;146"), + []byte("48;5;147"), + []byte("48;5;148"), + []byte("48;5;149"), + []byte("48;5;150"), + []byte("48;5;151"), + []byte("48;5;152"), + []byte("48;5;153"), + []byte("48;5;154"), + []byte("48;5;155"), + []byte("48;5;156"), + []byte("48;5;157"), + []byte("48;5;158"), + []byte("48;5;159"), + []byte("48;5;160"), + []byte("48;5;161"), + []byte("48;5;162"), + []byte("48;5;163"), + []byte("48;5;164"), + []byte("48;5;165"), + []byte("48;5;166"), + []byte("48;5;167"), + []byte("48;5;168"), + []byte("48;5;169"), + []byte("48;5;170"), + []byte("48;5;171"), + []byte("48;5;172"), + []byte("48;5;173"), + []byte("48;5;174"), + []byte("48;5;175"), + []byte("48;5;176"), + []byte("48;5;177"), + []byte("48;5;178"), + []byte("48;5;179"), + []byte("48;5;180"), + []byte("48;5;181"), + []byte("48;5;182"), + []byte("48;5;183"), + []byte("48;5;184"), + []byte("48;5;185"), + []byte("48;5;186"), + []byte("48;5;187"), + []byte("48;5;188"), + []byte("48;5;189"), + []byte("48;5;190"), + []byte("48;5;191"), + []byte("48;5;192"), + []byte("48;5;193"), + []byte("48;5;194"), + []byte("48;5;195"), + []byte("48;5;196"), + []byte("48;5;197"), + []byte("48;5;198"), + []byte("48;5;199"), + []byte("48;5;200"), + []byte("48;5;201"), + []byte("48;5;202"), + []byte("48;5;203"), + []byte("48;5;204"), + []byte("48;5;205"), + []byte("48;5;206"), + []byte("48;5;207"), + []byte("48;5;208"), + []byte("48;5;209"), + []byte("48;5;210"), + []byte("48;5;211"), + []byte("48;5;212"), + []byte("48;5;213"), + []byte("48;5;214"), + []byte("48;5;215"), + []byte("48;5;216"), + []byte("48;5;217"), + []byte("48;5;218"), + []byte("48;5;219"), + []byte("48;5;220"), + []byte("48;5;221"), + []byte("48;5;222"), + []byte("48;5;223"), + []byte("48;5;224"), + []byte("48;5;225"), + []byte("48;5;226"), + []byte("48;5;227"), + []byte("48;5;228"), + []byte("48;5;229"), + []byte("48;5;230"), + []byte("48;5;231"), + []byte("48;5;232"), + []byte("48;5;233"), + []byte("48;5;234"), + []byte("48;5;235"), + []byte("48;5;236"), + []byte("48;5;237"), + []byte("48;5;238"), + []byte("48;5;239"), + []byte("48;5;240"), + []byte("48;5;241"), + []byte("48;5;242"), + []byte("48;5;243"), + []byte("48;5;244"), + []byte("48;5;245"), + []byte("48;5;246"), + []byte("48;5;247"), + []byte("48;5;248"), + []byte("48;5;249"), + []byte("48;5;250"), + []byte("48;5;251"), + []byte("48;5;252"), + []byte("48;5;253"), + []byte("48;5;254"), + []byte("48;5;255"), } diff --git a/Godeps/_workspace/src/github.com/aybabtme/rgbterm/rainbow/rainbow.go b/Godeps/_workspace/src/github.com/aybabtme/rgbterm/rainbow/rainbow.go index 38e6d54b..aafc7d97 100644 --- a/Godeps/_workspace/src/github.com/aybabtme/rgbterm/rainbow/rainbow.go +++ b/Godeps/_workspace/src/github.com/aybabtme/rgbterm/rainbow/rainbow.go @@ -30,8 +30,14 @@ func (r *Rainbow) Write(p []byte) (int, error) { if r.h > 1.0 { r.h = 0 } + r, g, b := rgbterm.HSLtoRGB(r.h, r.s, r.l) - _, _ = buf.Write(rgbterm.Byte(p[i], r, g, b)) + if p[i] != '\n' { + _, _ = buf.Write(rgbterm.FgByte(p[i], r, g, b)) + } else { + buf.Write([]byte{p[i]}) + } + } _, err := buf.WriteTo(r.wrap) diff --git a/Godeps/_workspace/src/github.com/aybabtme/rgbterm/rgbterm.go b/Godeps/_workspace/src/github.com/aybabtme/rgbterm/rgbterm.go index 4409e4a5..2cbb4d20 100644 --- a/Godeps/_workspace/src/github.com/aybabtme/rgbterm/rgbterm.go +++ b/Godeps/_workspace/src/github.com/aybabtme/rgbterm/rgbterm.go @@ -24,6 +24,8 @@ package rgbterm var ( + before = []byte("\033[") + after = []byte("m") reset = []byte("\033[0;00m") fgcolors = fgTermRGB[16:232] bgcolors = bgTermRGB[16:232] @@ -33,8 +35,16 @@ var ( // the closest the RGB color. // // This is simply a helper for Bytes. -func String(in string, r, g, b uint8) string { - return string(Bytes([]byte(in), r, g, b)) +func String(in string, fr, fg, fb, br, bg, bb uint8) string { + return string(Bytes([]byte(in), fr, fg, fb, br, bg, bb)) +} + +// FgString colorizes the foreground of the input with the terminal color +// that matches the closest the RGB color. +// +// This is simply a helper for Bytes. +func FgString(in string, r, g, b uint8) string { + return string(FgBytes([]byte(in), r, g, b)) } // BgString colorizes the background of the input with the terminal color @@ -47,29 +57,45 @@ func BgString(in string, r, g, b uint8) string { // Bytes colorizes the input with the terminal color that matches // the closest the RGB color. -func Bytes(in []byte, r, g, b uint8) []byte { - return append(append(rgb(r, g, b, true), in...), reset...) +func Bytes(in []byte, fr, fg, fb, br, bg, bb uint8) []byte { + return colorize(rgb(fr, fg, fb, br, bg, bb), in) +} + +// Bytes colorizes the foreground with the terminal color that matches +// the closest the RGB color. +func FgBytes(in []byte, r, g, b uint8) []byte { + return colorize(color(r, g, b, true), in) } // BgBytes colorizes the background of the input with the terminal color // that matches the closest the RGB color. func BgBytes(in []byte, r, g, b uint8) []byte { - return append(append(rgb(r, g, b, false), in...), reset...) + return colorize(color(r, g, b, false), in) } // Byte colorizes the input with the terminal color that matches // the closest the RGB color. -func Byte(in byte, r, g, b uint8) []byte { - return append(append(rgb(r, g, b, true), in), reset...) +func FgByte(in byte, r, g, b uint8) []byte { + return colorize(color(r, g, b, true), []byte{in}) } // BgByte colorizes the background of the input with the terminal color // that matches the closest the RGB color. func BgByte(in byte, r, g, b uint8) []byte { - return append(append(rgb(r, g, b, false), in), reset...) + return colorize(color(r, g, b, false), []byte{in}) +} + +func colorize(color, in []byte) []byte { + return append(append(append(append(before, color...), after...), in...), reset...) +} + +func rgb(fr, fg, fb, br, bg, bb uint8) []byte { + fore := append(color(fr, fg, fb, true), byte(';')) + back := color(br, bg, bb, false) + return append(fore, back...) } -func rgb(r, g, b uint8, foreground bool) []byte { +func color(r, g, b uint8, foreground bool) []byte { // if all colors are equal, it might be in the grayscale range if r == g && g == b { color, ok := grayscale(r, foreground) diff --git a/Godeps/_workspace/src/github.com/aybabtme/rgbterm/rgbterm_test.go b/Godeps/_workspace/src/github.com/aybabtme/rgbterm/rgbterm_test.go index df629ea2..b77b2b97 100644 --- a/Godeps/_workspace/src/github.com/aybabtme/rgbterm/rgbterm_test.go +++ b/Godeps/_workspace/src/github.com/aybabtme/rgbterm/rgbterm_test.go @@ -15,12 +15,31 @@ func ExampleBytes() { h = 0.0 } r, g, b := rgbterm.HSLtoRGB(h, s, l) - fmt.Printf("%s", rgbterm.Bytes(data, r, g, b)) + fmt.Printf("%s", rgbterm.Bytes(data, r, g, b, 0, 0, 0)) //b, g, r)) } fmt.Println() // Output: - // ████████████████████████████████████████████████████████████████████████████████ + // ████████████████████████████████████████████████████████████████████████████████ + +} + +func ExampleBgBytes() { + data := []byte(" ") + + h, s, l := rgbterm.RGBtoHSL(252, 255, 43) + for i := 0; i < 80; i++ { + h += (5.0 / 360.0) + if h > 1.0 { + h = 0.0 + } + r, g, b := rgbterm.HSLtoRGB(h, s, l) + fmt.Printf("%s", rgbterm.BgBytes(data, r, g, b)) //b, g, r)) + } + fmt.Println() + + // Output: + //                                                                                  } @@ -31,10 +50,10 @@ func ExampleString() { // choose a word word := "=)" // colorize it! - coloredWord := rgbterm.String(word, r, g, b) + coloredWord := rgbterm.String(word, r, g, b, 0, 0, 0) fmt.Println("Oh!", coloredWord, "hello!") // Output: - // Oh! =) hello! + // Oh! =) hello! } diff --git a/Godeps/_workspace/src/github.com/codegangsta/cli/README.md b/Godeps/_workspace/src/github.com/codegangsta/cli/README.md index 5c83df6c..4b3ddb0a 100644 --- a/Godeps/_workspace/src/github.com/codegangsta/cli/README.md +++ b/Godeps/_workspace/src/github.com/codegangsta/cli/README.md @@ -68,8 +68,9 @@ Running this already gives you a ton of functionality, plus support for things l Being a programmer can be a lonely job. Thankfully by the power of automation that is not the case! Let's create a greeter app to fend off our demons of loneliness! +Start by creating a directory named `greet`, and within it, add a file, `greet.go` with the following code in it: + ``` go -/* greet.go */ package main import ( @@ -84,7 +85,7 @@ func main() { app.Action = func(c *cli.Context) { println("Hello friend!") } - + app.Run(os.Args) } ``` @@ -171,6 +172,8 @@ app.Flags = []cli.Flag { } ``` +That flag can then be set with `--lang spanish` or `-l spanish`. Note that giving two different forms of the same flag in the same command invocation is an error. + #### Values from the Environment You can also have the default value set from the environment via `EnvVar`. e.g. @@ -186,7 +189,18 @@ app.Flags = []cli.Flag { } ``` -That flag can then be set with `--lang spanish` or `-l spanish`. Note that giving two different forms of the same flag in the same command invocation is an error. +The `EnvVar` may also be given as a comma-delimited "cascade", where the first environment variable that resolves is used as the default. + +``` go +app.Flags = []cli.Flag { + cli.StringFlag{ + Name: "lang, l", + Value: "english", + Usage: "language for the greeting", + EnvVar: "LEGACY_COMPAT_LANG,APP_LANG,LANG", + }, +} +``` ### Subcommands @@ -196,7 +210,7 @@ Subcommands can be defined for a more git-like command line app. app.Commands = []cli.Command{ { Name: "add", - ShortName: "a", + Aliases: []string{"a"}, Usage: "add a task to the list", Action: func(c *cli.Context) { println("added task: ", c.Args().First()) @@ -204,7 +218,7 @@ app.Commands = []cli.Command{ }, { Name: "complete", - ShortName: "c", + Aliases: []string{"c"}, Usage: "complete a task on the list", Action: func(c *cli.Context) { println("completed task: ", c.Args().First()) @@ -212,7 +226,7 @@ app.Commands = []cli.Command{ }, { Name: "template", - ShortName: "r", + Aliases: []string{"r"}, Usage: "options for task templates", Subcommands: []cli.Command{ { @@ -230,7 +244,7 @@ app.Commands = []cli.Command{ }, }, }, - }, + }, } ... ``` @@ -248,8 +262,8 @@ app := cli.NewApp() app.EnableBashCompletion = true app.Commands = []cli.Command{ { - Name: "complete", - ShortName: "c", + Name: "complete", + Aliases: []string{"c"}, Usage: "complete a task on the list", Action: func(c *cli.Context) { println("completed task: ", c.Args().First()) @@ -260,7 +274,7 @@ app.Commands = []cli.Command{ return } for _, t := range tasks { - println(t) + fmt.Println(t) } }, } @@ -279,9 +293,6 @@ setting the `PROG` variable to the name of your program: ## Contribution Guidelines Feel free to put up a pull request to fix a bug or maybe add a feature. I will give it a code review and make sure that it does not break backwards compatibility. If I or any other collaborators agree that it is in line with the vision of the project, we will work with you to get the code into a mergeable state and merge it into the master branch. -If you are have contributed something significant to the project, I will most likely add you as a collaborator. As a collaborator you are given the ability to merge others pull requests. It is very important that new code does not break existing code, so be careful about what code you do choose to merge. If you have any questions feel free to link @codegangsta to the issue in question and we can review it together. +If you have contributed something significant to the project, I will most likely add you as a collaborator. As a collaborator you are given the ability to merge others pull requests. It is very important that new code does not break existing code, so be careful about what code you do choose to merge. If you have any questions feel free to link @codegangsta to the issue in question and we can review it together. If you feel like you have contributed to the project but have not yet been added as a collaborator, I probably forgot to add you. Hit @codegangsta up over email and we will get it figured out. - -## About -cli.go is written by none other than the [Code Gangsta](http://codegangsta.io) diff --git a/Godeps/_workspace/src/github.com/codegangsta/cli/app.go b/Godeps/_workspace/src/github.com/codegangsta/cli/app.go index 66e541c7..cd290051 100644 --- a/Godeps/_workspace/src/github.com/codegangsta/cli/app.go +++ b/Godeps/_workspace/src/github.com/codegangsta/cli/app.go @@ -2,8 +2,12 @@ package cli import ( "fmt" + "io" "io/ioutil" "os" + "strings" + "text/tabwriter" + "text/template" "time" ) @@ -24,21 +28,30 @@ type App struct { EnableBashCompletion bool // Boolean to hide built-in help command HideHelp bool + // Boolean to hide built-in version flag + HideVersion bool // An action to execute when the bash-completion flag is set BashComplete func(context *Context) // An action to execute before any subcommands are run, but after the context is ready // If a non-nil error is returned, no subcommands are run Before func(context *Context) error + // An action to execute after any subcommands are run, but after the subcommand has finished + // It is run even if Action() panics + After func(context *Context) error // The action to execute when no subcommands are specified Action func(context *Context) // Execute this function if the proper command cannot be found CommandNotFound func(context *Context, command string) // Compilation date Compiled time.Time - // Author + // List of all authors who contributed + Authors []Author + // Name of Author (Note: Use App.Authors, this is deprecated) Author string - // Author e-mail + // Email of Author (Note: Use App.Authors, this is deprecated) Email string + // Writer writer to write output to + Writer io.Writer } // Tries to find out when this binary was compiled. @@ -60,41 +73,71 @@ func NewApp() *App { BashComplete: DefaultAppComplete, Action: helpCommand.Action, Compiled: compileTime(), + Writer: os.Stdout, } } // Entry point to the cli app. Parses the arguments slice and routes to the proper flag/args combination -func (a *App) Run(arguments []string) error { +func (a *App) Run(arguments []string) (err error) { + if a.Author != "" || a.Email != "" { + a.Authors = append(a.Authors, Author{Name: a.Author, Email: a.Email}) + } + + if HelpPrinter == nil { + defer func() { + HelpPrinter = nil + }() + + HelpPrinter = func(templ string, data interface{}) { + funcMap := template.FuncMap{ + "join": strings.Join, + } + + w := tabwriter.NewWriter(a.Writer, 0, 8, 1, '\t', 0) + t := template.Must(template.New("help").Funcs(funcMap).Parse(templ)) + err := t.Execute(w, data) + if err != nil { + panic(err) + } + w.Flush() + } + } + // append help to commands if a.Command(helpCommand.Name) == nil && !a.HideHelp { a.Commands = append(a.Commands, helpCommand) - a.appendFlag(HelpFlag) + if (HelpFlag != BoolFlag{}) { + a.appendFlag(HelpFlag) + } } //append version/help flags if a.EnableBashCompletion { a.appendFlag(BashCompletionFlag) } - a.appendFlag(VersionFlag) + + if !a.HideVersion { + a.appendFlag(VersionFlag) + } // parse flags set := flagSet(a.Name, a.Flags) set.SetOutput(ioutil.Discard) - err := set.Parse(arguments[1:]) + err = set.Parse(arguments[1:]) nerr := normalizeFlags(a.Flags, set) if nerr != nil { - fmt.Println(nerr) + fmt.Fprintln(a.Writer, nerr) context := NewContext(a, set, set) ShowAppHelp(context) - fmt.Println("") + fmt.Fprintln(a.Writer) return nerr } context := NewContext(a, set, set) if err != nil { - fmt.Printf("Incorrect Usage.\n\n") + fmt.Fprintf(a.Writer, "Incorrect Usage.\n\n") ShowAppHelp(context) - fmt.Println("") + fmt.Fprintln(a.Writer) return err } @@ -110,6 +153,15 @@ func (a *App) Run(arguments []string) error { return nil } + if a.After != nil { + defer func() { + // err is always nil here. + // There is a check to see if it is non-nil + // just few lines before. + err = a.After(context) + }() + } + if a.Before != nil { err := a.Before(context) if err != nil { @@ -134,18 +186,20 @@ func (a *App) Run(arguments []string) error { // Another entry point to the cli app, takes care of passing arguments and error handling func (a *App) RunAndExitOnError() { if err := a.Run(os.Args); err != nil { - os.Stderr.WriteString(fmt.Sprintln(err)) + fmt.Fprintln(os.Stderr, err) os.Exit(1) } } // Invokes the subcommand given the context, parses ctx.Args() to generate command-specific flags -func (a *App) RunAsSubcommand(ctx *Context) error { +func (a *App) RunAsSubcommand(ctx *Context) (err error) { // append help to commands if len(a.Commands) > 0 { if a.Command(helpCommand.Name) == nil && !a.HideHelp { a.Commands = append(a.Commands, helpCommand) - a.appendFlag(HelpFlag) + if (HelpFlag != BoolFlag{}) { + a.appendFlag(HelpFlag) + } } } @@ -157,23 +211,23 @@ func (a *App) RunAsSubcommand(ctx *Context) error { // parse flags set := flagSet(a.Name, a.Flags) set.SetOutput(ioutil.Discard) - err := set.Parse(ctx.Args().Tail()) + err = set.Parse(ctx.Args().Tail()) nerr := normalizeFlags(a.Flags, set) context := NewContext(a, set, ctx.globalSet) if nerr != nil { - fmt.Println(nerr) + fmt.Fprintln(a.Writer, nerr) if len(a.Commands) > 0 { ShowSubcommandHelp(context) } else { ShowCommandHelp(ctx, context.Args().First()) } - fmt.Println("") + fmt.Fprintln(a.Writer) return nerr } if err != nil { - fmt.Printf("Incorrect Usage.\n\n") + fmt.Fprintf(a.Writer, "Incorrect Usage.\n\n") ShowSubcommandHelp(context) return err } @@ -192,6 +246,15 @@ func (a *App) RunAsSubcommand(ctx *Context) error { } } + if a.After != nil { + defer func() { + // err is always nil here. + // There is a check to see if it is non-nil + // just few lines before. + err = a.After(context) + }() + } + if a.Before != nil { err := a.Before(context) if err != nil { @@ -209,11 +272,7 @@ func (a *App) RunAsSubcommand(ctx *Context) error { } // Run default Action - if len(a.Commands) > 0 { - a.Action(context) - } else { - a.Action(ctx) - } + a.Action(context) return nil } @@ -244,3 +303,19 @@ func (a *App) appendFlag(flag Flag) { a.Flags = append(a.Flags, flag) } } + +// Author represents someone who has contributed to a cli project. +type Author struct { + Name string // The Authors name + Email string // The Authors email +} + +// String makes Author comply to the Stringer interface, to allow an easy print in the templating process +func (a Author) String() string { + e := "" + if a.Email != "" { + e = "<" + a.Email + "> " + } + + return fmt.Sprintf("%v %v", a.Name, e) +} diff --git a/Godeps/_workspace/src/github.com/codegangsta/cli/app_test.go b/Godeps/_workspace/src/github.com/codegangsta/cli/app_test.go index 81d11743..4a40b89c 100644 --- a/Godeps/_workspace/src/github.com/codegangsta/cli/app_test.go +++ b/Godeps/_workspace/src/github.com/codegangsta/cli/app_test.go @@ -1,6 +1,7 @@ package cli_test import ( + "flag" "fmt" "os" "testing" @@ -20,6 +21,9 @@ func ExampleApp() { app.Action = func(c *cli.Context) { fmt.Printf("Hello %v\n", c.String("name")) } + app.Author = "Harrison" + app.Email = "harrison@lolwut.com" + app.Authors = []cli.Author{cli.Author{Name: "Oliver Allen", Email: "oliver@toyshop.com"}} app.Run(os.Args) // Output: // Hello Jeremy @@ -33,13 +37,13 @@ func ExampleAppSubcommand() { app.Commands = []cli.Command{ { Name: "hello", - ShortName: "hi", + Aliases: []string{"hi"}, Usage: "use it to see a description", Description: "This is how we describe hello the function", Subcommands: []cli.Command{ { Name: "english", - ShortName: "en", + Aliases: []string{"en"}, Usage: "sends a greeting in english", Description: "greets someone in english", Flags: []cli.Flag{ @@ -74,7 +78,7 @@ func ExampleAppHelp() { app.Commands = []cli.Command{ { Name: "describeit", - ShortName: "d", + Aliases: []string{"d"}, Usage: "use it to see a description", Description: "This is how we describe describeit the function", Action: func(c *cli.Context) { @@ -104,7 +108,7 @@ func ExampleAppBashComplete() { app.Commands = []cli.Command{ { Name: "describeit", - ShortName: "d", + Aliases: []string{"d"}, Usage: "use it to see a description", Description: "This is how we describe describeit the function", Action: func(c *cli.Context) { @@ -158,8 +162,8 @@ var commandAppTests = []struct { func TestApp_Command(t *testing.T) { app := cli.NewApp() - fooCommand := cli.Command{Name: "foobar", ShortName: "f"} - batCommand := cli.Command{Name: "batbaz", ShortName: "b"} + fooCommand := cli.Command{Name: "foobar", Aliases: []string{"f"}} + batCommand := cli.Command{Name: "batbaz", Aliases: []string{"b"}} app.Commands = []cli.Command{ fooCommand, batCommand, @@ -192,6 +196,76 @@ func TestApp_CommandWithArgBeforeFlags(t *testing.T) { expect(t, firstArg, "my-arg") } +func TestApp_RunAsSubcommandParseFlags(t *testing.T) { + var context *cli.Context + + a := cli.NewApp() + a.Commands = []cli.Command{ + { + Name: "foo", + Action: func(c *cli.Context) { + context = c + }, + Flags: []cli.Flag{ + cli.StringFlag{ + Name: "lang", + Value: "english", + Usage: "language for the greeting", + }, + }, + Before: func(_ *cli.Context) error { return nil }, + }, + } + a.Run([]string{"", "foo", "--lang", "spanish", "abcd"}) + + expect(t, context.Args().Get(0), "abcd") + expect(t, context.String("lang"), "spanish") +} + +func TestApp_CommandWithFlagBeforeTerminator(t *testing.T) { + var parsedOption string + var args []string + + app := cli.NewApp() + command := cli.Command{ + Name: "cmd", + Flags: []cli.Flag{ + cli.StringFlag{Name: "option", Value: "", Usage: "some option"}, + }, + Action: func(c *cli.Context) { + parsedOption = c.String("option") + args = c.Args() + }, + } + app.Commands = []cli.Command{command} + + app.Run([]string{"", "cmd", "my-arg", "--option", "my-option", "--", "--notARealFlag"}) + + expect(t, parsedOption, "my-option") + expect(t, args[0], "my-arg") + expect(t, args[1], "--") + expect(t, args[2], "--notARealFlag") +} + +func TestApp_CommandWithNoFlagBeforeTerminator(t *testing.T) { + var args []string + + app := cli.NewApp() + command := cli.Command{ + Name: "cmd", + Action: func(c *cli.Context) { + args = c.Args() + }, + } + app.Commands = []cli.Command{command} + + app.Run([]string{"", "cmd", "my-arg", "--", "notAFlagAtAll"}) + + expect(t, args[0], "my-arg") + expect(t, args[1], "--") + expect(t, args[2], "notAFlagAtAll") +} + func TestApp_Float64Flag(t *testing.T) { var meters float64 @@ -265,6 +339,50 @@ func TestApp_ParseSliceFlags(t *testing.T) { } } +func TestApp_DefaultStdout(t *testing.T) { + app := cli.NewApp() + + if app.Writer != os.Stdout { + t.Error("Default output writer not set.") + } +} + +type mockWriter struct { + written []byte +} + +func (fw *mockWriter) Write(p []byte) (n int, err error) { + if fw.written == nil { + fw.written = p + } else { + fw.written = append(fw.written, p...) + } + + return len(p), nil +} + +func (fw *mockWriter) GetWritten() (b []byte) { + return fw.written +} + +func TestApp_SetStdout(t *testing.T) { + w := &mockWriter{} + + app := cli.NewApp() + app.Name = "test" + app.Writer = w + + err := app.Run([]string{"help"}) + + if err != nil { + t.Fatalf("Run error: %s", err) + } + + if len(w.written) == 0 { + t.Error("App did not write output to desired writer.") + } +} + func TestApp_BeforeFunc(t *testing.T) { beforeRun, subcommandRun := false, false beforeError := fmt.Errorf("fail") @@ -331,6 +449,87 @@ func TestApp_BeforeFunc(t *testing.T) { } +func TestApp_AfterFunc(t *testing.T) { + afterRun, subcommandRun := false, false + afterError := fmt.Errorf("fail") + var err error + + app := cli.NewApp() + + app.After = func(c *cli.Context) error { + afterRun = true + s := c.String("opt") + if s == "fail" { + return afterError + } + + return nil + } + + app.Commands = []cli.Command{ + cli.Command{ + Name: "sub", + Action: func(c *cli.Context) { + subcommandRun = true + }, + }, + } + + app.Flags = []cli.Flag{ + cli.StringFlag{Name: "opt"}, + } + + // run with the After() func succeeding + err = app.Run([]string{"command", "--opt", "succeed", "sub"}) + + if err != nil { + t.Fatalf("Run error: %s", err) + } + + if afterRun == false { + t.Errorf("After() not executed when expected") + } + + if subcommandRun == false { + t.Errorf("Subcommand not executed when expected") + } + + // reset + afterRun, subcommandRun = false, false + + // run with the Before() func failing + err = app.Run([]string{"command", "--opt", "fail", "sub"}) + + // should be the same error produced by the Before func + if err != afterError { + t.Errorf("Run error expected, but not received") + } + + if afterRun == false { + t.Errorf("After() not executed when expected") + } + + if subcommandRun == false { + t.Errorf("Subcommand not executed when expected") + } +} + +func TestAppNoHelpFlag(t *testing.T) { + oldFlag := cli.HelpFlag + defer func() { + cli.HelpFlag = oldFlag + }() + + cli.HelpFlag = cli.BoolFlag{} + + app := cli.NewApp() + err := app.Run([]string{"test", "-h"}) + + if err != flag.ErrHelp { + t.Errorf("expected error about missing help flag, but got: %s (%T)", err, err) + } +} + func TestAppHelpPrinter(t *testing.T) { oldPrinter := cli.HelpPrinter defer func() { diff --git a/Godeps/_workspace/src/github.com/codegangsta/cli/cli_test.go b/Godeps/_workspace/src/github.com/codegangsta/cli/cli_test.go index 879a793d..8a8df973 100644 --- a/Godeps/_workspace/src/github.com/codegangsta/cli/cli_test.go +++ b/Godeps/_workspace/src/github.com/codegangsta/cli/cli_test.go @@ -12,17 +12,17 @@ func Example() { app.Usage = "task list on the command line" app.Commands = []cli.Command{ { - Name: "add", - ShortName: "a", - Usage: "add a task to the list", + Name: "add", + Aliases: []string{"a"}, + Usage: "add a task to the list", Action: func(c *cli.Context) { println("added task: ", c.Args().First()) }, }, { - Name: "complete", - ShortName: "c", - Usage: "complete a task on the list", + Name: "complete", + Aliases: []string{"c"}, + Usage: "complete a task on the list", Action: func(c *cli.Context) { println("completed task: ", c.Args().First()) }, @@ -38,13 +38,13 @@ func ExampleSubcommand() { app.Commands = []cli.Command{ { Name: "hello", - ShortName: "hi", + Aliases: []string{"hi"}, Usage: "use it to see a description", Description: "This is how we describe hello the function", Subcommands: []cli.Command{ { Name: "english", - ShortName: "en", + Aliases: []string{"en"}, Usage: "sends a greeting in english", Description: "greets someone in english", Flags: []cli.Flag{ @@ -58,9 +58,9 @@ func ExampleSubcommand() { println("Hello, ", c.String("name")) }, }, { - Name: "spanish", - ShortName: "sp", - Usage: "sends a greeting in spanish", + Name: "spanish", + Aliases: []string{"sp"}, + Usage: "sends a greeting in spanish", Flags: []cli.Flag{ cli.StringFlag{ Name: "surname", @@ -72,9 +72,9 @@ func ExampleSubcommand() { println("Hola, ", c.String("surname")) }, }, { - Name: "french", - ShortName: "fr", - Usage: "sends a greeting in french", + Name: "french", + Aliases: []string{"fr"}, + Usage: "sends a greeting in french", Flags: []cli.Flag{ cli.StringFlag{ Name: "nickname", diff --git a/Godeps/_workspace/src/github.com/codegangsta/cli/command.go b/Godeps/_workspace/src/github.com/codegangsta/cli/command.go index 5622b38f..b61691c8 100644 --- a/Godeps/_workspace/src/github.com/codegangsta/cli/command.go +++ b/Godeps/_workspace/src/github.com/codegangsta/cli/command.go @@ -10,8 +10,10 @@ import ( type Command struct { // The name of the command Name string - // short name of the command. Typically one character + // short name of the command. Typically one character (deprecated, use `Aliases`) ShortName string + // A list of aliases for the command + Aliases []string // A short description of the usage of this command Usage string // A longer explanation of how the command works @@ -21,6 +23,9 @@ type Command struct { // An action to execute before any sub-subcommands are run, but after the context is ready // If a non-nil error is returned, no sub-subcommands are run Before func(context *Context) error + // An action to execute after any subcommands are run, but after the subcommand has finished + // It is run even if Action() panics + After func(context *Context) error // The function to call when this command is invoked Action func(context *Context) // List of child commands @@ -36,11 +41,11 @@ type Command struct { // Invokes the command given the context, parses ctx.Args() to generate command-specific flags func (c Command) Run(ctx *Context) error { - if len(c.Subcommands) > 0 || c.Before != nil { + if len(c.Subcommands) > 0 || c.Before != nil || c.After != nil { return c.startApp(ctx) } - if !c.HideHelp { + if !c.HideHelp && (HelpFlag != BoolFlag{}) { // append help to flags c.Flags = append( c.Flags, @@ -56,36 +61,48 @@ func (c Command) Run(ctx *Context) error { set.SetOutput(ioutil.Discard) firstFlagIndex := -1 + terminatorIndex := -1 for index, arg := range ctx.Args() { - if strings.HasPrefix(arg, "-") { - firstFlagIndex = index + if arg == "--" { + terminatorIndex = index break + } else if strings.HasPrefix(arg, "-") && firstFlagIndex == -1 { + firstFlagIndex = index } } var err error if firstFlagIndex > -1 && !c.SkipFlagParsing { args := ctx.Args() - regularArgs := args[1:firstFlagIndex] - flagArgs := args[firstFlagIndex:] + regularArgs := make([]string, len(args[1:firstFlagIndex])) + copy(regularArgs, args[1:firstFlagIndex]) + + var flagArgs []string + if terminatorIndex > -1 { + flagArgs = args[firstFlagIndex:terminatorIndex] + regularArgs = append(regularArgs, args[terminatorIndex:]...) + } else { + flagArgs = args[firstFlagIndex:] + } + err = set.Parse(append(flagArgs, regularArgs...)) } else { err = set.Parse(ctx.Args().Tail()) } if err != nil { - fmt.Printf("Incorrect Usage.\n\n") + fmt.Fprint(ctx.App.Writer, "Incorrect Usage.\n\n") ShowCommandHelp(ctx, c.Name) - fmt.Println("") + fmt.Fprintln(ctx.App.Writer) return err } nerr := normalizeFlags(c.Flags, set) if nerr != nil { - fmt.Println(nerr) - fmt.Println("") + fmt.Fprintln(ctx.App.Writer, nerr) + fmt.Fprintln(ctx.App.Writer) ShowCommandHelp(ctx, c.Name) - fmt.Println("") + fmt.Fprintln(ctx.App.Writer) return nerr } context := NewContext(ctx.App, set, ctx.globalSet) @@ -102,9 +119,24 @@ func (c Command) Run(ctx *Context) error { return nil } +func (c Command) Names() []string { + names := []string{c.Name} + + if c.ShortName != "" { + names = append(names, c.ShortName) + } + + return append(names, c.Aliases...) +} + // Returns true if Command.Name or Command.ShortName matches given name func (c Command) HasName(name string) bool { - return c.Name == name || c.ShortName == name + for _, n := range c.Names() { + if n == name { + return true + } + } + return false } func (c Command) startApp(ctx *Context) error { @@ -134,6 +166,7 @@ func (c Command) startApp(ctx *Context) error { // set the actions app.Before = c.Before + app.After = c.After if c.Action != nil { app.Action = c.Action } else { diff --git a/Godeps/_workspace/src/github.com/codegangsta/cli/command_test.go b/Godeps/_workspace/src/github.com/codegangsta/cli/command_test.go index c0f556ad..4125b0c1 100644 --- a/Godeps/_workspace/src/github.com/codegangsta/cli/command_test.go +++ b/Godeps/_workspace/src/github.com/codegangsta/cli/command_test.go @@ -17,7 +17,7 @@ func TestCommandDoNotIgnoreFlags(t *testing.T) { command := cli.Command{ Name: "test-cmd", - ShortName: "tc", + Aliases: []string{"tc"}, Usage: "this is for testing", Description: "testing", Action: func(_ *cli.Context) {}, @@ -37,7 +37,7 @@ func TestCommandIgnoreFlags(t *testing.T) { command := cli.Command{ Name: "test-cmd", - ShortName: "tc", + Aliases: []string{"tc"}, Usage: "this is for testing", Description: "testing", Action: func(_ *cli.Context) {}, diff --git a/Godeps/_workspace/src/github.com/codegangsta/cli/context.go b/Godeps/_workspace/src/github.com/codegangsta/cli/context.go index 8b44148e..37221bdc 100644 --- a/Godeps/_workspace/src/github.com/codegangsta/cli/context.go +++ b/Godeps/_workspace/src/github.com/codegangsta/cli/context.go @@ -13,11 +13,12 @@ import ( // can be used to retrieve context-specific Args and // parsed command-line options. type Context struct { - App *App - Command Command - flagSet *flag.FlagSet - globalSet *flag.FlagSet - setFlags map[string]bool + App *App + Command Command + flagSet *flag.FlagSet + globalSet *flag.FlagSet + setFlags map[string]bool + globalSetFlags map[string]bool } // Creates a new context. For use in when invoking an App or Command action. @@ -105,7 +106,12 @@ func (c *Context) GlobalGeneric(name string) interface{} { return lookupGeneric(name, c.globalSet) } -// Determines if the flag was actually set exists +// Returns the number of flags set +func (c *Context) NumFlags() int { + return c.flagSet.NFlag() +} + +// Determines if the flag was actually set func (c *Context) IsSet(name string) bool { if c.setFlags == nil { c.setFlags = make(map[string]bool) @@ -116,6 +122,17 @@ func (c *Context) IsSet(name string) bool { return c.setFlags[name] == true } +// Determines if the global flag was actually set +func (c *Context) GlobalIsSet(name string) bool { + if c.globalSetFlags == nil { + c.globalSetFlags = make(map[string]bool) + c.globalSet.Visit(func(f *flag.Flag) { + c.globalSetFlags[f.Name] = true + }) + } + return c.globalSetFlags[name] == true +} + // Returns a slice of flag names used in this context. func (c *Context) FlagNames() (names []string) { for _, flag := range c.Command.Flags { @@ -128,6 +145,18 @@ func (c *Context) FlagNames() (names []string) { return } +// Returns a slice of global flag names used by the app. +func (c *Context) GlobalFlagNames() (names []string) { + for _, flag := range c.App.Flags { + name := strings.Split(flag.getName(), ",")[0] + if name == "help" || name == "version" { + continue + } + names = append(names, name) + } + return +} + type Args []string // Returns the command line arguments associated with the context. diff --git a/Godeps/_workspace/src/github.com/codegangsta/cli/context_test.go b/Godeps/_workspace/src/github.com/codegangsta/cli/context_test.go index b2d24121..d4a1877f 100644 --- a/Godeps/_workspace/src/github.com/codegangsta/cli/context_test.go +++ b/Godeps/_workspace/src/github.com/codegangsta/cli/context_test.go @@ -69,9 +69,43 @@ func TestContext_IsSet(t *testing.T) { set := flag.NewFlagSet("test", 0) set.Bool("myflag", false, "doc") set.String("otherflag", "hello world", "doc") - c := cli.NewContext(nil, set, set) + globalSet := flag.NewFlagSet("test", 0) + globalSet.Bool("myflagGlobal", true, "doc") + c := cli.NewContext(nil, set, globalSet) set.Parse([]string{"--myflag", "bat", "baz"}) + globalSet.Parse([]string{"--myflagGlobal", "bat", "baz"}) expect(t, c.IsSet("myflag"), true) expect(t, c.IsSet("otherflag"), false) expect(t, c.IsSet("bogusflag"), false) + expect(t, c.IsSet("myflagGlobal"), false) +} + +func TestContext_GlobalIsSet(t *testing.T) { + set := flag.NewFlagSet("test", 0) + set.Bool("myflag", false, "doc") + set.String("otherflag", "hello world", "doc") + globalSet := flag.NewFlagSet("test", 0) + globalSet.Bool("myflagGlobal", true, "doc") + globalSet.Bool("myflagGlobalUnset", true, "doc") + c := cli.NewContext(nil, set, globalSet) + set.Parse([]string{"--myflag", "bat", "baz"}) + globalSet.Parse([]string{"--myflagGlobal", "bat", "baz"}) + expect(t, c.GlobalIsSet("myflag"), false) + expect(t, c.GlobalIsSet("otherflag"), false) + expect(t, c.GlobalIsSet("bogusflag"), false) + expect(t, c.GlobalIsSet("myflagGlobal"), true) + expect(t, c.GlobalIsSet("myflagGlobalUnset"), false) + expect(t, c.GlobalIsSet("bogusGlobal"), false) +} + +func TestContext_NumFlags(t *testing.T) { + set := flag.NewFlagSet("test", 0) + set.Bool("myflag", false, "doc") + set.String("otherflag", "hello world", "doc") + globalSet := flag.NewFlagSet("test", 0) + globalSet.Bool("myflagGlobal", true, "doc") + c := cli.NewContext(nil, set, globalSet) + set.Parse([]string{"--myflag", "--otherflag=foo"}) + globalSet.Parse([]string{"--myflagGlobal"}) + expect(t, c.NumFlags(), 2) } diff --git a/Godeps/_workspace/src/github.com/codegangsta/cli/flag.go b/Godeps/_workspace/src/github.com/codegangsta/cli/flag.go index b30bca30..25115866 100644 --- a/Godeps/_workspace/src/github.com/codegangsta/cli/flag.go +++ b/Godeps/_workspace/src/github.com/codegangsta/cli/flag.go @@ -21,6 +21,8 @@ var VersionFlag = BoolFlag{ } // This flag prints the help for all commands and subcommands +// Set to the zero value (BoolFlag{}) to disable flag -- keeps subcommand +// unless HideHelp is set to true) var HelpFlag = BoolFlag{ Name: "help, h", Usage: "show help", @@ -67,15 +69,24 @@ type GenericFlag struct { EnvVar string } +// String returns the string representation of the generic flag to display the +// help text to the user (uses the String() method of the generic flag to show +// the value) func (f GenericFlag) String() string { - return withEnvHint(f.EnvVar, fmt.Sprintf("%s%s %v\t`%v` %s", prefixFor(f.Name), f.Name, f.Value, "-"+f.Name+" option -"+f.Name+" option", f.Usage)) + return withEnvHint(f.EnvVar, fmt.Sprintf("%s%s \"%v\"\t%v", prefixFor(f.Name), f.Name, f.Value, f.Usage)) } +// Apply takes the flagset and calls Set on the generic flag with the value +// provided by the user for parsing by the flag func (f GenericFlag) Apply(set *flag.FlagSet) { val := f.Value if f.EnvVar != "" { - if envVal := os.Getenv(f.EnvVar); envVal != "" { - val.Set(envVal) + for _, envVar := range strings.Split(f.EnvVar, ",") { + envVar = strings.TrimSpace(envVar) + if envVal := os.Getenv(envVar); envVal != "" { + val.Set(envVal) + break + } } } @@ -113,17 +124,22 @@ type StringSliceFlag struct { func (f StringSliceFlag) String() string { firstName := strings.Trim(strings.Split(f.Name, ",")[0], " ") pref := prefixFor(firstName) - return withEnvHint(f.EnvVar, fmt.Sprintf("%s '%v'\t%v", prefixedNames(f.Name), pref+firstName+" option "+pref+firstName+" option", f.Usage)) + return withEnvHint(f.EnvVar, fmt.Sprintf("%s [%v]\t%v", prefixedNames(f.Name), pref+firstName+" option "+pref+firstName+" option", f.Usage)) } func (f StringSliceFlag) Apply(set *flag.FlagSet) { if f.EnvVar != "" { - if envVal := os.Getenv(f.EnvVar); envVal != "" { - newVal := &StringSlice{} - for _, s := range strings.Split(envVal, ",") { - newVal.Set(s) + for _, envVar := range strings.Split(f.EnvVar, ",") { + envVar = strings.TrimSpace(envVar) + if envVal := os.Getenv(envVar); envVal != "" { + newVal := &StringSlice{} + for _, s := range strings.Split(envVal, ",") { + s = strings.TrimSpace(s) + newVal.Set(s) + } + f.Value = newVal + break } - f.Value = newVal } } @@ -167,20 +183,25 @@ type IntSliceFlag struct { func (f IntSliceFlag) String() string { firstName := strings.Trim(strings.Split(f.Name, ",")[0], " ") pref := prefixFor(firstName) - return withEnvHint(f.EnvVar, fmt.Sprintf("%s '%v'\t%v", prefixedNames(f.Name), pref+firstName+" option "+pref+firstName+" option", f.Usage)) + return withEnvHint(f.EnvVar, fmt.Sprintf("%s [%v]\t%v", prefixedNames(f.Name), pref+firstName+" option "+pref+firstName+" option", f.Usage)) } func (f IntSliceFlag) Apply(set *flag.FlagSet) { if f.EnvVar != "" { - if envVal := os.Getenv(f.EnvVar); envVal != "" { - newVal := &IntSlice{} - for _, s := range strings.Split(envVal, ",") { - err := newVal.Set(s) - if err != nil { - fmt.Fprintf(os.Stderr, err.Error()) + for _, envVar := range strings.Split(f.EnvVar, ",") { + envVar = strings.TrimSpace(envVar) + if envVal := os.Getenv(envVar); envVal != "" { + newVal := &IntSlice{} + for _, s := range strings.Split(envVal, ",") { + s = strings.TrimSpace(s) + err := newVal.Set(s) + if err != nil { + fmt.Fprintf(os.Stderr, err.Error()) + } } + f.Value = newVal + break } - f.Value = newVal } } @@ -206,10 +227,14 @@ func (f BoolFlag) String() string { func (f BoolFlag) Apply(set *flag.FlagSet) { val := false if f.EnvVar != "" { - if envVal := os.Getenv(f.EnvVar); envVal != "" { - envValBool, err := strconv.ParseBool(envVal) - if err == nil { - val = envValBool + for _, envVar := range strings.Split(f.EnvVar, ",") { + envVar = strings.TrimSpace(envVar) + if envVal := os.Getenv(envVar); envVal != "" { + envValBool, err := strconv.ParseBool(envVal) + if err == nil { + val = envValBool + } + break } } } @@ -236,10 +261,14 @@ func (f BoolTFlag) String() string { func (f BoolTFlag) Apply(set *flag.FlagSet) { val := true if f.EnvVar != "" { - if envVal := os.Getenv(f.EnvVar); envVal != "" { - envValBool, err := strconv.ParseBool(envVal) - if err == nil { - val = envValBool + for _, envVar := range strings.Split(f.EnvVar, ",") { + envVar = strings.TrimSpace(envVar) + if envVal := os.Getenv(envVar); envVal != "" { + envValBool, err := strconv.ParseBool(envVal) + if err == nil { + val = envValBool + break + } } } } @@ -265,7 +294,7 @@ func (f StringFlag) String() string { fmtString = "%s %v\t%v" if len(f.Value) > 0 { - fmtString = "%s '%v'\t%v" + fmtString = "%s \"%v\"\t%v" } else { fmtString = "%s %v\t%v" } @@ -275,8 +304,12 @@ func (f StringFlag) String() string { func (f StringFlag) Apply(set *flag.FlagSet) { if f.EnvVar != "" { - if envVal := os.Getenv(f.EnvVar); envVal != "" { - f.Value = envVal + for _, envVar := range strings.Split(f.EnvVar, ",") { + envVar = strings.TrimSpace(envVar) + if envVal := os.Getenv(envVar); envVal != "" { + f.Value = envVal + break + } } } @@ -297,15 +330,19 @@ type IntFlag struct { } func (f IntFlag) String() string { - return withEnvHint(f.EnvVar, fmt.Sprintf("%s '%v'\t%v", prefixedNames(f.Name), f.Value, f.Usage)) + return withEnvHint(f.EnvVar, fmt.Sprintf("%s \"%v\"\t%v", prefixedNames(f.Name), f.Value, f.Usage)) } func (f IntFlag) Apply(set *flag.FlagSet) { if f.EnvVar != "" { - if envVal := os.Getenv(f.EnvVar); envVal != "" { - envValInt, err := strconv.ParseUint(envVal, 10, 64) - if err == nil { - f.Value = int(envValInt) + for _, envVar := range strings.Split(f.EnvVar, ",") { + envVar = strings.TrimSpace(envVar) + if envVal := os.Getenv(envVar); envVal != "" { + envValInt, err := strconv.ParseInt(envVal, 0, 64) + if err == nil { + f.Value = int(envValInt) + break + } } } } @@ -327,15 +364,19 @@ type DurationFlag struct { } func (f DurationFlag) String() string { - return withEnvHint(f.EnvVar, fmt.Sprintf("%s '%v'\t%v", prefixedNames(f.Name), f.Value, f.Usage)) + return withEnvHint(f.EnvVar, fmt.Sprintf("%s \"%v\"\t%v", prefixedNames(f.Name), f.Value, f.Usage)) } func (f DurationFlag) Apply(set *flag.FlagSet) { if f.EnvVar != "" { - if envVal := os.Getenv(f.EnvVar); envVal != "" { - envValDuration, err := time.ParseDuration(envVal) - if err == nil { - f.Value = envValDuration + for _, envVar := range strings.Split(f.EnvVar, ",") { + envVar = strings.TrimSpace(envVar) + if envVal := os.Getenv(envVar); envVal != "" { + envValDuration, err := time.ParseDuration(envVal) + if err == nil { + f.Value = envValDuration + break + } } } } @@ -357,15 +398,18 @@ type Float64Flag struct { } func (f Float64Flag) String() string { - return withEnvHint(f.EnvVar, fmt.Sprintf("%s '%v'\t%v", prefixedNames(f.Name), f.Value, f.Usage)) + return withEnvHint(f.EnvVar, fmt.Sprintf("%s \"%v\"\t%v", prefixedNames(f.Name), f.Value, f.Usage)) } func (f Float64Flag) Apply(set *flag.FlagSet) { if f.EnvVar != "" { - if envVal := os.Getenv(f.EnvVar); envVal != "" { - envValFloat, err := strconv.ParseFloat(envVal, 10) - if err == nil { - f.Value = float64(envValFloat) + for _, envVar := range strings.Split(f.EnvVar, ",") { + envVar = strings.TrimSpace(envVar) + if envVal := os.Getenv(envVar); envVal != "" { + envValFloat, err := strconv.ParseFloat(envVal, 10) + if err == nil { + f.Value = float64(envValFloat) + } } } } @@ -404,7 +448,7 @@ func prefixedNames(fullName string) (prefixed string) { func withEnvHint(envVar, str string) string { envText := "" if envVar != "" { - envText = fmt.Sprintf(" [$%s]", envVar) + envText = fmt.Sprintf(" [$%s]", strings.Join(strings.Split(envVar, ","), ", $")) } return str + envText } diff --git a/Godeps/_workspace/src/github.com/codegangsta/cli/flag_test.go b/Godeps/_workspace/src/github.com/codegangsta/cli/flag_test.go index bc5059ca..f0f096a2 100644 --- a/Godeps/_workspace/src/github.com/codegangsta/cli/flag_test.go +++ b/Godeps/_workspace/src/github.com/codegangsta/cli/flag_test.go @@ -38,7 +38,7 @@ var stringFlagTests = []struct { {"help", "", "--help \t"}, {"h", "", "-h \t"}, {"h", "", "-h \t"}, - {"test", "Something", "--test 'Something'\t"}, + {"test", "Something", "--test \"Something\"\t"}, } func TestStringFlagHelpOutput(t *testing.T) { @@ -54,7 +54,7 @@ func TestStringFlagHelpOutput(t *testing.T) { } func TestStringFlagWithEnvVarHelpOutput(t *testing.T) { - + os.Clearenv() os.Setenv("APP_FOO", "derp") for _, test := range stringFlagTests { flag := cli.StringFlag{Name: test.name, Value: test.value, EnvVar: "APP_FOO"} @@ -75,22 +75,22 @@ var stringSliceFlagTests = []struct { s := &cli.StringSlice{} s.Set("") return s - }(), "--help '--help option --help option'\t"}, + }(), "--help [--help option --help option]\t"}, {"h", func() *cli.StringSlice { s := &cli.StringSlice{} s.Set("") return s - }(), "-h '-h option -h option'\t"}, + }(), "-h [-h option -h option]\t"}, {"h", func() *cli.StringSlice { s := &cli.StringSlice{} s.Set("") return s - }(), "-h '-h option -h option'\t"}, + }(), "-h [-h option -h option]\t"}, {"test", func() *cli.StringSlice { s := &cli.StringSlice{} s.Set("Something") return s - }(), "--test '--test option --test option'\t"}, + }(), "--test [--test option --test option]\t"}, } func TestStringSliceFlagHelpOutput(t *testing.T) { @@ -106,7 +106,7 @@ func TestStringSliceFlagHelpOutput(t *testing.T) { } func TestStringSliceFlagWithEnvVarHelpOutput(t *testing.T) { - + os.Clearenv() os.Setenv("APP_QWWX", "11,4") for _, test := range stringSliceFlagTests { flag := cli.StringSliceFlag{Name: test.name, Value: test.value, EnvVar: "APP_QWWX"} @@ -122,8 +122,8 @@ var intFlagTests = []struct { name string expected string }{ - {"help", "--help '0'\t"}, - {"h", "-h '0'\t"}, + {"help", "--help \"0\"\t"}, + {"h", "-h \"0\"\t"}, } func TestIntFlagHelpOutput(t *testing.T) { @@ -139,7 +139,7 @@ func TestIntFlagHelpOutput(t *testing.T) { } func TestIntFlagWithEnvVarHelpOutput(t *testing.T) { - + os.Clearenv() os.Setenv("APP_BAR", "2") for _, test := range intFlagTests { flag := cli.IntFlag{Name: test.name, EnvVar: "APP_BAR"} @@ -155,8 +155,8 @@ var durationFlagTests = []struct { name string expected string }{ - {"help", "--help '0'\t"}, - {"h", "-h '0'\t"}, + {"help", "--help \"0\"\t"}, + {"h", "-h \"0\"\t"}, } func TestDurationFlagHelpOutput(t *testing.T) { @@ -172,7 +172,7 @@ func TestDurationFlagHelpOutput(t *testing.T) { } func TestDurationFlagWithEnvVarHelpOutput(t *testing.T) { - + os.Clearenv() os.Setenv("APP_BAR", "2h3m6s") for _, test := range durationFlagTests { flag := cli.DurationFlag{Name: test.name, EnvVar: "APP_BAR"} @@ -189,14 +189,14 @@ var intSliceFlagTests = []struct { value *cli.IntSlice expected string }{ - {"help", &cli.IntSlice{}, "--help '--help option --help option'\t"}, - {"h", &cli.IntSlice{}, "-h '-h option -h option'\t"}, - {"h", &cli.IntSlice{}, "-h '-h option -h option'\t"}, + {"help", &cli.IntSlice{}, "--help [--help option --help option]\t"}, + {"h", &cli.IntSlice{}, "-h [-h option -h option]\t"}, + {"h", &cli.IntSlice{}, "-h [-h option -h option]\t"}, {"test", func() *cli.IntSlice { i := &cli.IntSlice{} i.Set("9") return i - }(), "--test '--test option --test option'\t"}, + }(), "--test [--test option --test option]\t"}, } func TestIntSliceFlagHelpOutput(t *testing.T) { @@ -212,7 +212,7 @@ func TestIntSliceFlagHelpOutput(t *testing.T) { } func TestIntSliceFlagWithEnvVarHelpOutput(t *testing.T) { - + os.Clearenv() os.Setenv("APP_SMURF", "42,3") for _, test := range intSliceFlagTests { flag := cli.IntSliceFlag{Name: test.name, Value: test.value, EnvVar: "APP_SMURF"} @@ -228,8 +228,8 @@ var float64FlagTests = []struct { name string expected string }{ - {"help", "--help '0'\t"}, - {"h", "-h '0'\t"}, + {"help", "--help \"0\"\t"}, + {"h", "-h \"0\"\t"}, } func TestFloat64FlagHelpOutput(t *testing.T) { @@ -245,7 +245,7 @@ func TestFloat64FlagHelpOutput(t *testing.T) { } func TestFloat64FlagWithEnvVarHelpOutput(t *testing.T) { - + os.Clearenv() os.Setenv("APP_BAZ", "99.4") for _, test := range float64FlagTests { flag := cli.Float64Flag{Name: test.name, EnvVar: "APP_BAZ"} @@ -262,15 +262,14 @@ var genericFlagTests = []struct { value cli.Generic expected string }{ - {"help", &Parser{}, "--help \t`-help option -help option` "}, - {"h", &Parser{}, "-h \t`-h option -h option` "}, - {"test", &Parser{}, "--test \t`-test option -test option` "}, + {"test", &Parser{"abc", "def"}, "--test \"abc,def\"\ttest flag"}, + {"t", &Parser{"abc", "def"}, "-t \"abc,def\"\ttest flag"}, } func TestGenericFlagHelpOutput(t *testing.T) { for _, test := range genericFlagTests { - flag := cli.GenericFlag{Name: test.name} + flag := cli.GenericFlag{Name: test.name, Value: test.value, Usage: "test flag"} output := flag.String() if output != test.expected { @@ -280,7 +279,7 @@ func TestGenericFlagHelpOutput(t *testing.T) { } func TestGenericFlagWithEnvVarHelpOutput(t *testing.T) { - + os.Clearenv() os.Setenv("APP_ZAP", "3") for _, test := range genericFlagTests { flag := cli.GenericFlag{Name: test.name, EnvVar: "APP_ZAP"} @@ -309,6 +308,7 @@ func TestParseMultiString(t *testing.T) { } func TestParseMultiStringFromEnv(t *testing.T) { + os.Clearenv() os.Setenv("APP_COUNT", "20") (&cli.App{ Flags: []cli.Flag{ @@ -325,6 +325,24 @@ func TestParseMultiStringFromEnv(t *testing.T) { }).Run([]string{"run"}) } +func TestParseMultiStringFromEnvCascade(t *testing.T) { + os.Clearenv() + os.Setenv("APP_COUNT", "20") + (&cli.App{ + Flags: []cli.Flag{ + cli.StringFlag{Name: "count, c", EnvVar: "COMPAT_COUNT,APP_COUNT"}, + }, + Action: func(ctx *cli.Context) { + if ctx.String("count") != "20" { + t.Errorf("main name not set") + } + if ctx.String("c") != "20" { + t.Errorf("short name not set") + } + }, + }).Run([]string{"run"}) +} + func TestParseMultiStringSlice(t *testing.T) { (&cli.App{ Flags: []cli.Flag{ @@ -342,6 +360,7 @@ func TestParseMultiStringSlice(t *testing.T) { } func TestParseMultiStringSliceFromEnv(t *testing.T) { + os.Clearenv() os.Setenv("APP_INTERVALS", "20,30,40") (&cli.App{ @@ -359,6 +378,25 @@ func TestParseMultiStringSliceFromEnv(t *testing.T) { }).Run([]string{"run"}) } +func TestParseMultiStringSliceFromEnvCascade(t *testing.T) { + os.Clearenv() + os.Setenv("APP_INTERVALS", "20,30,40") + + (&cli.App{ + Flags: []cli.Flag{ + cli.StringSliceFlag{Name: "intervals, i", Value: &cli.StringSlice{}, EnvVar: "COMPAT_INTERVALS,APP_INTERVALS"}, + }, + Action: func(ctx *cli.Context) { + if !reflect.DeepEqual(ctx.StringSlice("intervals"), []string{"20", "30", "40"}) { + t.Errorf("main name not set from env") + } + if !reflect.DeepEqual(ctx.StringSlice("i"), []string{"20", "30", "40"}) { + t.Errorf("short name not set from env") + } + }, + }).Run([]string{"run"}) +} + func TestParseMultiInt(t *testing.T) { a := cli.App{ Flags: []cli.Flag{ @@ -377,6 +415,7 @@ func TestParseMultiInt(t *testing.T) { } func TestParseMultiIntFromEnv(t *testing.T) { + os.Clearenv() os.Setenv("APP_TIMEOUT_SECONDS", "10") a := cli.App{ Flags: []cli.Flag{ @@ -394,6 +433,25 @@ func TestParseMultiIntFromEnv(t *testing.T) { a.Run([]string{"run"}) } +func TestParseMultiIntFromEnvCascade(t *testing.T) { + os.Clearenv() + os.Setenv("APP_TIMEOUT_SECONDS", "10") + a := cli.App{ + Flags: []cli.Flag{ + cli.IntFlag{Name: "timeout, t", EnvVar: "COMPAT_TIMEOUT_SECONDS,APP_TIMEOUT_SECONDS"}, + }, + Action: func(ctx *cli.Context) { + if ctx.Int("timeout") != 10 { + t.Errorf("main name not set") + } + if ctx.Int("t") != 10 { + t.Errorf("short name not set") + } + }, + } + a.Run([]string{"run"}) +} + func TestParseMultiIntSlice(t *testing.T) { (&cli.App{ Flags: []cli.Flag{ @@ -411,6 +469,7 @@ func TestParseMultiIntSlice(t *testing.T) { } func TestParseMultiIntSliceFromEnv(t *testing.T) { + os.Clearenv() os.Setenv("APP_INTERVALS", "20,30,40") (&cli.App{ @@ -428,6 +487,25 @@ func TestParseMultiIntSliceFromEnv(t *testing.T) { }).Run([]string{"run"}) } +func TestParseMultiIntSliceFromEnvCascade(t *testing.T) { + os.Clearenv() + os.Setenv("APP_INTERVALS", "20,30,40") + + (&cli.App{ + Flags: []cli.Flag{ + cli.IntSliceFlag{Name: "intervals, i", Value: &cli.IntSlice{}, EnvVar: "COMPAT_INTERVALS,APP_INTERVALS"}, + }, + Action: func(ctx *cli.Context) { + if !reflect.DeepEqual(ctx.IntSlice("intervals"), []int{20, 30, 40}) { + t.Errorf("main name not set from env") + } + if !reflect.DeepEqual(ctx.IntSlice("i"), []int{20, 30, 40}) { + t.Errorf("short name not set from env") + } + }, + }).Run([]string{"run"}) +} + func TestParseMultiFloat64(t *testing.T) { a := cli.App{ Flags: []cli.Flag{ @@ -446,6 +524,7 @@ func TestParseMultiFloat64(t *testing.T) { } func TestParseMultiFloat64FromEnv(t *testing.T) { + os.Clearenv() os.Setenv("APP_TIMEOUT_SECONDS", "15.5") a := cli.App{ Flags: []cli.Flag{ @@ -463,6 +542,25 @@ func TestParseMultiFloat64FromEnv(t *testing.T) { a.Run([]string{"run"}) } +func TestParseMultiFloat64FromEnvCascade(t *testing.T) { + os.Clearenv() + os.Setenv("APP_TIMEOUT_SECONDS", "15.5") + a := cli.App{ + Flags: []cli.Flag{ + cli.Float64Flag{Name: "timeout, t", EnvVar: "COMPAT_TIMEOUT_SECONDS,APP_TIMEOUT_SECONDS"}, + }, + Action: func(ctx *cli.Context) { + if ctx.Float64("timeout") != 15.5 { + t.Errorf("main name not set") + } + if ctx.Float64("t") != 15.5 { + t.Errorf("short name not set") + } + }, + } + a.Run([]string{"run"}) +} + func TestParseMultiBool(t *testing.T) { a := cli.App{ Flags: []cli.Flag{ @@ -481,6 +579,7 @@ func TestParseMultiBool(t *testing.T) { } func TestParseMultiBoolFromEnv(t *testing.T) { + os.Clearenv() os.Setenv("APP_DEBUG", "1") a := cli.App{ Flags: []cli.Flag{ @@ -498,6 +597,25 @@ func TestParseMultiBoolFromEnv(t *testing.T) { a.Run([]string{"run"}) } +func TestParseMultiBoolFromEnvCascade(t *testing.T) { + os.Clearenv() + os.Setenv("APP_DEBUG", "1") + a := cli.App{ + Flags: []cli.Flag{ + cli.BoolFlag{Name: "debug, d", EnvVar: "COMPAT_DEBUG,APP_DEBUG"}, + }, + Action: func(ctx *cli.Context) { + if ctx.Bool("debug") != true { + t.Errorf("main name not set from env") + } + if ctx.Bool("d") != true { + t.Errorf("short name not set from env") + } + }, + } + a.Run([]string{"run"}) +} + func TestParseMultiBoolT(t *testing.T) { a := cli.App{ Flags: []cli.Flag{ @@ -516,6 +634,7 @@ func TestParseMultiBoolT(t *testing.T) { } func TestParseMultiBoolTFromEnv(t *testing.T) { + os.Clearenv() os.Setenv("APP_DEBUG", "0") a := cli.App{ Flags: []cli.Flag{ @@ -533,6 +652,25 @@ func TestParseMultiBoolTFromEnv(t *testing.T) { a.Run([]string{"run"}) } +func TestParseMultiBoolTFromEnvCascade(t *testing.T) { + os.Clearenv() + os.Setenv("APP_DEBUG", "0") + a := cli.App{ + Flags: []cli.Flag{ + cli.BoolTFlag{Name: "debug, d", EnvVar: "COMPAT_DEBUG,APP_DEBUG"}, + }, + Action: func(ctx *cli.Context) { + if ctx.BoolT("debug") != false { + t.Errorf("main name not set from env") + } + if ctx.BoolT("d") != false { + t.Errorf("short name not set from env") + } + }, + } + a.Run([]string{"run"}) +} + type Parser [2]string func (p *Parser) Set(value string) error { @@ -569,6 +707,7 @@ func TestParseGeneric(t *testing.T) { } func TestParseGenericFromEnv(t *testing.T) { + os.Clearenv() os.Setenv("APP_SERVE", "20,30") a := cli.App{ Flags: []cli.Flag{ @@ -585,3 +724,19 @@ func TestParseGenericFromEnv(t *testing.T) { } a.Run([]string{"run"}) } + +func TestParseGenericFromEnvCascade(t *testing.T) { + os.Clearenv() + os.Setenv("APP_FOO", "99,2000") + a := cli.App{ + Flags: []cli.Flag{ + cli.GenericFlag{Name: "foos", Value: &Parser{}, EnvVar: "COMPAT_FOO,APP_FOO"}, + }, + Action: func(ctx *cli.Context) { + if !reflect.DeepEqual(ctx.Generic("foos"), &Parser{"99", "2000"}) { + t.Errorf("value not set from env") + } + }, + } + a.Run([]string{"run"}) +} diff --git a/Godeps/_workspace/src/github.com/codegangsta/cli/help.go b/Godeps/_workspace/src/github.com/codegangsta/cli/help.go index 5020cb6f..7c4f81be 100644 --- a/Godeps/_workspace/src/github.com/codegangsta/cli/help.go +++ b/Godeps/_workspace/src/github.com/codegangsta/cli/help.go @@ -1,11 +1,6 @@ package cli -import ( - "fmt" - "os" - "text/tabwriter" - "text/template" -) +import "fmt" // The text template for the Default help topic. // cli.go uses text/template to render templates. You can @@ -17,14 +12,13 @@ USAGE: {{.Name}} {{if .Flags}}[global options] {{end}}command{{if .Flags}} [command options]{{end}} [arguments...] VERSION: - {{.Version}}{{if or .Author .Email}} - -AUTHOR:{{if .Author}} - {{.Author}}{{if .Email}} - <{{.Email}}>{{end}}{{else}} - {{.Email}}{{end}}{{end}} + {{.Version}} +AUTHOR(S): + {{range .Authors}}{{ . }} + {{end}} COMMANDS: - {{range .Commands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}} + {{range .Commands}}{{join .Names ", "}}{{ "\t" }}{{.Usage}} {{end}}{{if .Flags}} GLOBAL OPTIONS: {{range .Flags}}{{.}} @@ -58,7 +52,7 @@ USAGE: {{.Name}} command{{if .Flags}} [command options]{{end}} [arguments...] COMMANDS: - {{range .Commands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}} + {{range .Commands}}{{join .Names ", "}}{{ "\t" }}{{.Usage}} {{end}}{{if .Flags}} OPTIONS: {{range .Flags}}{{.}} @@ -66,9 +60,9 @@ OPTIONS: ` var helpCommand = Command{ - Name: "help", - ShortName: "h", - Usage: "Shows a list of commands or help for one command", + Name: "help", + Aliases: []string{"h"}, + Usage: "Shows a list of commands or help for one command", Action: func(c *Context) { args := c.Args() if args.Present() { @@ -80,9 +74,9 @@ var helpCommand = Command{ } var helpSubcommand = Command{ - Name: "help", - ShortName: "h", - Usage: "Shows a list of commands or help for one command", + Name: "help", + Aliases: []string{"h"}, + Usage: "Shows a list of commands or help for one command", Action: func(c *Context) { args := c.Args() if args.Present() { @@ -94,7 +88,9 @@ var helpSubcommand = Command{ } // Prints help for the App -var HelpPrinter = printHelp +type helpPrinter func(templ string, data interface{}) + +var HelpPrinter helpPrinter = nil // Prints version for the App var VersionPrinter = printVersion @@ -106,15 +102,20 @@ func ShowAppHelp(c *Context) { // Prints the list of subcommands as the default app completion method func DefaultAppComplete(c *Context) { for _, command := range c.App.Commands { - fmt.Println(command.Name) - if command.ShortName != "" { - fmt.Println(command.ShortName) + for _, name := range command.Names() { + fmt.Fprintln(c.App.Writer, name) } } } // Prints help for the given command func ShowCommandHelp(c *Context, command string) { + // show the subcommand help for a command with subcommands + if command == "" { + HelpPrinter(SubcommandHelpTemplate, c.App) + return + } + for _, c := range c.App.Commands { if c.HasName(command) { HelpPrinter(CommandHelpTemplate, c) @@ -125,13 +126,13 @@ func ShowCommandHelp(c *Context, command string) { if c.App.CommandNotFound != nil { c.App.CommandNotFound(c, command) } else { - fmt.Printf("No help topic for '%v'\n", command) + fmt.Fprintf(c.App.Writer, "No help topic for '%v'\n", command) } } // Prints help for the given subcommand func ShowSubcommandHelp(c *Context) { - HelpPrinter(SubcommandHelpTemplate, c.App) + ShowCommandHelp(c, c.Command.Name) } // Prints the version number of the App @@ -140,7 +141,7 @@ func ShowVersion(c *Context) { } func printVersion(c *Context) { - fmt.Printf("%v version %v\n", c.App.Name, c.App.Version) + fmt.Fprintf(c.App.Writer, "%v version %v\n", c.App.Name, c.App.Version) } // Prints the lists of commands within a given context @@ -159,16 +160,6 @@ func ShowCommandCompletions(ctx *Context, command string) { } } -func printHelp(templ string, data interface{}) { - w := tabwriter.NewWriter(os.Stdout, 0, 8, 1, '\t', 0) - t := template.Must(template.New("help").Parse(templ)) - err := t.Execute(w, data) - if err != nil { - panic(err) - } - w.Flush() -} - func checkVersion(c *Context) bool { if c.GlobalBool("version") { ShowVersion(c) @@ -206,7 +197,7 @@ func checkSubcommandHelp(c *Context) bool { } func checkCompletions(c *Context) bool { - if c.GlobalBool(BashCompletionFlag.Name) && c.App.EnableBashCompletion { + if (c.GlobalBool(BashCompletionFlag.Name) || c.Bool(BashCompletionFlag.Name)) && c.App.EnableBashCompletion { ShowCompletions(c) return true } diff --git a/Godeps/_workspace/src/github.com/kr/logfmt/scanner_test.go b/Godeps/_workspace/src/github.com/kr/logfmt/scanner_test.go index 35452259..ac9b2f05 100644 --- a/Godeps/_workspace/src/github.com/kr/logfmt/scanner_test.go +++ b/Godeps/_workspace/src/github.com/kr/logfmt/scanner_test.go @@ -2,7 +2,6 @@ package logfmt import ( "reflect" - "strconv" "testing" ) @@ -27,14 +26,6 @@ func TestScannerSimple(t *testing.T) { {"x", "sf"}, }, }, - { - `quotes=` + strconv.Quote(`outside double quotes "inside double quotes 'inside single quotes'"`), - []T{{"quotes", `outside double quotes "inside double quotes 'inside single quotes'"`}}, - }, - { - `equals="UPDATE herp SET is_derp=0 WHERE herp_id=9000 AND derp_id=1"`, - []T{{"equals", `UPDATE herp SET is_derp=0 WHERE herp_id=9000 AND derp_id=1`}}, - }, {`x= `, []T{{"x", ""}}}, {`y=`, []T{{"y", ""}}}, {`y`, []T{{"y", ""}}},