commands.go 2.58 KB
Newer Older
1 2 3 4 5
// 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 using IPFS from outside of
// the Go language.
6 7 8
package commands

import (
9
	"bytes"
10
	"io"
11
	"sort"
12
	"strings"
13

14
	cmds "github.com/ipfs/go-ipfs/commands"
15 16 17 18 19
)

type Command struct {
	Name        string
	Subcommands []Command
20 21 22 23 24
	Options     []Option
}

type Option struct {
	Names []string
25 26
}

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

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

61 62 63 64 65 66
func cmd2outputCmd(name string, cmd *cmds.Command) Command {
	opts := make([]Option, len(cmd.Options))
	for i, opt := range cmd.Options {
		opts[i] = Option{opt.Names()}
	}

67 68 69
	output := Command{
		Name:        name,
		Subcommands: make([]Command, len(cmd.Subcommands)),
70
		Options:     opts,
71 72 73 74
	}

	i := 0
	for name, sub := range cmd.Subcommands {
75
		output.Subcommands[i] = cmd2outputCmd(name, sub)
76 77 78 79 80 81
		i++
	}

	return output
}

82
func cmdPathStrings(cmd *Command, showOptions bool) []string {
83
	var cmds []string
84

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

108 109 110
	recurse("", cmd)
	sort.Sort(sort.StringSlice(cmds))
	return cmds
111
}