Skip to content

Commit

Permalink
feat: more customization commands (#175)
Browse files Browse the repository at this point in the history
  • Loading branch information
jahvon authored Oct 10, 2024
1 parent 74748d8 commit 015e778
Show file tree
Hide file tree
Showing 25 changed files with 360 additions and 35 deletions.
102 changes: 101 additions & 1 deletion cmd/internal/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"strconv"
"strings"
"time"

tuikitIO "github.com/jahvon/tuikit/io"
"github.com/jahvon/tuikit/types"
Expand Down Expand Up @@ -44,7 +45,7 @@ func registerConfigResetCmd(ctx *context.Context, configCmd *cobra.Command) {
func resetConfigFunc(ctx *context.Context, _ *cobra.Command, _ []string) {
logger := ctx.Logger
form, err := views.NewForm(
io.Theme(),
io.Theme(ctx.Config.Theme.String()),
ctx.StdIn(),
ctx.StdOut(),
&views.FormField{
Expand Down Expand Up @@ -80,6 +81,9 @@ func registerSetConfigCmd(ctx *context.Context, configCmd *cobra.Command) {
registerSetWorkspaceModeCmd(ctx, setCmd)
registerSetLogModeCmd(ctx, setCmd)
registerSetTUICmd(ctx, setCmd)
registerSetNotificationsCmd(ctx, setCmd)
registerSetThemeCmd(ctx, setCmd)
registerSetTimeoutCmd(ctx, setCmd)
configCmd.AddCommand(setCmd)
}

Expand Down Expand Up @@ -190,6 +194,102 @@ func setInteractiveFunc(ctx *context.Context, _ *cobra.Command, args []string) {
logger.PlainTextSuccess("Interactive UI " + strVal)
}

func registerSetNotificationsCmd(ctx *context.Context, setCmd *cobra.Command) {
notificationsCmd := &cobra.Command{
Use: "notifications [true|false]",
Short: "Enable or disable notifications.",
Args: cobra.ExactArgs(1),
ValidArgs: []string{"true", "false"},
Run: func(cmd *cobra.Command, args []string) { setNotificationsFunc(ctx, cmd, args) },
}
RegisterFlag(ctx, notificationsCmd, *flags.SetSoundNotificationFlag)
setCmd.AddCommand(notificationsCmd)
}

func setNotificationsFunc(ctx *context.Context, cmd *cobra.Command, args []string) {
logger := ctx.Logger
enabled, err := strconv.ParseBool(args[0])
if err != nil {
logger.FatalErr(errors.Wrap(err, "invalid boolean value"))
}
sound := flags.ValueFor[bool](ctx, cmd, *flags.SetSoundNotificationFlag, false)

userConfig := ctx.Config
if userConfig.Interactive == nil {
userConfig.Interactive = &config.Interactive{}
}
userConfig.Interactive.NotifyOnCompletion = &enabled
if sound {
userConfig.Interactive.SoundOnCompletion = &enabled
}
if err := filesystem.WriteConfig(userConfig); err != nil {
logger.FatalErr(err)
}
strVal := "disabled"
if enabled {
strVal = "enabled"
}
logger.PlainTextSuccess("Notifications " + strVal)
}

func registerSetThemeCmd(ctx *context.Context, setCmd *cobra.Command) {
themeCmd := &cobra.Command{
Use: "theme [default|dark|light|dracula|tokyo-night]",
Short: "Set the theme for the TUI views",
Args: cobra.ExactArgs(1),
ValidArgs: []string{
string(config.ConfigThemeDefault),
string(config.ConfigThemeDark),
string(config.ConfigThemeLight),
string(config.ConfigThemeDracula),
string(config.ConfigThemeTokyoNight),
},
Run: func(cmd *cobra.Command, args []string) { setThemeFunc(ctx, cmd, args) },
}
setCmd.AddCommand(themeCmd)
}

func setThemeFunc(ctx *context.Context, _ *cobra.Command, args []string) {
logger := ctx.Logger
themeName := args[0]

userConfig := ctx.Config
if userConfig.Interactive == nil {
userConfig.Interactive = &config.Interactive{}
}
userConfig.Theme = config.ConfigTheme(themeName)
if err := filesystem.WriteConfig(userConfig); err != nil {
logger.FatalErr(err)
}
logger.PlainTextSuccess("Theme set to " + themeName)
}

func registerSetTimeoutCmd(ctx *context.Context, setCmd *cobra.Command) {
timeoutCmd := &cobra.Command{
Use: "timeout DURATION",
Short: "Set the default timeout for executables.",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) { setTimeoutFunc(ctx, cmd, args) },
}
setCmd.AddCommand(timeoutCmd)
}

func setTimeoutFunc(ctx *context.Context, _ *cobra.Command, args []string) {
logger := ctx.Logger
timeoutStr := args[0]
timeout, err := time.ParseDuration(timeoutStr)
if err != nil {
logger.FatalErr(errors.Wrap(err, "invalid duration"))
}

userConfig := ctx.Config
userConfig.DefaultTimeout = timeout
if err := filesystem.WriteConfig(userConfig); err != nil {
logger.FatalErr(err)
}
logger.PlainTextSuccess("Default timeout set to " + timeoutStr)
}

func registerViewConfigCmd(ctx *context.Context, configCmd *cobra.Command) {
viewCmd := &cobra.Command{
Use: "view",
Expand Down
4 changes: 2 additions & 2 deletions cmd/internal/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ func execFunc(ctx *context.Context, cmd *cobra.Command, verb executable.Verb, ar
setAuthEnv(ctx, cmd, e)
textInputs := pendingFormFields(ctx, e)
if len(textInputs) > 0 {
form, err := views.NewForm(io.Theme(), ctx.StdIn(), ctx.StdOut(), textInputs...)
form, err := views.NewForm(io.Theme(ctx.Config.Theme.String()), ctx.StdIn(), ctx.StdOut(), textInputs...)
if err != nil {
logger.FatalErr(err)
}
Expand Down Expand Up @@ -177,7 +177,7 @@ func runByRef(ctx *context.Context, cmd *cobra.Command, argsStr string) error {
func setAuthEnv(ctx *context.Context, _ *cobra.Command, executable *executable.Executable) {
if authRequired(ctx, executable) {
form, err := views.NewForm(
io.Theme(),
io.Theme(ctx.Config.Theme.String()),
ctx.StdIn(),
ctx.StdOut(),
&views.FormField{
Expand Down
6 changes: 6 additions & 0 deletions cmd/internal/flags/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,3 +163,9 @@ var TemplateFilePathFlag = &Metadata{
Default: "",
Required: false,
}

var SetSoundNotificationFlag = &Metadata{
Name: "sound",
Usage: "Update completion sound notification setting",
Default: false,
}
3 changes: 2 additions & 1 deletion cmd/internal/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ func WaitForTUI(ctx *context.Context, cmd *cobra.Command) {

func printContext(ctx *context.Context, cmd *cobra.Command) {
if TUIEnabled(ctx, cmd) {
ctx.Logger.Println(io.Theme().RenderHeader(context.AppName, context.HeaderCtxKey, ctx.String(), 0))
ctx.Logger.Println(io.Theme(ctx.Config.Theme.String()).
RenderHeader(context.AppName, context.HeaderCtxKey, ctx.String(), 0))
}
}

Expand Down
2 changes: 1 addition & 1 deletion cmd/internal/library.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ func libraryFunc(ctx *context.Context, cmd *cobra.Command, _ []string) {
Tags: tagsFilter,
Substring: subStr,
},
io.Theme(),
io.Theme(ctx.Config.Theme.String()),
runFunc,
)
SetView(ctx, cmd, libraryModel)
Expand Down
4 changes: 2 additions & 2 deletions cmd/internal/secret.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func deleteSecretFunc(ctx *context.Context, _ *cobra.Command, args []string) {
reference := args[0]

form, err := views.NewForm(
io.Theme(),
io.Theme(ctx.Config.Theme.String()),
ctx.StdIn(),
ctx.StdOut(),
&views.FormField{
Expand Down Expand Up @@ -138,7 +138,7 @@ func setSecretFunc(ctx *context.Context, _ *cobra.Command, args []string) {
switch {
case len(args) == 1:
form, err := views.NewForm(
io.Theme(),
io.Theme(ctx.Config.Theme.String()),
ctx.StdIn(),
ctx.StdOut(),
&views.FormField{
Expand Down
2 changes: 1 addition & 1 deletion cmd/internal/workspace.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ func deleteWsFunc(ctx *context.Context, _ *cobra.Command, args []string) {
name := args[0]

form, err := views.NewForm(
io.Theme(),
io.Theme(ctx.Config.Theme.String()),
ctx.StdIn(),
ctx.StdOut(),
&views.FormField{
Expand Down
3 changes: 3 additions & 0 deletions docs/cli/flow_config_set.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ Update flow configuration values.
* [flow config](flow_config.md) - Update flow configuration values.
* [flow config set log-mode](flow_config_set_log-mode.md) - Set the default log mode.
* [flow config set namespace](flow_config_set_namespace.md) - Change the current namespace.
* [flow config set notifications](flow_config_set_notifications.md) - Enable or disable notifications.
* [flow config set theme](flow_config_set_theme.md) - Set the theme for the TUI views
* [flow config set timeout](flow_config_set_timeout.md) - Set the default timeout for executables.
* [flow config set tui](flow_config_set_tui.md) - Enable or disable the interactive terminal UI experience.
* [flow config set workspace-mode](flow_config_set_workspace-mode.md) - Switch between fixed and dynamic workspace modes.

27 changes: 27 additions & 0 deletions docs/cli/flow_config_set_notifications.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
## flow config set notifications

Enable or disable notifications.

```
flow config set notifications [true|false] [flags]
```

### Options

```
-h, --help help for notifications
--sound Update completion sound notification setting
```

### Options inherited from parent commands

```
-x, --non-interactive Disable displaying flow output via terminal UI rendering. This is only needed if the interactive output is enabled by default in flow's configuration.
--sync Sync flow cache and workspaces
--verbosity int Log verbosity level (-1 to 1)
```

### SEE ALSO

* [flow config set](flow_config_set.md) - Update flow configuration values.

26 changes: 26 additions & 0 deletions docs/cli/flow_config_set_theme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
## flow config set theme

Set the theme for the TUI views

```
flow config set theme [default|dark|light|dracula|tokyo-night] [flags]
```

### Options

```
-h, --help help for theme
```

### Options inherited from parent commands

```
-x, --non-interactive Disable displaying flow output via terminal UI rendering. This is only needed if the interactive output is enabled by default in flow's configuration.
--sync Sync flow cache and workspaces
--verbosity int Log verbosity level (-1 to 1)
```

### SEE ALSO

* [flow config set](flow_config_set.md) - Update flow configuration values.

26 changes: 26 additions & 0 deletions docs/cli/flow_config_set_timeout.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
## flow config set timeout

Set the default timeout for executables.

```
flow config set timeout DURATION [flags]
```

### Options

```
-h, --help help for timeout
```

### Options inherited from parent commands

```
-x, --non-interactive Disable displaying flow output via terminal UI rendering. This is only needed if the interactive output is enabled by default in flow's configuration.
--sync Sync flow cache and workspaces
--verbosity int Log verbosity level (-1 to 1)
```

### SEE ALSO

* [flow config set](flow_config_set.md) - Update flow configuration values.

37 changes: 37 additions & 0 deletions docs/guide/interactive.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,35 @@
The interactive TUI can be customized in the [flow config file](../types/config.md). Additionally,
there are several [flow config commands](../cli/flow_config.md) that can be used to change the TUI settings.

> [!TIP]
> You can view your current settings with the config view command:
> ```shell
> flow config view
> ```
### Changing the TUI theme
There are several themes available in the TUI:
- `default` (everforest)
- `light`
- `dark`
- `dracula`
- `tokyo-night`
Use the following command to change the theme:
```shell
flow config set theme (default|light|dark|dracula|tokyo-night)
```
### Changing desktop notification settings

Desktop notifications can be sent when executables are completed. Use the following command to enable or disable desktop notifications:

```shell
flow config set notifications (true|false) # --sound
```

### Changing the log mode

There are 4 log modes available in the TUI:
Expand Down Expand Up @@ -37,6 +66,14 @@ There are 2 workspace modes available in the TUI:

See the [workspace guide](workspace.md) for more information on workspaces.

### Changing the default executable timeout

The global default executable timeout is 30 minutes. Use the following command to change the default executable timeout:

```shell
flow config set timeout <duration>
```

### Disable the TUI

In some cases, you may want to disable the interactive TUI (in CI/CD pipelines and containers, for example).
Expand Down
5 changes: 3 additions & 2 deletions docs/guide/templating.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
Guide coming soon...
flow can be used to render templates using the [flow template](../cli/flow_template.md) command.
Templates are defined using the templating language. The `flow template` command can be used to render templates using the following syntax:

In the meantime, see [Template](../types/template.md) and [flow template](../cli/flow_template.md).
```shell
17 changes: 17 additions & 0 deletions docs/schemas/config_schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@
"type": "string",
"default": "logfmt"
},
"defaultTimeout": {
"description": "The default timeout to use when running executables.\nThis should be a valid duration string.\n",
"type": "string",
"default": "30m"
},
"interactive": {
"$ref": "#/definitions/Interactive"
},
Expand All @@ -56,6 +61,18 @@
"type": "string"
}
},
"theme": {
"description": "The theme of the interactive UI.",
"type": "string",
"default": "default",
"enum": [
"default",
"dark",
"light",
"dracula",
"tokyo-night"
]
},
"workspaceMode": {
"description": "The mode of the workspace. This can be either `fixed` or `dynamic`.\nIn `fixed` mode, the current workspace used at runtime is always the one set in the currentWorkspace config field.\nIn `dynamic` mode, the current workspace used at runtime is determined by the current directory.\nIf the current directory is within a workspace, that workspace is used.\n",
"type": "string",
Expand Down
2 changes: 2 additions & 0 deletions docs/types/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@ Alternatively, a custom path can be set using the `FLOW_CONFIG_PATH` environment
| `currentNamespace` | The name of the current namespace. Namespaces are used to reference executables in the CLI using the format `workspace:namespace/name`. If the namespace is not set, only executables defined without a namespace will be discovered. | `string` | | |
| `currentWorkspace` | The name of the current workspace. This should match a key in the `workspaces` or `remoteWorkspaces` map. | `string` | | |
| `defaultLogMode` | The default log mode to use when running executables. This can either be `hidden`, `json`, `logfmt` or `text` `hidden` will not display any logs. `json` will display logs in JSON format. `logfmt` will display logs with a log level, timestamp, and message. `text` will just display the log message. | `string` | logfmt | |
| `defaultTimeout` | The default timeout to use when running executables. This should be a valid duration string. | `string` | 30m | |
| `interactive` | | [Interactive](#Interactive) | <no value> | |
| `templates` | A map of flowfile template names to their paths. | `map` (`string` -> `string`) | map[] | |
| `theme` | The theme of the interactive UI. | `string` | default | |
| `workspaceMode` | The mode of the workspace. This can be either `fixed` or `dynamic`. In `fixed` mode, the current workspace used at runtime is always the one set in the currentWorkspace config field. In `dynamic` mode, the current workspace used at runtime is determined by the current directory. If the current directory is within a workspace, that workspace is used. | `string` | dynamic | |
| `workspaces` | Map of workspace names to their paths. The path should be a valid absolute path to the workspace directory. | `map` (`string` -> `string`) | <no value> | |

Expand Down
Loading

0 comments on commit 015e778

Please sign in to comment.