Skip to content

Commit

Permalink
Merge pull request #1 from kristofferahl/feature/required-options
Browse files Browse the repository at this point in the history
Feature: Required options
  • Loading branch information
kristofferahl authored Sep 11, 2021
2 parents c9d141a + 9ad29c9 commit 8cf5cc4
Show file tree
Hide file tree
Showing 19 changed files with 315 additions and 98 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ name: CI

on:
push:
branches: [master]
branches:
- master
- feature/*
pull_request:
branches: [master]

Expand Down
51 changes: 37 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
Declarative **command line builder** for teams and one man bands

## Use cases

- Build a feature rich CLI from scratch using only scripts and yaml
- Bundle existing scripts and tools as a single CLI
- Encode best practices and team conventions for using scripts and dev/ops tools

## Feature highlights

- **Declarative**: Add new commands and options and run them at once. No need to re-compile.
- **Unified syntax**: Provides a standard for using commands and options.
- **Supports multi level commands**: `mycli get status` and `mycli get files`
Expand All @@ -18,51 +20,59 @@ Declarative **command line builder** for teams and one man bands
- **Easy setup**: Download centry, create a manifest file and you are good to go

## Full documentation

- v1 - [./docs/index.md](./docs/index.md)

## Install

### Mac

```bash
curl -L https://github.com/kristofferahl/go-centry/releases/download/v1.0.0/go-centry_1.0.0_Darwin_x86_64.tar.gz | tar -xzv -C /usr/local/bin/
```

### Linux

```bash
curl -L https://github.com/kristofferahl/go-centry/releases/download/v1.0.0/go-centry_1.0.0_Linux_x86_64.tar.gz | tar -xzv -C /usr/local/bin/
```

## Getting started

**The documentation and examples below assumes that**

1. You are running `bash` version 3.2 or later
1. You have "installed" the `go-centry_*` binary for your OS and made it available in your path as `mycli` (by renaming the file)
1. You have created an empty directory to hold your commands and manifest file

## Setup

1. Create the manifest file for the CLI and name it `centry.yaml` by running the following command in your shell.
```bash
echo "commands: []
config:
name: mycli" > centry.yaml
```
```bash
echo "commands: []
config:
name: mycli" > centry.yaml
```
2. Verify that it's working by running
```
mycli --help
```
```
mycli --help
```
This should display the contextual help for the cli and the name **mycli** at the top.

## The manifest file

This is where you define root level commands and options, do configuration overrides and import scripts to be available for all your commands.

By default, `centry` will look for a `centry.yaml` file in the **current directory**. You may change the location and name of the manifest file but this requires you to let centry know where to find it. This can be done by setting the environment variable `CENTRY_FILE` or by way of passing `--centry-file <path>` as the **first** argument.

## Commands

In `centry`, commands are simple shell scripts with a matching function name in it.

Let's start by creating a file called `hello.sh` with the following content.

*`// file: hello.sh`*
_`// file: hello.sh`_

```
#!/usr/bin/env bash
Expand All @@ -73,7 +83,8 @@ hello() {

Before you can use the `hello` function as a command, you need to tell `centry` where to find it. Open `centry.yaml` in an editor of choise and modify it to look like this:

*`// file: centry.yaml`*
_`// file: centry.yaml`_

```yaml
commands:
- name: hello
Expand All @@ -85,17 +96,20 @@ config:
```
You should now be able to able to run the command.
```bash
mycli hello ↵
Hello centry
```

## Options

In `centry`, options are flags you use to pass named arguments to your command functions. This enables easier discovery of your cli and less friction for users. They may be specified in long (`--option`) or short (`-o`) form.

Let's add a `--name` option to the hello command. This is done by adding `annotations` in your script. Edit `hello.sh` to look like this.

*`// file: hello.sh`*
_`// file: hello.sh`_

```
#!/usr/bin/env bash
Expand All @@ -106,20 +120,23 @@ hello() {
```

Running the `hello` command again would look like this

```bash
mycli hello ↵
Hello
```

To pass a name to be echoed back to you, call the command with the `--name` option.

```bash
mycli hello --name William ↵
Hello William
```

If you want to add a description for the `--name` option you should add an additional annotation to the `hello.sh` file.

*`// file: hello.sh`*
_`// file: hello.sh`_

```
#!/usr/bin/env bash
Expand All @@ -129,7 +146,9 @@ hello() {
echo "Hello ${NAME}"
}
```

Displaying the contextual help (using the `--help` option) should now look something like this.

```bash
mycli hello --help ↵
NAME:
Expand All @@ -144,9 +163,11 @@ OPTIONS:
```

## Arguments

A command may also accept any number of arguments. All arguments not matching an option of a command will be passed on to the function.

*`// file: hello.sh`*
_`// file: hello.sh`_

```
#!/usr/bin/env bash
Expand All @@ -159,6 +180,7 @@ hello() {
```

NOTE: Arguments must always be passed after the last option.

```bash
mycli hello --name William arg1 arg2 ↵
Hello William
Expand All @@ -170,14 +192,15 @@ Arguments (2): arg1 arg2
**NOTE: Only available for Bash**

To make discovery of `mycli` easier, we may want to enable bash completions. Follow the steps below to set it up.

```bash
curl -o bash_autocomplete https://raw.githubusercontent.com/kristofferahl/go-centry/master/bash_autocomplete
PROG=mycli source bash_autocomplete
```

Now, let try it out by typing `mycli` followed by a space and then hit `tab`. This will display any command available at the root level. If there is only one, the command name will be autocompleted. It works for options too.

```bash
mycli -- ➡
--centry-config-log-level --centry-quiet --help
```

38 changes: 22 additions & 16 deletions cmd/centry/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ import (
"github.com/urfave/cli/v2"
)

func withCommandDefaults(c *cli.Command) *cli.Command {
if c.CustomHelpTemplate == "" {
c.CustomHelpTemplate = commandHelpTemplate
}
c.HideHelpCommand = true
return c
}

func registerInternalCommands(runtime *Runtime) {
context := runtime.context

Expand All @@ -22,15 +30,15 @@ func registerInternalCommands(runtime *Runtime) {
"command": "serve",
}),
}
internalCmd := &cli.Command{
internalCmd := withCommandDefaults(&cli.Command{
Name: "internal",
Usage: "Internal centry commands",
UsageText: "",
Hidden: context.manifest.Config.HideInternalCommands,
Subcommands: []*cli.Command{
serveCmd.ToCLICommand(),
},
}
})
runtime.cli.Commands = append(runtime.cli.Commands, internalCmd)
}
}
Expand Down Expand Up @@ -93,13 +101,12 @@ func registerManifestCommands(runtime *Runtime, options *cmd.OptionsSet) {
runtime.cli.Commands = append(runtime.cli.Commands, cliCmd)
} else {
// add placeholder
runtime.cli.Commands = append(runtime.cli.Commands, &cli.Command{
Name: cmdKeyPart,
Usage: cmdDescription,
UsageText: cmdHelp,
HideHelpCommand: true,
Action: nil,
})
runtime.cli.Commands = append(runtime.cli.Commands, withCommandDefaults(&cli.Command{
Name: cmdKeyPart,
Usage: cmdDescription,
UsageText: cmdHelp,
Action: nil,
}))
}
}
root = getCommand(runtime.cli.Commands, cmdKeyPart)
Expand All @@ -110,13 +117,12 @@ func registerManifestCommands(runtime *Runtime, options *cmd.OptionsSet) {
root.Subcommands = append(root.Subcommands, cliCmd)
} else {
// add placeholder
root.Subcommands = append(root.Subcommands, &cli.Command{
Name: cmdKeyPart,
Usage: "...",
UsageText: "",
HideHelpCommand: true,
Action: nil,
})
root.Subcommands = append(root.Subcommands, withCommandDefaults(&cli.Command{
Name: cmdKeyPart,
Usage: "...",
UsageText: "",
Action: nil,
}))
}
}
root = getCommand(root.Subcommands, cmdKeyPart)
Expand Down
20 changes: 19 additions & 1 deletion cmd/centry/help.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,26 @@ COMMANDS:{{range .VisibleCategories}}{{if .Name}}
GLOBAL OPTIONS:
{{range $index, $option := .VisibleFlags}}{{if $index}}
{{end}}{{$option}}{{end}}{{end}}{{if .Copyright}}
{{end}}{{$option}}{{if $option.Required}}{{if or ($option.Usage) ($option.Value)}} {{end}}(required: true){{end}}{{end}}{{end}}{{if .Copyright}}
COPYRIGHT:
{{.Copyright}}{{end}}
`

var commandHelpTemplate = `NAME:
{{.HelpName}} - {{.Usage}}
USAGE:
{{if .UsageText}}{{.UsageText | nindent 3 | trim}}{{else}}{{.HelpName}}{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Category}}
CATEGORY:
{{.Category}}{{end}}{{if .Description}}
DESCRIPTION:
{{.Description | nindent 3 | trim}}{{end}}{{if .VisibleFlags}}
OPTIONS:
{{range .VisibleFlags}}{{.}}{{if .Required}}{{if or (.Usage) (.Value)}} {{end}}(required: true){{end}}
{{end}}{{end}}
`

Loading

0 comments on commit 8cf5cc4

Please sign in to comment.