diff --git a/go.mod b/go.mod index b9fb5da..26daea9 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4 github.com/pkg/errors v0.8.1 // indirect github.com/stretchr/testify v1.3.0 + go.coder.com/cli v0.1.0 go.coder.com/flog v0.0.0-20190129195112-eaed154a0db8 go.coder.com/retry v0.0.0-20180926062817-cf12c95974ac golang.org/x/crypto v0.0.0-20190422183909-d864b10871cd diff --git a/go.sum b/go.sum index 8ebc634..c24ed7b 100644 --- a/go.sum +++ b/go.sum @@ -17,6 +17,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.1.4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +go.coder.com/cli v0.1.0 h1:ZAjpjXJxMnwj1TqXUi7nnXXuxiPRfwfoC2kViN93oMM= +go.coder.com/cli v0.1.0/go.mod h1:pbVagI9YH/HHMManxPFML4P527GDREwsb+yciZ7mtB8= go.coder.com/flog v0.0.0-20190129195112-eaed154a0db8 h1:PtQ3moPi4EAz3cyQhkUs1IGIXa2QgJpP60yMjOdu0kk= go.coder.com/flog v0.0.0-20190129195112-eaed154a0db8/go.mod h1:83JsYgXYv0EOaXjIMnaZ1Fl6ddNB3fJnDZ/8845mUJ8= go.coder.com/retry v0.0.0-20180926062817-cf12c95974ac h1:ekdpsuykRy/E+SDq5BquFomNhRCk8OOyhtnACW9Bi50= diff --git a/main.go b/main.go index 2d0866f..a09df53 100644 --- a/main.go +++ b/main.go @@ -6,9 +6,9 @@ import ( "math/rand" "os" "strings" - "text/tabwriter" "time" + "go.coder.com/cli" "go.coder.com/flog" ) @@ -18,44 +18,65 @@ func init() { const helpTabWidth = 5 -var helpTab = strings.Repeat(" ", helpTabWidth) - -// version is overwritten by ci/build.sh. -var version string +var ( + helpTab = strings.Repeat(" ", helpTabWidth) + // version is overwritten by ci/build.sh. + version string +) func main() { - var ( - skipSyncFlag = flag.Bool("skipsync", false, "skip syncing local settings and extensions to remote host") - sshFlags = flag.String("ssh-flags", "", "custom SSH flags") - syncBack = flag.Bool("b", false, "sync extensions back on termination") - printVersion = flag.Bool("version", false, "print version information and exit") - ) + cli.RunRoot(&rootCmd{}) +} + +var _ interface { + cli.Command + cli.FlaggedCommand +} = new(rootCmd) - flag.Usage = usage +type rootCmd struct { + skipSync bool + syncBack bool + printVersion bool + sshFlags string +} + +func (c *rootCmd) Spec() cli.CommandSpec { + return cli.CommandSpec{ + Name: "sshcode", + Usage: c.usage(), + Desc: c.description(), + } +} + +func (c *rootCmd) RegisterFlags(fl *flag.FlagSet) { + fl.BoolVar(&c.skipSync, "skipsync", false, "skip syncing local settings and extensions to remote host") + fl.BoolVar(&c.syncBack, "b", false, "sync extensions back on termination") + fl.BoolVar(&c.printVersion, "version", false, "print version information and exit") + fl.StringVar(&c.sshFlags, "ssh-flags", "", "custom SSH flags") +} - flag.Parse() - if *printVersion { +func (c *rootCmd) Run(fl *flag.FlagSet) { + if c.printVersion { fmt.Printf("%v\n", version) os.Exit(0) } - host := flag.Arg(0) - + host := fl.Arg(0) if host == "" { // If no host is specified output the usage. - flag.Usage() + fl.Usage() os.Exit(1) } - dir := flag.Arg(1) + dir := fl.Arg(1) if dir == "" { dir = "~" } err := sshCode(host, dir, options{ - skipSync: *skipSyncFlag, - sshFlags: *sshFlags, - syncBack: *syncBack, + skipSync: c.skipSync, + sshFlags: c.sshFlags, + syncBack: c.syncBack, }) if err != nil { @@ -63,53 +84,25 @@ func main() { } } -func usage() { - fmt.Printf(`Usage: %v [FLAGS] HOST [DIR] -Start VS Code via code-server over SSH. +func (c *rootCmd) usage() string { + return "[FLAGS] HOST [DIR]" +} + +func (c *rootCmd) description() string { + return fmt.Sprintf(`Start VS Code via code-server over SSH. Environment variables: - %v use special VS Code settings dir. - %v use special VS Code extensions dir. +%v%v use special VS Code settings dir. +%v%v use special VS Code extensions dir. More info: https://github.com/cdr/sshcode Arguments: %vHOST is passed into the ssh command. Valid formats are '' or 'gcp:'. -%vDIR is optional. - -%v`, - os.Args[0], - vsCodeConfigDirEnv, - vsCodeExtensionsDirEnv, +%vDIR is optional.`, + helpTab, vsCodeConfigDirEnv, + helpTab, vsCodeExtensionsDirEnv, helpTab, helpTab, - flagHelp(), ) - -} - -// flagHelp generates a friendly help string for all globally registered command -// line flags. -func flagHelp() string { - var bd strings.Builder - - w := tabwriter.NewWriter(&bd, 3, 10, helpTabWidth, ' ', 0) - - fmt.Fprintf(w, "Flags:\n") - var count int - flag.VisitAll(func(f *flag.Flag) { - count++ - if f.DefValue == "" { - fmt.Fprintf(w, "\t-%v\t%v\n", f.Name, f.Usage) - } else { - fmt.Fprintf(w, "\t-%v\t%v\t(%v)\n", f.Name, f.Usage, f.DefValue) - } - }) - if count == 0 { - return "\n" - } - - w.Flush() - - return bd.String() }