Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CLI: discoverability and consistency #2542

Merged
merged 36 commits into from
Apr 28, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
4d38ee5
reduces help indent from 4 to 2 spaces
hackergrrl Apr 8, 2016
e124292
reduces horz/vert space taken by "ipfs" cmd
hackergrrl Apr 8, 2016
d1a296e
show subcommands on shorthelp
hackergrrl Apr 8, 2016
e5df829
Drops colons at the end of cmd headings.
hackergrrl Apr 8, 2016
d25f640
more consistent output between short-/long-help
hackergrrl Apr 8, 2016
dd2679d
Puts DESCRIPTION before SUBCOMMANDS.
hackergrrl Apr 8, 2016
b4f8f4e
Keeps ipfs cmd from outputting its subcmds twice.
hackergrrl Apr 8, 2016
e26625a
Removes redundant synopsis from "file"
hackergrrl Apr 8, 2016
8215e33
Removes extra whitespace from longhelp
hackergrrl Apr 8, 2016
aebe3b5
Consistent spacing whether SUBCMDS or not.
hackergrrl Apr 8, 2016
ef64a0c
Removes redundant SUBCMD output from ipfs object.
hackergrrl Apr 8, 2016
c43db2d
Removes redundant synopsis from "name"
hackergrrl Apr 8, 2016
5e4eacb
Newline after Description only if it exists.
hackergrrl Apr 8, 2016
7756618
Removes redundant synopsis from "bootstrap"
hackergrrl Apr 8, 2016
1a268b0
Removes redundant synopsis from "swarm"
hackergrrl Apr 8, 2016
23dca67
Removes trailing newline in ping help.
hackergrrl Apr 8, 2016
726bebd
Prints shorthelp on parse error.
hackergrrl Apr 8, 2016
2b201bc
tiny comment fixes
hackergrrl Apr 8, 2016
233989b
updates README usage
hackergrrl Apr 8, 2016
20b3e98
Don't include extra whitespace if no .MoreHelp
hackergrrl Apr 8, 2016
eb9de5f
description improvements
hackergrrl Apr 8, 2016
124c51d
Hides the obscure 'file' subcommand.
hackergrrl Apr 8, 2016
60f1fc1
Splits 'ipfs daemon' into Short and Long help.
hackergrrl Apr 8, 2016
2a41d45
Removes redundant synopsis from "config"
hackergrrl Apr 8, 2016
bd70017
Wraps lines to keep from going over 80.
hackergrrl Apr 8, 2016
be15ed8
specify repo separately
hackergrrl Apr 12, 2016
4aa5733
s/structure/hierarchy
hackergrrl Apr 12, 2016
479ef39
missing .
hackergrrl Apr 13, 2016
cdb8625
Removes trailing colon from 'usage' test.
hackergrrl Apr 20, 2016
cb029a0
Updates sharness test error messages.
hackergrrl Apr 20, 2016
73d1d96
Removes trailing colon from 'usage' test.
hackergrrl Apr 20, 2016
17509ec
Updates add-symlink to use /bin/sh.
hackergrrl Apr 20, 2016
0b861e4
Removes "hierarchy".
hackergrrl Apr 20, 2016
af79a84
Updates "ipfs ping" synopsis.
hackergrrl Apr 20, 2016
bd08815
Updates t0040 with latest wording.
hackergrrl Apr 20, 2016
20eb0c8
Removes unnecessary daemon setup.
Apr 25, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 47 additions & 50 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,56 +122,53 @@ or install it from source with `go get -u github.com/ipfs/ipfs-update`.
## Usage

```
USAGE:

ipfs - global p2p merkle-dag filesystem

ipfs [<flags>] <command> [<arg>] ...

BASIC COMMANDS

init Initialize ipfs local configuration
add <path> Add an object to ipfs
cat <ref> Show ipfs object data
get <ref> Download ipfs objects
ls <ref> List links from an object
refs <ref> List hashes of links from an object

DATA STRUCTURE COMMANDS

block Interact with raw blocks in the datastore
object Interact with raw dag nodes
file Interact with Unix filesystem objects

ADVANCED COMMANDS

daemon Start a long-running daemon process
mount Mount an ipfs read-only mountpoint
resolve Resolve any type of name
name Publish or resolve IPNS names
dns Resolve DNS links
pin Pin objects to local storage
repo gc Garbage collect unpinned objects

NETWORK COMMANDS

id Show info about ipfs peers
bootstrap Add or remove bootstrap peers
swarm Manage connections to the p2p network
dht Query the DHT for values or peers
ping Measure the latency of a connection
diag Print diagnostics

TOOL COMMANDS

config Manage configuration
version Show ipfs version information
update Download and apply go-ipfs updates
commands List all available commands

Use 'ipfs <command> --help' to learn more about each command.


ipfs - Global p2p merkle-dag filesystem.

ipfs [<flags>] <command> [<arg>] ...

SUBCOMMANDS
BASIC COMMANDS
init Initialize ipfs local configuration
add <path> Add a file to ipfs
cat <ref> Show ipfs object data
get <ref> Download ipfs objects
ls <ref> List links from an object
refs <ref> List hashes of links from an object

DATA STRUCTURE COMMANDS
block Interact with raw blocks in the datastore
object Interact with raw dag nodes
files Interact with objects as if they were a unix filesystem

ADVANCED COMMANDS
daemon Start a long-running daemon process
mount Mount an ipfs read-only mountpoint
resolve Resolve any type of name
name Publish or resolve IPNS names
dns Resolve DNS links
pin Pin objects to local storage
repo Manipulate an IPFS repository

NETWORK COMMANDS
id Show info about ipfs peers
bootstrap Add or remove bootstrap peers
swarm Manage connections to the p2p network
dht Query the DHT for values or peers
ping Measure the latency of a connection
diag Print diagnostics

TOOL COMMANDS
config Manage configuration
version Show ipfs version information
update Download and apply go-ipfs updates
commands List all available commands

Use 'ipfs <command> --help' to learn more about each command.

ipfs uses a repository in the local file system. By default, the repo is located
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where? ipfs uses a repository...? I think this use is IPFS as a command line tool, which is referred to as ipfs not IPFS. (This must be true here, since IPFS does not use a repository in the local file system -- it's abstracted away at the highest level.)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, you are right :) I read it as 'IPFS, the system', not the cli

at ~/.ipfs. To change the repo location, set the $IPFS_PATH environment variable:

export IPFS_PATH=/path/to/ipfsrepo
```

## Getting Started
Expand Down
3 changes: 2 additions & 1 deletion cmd/ipfs/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ over the network. Most applications that use IPFS will do so by
communicating with a daemon over the HTTP API. While the daemon is
running, calls to 'ipfs' commands will be sent over the network to
the daemon.

`,
LongDescription: `
The daemon will start listening on ports on the network, which are
documented in (and can be modified through) 'ipfs config Addresses'.
For example, to change the 'Gateway' port:
Expand Down
2 changes: 0 additions & 2 deletions cmd/ipfs/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ var initCmd = &cmds.Command{
ShortDescription: `
Initializes IPFS configuration files and generates a new keypair.

IPFS_PATH environment variable

ipfs uses a repository in the local file system. By default, the repo is located
at ~/.ipfs. To change the repo location, set the $IPFS_PATH environment variable:

Expand Down
2 changes: 1 addition & 1 deletion cmd/ipfs/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ func main() {
if invoc.cmd != nil {
// we need a newline space.
fmt.Fprintf(os.Stderr, "\n")
printMetaHelp(os.Stderr)
printHelp(false, os.Stderr)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's the diff here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

printMetaHelp will print "Use 'ipfs %s --help' for information about this command", while printHelp(false, writer) will print the command's short help (subcommands, tagline, etc).

I highly recommend building the branch and playing with the changes live!

}
os.Exit(1)
}
Expand Down
38 changes: 22 additions & 16 deletions commands/cli/helptext.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const (

whitespace = "\r\n\t "

indentStr = " "
indentStr = " "
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to be more of enforcing a personal opinion or habit.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No -- this falls under "Terminal formatting / sizing: reduce horizontal indent on help docs".

Let's reduce the tool's horizontal footprint so 80 char terminals don't experience weird line wrap. (Fully dynamic smart wrapping would be even cooler, but that's a bit bigger scope than this.)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that the commands lib should change the formatting of the helptext at all, otherwise we might try to format things a certain way only to have the code screw things up.

A better option I think is to have a commands_test.go file (or similar) that goes through each command and ensures their helptext looks correct (tabs vs spaces, etc)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed that this should be a concern of the library user and not the core commands lib. I can file an issue for that -- it seems like a bigger job than what's in scope for this PR.

)

type helpFields struct {
Expand Down Expand Up @@ -74,38 +74,38 @@ func (f *helpFields) IndentAll() {

const usageFormat = "{{if .Usage}}{{.Usage}}{{else}}{{.Path}}{{if .ArgUsage}} {{.ArgUsage}}{{end}} - {{.Tagline}}{{end}}"

const longHelpFormat = `
const longHelpFormat = `USAGE
{{.Indent}}{{template "usage" .}}

{{if .Arguments}}ARGUMENTS:
{{if .Arguments}}ARGUMENTS

{{.Arguments}}

{{end}}{{if .Options}}OPTIONS:
{{end}}{{if .Options}}OPTIONS

{{.Options}}

{{end}}{{if .Subcommands}}SUBCOMMANDS:
{{end}}{{if .Description}}DESCRIPTION

{{.Description}}

{{end}}{{if .Subcommands}}SUBCOMMANDS
{{.Subcommands}}

{{.Indent}}Use '{{.Path}} <subcmd> --help' for more information about each command.

{{end}}{{if .Description}}DESCRIPTION:

{{.Description}}

{{end}}
`
const shortHelpFormat = `USAGE:

const shortHelpFormat = `USAGE
{{.Indent}}{{template "usage" .}}
{{if .Synopsis}}
{{.Synopsis}}
{{end}}{{if .Description}}
{{.Description}}
{{end}}
{{if .MoreHelp}}Use '{{.Path}} --help' for more information about this command.
{{end}}{{if .Subcommands}}
SUBCOMMANDS
{{.Subcommands}}
{{end}}{{if .MoreHelp}}
Use '{{.Path}} --help' for more information about this command.
{{end}}
`

Expand All @@ -119,7 +119,7 @@ func init() {
shortHelpTemplate = template.Must(usageTemplate.New("shortHelp").Parse(shortHelpFormat))
}

// LongHelp returns a formatted CLI helptext string, generated for the given command
// LongHelp writes a formatted CLI helptext string to a Writer for the given command
func LongHelp(rootName string, root *cmds.Command, path []string, out io.Writer) error {
cmd, err := root.Get(path)
if err != nil {
Expand Down Expand Up @@ -169,7 +169,7 @@ func LongHelp(rootName string, root *cmds.Command, path []string, out io.Writer)
return longHelpTemplate.Execute(out, fields)
}

// ShortHelp returns a formatted CLI helptext string, generated for the given command
// ShortHelp writes a formatted CLI helptext string to a Writer for the given command
func ShortHelp(rootName string, root *cmds.Command, path []string, out io.Writer) error {
cmd, err := root.Get(path)
if err != nil {
Expand All @@ -193,10 +193,16 @@ func ShortHelp(rootName string, root *cmds.Command, path []string, out io.Writer
Tagline: cmd.Helptext.Tagline,
Synopsis: cmd.Helptext.Synopsis,
Description: cmd.Helptext.ShortDescription,
Subcommands: cmd.Helptext.Subcommands,
Usage: cmd.Helptext.Usage,
MoreHelp: (cmd != root),
}

// autogen fields that are empty
if len(fields.Subcommands) == 0 {
fields.Subcommands = strings.Join(subcommandText(cmd, rootName, path), "\n")
}

// trim the extra newlines (see TrimNewlines doc)
fields.TrimNewlines()

Expand Down
6 changes: 2 additions & 4 deletions core/commands/add.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,9 @@ const (

var AddCmd = &cmds.Command{
Helptext: cmds.HelpText{
Tagline: "Add a file to ipfs.",
Tagline: "Add a file or directory to ipfs.",
ShortDescription: `
Adds contents of <path> to ipfs. Use -r to add directories.
Note that directories are added recursively, to form the ipfs
MerkleDAG.
Adds contents of <path> to ipfs. Use -r to add directories (recursively).
`,
LongDescription: `
Adds contents of <path> to ipfs. Use -r to add directories.
Expand Down
5 changes: 0 additions & 5 deletions core/commands/bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,6 @@ var peerOptionDesc = "A peer to add to the bootstrap list (in the format '<multi
var BootstrapCmd = &cmds.Command{
Helptext: cmds.HelpText{
Tagline: "Show or edit the list of bootstrap peers.",
Synopsis: `
ipfs bootstrap list - Show peers in the bootstrap list
ipfs bootstrap add <peer>... - Add peers to the bootstrap list
ipfs bootstrap rm <peer>... - Removes peers from the bootstrap list
`,
ShortDescription: `
Running 'ipfs bootstrap' with no arguments will run 'ipfs bootstrap list'.
` + bootstrapSecurityWarning,
Expand Down
7 changes: 0 additions & 7 deletions core/commands/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,6 @@ type ConfigField struct {
var ConfigCmd = &cmds.Command{
Helptext: cmds.HelpText{
Tagline: "Get and set IPFS config values.",
Synopsis: `
ipfs config <key> - Get value of <key>
ipfs config <key> <value> - Set value of <key> to <value>
ipfs config show - Show config file
ipfs config edit - Edit config file in $EDITOR
ipfs config replace <file> - Replaces the config file with <file>
`,
ShortDescription: `
'ipfs config' controls configuration variables. It works like 'git config'.
The configuration values are stored in a config file inside your IPFS
Expand Down
4 changes: 0 additions & 4 deletions core/commands/name.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,6 @@ type IpnsEntry struct {
var NameCmd = &cmds.Command{
Helptext: cmds.HelpText{
Tagline: "IPFS namespace (IPNS) tool.",
Synopsis: `
ipfs name publish [<name>] <ipfs-path> - Publish an object to IPNS
ipfs name resolve [<name>] - Gets the value currently published at an IPNS name
`,
ShortDescription: `
IPNS is a PKI namespace, where names are the hashes of public keys, and
the private key enables publishing new (signed) values. In both publish
Expand Down
10 changes: 0 additions & 10 deletions core/commands/object/object.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,6 @@ var ObjectCmd = &cmds.Command{
ShortDescription: `
'ipfs object' is a plumbing command used to manipulate DAG objects
directly.`,
Synopsis: `
ipfs object data <key> - Outputs raw bytes in an object
ipfs object diff <key1> <key2> - Diffs two given objects
ipfs object get <key> - Get the DAG node named by <key>
ipfs object links <key> - Outputs links pointed to by object
ipfs object new <template> - Create new ipfs objects
ipfs object patch <args> - Create new object from old ones
ipfs object put <data> - Stores input, outputs its key
ipfs object stat <key> - Outputs statistics of object
`,
},

Subcommands: map[string]*cmds.Command{
Expand Down
2 changes: 1 addition & 1 deletion core/commands/pin.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ var addPinCmd = &cmds.Command{

var rmPinCmd = &cmds.Command{
Helptext: cmds.HelpText{
Tagline: "Removes the pinned object from local storage. (By default, recursively. Use -r=false for direct pins).",
Tagline: "Removes the pinned object from local storage.",
ShortDescription: `
Removes the pin from the given object allowing it to be garbage
collected if needed. (By default, recursively. Use -r=false for direct pins)
Expand Down
6 changes: 2 additions & 4 deletions core/commands/ping.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,8 @@ type PingResult struct {

var PingCmd = &cmds.Command{
Helptext: cmds.HelpText{
Tagline: "Send echo request packets to IPFS hosts.",
Synopsis: `
Send pings to a peer using the routing system to discover its address
`,
Tagline: "Send echo request packets to IPFS hosts.",
Synopsis: "Send pings to a peer to verify connectivity and determine latency.",
ShortDescription: `
'ipfs ping' is a tool to test sending data to other nodes. It finds nodes
via the routing system, sends pings, waits for pongs, and prints out round-
Expand Down
3 changes: 2 additions & 1 deletion core/commands/refs.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ var RefsCmd = &cmds.Command{
Helptext: cmds.HelpText{
Tagline: "Lists links (references) from an object.",
ShortDescription: `
Displays the link hashes an IPFS or IPNS object(s) contains, with the following format:
Lists the hashes of all the links an IPFS or IPNS object(s) contains,
with the following format:

<link base58 hash>

Expand Down
Loading