1cli v1 manual
2===
3
4<!-- toc -->
5
6- [Getting Started](#getting-started)
7- [Examples](#examples)
8  * [Arguments](#arguments)
9  * [Flags](#flags)
10    + [Placeholder Values](#placeholder-values)
11    + [Alternate Names](#alternate-names)
12    + [Ordering](#ordering)
13    + [Values from the Environment](#values-from-the-environment)
14    + [Values from files](#values-from-files)
15    + [Values from alternate input sources (YAML, TOML, and others)](#values-from-alternate-input-sources-yaml-toml-and-others)
16    + [Precedence](#precedence)
17  * [Subcommands](#subcommands)
18  * [Subcommands categories](#subcommands-categories)
19  * [Exit code](#exit-code)
20  * [Combining short options](#combining-short-options)
21  * [Bash Completion](#bash-completion)
22    + [Enabling](#enabling)
23    + [Distribution](#distribution)
24    + [Customization](#customization)
25  * [Generated Help Text](#generated-help-text)
26    + [Customization](#customization-1)
27  * [Version Flag](#version-flag)
28    + [Customization](#customization-2)
29    + [Full API Example](#full-api-example)
30
31<!-- tocstop -->
32
33## Getting Started
34
35One of the philosophies behind cli is that an API should be playful and full of
36discovery. So a cli app can be as little as one line of code in `main()`.
37
38<!-- {
39  "args": ["&#45;&#45;help"],
40  "output": "A new cli application"
41} -->
42``` go
43package main
44
45import (
46  "log"
47  "os"
48
49  "github.com/urfave/cli"
50)
51
52func main() {
53  err := cli.NewApp().Run(os.Args)
54  if err != nil {
55    log.Fatal(err)
56  }
57}
58```
59
60This app will run and show help text, but is not very useful. Let's give an
61action to execute and some help documentation:
62
63<!-- {
64  "output": "boom! I say!"
65} -->
66``` go
67package main
68
69import (
70  "fmt"
71  "log"
72  "os"
73
74  "github.com/urfave/cli"
75)
76
77func main() {
78  app := cli.NewApp()
79  app.Name = "boom"
80  app.Usage = "make an explosive entrance"
81  app.Action = func(c *cli.Context) error {
82    fmt.Println("boom! I say!")
83    return nil
84  }
85
86  err := app.Run(os.Args)
87  if err != nil {
88    log.Fatal(err)
89  }
90}
91```
92
93Running this already gives you a ton of functionality, plus support for things
94like subcommands and flags, which are covered below.
95
96## Examples
97
98Being a programmer can be a lonely job. Thankfully by the power of automation
99that is not the case! Let's create a greeter app to fend off our demons of
100loneliness!
101
102Start by creating a directory named `greet`, and within it, add a file,
103`greet.go` with the following code in it:
104
105<!-- {
106  "output": "Hello friend!"
107} -->
108``` go
109package main
110
111import (
112  "fmt"
113  "log"
114  "os"
115
116  "github.com/urfave/cli"
117)
118
119func main() {
120  app := cli.NewApp()
121  app.Name = "greet"
122  app.Usage = "fight the loneliness!"
123  app.Action = func(c *cli.Context) error {
124    fmt.Println("Hello friend!")
125    return nil
126  }
127
128  err := app.Run(os.Args)
129  if err != nil {
130    log.Fatal(err)
131  }
132}
133```
134
135Install our command to the `$GOPATH/bin` directory:
136
137```
138$ go install
139```
140
141Finally run our new command:
142
143```
144$ greet
145Hello friend!
146```
147
148cli also generates neat help text:
149
150```
151$ greet help
152NAME:
153    greet - fight the loneliness!
154
155USAGE:
156    greet [global options] command [command options] [arguments...]
157
158VERSION:
159    0.0.0
160
161COMMANDS:
162    help, h  Shows a list of commands or help for one command
163
164GLOBAL OPTIONS
165    --version Shows version information
166```
167
168### Arguments
169
170You can lookup arguments by calling the `Args` function on `cli.Context`, e.g.:
171
172<!-- {
173  "output": "Hello \""
174} -->
175``` go
176package main
177
178import (
179  "fmt"
180  "log"
181  "os"
182
183  "github.com/urfave/cli"
184)
185
186func main() {
187  app := cli.NewApp()
188
189  app.Action = func(c *cli.Context) error {
190    fmt.Printf("Hello %q", c.Args().Get(0))
191    return nil
192  }
193
194  err := app.Run(os.Args)
195  if err != nil {
196    log.Fatal(err)
197  }
198}
199```
200
201### Flags
202
203Setting and querying flags is simple.
204
205<!-- {
206  "output": "Hello Nefertiti"
207} -->
208``` go
209package main
210
211import (
212  "fmt"
213  "log"
214  "os"
215
216  "github.com/urfave/cli"
217)
218
219func main() {
220  app := cli.NewApp()
221
222  app.Flags = []cli.Flag {
223    cli.StringFlag{
224      Name: "lang",
225      Value: "english",
226      Usage: "language for the greeting",
227    },
228  }
229
230  app.Action = func(c *cli.Context) error {
231    name := "Nefertiti"
232    if c.NArg() > 0 {
233      name = c.Args().Get(0)
234    }
235    if c.String("lang") == "spanish" {
236      fmt.Println("Hola", name)
237    } else {
238      fmt.Println("Hello", name)
239    }
240    return nil
241  }
242
243  err := app.Run(os.Args)
244  if err != nil {
245    log.Fatal(err)
246  }
247}
248```
249
250You can also set a destination variable for a flag, to which the content will be
251scanned.
252
253<!-- {
254  "output": "Hello someone"
255} -->
256``` go
257package main
258
259import (
260  "log"
261  "os"
262  "fmt"
263
264  "github.com/urfave/cli"
265)
266
267func main() {
268  var language string
269
270  app := cli.NewApp()
271
272  app.Flags = []cli.Flag {
273    cli.StringFlag{
274      Name:        "lang",
275      Value:       "english",
276      Usage:       "language for the greeting",
277      Destination: &language,
278    },
279  }
280
281  app.Action = func(c *cli.Context) error {
282    name := "someone"
283    if c.NArg() > 0 {
284      name = c.Args()[0]
285    }
286    if language == "spanish" {
287      fmt.Println("Hola", name)
288    } else {
289      fmt.Println("Hello", name)
290    }
291    return nil
292  }
293
294  err := app.Run(os.Args)
295  if err != nil {
296    log.Fatal(err)
297  }
298}
299```
300
301See full list of flags at http://godoc.org/github.com/urfave/cli
302
303#### Placeholder Values
304
305Sometimes it's useful to specify a flag's value within the usage string itself.
306Such placeholders are indicated with back quotes.
307
308For example this:
309
310<!-- {
311  "args": ["&#45;&#45;help"],
312  "output": "&#45;&#45;config FILE, &#45;c FILE"
313} -->
314```go
315package main
316
317import (
318  "log"
319  "os"
320
321  "github.com/urfave/cli"
322)
323
324func main() {
325  app := cli.NewApp()
326
327  app.Flags = []cli.Flag{
328    cli.StringFlag{
329      Name:  "config, c",
330      Usage: "Load configuration from `FILE`",
331    },
332  }
333
334  err := app.Run(os.Args)
335  if err != nil {
336    log.Fatal(err)
337  }
338}
339```
340
341Will result in help output like:
342
343```
344--config FILE, -c FILE   Load configuration from FILE
345```
346
347Note that only the first placeholder is used. Subsequent back-quoted words will
348be left as-is.
349
350#### Alternate Names
351
352You can set alternate (or short) names for flags by providing a comma-delimited
353list for the `Name`. e.g.
354
355<!-- {
356  "args": ["&#45;&#45;help"],
357  "output": "&#45;&#45;lang value, &#45;l value.*language for the greeting.*default: \"english\""
358} -->
359``` go
360package main
361
362import (
363  "log"
364  "os"
365
366  "github.com/urfave/cli"
367)
368
369func main() {
370  app := cli.NewApp()
371
372  app.Flags = []cli.Flag {
373    cli.StringFlag{
374      Name: "lang, l",
375      Value: "english",
376      Usage: "language for the greeting",
377    },
378  }
379
380  err := app.Run(os.Args)
381  if err != nil {
382    log.Fatal(err)
383  }
384}
385```
386
387That flag can then be set with `--lang spanish` or `-l spanish`. Note that
388giving two different forms of the same flag in the same command invocation is an
389error.
390
391#### Ordering
392
393Flags for the application and commands are shown in the order they are defined.
394However, it's possible to sort them from outside this library by using `FlagsByName`
395or `CommandsByName` with `sort`.
396
397For example this:
398
399<!-- {
400  "args": ["&#45;&#45;help"],
401  "output": "add a task to the list\n.*complete a task on the list\n.*\n\n.*\n.*Load configuration from FILE\n.*Language for the greeting.*"
402} -->
403``` go
404package main
405
406import (
407  "log"
408  "os"
409  "sort"
410
411  "github.com/urfave/cli"
412)
413
414func main() {
415  app := cli.NewApp()
416
417  app.Flags = []cli.Flag {
418    cli.StringFlag{
419      Name: "lang, l",
420      Value: "english",
421      Usage: "Language for the greeting",
422    },
423    cli.StringFlag{
424      Name: "config, c",
425      Usage: "Load configuration from `FILE`",
426    },
427  }
428
429  app.Commands = []cli.Command{
430    {
431      Name:    "complete",
432      Aliases: []string{"c"},
433      Usage:   "complete a task on the list",
434      Action:  func(c *cli.Context) error {
435        return nil
436      },
437    },
438    {
439      Name:    "add",
440      Aliases: []string{"a"},
441      Usage:   "add a task to the list",
442      Action:  func(c *cli.Context) error {
443        return nil
444      },
445    },
446  }
447
448  sort.Sort(cli.FlagsByName(app.Flags))
449  sort.Sort(cli.CommandsByName(app.Commands))
450
451  err := app.Run(os.Args)
452  if err != nil {
453    log.Fatal(err)
454  }
455}
456```
457
458Will result in help output like:
459
460```
461--config FILE, -c FILE  Load configuration from FILE
462--lang value, -l value  Language for the greeting (default: "english")
463```
464
465#### Values from the Environment
466
467You can also have the default value set from the environment via `EnvVar`.  e.g.
468
469<!-- {
470  "args": ["&#45;&#45;help"],
471  "output": "language for the greeting.*APP_LANG"
472} -->
473``` go
474package main
475
476import (
477  "log"
478  "os"
479
480  "github.com/urfave/cli"
481)
482
483func main() {
484  app := cli.NewApp()
485
486  app.Flags = []cli.Flag {
487    cli.StringFlag{
488      Name: "lang, l",
489      Value: "english",
490      Usage: "language for the greeting",
491      EnvVar: "APP_LANG",
492    },
493  }
494
495  err := app.Run(os.Args)
496  if err != nil {
497    log.Fatal(err)
498  }
499}
500```
501
502The `EnvVar` may also be given as a comma-delimited "cascade", where the first
503environment variable that resolves is used as the default.
504
505<!-- {
506  "args": ["&#45;&#45;help"],
507  "output": "language for the greeting.*LEGACY_COMPAT_LANG.*APP_LANG.*LANG"
508} -->
509``` go
510package main
511
512import (
513  "log"
514  "os"
515
516  "github.com/urfave/cli"
517)
518
519func main() {
520  app := cli.NewApp()
521
522  app.Flags = []cli.Flag {
523    cli.StringFlag{
524      Name: "lang, l",
525      Value: "english",
526      Usage: "language for the greeting",
527      EnvVar: "LEGACY_COMPAT_LANG,APP_LANG,LANG",
528    },
529  }
530
531  err := app.Run(os.Args)
532  if err != nil {
533    log.Fatal(err)
534  }
535}
536```
537
538#### Values from files
539
540You can also have the default value set from file via `FilePath`.  e.g.
541
542<!-- {
543  "args": ["&#45;&#45;help"],
544  "output": "password for the mysql database"
545} -->
546``` go
547package main
548
549import (
550  "log"
551  "os"
552
553  "github.com/urfave/cli"
554)
555
556func main() {
557  app := cli.NewApp()
558
559  app.Flags = []cli.Flag {
560    cli.StringFlag{
561      Name: "password, p",
562      Usage: "password for the mysql database",
563      FilePath: "/etc/mysql/password",
564    },
565  }
566
567  err := app.Run(os.Args)
568  if err != nil {
569    log.Fatal(err)
570  }
571}
572```
573
574Note that default values set from file (e.g. `FilePath`) take precedence over
575default values set from the environment (e.g. `EnvVar`).
576
577#### Values from alternate input sources (YAML, TOML, and others)
578
579There is a separate package altsrc that adds support for getting flag values
580from other file input sources.
581
582Currently supported input source formats:
583* YAML
584* JSON
585* TOML
586
587In order to get values for a flag from an alternate input source the following
588code would be added to wrap an existing cli.Flag like below:
589
590``` go
591  altsrc.NewIntFlag(cli.IntFlag{Name: "test"})
592```
593
594Initialization must also occur for these flags. Below is an example initializing
595getting data from a yaml file below.
596
597``` go
598  command.Before = altsrc.InitInputSourceWithContext(command.Flags, NewYamlSourceFromFlagFunc("load"))
599```
600
601The code above will use the "load" string as a flag name to get the file name of
602a yaml file from the cli.Context.  It will then use that file name to initialize
603the yaml input source for any flags that are defined on that command.  As a note
604the "load" flag used would also have to be defined on the command flags in order
605for this code snippet to work.
606
607Currently only YAML, JSON, and TOML files are supported but developers can add support
608for other input sources by implementing the altsrc.InputSourceContext for their
609given sources.
610
611Here is a more complete sample of a command using YAML support:
612
613<!-- {
614  "args": ["test-cmd", "&#45;&#45;help"],
615  "output": "&#45&#45;test value.*default: 0"
616} -->
617``` go
618package notmain
619
620import (
621  "fmt"
622  "log"
623  "os"
624
625  "github.com/urfave/cli"
626  "github.com/urfave/cli/altsrc"
627)
628
629func main() {
630  app := cli.NewApp()
631
632  flags := []cli.Flag{
633    altsrc.NewIntFlag(cli.IntFlag{Name: "test"}),
634    cli.StringFlag{Name: "load"},
635  }
636
637  app.Action = func(c *cli.Context) error {
638    fmt.Println("yaml ist rad")
639    return nil
640  }
641
642  app.Before = altsrc.InitInputSourceWithContext(flags, altsrc.NewYamlSourceFromFlagFunc("load"))
643  app.Flags = flags
644
645  err := app.Run(os.Args)
646  if err != nil {
647    log.Fatal(err)
648  }
649}
650```
651
652#### Precedence
653
654The precedence for flag value sources is as follows (highest to lowest):
655
6560. Command line flag value from user
6570. Environment variable (if specified)
6580. Configuration file (if specified)
6590. Default defined on the flag
660
661### Subcommands
662
663Subcommands can be defined for a more git-like command line app.
664
665<!-- {
666  "args": ["template", "add"],
667  "output": "new task template: .+"
668} -->
669```go
670package main
671
672import (
673  "fmt"
674  "log"
675  "os"
676
677  "github.com/urfave/cli"
678)
679
680func main() {
681  app := cli.NewApp()
682
683  app.Commands = []cli.Command{
684    {
685      Name:    "add",
686      Aliases: []string{"a"},
687      Usage:   "add a task to the list",
688      Action:  func(c *cli.Context) error {
689        fmt.Println("added task: ", c.Args().First())
690        return nil
691      },
692    },
693    {
694      Name:    "complete",
695      Aliases: []string{"c"},
696      Usage:   "complete a task on the list",
697      Action:  func(c *cli.Context) error {
698        fmt.Println("completed task: ", c.Args().First())
699        return nil
700      },
701    },
702    {
703      Name:        "template",
704      Aliases:     []string{"t"},
705      Usage:       "options for task templates",
706      Subcommands: []cli.Command{
707        {
708          Name:  "add",
709          Usage: "add a new template",
710          Action: func(c *cli.Context) error {
711            fmt.Println("new task template: ", c.Args().First())
712            return nil
713          },
714        },
715        {
716          Name:  "remove",
717          Usage: "remove an existing template",
718          Action: func(c *cli.Context) error {
719            fmt.Println("removed task template: ", c.Args().First())
720            return nil
721          },
722        },
723      },
724    },
725  }
726
727  err := app.Run(os.Args)
728  if err != nil {
729    log.Fatal(err)
730  }
731}
732```
733
734### Subcommands categories
735
736For additional organization in apps that have many subcommands, you can
737associate a category for each command to group them together in the help
738output.
739
740E.g.
741
742```go
743package main
744
745import (
746  "log"
747  "os"
748
749  "github.com/urfave/cli"
750)
751
752func main() {
753  app := cli.NewApp()
754
755  app.Commands = []cli.Command{
756    {
757      Name: "noop",
758    },
759    {
760      Name:     "add",
761      Category: "Template actions",
762    },
763    {
764      Name:     "remove",
765      Category: "Template actions",
766    },
767  }
768
769  err := app.Run(os.Args)
770  if err != nil {
771    log.Fatal(err)
772  }
773}
774```
775
776Will include:
777
778```
779COMMANDS:
780  noop
781
782  Template actions:
783    add
784    remove
785```
786
787### Exit code
788
789Calling `App.Run` will not automatically call `os.Exit`, which means that by
790default the exit code will "fall through" to being `0`.  An explicit exit code
791may be set by returning a non-nil error that fulfills `cli.ExitCoder`, *or* a
792`cli.MultiError` that includes an error that fulfills `cli.ExitCoder`, e.g.:
793<!-- {
794  "error": "Ginger croutons are not in the soup"
795} -->
796``` go
797package main
798
799import (
800  "log"
801  "os"
802
803  "github.com/urfave/cli"
804)
805
806func main() {
807  app := cli.NewApp()
808  app.Flags = []cli.Flag{
809    cli.BoolFlag{
810      Name:  "ginger-crouton",
811      Usage: "Add ginger croutons to the soup",
812    },
813  }
814  app.Action = func(ctx *cli.Context) error {
815    if !ctx.Bool("ginger-crouton") {
816      return cli.NewExitError("Ginger croutons are not in the soup", 86)
817    }
818    return nil
819  }
820
821  err := app.Run(os.Args)
822  if err != nil {
823    log.Fatal(err)
824  }
825}
826```
827
828### Combining short options
829
830Traditional use of options using their shortnames look like this:
831
832```
833$ cmd -s -o -m "Some message"
834```
835
836Suppose you want users to be able to combine options with their shortnames. This
837can be done using the `UseShortOptionHandling` bool in your app configuration,
838or for individual commands by attaching it to the command configuration. For
839example:
840
841<!-- {
842  "args": ["short", "&#45;som", "Some message"],
843  "output": "serve: true\noption: true\nmessage: Some message\n"
844} -->
845``` go
846package main
847
848import (
849  "fmt"
850  "log"
851  "os"
852
853  "github.com/urfave/cli"
854)
855
856func main() {
857  app := cli.NewApp()
858  app.UseShortOptionHandling = true
859  app.Commands = []cli.Command{
860    {
861      Name:  "short",
862      Usage: "complete a task on the list",
863      Flags: []cli.Flag{
864        cli.BoolFlag{Name: "serve, s"},
865        cli.BoolFlag{Name: "option, o"},
866        cli.StringFlag{Name: "message, m"},
867      },
868      Action: func(c *cli.Context) error {
869        fmt.Println("serve:", c.Bool("serve"))
870        fmt.Println("option:", c.Bool("option"))
871        fmt.Println("message:", c.String("message"))
872        return nil
873      },
874    },
875  }
876
877  err := app.Run(os.Args)
878  if err != nil {
879    log.Fatal(err)
880  }
881}
882```
883
884If your program has any number of bool flags such as `serve` and `option`, and
885optionally one non-bool flag `message`, with the short options of `-s`, `-o`,
886and `-m` respectively, setting `UseShortOptionHandling` will also support the
887following syntax:
888
889```
890$ cmd -som "Some message"
891```
892
893If you enable `UseShortOptionHandling`, then you must not use any flags that
894have a single leading `-` or this will result in failures. For example,
895`-option` can no longer be used. Flags with two leading dashes (such as
896`--options`) are still valid.
897
898### Bash Completion
899
900You can enable completion commands by setting the `EnableBashCompletion`
901flag on the `App` object.  By default, this setting will only auto-complete to
902show an app's subcommands, but you can write your own completion methods for
903the App or its subcommands.
904
905<!-- {
906  "args": ["complete", "&#45;&#45;generate&#45;bash&#45;completion"],
907  "output": "laundry"
908} -->
909``` go
910package main
911
912import (
913  "fmt"
914  "log"
915  "os"
916
917  "github.com/urfave/cli"
918)
919
920func main() {
921  tasks := []string{"cook", "clean", "laundry", "eat", "sleep", "code"}
922
923  app := cli.NewApp()
924  app.EnableBashCompletion = true
925  app.Commands = []cli.Command{
926    {
927      Name:  "complete",
928      Aliases: []string{"c"},
929      Usage: "complete a task on the list",
930      Action: func(c *cli.Context) error {
931         fmt.Println("completed task: ", c.Args().First())
932         return nil
933      },
934      BashComplete: func(c *cli.Context) {
935        // This will complete if no args are passed
936        if c.NArg() > 0 {
937          return
938        }
939        for _, t := range tasks {
940          fmt.Println(t)
941        }
942      },
943    },
944  }
945
946  err := app.Run(os.Args)
947  if err != nil {
948    log.Fatal(err)
949  }
950}
951```
952
953#### Enabling
954
955Source the `autocomplete/bash_autocomplete` file in your `.bashrc` file while
956setting the `PROG` variable to the name of your program:
957
958`PROG=myprogram source /.../cli/autocomplete/bash_autocomplete`
959
960#### Distribution
961
962Copy `autocomplete/bash_autocomplete` into `/etc/bash_completion.d/` and rename
963it to the name of the program you wish to add autocomplete support for (or
964automatically install it there if you are distributing a package). Don't forget
965to source the file to make it active in the current shell.
966
967```
968sudo cp src/bash_autocomplete /etc/bash_completion.d/<myprogram>
969source /etc/bash_completion.d/<myprogram>
970```
971
972Alternatively, you can just document that users should source the generic
973`autocomplete/bash_autocomplete` in their bash configuration with `$PROG` set
974to the name of their program (as above).
975
976#### Customization
977
978The default bash completion flag (`--generate-bash-completion`) is defined as
979`cli.BashCompletionFlag`, and may be redefined if desired, e.g.:
980
981<!-- {
982  "args": ["&#45;&#45;compgen"],
983  "output": "wat\nhelp\nh"
984} -->
985``` go
986package main
987
988import (
989  "log"
990  "os"
991
992  "github.com/urfave/cli"
993)
994
995func main() {
996  cli.BashCompletionFlag = cli.BoolFlag{
997    Name:   "compgen",
998    Hidden: true,
999  }
1000
1001  app := cli.NewApp()
1002  app.EnableBashCompletion = true
1003  app.Commands = []cli.Command{
1004    {
1005      Name: "wat",
1006    },
1007  }
1008  err := app.Run(os.Args)
1009  if err != nil {
1010    log.Fatal(err)
1011  }
1012}
1013```
1014
1015### Generated Help Text
1016
1017The default help flag (`-h/--help`) is defined as `cli.HelpFlag` and is checked
1018by the cli internals in order to print generated help text for the app, command,
1019or subcommand, and break execution.
1020
1021#### Customization
1022
1023All of the help text generation may be customized, and at multiple levels.  The
1024templates are exposed as variables `AppHelpTemplate`, `CommandHelpTemplate`, and
1025`SubcommandHelpTemplate` which may be reassigned or augmented, and full override
1026is possible by assigning a compatible func to the `cli.HelpPrinter` variable,
1027e.g.:
1028
1029<!-- {
1030  "output": "Ha HA.  I pwnd the help!!1"
1031} -->
1032``` go
1033package main
1034
1035import (
1036  "fmt"
1037  "log"
1038  "io"
1039  "os"
1040
1041  "github.com/urfave/cli"
1042)
1043
1044func main() {
1045  // EXAMPLE: Append to an existing template
1046  cli.AppHelpTemplate = fmt.Sprintf(`%s
1047
1048WEBSITE: http://awesometown.example.com
1049
1050SUPPORT: support@awesometown.example.com
1051
1052`, cli.AppHelpTemplate)
1053
1054  // EXAMPLE: Override a template
1055  cli.AppHelpTemplate = `NAME:
1056   {{.Name}} - {{.Usage}}
1057USAGE:
1058   {{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}
1059   {{if len .Authors}}
1060AUTHOR:
1061   {{range .Authors}}{{ . }}{{end}}
1062   {{end}}{{if .Commands}}
1063COMMANDS:
1064{{range .Commands}}{{if not .HideHelp}}   {{join .Names ", "}}{{ "\t"}}{{.Usage}}{{ "\n" }}{{end}}{{end}}{{end}}{{if .VisibleFlags}}
1065GLOBAL OPTIONS:
1066   {{range .VisibleFlags}}{{.}}
1067   {{end}}{{end}}{{if .Copyright }}
1068COPYRIGHT:
1069   {{.Copyright}}
1070   {{end}}{{if .Version}}
1071VERSION:
1072   {{.Version}}
1073   {{end}}
1074`
1075
1076  // EXAMPLE: Replace the `HelpPrinter` func
1077  cli.HelpPrinter = func(w io.Writer, templ string, data interface{}) {
1078    fmt.Println("Ha HA.  I pwnd the help!!1")
1079  }
1080
1081  err := cli.NewApp().Run(os.Args)
1082  if err != nil {
1083    log.Fatal(err)
1084  }
1085}
1086```
1087
1088The default flag may be customized to something other than `-h/--help` by
1089setting `cli.HelpFlag`, e.g.:
1090
1091<!-- {
1092  "args": ["&#45;&#45halp"],
1093  "output": "haaaaalp.*HALP"
1094} -->
1095``` go
1096package main
1097
1098import (
1099  "log"
1100  "os"
1101
1102  "github.com/urfave/cli"
1103)
1104
1105func main() {
1106  cli.HelpFlag = cli.BoolFlag{
1107    Name: "halp, haaaaalp",
1108    Usage: "HALP",
1109    EnvVar: "SHOW_HALP,HALPPLZ",
1110  }
1111
1112  err := cli.NewApp().Run(os.Args)
1113  if err != nil {
1114    log.Fatal(err)
1115  }
1116}
1117```
1118
1119### Version Flag
1120
1121The default version flag (`-v/--version`) is defined as `cli.VersionFlag`, which
1122is checked by the cli internals in order to print the `App.Version` via
1123`cli.VersionPrinter` and break execution.
1124
1125#### Customization
1126
1127The default flag may be customized to something other than `-v/--version` by
1128setting `cli.VersionFlag`, e.g.:
1129
1130<!-- {
1131  "args": ["&#45;&#45print-version"],
1132  "output": "partay version 19\\.99\\.0"
1133} -->
1134``` go
1135package main
1136
1137import (
1138  "log"
1139  "os"
1140
1141  "github.com/urfave/cli"
1142)
1143
1144func main() {
1145  cli.VersionFlag = cli.BoolFlag{
1146    Name: "print-version, V",
1147    Usage: "print only the version",
1148  }
1149
1150  app := cli.NewApp()
1151  app.Name = "partay"
1152  app.Version = "19.99.0"
1153  err := app.Run(os.Args)
1154  if err != nil {
1155    log.Fatal(err)
1156  }
1157}
1158```
1159
1160Alternatively, the version printer at `cli.VersionPrinter` may be overridden, e.g.:
1161
1162<!-- {
1163  "args": ["&#45;&#45version"],
1164  "output": "version=19\\.99\\.0 revision=fafafaf"
1165} -->
1166``` go
1167package main
1168
1169import (
1170  "fmt"
1171  "log"
1172  "os"
1173
1174  "github.com/urfave/cli"
1175)
1176
1177var (
1178  Revision = "fafafaf"
1179)
1180
1181func main() {
1182  cli.VersionPrinter = func(c *cli.Context) {
1183    fmt.Printf("version=%s revision=%s\n", c.App.Version, Revision)
1184  }
1185
1186  app := cli.NewApp()
1187  app.Name = "partay"
1188  app.Version = "19.99.0"
1189  err := app.Run(os.Args)
1190  if err != nil {
1191    log.Fatal(err)
1192  }
1193}
1194```
1195
1196#### Full API Example
1197
1198**Notice**: This is a contrived (functioning) example meant strictly for API
1199demonstration purposes.  Use of one's imagination is encouraged.
1200
1201<!-- {
1202  "output": "made it!\nPhew!"
1203} -->
1204``` go
1205package main
1206
1207import (
1208  "errors"
1209  "flag"
1210  "fmt"
1211  "io"
1212  "io/ioutil"
1213  "os"
1214  "time"
1215
1216  "github.com/urfave/cli"
1217)
1218
1219func init() {
1220  cli.AppHelpTemplate += "\nCUSTOMIZED: you bet ur muffins\n"
1221  cli.CommandHelpTemplate += "\nYMMV\n"
1222  cli.SubcommandHelpTemplate += "\nor something\n"
1223
1224  cli.HelpFlag = cli.BoolFlag{Name: "halp"}
1225  cli.BashCompletionFlag = cli.BoolFlag{Name: "compgen", Hidden: true}
1226  cli.VersionFlag = cli.BoolFlag{Name: "print-version, V"}
1227
1228  cli.HelpPrinter = func(w io.Writer, templ string, data interface{}) {
1229    fmt.Fprintf(w, "best of luck to you\n")
1230  }
1231  cli.VersionPrinter = func(c *cli.Context) {
1232    fmt.Fprintf(c.App.Writer, "version=%s\n", c.App.Version)
1233  }
1234  cli.OsExiter = func(c int) {
1235    fmt.Fprintf(cli.ErrWriter, "refusing to exit %d\n", c)
1236  }
1237  cli.ErrWriter = ioutil.Discard
1238  cli.FlagStringer = func(fl cli.Flag) string {
1239    return fmt.Sprintf("\t\t%s", fl.GetName())
1240  }
1241}
1242
1243type hexWriter struct{}
1244
1245func (w *hexWriter) Write(p []byte) (int, error) {
1246  for _, b := range p {
1247    fmt.Printf("%x", b)
1248  }
1249  fmt.Printf("\n")
1250
1251  return len(p), nil
1252}
1253
1254type genericType struct{
1255  s string
1256}
1257
1258func (g *genericType) Set(value string) error {
1259  g.s = value
1260  return nil
1261}
1262
1263func (g *genericType) String() string {
1264  return g.s
1265}
1266
1267func main() {
1268  app := cli.NewApp()
1269  app.Name = "kənˈtrīv"
1270  app.Version = "19.99.0"
1271  app.Compiled = time.Now()
1272  app.Authors = []cli.Author{
1273    cli.Author{
1274      Name:  "Example Human",
1275      Email: "human@example.com",
1276    },
1277  }
1278  app.Copyright = "(c) 1999 Serious Enterprise"
1279  app.HelpName = "contrive"
1280  app.Usage = "demonstrate available API"
1281  app.UsageText = "contrive - demonstrating the available API"
1282  app.ArgsUsage = "[args and such]"
1283  app.Commands = []cli.Command{
1284    cli.Command{
1285      Name:        "doo",
1286      Aliases:     []string{"do"},
1287      Category:    "motion",
1288      Usage:       "do the doo",
1289      UsageText:   "doo - does the dooing",
1290      Description: "no really, there is a lot of dooing to be done",
1291      ArgsUsage:   "[arrgh]",
1292      Flags: []cli.Flag{
1293        cli.BoolFlag{Name: "forever, forevvarr"},
1294      },
1295      Subcommands: cli.Commands{
1296        cli.Command{
1297          Name:   "wop",
1298          Action: wopAction,
1299        },
1300      },
1301      SkipFlagParsing: false,
1302      HideHelp:        false,
1303      Hidden:          false,
1304      HelpName:        "doo!",
1305      BashComplete: func(c *cli.Context) {
1306        fmt.Fprintf(c.App.Writer, "--better\n")
1307      },
1308      Before: func(c *cli.Context) error {
1309        fmt.Fprintf(c.App.Writer, "brace for impact\n")
1310        return nil
1311      },
1312      After: func(c *cli.Context) error {
1313        fmt.Fprintf(c.App.Writer, "did we lose anyone?\n")
1314        return nil
1315      },
1316      Action: func(c *cli.Context) error {
1317        c.Command.FullName()
1318        c.Command.HasName("wop")
1319        c.Command.Names()
1320        c.Command.VisibleFlags()
1321        fmt.Fprintf(c.App.Writer, "dodododododoodododddooooododododooo\n")
1322        if c.Bool("forever") {
1323          c.Command.Run(c)
1324        }
1325        return nil
1326      },
1327      OnUsageError: func(c *cli.Context, err error, isSubcommand bool) error {
1328        fmt.Fprintf(c.App.Writer, "for shame\n")
1329        return err
1330      },
1331    },
1332  }
1333  app.Flags = []cli.Flag{
1334    cli.BoolFlag{Name: "fancy"},
1335    cli.BoolTFlag{Name: "fancier"},
1336    cli.DurationFlag{Name: "howlong, H", Value: time.Second * 3},
1337    cli.Float64Flag{Name: "howmuch"},
1338    cli.GenericFlag{Name: "wat", Value: &genericType{}},
1339    cli.Int64Flag{Name: "longdistance"},
1340    cli.Int64SliceFlag{Name: "intervals"},
1341    cli.IntFlag{Name: "distance"},
1342    cli.IntSliceFlag{Name: "times"},
1343    cli.StringFlag{Name: "dance-move, d"},
1344    cli.StringSliceFlag{Name: "names, N"},
1345    cli.UintFlag{Name: "age"},
1346    cli.Uint64Flag{Name: "bigage"},
1347  }
1348  app.EnableBashCompletion = true
1349  app.UseShortOptionHandling = true
1350  app.HideHelp = false
1351  app.HideVersion = false
1352  app.BashComplete = func(c *cli.Context) {
1353    fmt.Fprintf(c.App.Writer, "lipstick\nkiss\nme\nlipstick\nringo\n")
1354  }
1355  app.Before = func(c *cli.Context) error {
1356    fmt.Fprintf(c.App.Writer, "HEEEERE GOES\n")
1357    return nil
1358  }
1359  app.After = func(c *cli.Context) error {
1360    fmt.Fprintf(c.App.Writer, "Phew!\n")
1361    return nil
1362  }
1363  app.CommandNotFound = func(c *cli.Context, command string) {
1364    fmt.Fprintf(c.App.Writer, "Thar be no %q here.\n", command)
1365  }
1366  app.OnUsageError = func(c *cli.Context, err error, isSubcommand bool) error {
1367    if isSubcommand {
1368      return err
1369    }
1370
1371    fmt.Fprintf(c.App.Writer, "WRONG: %#v\n", err)
1372    return nil
1373  }
1374  app.Action = func(c *cli.Context) error {
1375    cli.DefaultAppComplete(c)
1376    cli.HandleExitCoder(errors.New("not an exit coder, though"))
1377    cli.ShowAppHelp(c)
1378    cli.ShowCommandCompletions(c, "nope")
1379    cli.ShowCommandHelp(c, "also-nope")
1380    cli.ShowCompletions(c)
1381    cli.ShowSubcommandHelp(c)
1382    cli.ShowVersion(c)
1383
1384    categories := c.App.Categories()
1385    categories.AddCommand("sounds", cli.Command{
1386      Name: "bloop",
1387    })
1388
1389    for _, category := range c.App.Categories() {
1390      fmt.Fprintf(c.App.Writer, "%s\n", category.Name)
1391      fmt.Fprintf(c.App.Writer, "%#v\n", category.Commands)
1392      fmt.Fprintf(c.App.Writer, "%#v\n", category.VisibleCommands())
1393    }
1394
1395    fmt.Printf("%#v\n", c.App.Command("doo"))
1396    if c.Bool("infinite") {
1397      c.App.Run([]string{"app", "doo", "wop"})
1398    }
1399
1400    if c.Bool("forevar") {
1401      c.App.RunAsSubcommand(c)
1402    }
1403    c.App.Setup()
1404    fmt.Printf("%#v\n", c.App.VisibleCategories())
1405    fmt.Printf("%#v\n", c.App.VisibleCommands())
1406    fmt.Printf("%#v\n", c.App.VisibleFlags())
1407
1408    fmt.Printf("%#v\n", c.Args().First())
1409    if len(c.Args()) > 0 {
1410      fmt.Printf("%#v\n", c.Args()[1])
1411    }
1412    fmt.Printf("%#v\n", c.Args().Present())
1413    fmt.Printf("%#v\n", c.Args().Tail())
1414
1415    set := flag.NewFlagSet("contrive", 0)
1416    nc := cli.NewContext(c.App, set, c)
1417
1418    fmt.Printf("%#v\n", nc.Args())
1419    fmt.Printf("%#v\n", nc.Bool("nope"))
1420    fmt.Printf("%#v\n", nc.BoolT("nerp"))
1421    fmt.Printf("%#v\n", nc.Duration("howlong"))
1422    fmt.Printf("%#v\n", nc.Float64("hay"))
1423    fmt.Printf("%#v\n", nc.Generic("bloop"))
1424    fmt.Printf("%#v\n", nc.Int64("bonk"))
1425    fmt.Printf("%#v\n", nc.Int64Slice("burnks"))
1426    fmt.Printf("%#v\n", nc.Int("bips"))
1427    fmt.Printf("%#v\n", nc.IntSlice("blups"))
1428    fmt.Printf("%#v\n", nc.String("snurt"))
1429    fmt.Printf("%#v\n", nc.StringSlice("snurkles"))
1430    fmt.Printf("%#v\n", nc.Uint("flub"))
1431    fmt.Printf("%#v\n", nc.Uint64("florb"))
1432    fmt.Printf("%#v\n", nc.GlobalBool("global-nope"))
1433    fmt.Printf("%#v\n", nc.GlobalBoolT("global-nerp"))
1434    fmt.Printf("%#v\n", nc.GlobalDuration("global-howlong"))
1435    fmt.Printf("%#v\n", nc.GlobalFloat64("global-hay"))
1436    fmt.Printf("%#v\n", nc.GlobalGeneric("global-bloop"))
1437    fmt.Printf("%#v\n", nc.GlobalInt("global-bips"))
1438    fmt.Printf("%#v\n", nc.GlobalIntSlice("global-blups"))
1439    fmt.Printf("%#v\n", nc.GlobalString("global-snurt"))
1440    fmt.Printf("%#v\n", nc.GlobalStringSlice("global-snurkles"))
1441
1442    fmt.Printf("%#v\n", nc.FlagNames())
1443    fmt.Printf("%#v\n", nc.GlobalFlagNames())
1444    fmt.Printf("%#v\n", nc.GlobalIsSet("wat"))
1445    fmt.Printf("%#v\n", nc.GlobalSet("wat", "nope"))
1446    fmt.Printf("%#v\n", nc.NArg())
1447    fmt.Printf("%#v\n", nc.NumFlags())
1448    fmt.Printf("%#v\n", nc.Parent())
1449
1450    nc.Set("wat", "also-nope")
1451
1452    ec := cli.NewExitError("ohwell", 86)
1453    fmt.Fprintf(c.App.Writer, "%d", ec.ExitCode())
1454    fmt.Printf("made it!\n")
1455    return nil
1456  }
1457
1458  if os.Getenv("HEXY") != "" {
1459    app.Writer = &hexWriter{}
1460    app.ErrWriter = &hexWriter{}
1461  }
1462
1463  app.Metadata = map[string]interface{}{
1464    "layers":     "many",
1465    "explicable": false,
1466    "whatever-values": 19.99,
1467  }
1468
1469
1470  // ignore error so we don't exit non-zero and break gfmrun README example tests
1471  _ = app.Run(os.Args)
1472}
1473
1474func wopAction(c *cli.Context) error {
1475  fmt.Fprintf(c.App.Writer, ":wave: over here, eh\n")
1476  return nil
1477}
1478```
1479