Skip to content

Commit

Permalink
📝 command properties docs
Browse files Browse the repository at this point in the history
  • Loading branch information
jcaillon committed May 24, 2024
1 parent 3a524ce commit 4f650c7
Show file tree
Hide file tree
Showing 4 changed files with 190 additions and 25 deletions.
180 changes: 169 additions & 11 deletions docs/content/docs/025.command-properties/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,187 @@ weight: 25
url: /docs/command-properties
---

This page describes the properties available to define a command.

You can check the [showcase commands][showcase-examples] to get definition examples.

## 🫚 Top level properties

The available properties are:

| Property | Default value | Description |
|----------|---------------|-------------|
| **command** | N/A | The name with which your command can be called by the user. E.g. `mycmd` will be accessible with `valet mycmd`. |
| **sudo** | | `true` if your command uses `sudo`; in which case we will prompt the user for sudo password before executing the command. `false` otherwise. |
| **shortDescription** | | shortly describe your command; this will appear next to your command name in the valet menu. |
| **description** | | long description of your command and its purpose. |
| **options** | | a list of options for your command. Don't forget that, by definition, an option is optional (i.e. it is not mandatory like an argument). If you expect an option to be defined, then it is an argument. |
| **arguments** | | a list of mandatory arguments for your command. If the user does not provide an argument, your command should fail. Otherwise, that means it is an option, not an argument. |
| **examples** | | a list of examples for your command. |
### ✔️ command

All commands will have, by default, an `-h, --help` option to display the help of this command.
The name with which your command can be called by the user. E.g. `mycmd` will be accessible with `valet mycmd`.

## 🎚️ Options
| Mandatory? | Default value? |
|----------|---------------|
| yes ✔️ | N/A |

### ✔️ function

The name of the function that corresponds to the command. This is the function that will be called by Valet when the user executes this command.

| Mandatory? | Default value? |
|----------|---------------|
| yes ✔️ | N/A |

### ✔️ shortDescription

Shortly describe your command. This will appear next to your command name in the valet menu.

This should be a single, short, line.

| Mandatory? | Default value? |
|----------|---------------|
| yes ✔️ | N/A |

### ✔️ description

Long description of your command and its purpose. It will display when getting the help/usage on the command using `valet help command` or `valet command --help`.

| Mandatory? | Default value? |
|----------|---------------|
| yes ✔️ | N/A |

### sudo

Set to `true` if you intend to use `sudo` in your command. It will define a `SUDO` variable that you should instead (e.g. `${SUDO} cp stuff /usr/bin/local/stuff` instead of `sudo cp stuff /usr/bin/local/stuff`).

The idea is to make your command compatible for systems with and without `sudo`. The variable `SUDO` will be defined as empty if the sudo command can not be found.

If `true`, it will prompt the user for sudo password before executing the command.

| Mandatory? | Default value? |
|----------|---------------|
| no | false |

### hideInMenu

Set to `true` if you do not want this command to appear in the Valet menu. The command will still get listed in the help/usage of valet.

| Mandatory? | Default value? |
|----------|---------------|
| no | false |

### arguments

A list of arguments for your command. See [Arguments](#-arguments) for the details of an argument.

| Mandatory? | Default value? |
|----------|---------------|
| no | N/A |

### options

A list of options for your command. See [Options](#️-options) for the details of an option.

By definition, an option is optional (i.e. it is not mandatory like an argument). If you expect an option to be defined, then it is an argument.

{{< callout type="info" emoji="💡" >}}
All commands have, by default, an `-h, --help` option to display the help of the command.
{{< /callout >}}

| Mandatory? | Default value? |
|----------|---------------|
| no | N/A |

### examples

A list of examples for your command. See [Examples](#-examples) for the details of an example.

They are used exclusively in the command help/usage text.

## 💬 Arguments

Arguments are parsed in the order given in the list of arguments for the command definition.

### ✔️ name

The argument name.

When calling `core::parseArguments` the argument will be parsed to local variable which name correspond to the camelCase equivalent of its name.

Moreover, the name can be suffixed to enable extra features:

- The name ends with `...` then the argument will be defined as an array and the variable will hold all remaining arguments. Only the last argument can be suffixed like that.
- The name ends with `?` then the argument is optional (otherwise there will be an error if the user does not provide a value). Only the last arguments can be suffixed like that.
- The name ends with `?...` then the argument is an optional array (combination of the two above).

Example of a argument names and their corresponding variables:

- `my-arg1``local myArg1`
- `files...``local -a files`
- `commands?...``local -a commands`

| Mandatory? | Default value? |
|----------|---------------|
| yes ✔️ | N/A |

### ✔️ description

The description for this argument. It will be used to display the help/usage of the command.

| Mandatory? | Default value? |
|----------|---------------|
| yes ✔️ | N/A |

## 🎚️ Options

### ✔️ name

The option name(s). An option can have one or more long name and up to one short name. Each name is separated with `, `.

- A short name is composed of a single hyphen and a single letter. E.g. `-o` or `-b`.
- A long name is composed of two hyphens then a valid string (alpha numerical that can contain hyphens). E.g. `--option` or `--my-great-option`.

An option can be a simple true/false flag or it can hold a user value:

- If the option ends with ` <something>`, then the option will hold a value passed by the user.
- Otherwise, the option will be a simple flag and will be equal to `true` if the user passed the option, `false` otherwise.

When calling `core::parseArguments` options will be parsed to local variable which name correspond to the camelCase equivalent of the first long option name.

Example of a valid option names and their corresponding variable name:

- `-x, --profiling``local profiling`
- `--thing``local thing`
- `-l, --log-level, --log <level>``local logLevel`

| Mandatory? | Default value? |
|----------|---------------|
| yes ✔️ | N/A |

### ✔️ description

The description for this option. It will be used to display the help/usage of the command.

| Mandatory? | Default value? |
|----------|---------------|
| yes ✔️ | N/A |

## 🎈 Examples

Examples are used in the command help/usage and let the user quickly understand how to use the command.

### ✔️ name

The command for this example. You should not include `valet` as it will be preprended automatically.

| Mandatory? | Default value? |
|----------|---------------|
| yes ✔️ | N/A |

### ✔️ description

The description for this example.

| Mandatory? | Default value? |
|----------|---------------|
| yes ✔️ | N/A |

{{< cards >}}
{{< card icon="arrow-circle-left" link="../new-commands" title="New commands" >}}
{{< card icon="arrow-circle-right" link="../test-commands" title="Test commands" >}}
{{< /cards >}}

[showcase-examples]: https://github.com/jcaillon/valet/tree/main/examples.d/showcase
16 changes: 15 additions & 1 deletion docs/content/docs/600.performance-tips/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ echo "${MY_GLOBAL_VAR}"

Using a global variable seem to be a bad idea and can lead to confusion in the code if you are not rigorous. But the cost in performance of the first solution is huge (try to time these 2 codes in 1000 iterations).

Avoid code mistakes by deciding on 1 global variable for all your functions and always assign this variable in each return path of a function (otherwise you might use a value from a previous function call!).
Avoid code mistakes by deciding on 1 global variable for all your functions and always assign this variable in each return path of a function (otherwise you might use a value from a previous function call!). In valet, this variable is named `RETURNED_VALUE`.

## Read a whole file

Expand All @@ -69,6 +69,13 @@ echo "${myString}"

> With this technique, the last line of the file is always read, even if it does not have a trailing newline.
In valet, you can do:

```bash
io::readFile file
echo "${RETURNED_VALUE}"
```

## Read a file, line by line

This example is for the newline (`$'\n'`) delimiter which is the default delimiter of read, but you can specify any delimiter with `IFS=''` + the `-d ''` option.
Expand Down Expand Up @@ -117,6 +124,13 @@ tput cols 2>/dev/null 1> /tmp/file
read -r myvar < /tmp/file
```

In valet, you can do:

```bash
io::invoke tput cols
myvar="${RETURNED_VALUE}"
```

## Loop through line or fields of the content of a variable

Instead of [here string](https://tldp.org/LDP/abs/html/x17837.html#HERESTRINGSREF):
Expand Down
1 change: 0 additions & 1 deletion valet.d/commands.d/self-config.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ fi
: "---
command: self config
function: selfConfig
hideInMenu: true
author: github.com/jcaillon
shortDescription: Open the configuration file of Valet with your default editor.
description: |-
Expand Down
18 changes: 6 additions & 12 deletions valet.d/commands.d/self-export.sh
Original file line number Diff line number Diff line change
Expand Up @@ -89,23 +89,17 @@ function selfExport() {
function exportFunctionsForLibrary() {
local libraryName="${1}"

io::invoke declare -F
local listOfFunctions="${RETURNED_VALUE//declare -? /}"

listOfFunctions="${listOfFunctions//$'\n'/ }"
local -a filteredListOfFunctions=()
for function in ${listOfFunctions}; do
if [[ "${function}" == "${libraryName}::"* ]]; then
filteredListOfFunctions+=("${function}")
fi
done
io::invoke compgen -A 'function' "${libraryName}::"
local filteredListOfFunctions="${RETURNED_VALUE//$'\n'/ }"

# leave if empty
if [[ ${#filteredListOfFunctions[@]} -eq 0 ]]; then
if [[ -z ${filteredListOfFunctions} ]]; then
return 1
fi

io::invoke declare -f "${filteredListOfFunctions[@]}"
local IFS=' '
# shellcheck disable=SC2086
io::invoke declare -f ${filteredListOfFunctions}

RETURNED_VALUE="${RETURNED_VALUE//declare -? /}"

Expand Down

0 comments on commit 4f650c7

Please sign in to comment.