commands.go 2.49 KB
Newer Older
1 2 3 4 5 6 7
/*
Package commands implements the IPFS command interface

Using github.com/ipfs/go-ipfs/commands to define the command line and
HTTP APIs.  This is the interface available to folks consuming IPFS
from outside of the Go language.
*/
8 9 10
package commands

import (
11
	"bytes"
12
	"io"
13
	"sort"
14
	"strings"
15

16
	cmds "github.com/ipfs/go-ipfs/commands"
17 18 19 20 21
)

type Command struct {
	Name        string
	Subcommands []Command
rht's avatar
rht committed
22
	Options     []cmds.Option
23
	ShowOptions bool
24 25
}

26
const (
27
	flagsOptionName = "flags"
28 29
)

30 31 32 33
// CommandsCmd takes in a root command,
// and returns a command that lists the subcommands in that root
func CommandsCmd(root *cmds.Command) *cmds.Command {
	return &cmds.Command{
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
34 35 36 37
		Helptext: cmds.HelpText{
			Tagline:          "List all available commands.",
			ShortDescription: `Lists all available commands (and subcommands) and exits.`,
		},
38 39 40
		Options: []cmds.Option{
			cmds.BoolOption(flagsOptionName, "f", "Show command flags"),
		},
41
		Run: func(req cmds.Request, res cmds.Response) {
42
			showOptions, _, _ := req.Option(flagsOptionName).Bool()
43 44
			rootCmd := cmd2outputCmd("ipfs", root, showOptions)
			res.SetOutput(&rootCmd)
45
		},
46
		Marshalers: cmds.MarshalerMap{
47
			cmds.Text: func(res cmds.Response) (io.Reader, error) {
48
				v := res.Output().(*Command)
49
				buf := new(bytes.Buffer)
50 51 52
				for _, s := range cmdPathStrings(v) {
					buf.Write([]byte(s + "\n"))
				}
53
				return buf, nil
54
			},
55
		},
56
		Type: Command{},
57
	}
58 59
}

60
func cmd2outputCmd(name string, cmd *cmds.Command, showOptions bool) Command {
61 62 63
	output := Command{
		Name:        name,
		Subcommands: make([]Command, len(cmd.Subcommands)),
rht's avatar
rht committed
64
		Options:     cmd.Options,
65
		ShowOptions: showOptions,
66 67 68 69
	}

	i := 0
	for name, sub := range cmd.Subcommands {
70
		output.Subcommands[i] = cmd2outputCmd(name, sub, showOptions)
71 72 73 74 75 76
		i++
	}

	return output
}

77 78
func cmdPathStrings(cmd *Command) []string {
	var cmds []string
79

80 81
	var recurse func(prefix string, cmd *Command)
	recurse = func(prefix string, cmd *Command) {
rht's avatar
rht committed
82 83
		newPrefix := prefix + cmd.Name
		cmds = append(cmds, newPrefix)
84
		if prefix != "" && cmd.ShowOptions {
rht's avatar
rht committed
85
			for _, option := range cmd.Options {
86 87 88 89 90 91 92 93 94
				names := option.Names()
				var cmdOpts []string
				for _, flag := range names {
					if len(flag) == 1 {
						flag = "-" + flag
					} else {
						flag = "--" + flag
					}
					cmdOpts = append(cmdOpts, newPrefix+" "+flag)
rht's avatar
rht committed
95
				}
96
				cmds = append(cmds, strings.Join(cmdOpts, " / "))
rht's avatar
rht committed
97 98
			}
		}
99
		for _, sub := range cmd.Subcommands {
rht's avatar
rht committed
100
			recurse(newPrefix+" ", &sub)
101
		}
102 103
	}

104 105 106
	recurse("", cmd)
	sort.Sort(sort.StringSlice(cmds))
	return cmds
107
}