wsh setbg + updated tab background docs (#1394)

This commit is contained in:
Mike Sawka 2024-12-05 10:27:08 -08:00 committed by GitHub
parent b4b0222c9d
commit 942eeaa8e9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 536 additions and 11 deletions

147
cmd/wsh/cmd/csscolormap.go Normal file
View File

@ -0,0 +1,147 @@
// Copyright 2024, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0
package cmd
var CssColorNames = map[string]bool{
"aliceblue": true,
"antiquewhite": true,
"aqua": true,
"aquamarine": true,
"azure": true,
"beige": true,
"bisque": true,
"black": true,
"blanchedalmond": true,
"blue": true,
"blueviolet": true,
"brown": true,
"burlywood": true,
"cadetblue": true,
"chartreuse": true,
"chocolate": true,
"coral": true,
"cornflowerblue": true,
"cornsilk": true,
"crimson": true,
"cyan": true,
"darkblue": true,
"darkcyan": true,
"darkgoldenrod": true,
"darkgray": true,
"darkgreen": true,
"darkkhaki": true,
"darkmagenta": true,
"darkolivegreen": true,
"darkorange": true,
"darkorchid": true,
"darkred": true,
"darksalmon": true,
"darkseagreen": true,
"darkslateblue": true,
"darkslategray": true,
"darkturquoise": true,
"darkviolet": true,
"deeppink": true,
"deepskyblue": true,
"dimgray": true,
"dodgerblue": true,
"firebrick": true,
"floralwhite": true,
"forestgreen": true,
"fuchsia": true,
"gainsboro": true,
"ghostwhite": true,
"gold": true,
"goldenrod": true,
"gray": true,
"green": true,
"greenyellow": true,
"honeydew": true,
"hotpink": true,
"indianred": true,
"indigo": true,
"ivory": true,
"khaki": true,
"lavender": true,
"lavenderblush": true,
"lawngreen": true,
"lemonchiffon": true,
"lightblue": true,
"lightcoral": true,
"lightcyan": true,
"lightgoldenrodyellow": true,
"lightgray": true,
"lightgreen": true,
"lightpink": true,
"lightsalmon": true,
"lightseagreen": true,
"lightskyblue": true,
"lightslategray": true,
"lightsteelblue": true,
"lightyellow": true,
"lime": true,
"limegreen": true,
"linen": true,
"magenta": true,
"maroon": true,
"mediumaquamarine": true,
"mediumblue": true,
"mediumorchid": true,
"mediumpurple": true,
"mediumseagreen": true,
"mediumslateblue": true,
"mediumspringgreen": true,
"mediumturquoise": true,
"mediumvioletred": true,
"midnightblue": true,
"mintcream": true,
"mistyrose": true,
"moccasin": true,
"navajowhite": true,
"navy": true,
"oldlace": true,
"olive": true,
"olivedrab": true,
"orange": true,
"orangered": true,
"orchid": true,
"palegoldenrod": true,
"palegreen": true,
"paleturquoise": true,
"palevioletred": true,
"papayawhip": true,
"peachpuff": true,
"peru": true,
"pink": true,
"plum": true,
"powderblue": true,
"purple": true,
"red": true,
"rosybrown": true,
"royalblue": true,
"saddlebrown": true,
"salmon": true,
"sandybrown": true,
"seagreen": true,
"seashell": true,
"sienna": true,
"silver": true,
"skyblue": true,
"slateblue": true,
"slategray": true,
"snow": true,
"springgreen": true,
"steelblue": true,
"tan": true,
"teal": true,
"thistle": true,
"tomato": true,
"turquoise": true,
"violet": true,
"wheat": true,
"white": true,
"whitesmoke": true,
"yellow": true,
"yellowgreen": true,
}

186
cmd/wsh/cmd/wshcmd-setbg.go Normal file
View File

@ -0,0 +1,186 @@
// Copyright 2024, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0
package cmd
import (
"encoding/hex"
"encoding/json"
"fmt"
"os"
"path/filepath"
"strings"
"github.com/spf13/cobra"
"github.com/wavetermdev/waveterm/pkg/util/utilfn"
"github.com/wavetermdev/waveterm/pkg/wavebase"
"github.com/wavetermdev/waveterm/pkg/wshrpc"
"github.com/wavetermdev/waveterm/pkg/wshrpc/wshclient"
)
var setBgCmd = &cobra.Command{
Use: "setbg [--opacity value] [--tile|--center] [--scale value] (image-path|\"#color\"|color-name)",
Short: "set background image or color for a tab",
Long: `Set a background image or color for a tab. Colors can be specified as:
- A quoted hex value like "#ff0000" (quotes required to prevent # being interpreted as a shell comment)
- A CSS color name like "blue" or "forestgreen"
Or provide a path to a supported image file (jpg, png, gif, webp, or svg).
You can also:
- Use --clear to remove the background
- Use --opacity without other arguments to change just the opacity
- Use --center for centered images without scaling (good for logos)
- Use --scale with --center to control image size
- Use --print to see the metadata without applying it`,
RunE: setBgRun,
PreRunE: preRunSetupRpcClient,
}
var (
setBgOpacity float64
setBgTile bool
setBgCenter bool
setBgSize string
setBgClear bool
setBgPrint bool
)
func init() {
rootCmd.AddCommand(setBgCmd)
setBgCmd.Flags().Float64Var(&setBgOpacity, "opacity", 0.5, "background opacity (0.0-1.0)")
setBgCmd.Flags().BoolVar(&setBgTile, "tile", false, "tile the background image")
setBgCmd.Flags().BoolVar(&setBgCenter, "center", false, "center the image without scaling")
setBgCmd.Flags().StringVar(&setBgSize, "size", "auto", "size for centered images (px, %, or auto)")
setBgCmd.Flags().BoolVar(&setBgClear, "clear", false, "clear the background")
setBgCmd.Flags().BoolVar(&setBgPrint, "print", false, "print the metadata without applying it")
// Make tile and center mutually exclusive
setBgCmd.MarkFlagsMutuallyExclusive("tile", "center")
}
func validateHexColor(color string) error {
if !strings.HasPrefix(color, "#") {
return fmt.Errorf("color must start with #")
}
colorHex := color[1:]
if len(colorHex) != 6 && len(colorHex) != 8 {
return fmt.Errorf("color must be in #RRGGBB or #RRGGBBAA format")
}
_, err := hex.DecodeString(colorHex)
if err != nil {
return fmt.Errorf("invalid hex color: %v", err)
}
return nil
}
func setBgRun(cmd *cobra.Command, args []string) (rtnErr error) {
defer func() {
sendActivity("setbg", rtnErr == nil)
}()
// Create base metadata
meta := map[string]interface{}{}
// Handle opacity-only change or clear
if len(args) == 0 {
if !cmd.Flags().Changed("opacity") && !setBgClear {
OutputHelpMessage(cmd)
return fmt.Errorf("setbg requires an image path or color value")
}
if setBgOpacity < 0 || setBgOpacity > 1 {
return fmt.Errorf("opacity must be between 0.0 and 1.0")
}
if cmd.Flags().Changed("opacity") {
meta["bg:opacity"] = setBgOpacity
}
} else if len(args) > 1 {
OutputHelpMessage(cmd)
return fmt.Errorf("too many arguments")
} else {
// Handle background setting
meta["bg:*"] = true
if setBgOpacity < 0 || setBgOpacity > 1 {
return fmt.Errorf("opacity must be between 0.0 and 1.0")
}
meta["bg:opacity"] = setBgOpacity
input := args[0]
var bgStyle string
// Check for hex color
if strings.HasPrefix(input, "#") {
if err := validateHexColor(input); err != nil {
return err
}
bgStyle = input
} else if CssColorNames[strings.ToLower(input)] {
// Handle CSS color name
bgStyle = strings.ToLower(input)
} else {
// Handle image input
absPath, err := filepath.Abs(wavebase.ExpandHomeDirSafe(input))
if err != nil {
return fmt.Errorf("resolving image path: %v", err)
}
fileInfo, err := os.Stat(absPath)
if err != nil {
return fmt.Errorf("cannot access image file: %v", err)
}
if fileInfo.IsDir() {
return fmt.Errorf("path is a directory, not an image file")
}
mimeType := utilfn.DetectMimeType(absPath, fileInfo, true)
switch mimeType {
case "image/jpeg", "image/png", "image/gif", "image/webp", "image/svg+xml":
// Valid image type
default:
return fmt.Errorf("file does not appear to be a valid image (detected type: %s)", mimeType)
}
// Create URL-safe path
escapedPath := strings.ReplaceAll(absPath, "'", "\\'")
bgStyle = fmt.Sprintf("url('%s')", escapedPath)
switch {
case setBgTile:
bgStyle += " repeat"
case setBgCenter:
bgStyle += fmt.Sprintf(" no-repeat center/%s", setBgSize)
default:
bgStyle += " center/cover no-repeat"
}
}
meta["bg"] = bgStyle
}
if setBgPrint {
jsonBytes, err := json.MarshalIndent(meta, "", " ")
if err != nil {
return fmt.Errorf("error formatting metadata: %v", err)
}
WriteStdout(string(jsonBytes) + "\n")
return nil
}
// Resolve tab reference
oRef, err := resolveSimpleId("tab")
if err != nil {
return err
}
// Send RPC request
setMetaWshCmd := wshrpc.CommandSetMetaData{
ORef: *oRef,
Meta: meta,
}
err = wshclient.SetMetaCommand(RpcClient, setMetaWshCmd, &wshrpc.RpcOpts{Timeout: 2000})
if err != nil {
return fmt.Errorf("setting background: %v", err)
}
WriteStdout("background set\n")
return nil
}

View File

@ -65,6 +65,41 @@ You can also suppress the help widgets in the bottom right by setting the config
<div style={{ clear: "both" }} />
## Tab Backgrounds
Wave supports powerful custom backgrounds for your tabs using images, patterns, gradients, and colors. The quickest way to set an image background is using the `wsh setbg` command:
```bash
# Set an image background with 50% opacity (default)
wsh setbg ~/pictures/background.jpg
# Set a color background (use quotes to prevent # being interpreted as a shell comment)
wsh setbg "#ff0000" # hex color
wsh setbg forestgreen # CSS color name
# Adjust opacity
wsh setbg --opacity 0.3 ~/pictures/light-pattern.png
wsh setbg --opacity 0.7 # change only opacity of current background
# Image positioning options
wsh setbg --tile ~/pictures/texture.png # create tiled pattern
wsh setbg --center ~/pictures/logo.png # center without scaling
wsh setbg --center --size 200px ~/pictures/logo.png # center with specific size (px, %, auto)
# Remove background
wsh setbg --clear
```
You can use any JPEG, PNG, GIF, WebP, or SVG image as your background. The `--center` option is particularly useful for logos or icons where you want to maintain the original size.
To preview the metadata for any background without applying it, use the `--print` flag:
```bash
wsh setbg --print "#ff0000"
```
For more advanced customization options including gradients, colors, and saving your own background presets, check out our [Background Configuration](/presets#background-configurations) documentation.
## Presets
For more advanced customization, to set up multiple AI models, and your own tab backgrounds, check out our [Presets Documentation](./presets).

View File

@ -18,7 +18,7 @@ wsh editconfig presets.json
:::
### File format
## File format
Presets follow the following format:
@ -61,7 +61,7 @@ A complete example of a preset for an AI model is the following:
}
```
### Preset type
## Preset Types
The type of the preset determines where it can be discovered in the app. Currently, the two types that will be discovered in the app are `bg` and `ai`.
@ -90,7 +90,7 @@ Configs in a preset are applied in order to override the default config values,
:::
#### AI configurations
## AI Configurations
| Key Name | Type | Function |
| ------------- | ------ | -------------------------------------------------------------------------------------------------- |
@ -106,16 +106,105 @@ Configs in a preset are applied in order to override the default config values,
| ai:maxtokens | int | max tokens to pass to API |
| ai:timeoutms | int | timeout (in milliseconds) for AI calls |
#### Background configurations
<a name="background-configurations" />
## Background Configurations
Wave's background system harnesses the full power of CSS backgrounds, letting you create rich visual effects through the "background" attribute. You can apply solid colors, gradients (both linear and radial), images, and even blend multiple elements together. The system offers preset configurations while maintaining the flexibility of pure CSS, making it both powerful and easy to use.
| Key Name | Type | Function |
| -------------------- | ------ | ----------------------------------------------------------------------------------------------- |
| bg:\* | bool | reset all existing bg keys |
| bg:opacity | float | the opacity of the background |
| -------------------- | ------ | ------------------------------------------------------------------------------------------------------- |
| bg:\* | bool | reset all existing bg keys (recommended to prevent any existing background settings from carrying over) |
| bg | string | CSS `background` attribute for the tab (supports colors, gradients images, etc.) |
| bg:opacity | float | the opacity of the background (defaults to 0.5) |
| bg:blendmode | string | the [blend mode](https://developer.mozilla.org/en-US/docs/Web/CSS/blend-mode) of the background |
| bg:bordercolor | string | the color of the border |
| bg:bordercolor | string | the color of the border when a block is not active (rarely used) |
| bg:activebordercolor | string | the color of the border when a block is active |
### Simple solid color with opacity:
```json
{
"bg@blue": {
"display:name": "Blue",
"bg:*": true,
"bg": "blue",
"bg:opacity": 0.3,
"bg:activebordercolor": "rgba(0, 0, 255, 1.0)"
}
}
```
### Complex gradient combining multiple effects:
```json
{
"bg@duskhorizon": {
"display:name": "Dusk Horizon",
"bg:*": true,
"bg": "linear-gradient(0deg, rgba(128,0,0,1) 0%, rgba(204,85,0,0.7) 20%, rgba(255,140,0,0.6) 45%, rgba(160,90,160,0.5) 65%, rgba(60,60,120,1) 100%), radial-gradient(circle at 30% 30%, rgba(255,255,255,0.1), transparent 60%), radial-gradient(circle at 70% 70%, rgba(255,255,255,0.05), transparent 70%)",
"bg:opacity": 0.9,
"bg:blendmode": "overlay"
}
}
```
### Repeating pattern background:
```json
{
"bg@pattern": {
"display:name": "Diamond Pattern",
"bg:*": true,
"bg": "url('/path/to/pattern.png') repeat",
"bg:opacity": 0.15
}
}
```
### Full-cover background image:
```json
{
"bg@cover": {
"display:name": "Ocean Scene",
"bg:*": true,
"bg": "url('/path/to/ocean.jpg') center/cover no-repeat",
"bg:opacity": 0.2
}
}
```
Replace image URLs with your own assets. All examples use reduced opacity to work well with dark themes.
:::info
Background images can be specified using URLs or local file paths. While URLs are supported, it's recommended to download and serve images locally for better reliability. For local files, you must use absolute paths or paths starting with `~` (e.g. `~/Downloads/background.png`). The system will automatically rewrite local paths to ensure proper access. We support all common web image formats: PNG, JPEG/JPG, WebP, GIF, and SVG.
:::
:::tip
You can use `wsh setbg --print` to help generate the JSON for your background presets. For example:
```bash
# Preview the metadata for a gradient background
wsh setbg --print "#ff0000"
{
"bg:*": true,
"bg": "#ff0000",
"bg:opacity": 0.5
}
# Preview a centered logo configuration
wsh setbg --print --center --opacity 0.3 ~/logo.png
{
"bg:*": true,
"bg": "url('/absolute/path/to/logo.png') no-repeat center/auto",
"bg:opacity": 0.3
}
```
Copy the output and use it as a starting point for your preset configuration, just add the required `display:name` field!
:::
#### Unset a default value
To unset a default value in a preset, add an override that sets it to an empty string, like `""`.

View File

@ -145,6 +145,74 @@ wsh editconfig widgets.json
---
## setbg
The `setbg` command allows you to set a background image or color for the current tab with various customization options.
```bash
wsh setbg [--opacity value] [--tile|--center] [--size value] (image-path|"#color"|color-name)
```
You can set a background using:
- An image file (displayed as cover, tiled, or centered)
- A hex color (must be quoted like "#ff0000")
- A CSS color name (like "blue" or "forestgreen")
Flags:
- `--opacity value` - set the background opacity (0.0-1.0, default 0.5)
- `--tile` - tile the background image instead of using cover mode
- `--center` - center the image without scaling (good for logos)
- `--size` - size for centered images (px, %, or auto)
- `--clear` - remove the background
- `--print` - show the metadata without applying it
Supported image formats: JPEG, PNG, GIF, WebP, and SVG.
Examples:
```bash
# Set an image background with default settings
wsh setbg ~/pictures/background.jpg
# Set a background with custom opacity
wsh setbg --opacity 0.3 ~/pictures/light-pattern.png
# Set a tiled background
wsh setbg --tile --opacity 0.2 ~/pictures/texture.png
# Center an image (good for logos)
wsh setbg --center ~/pictures/logo.png
wsh setbg --center --size 200px ~/pictures/logo.png
# Set color backgrounds
wsh setbg "#ff0000" # hex color (requires quotes)
wsh setbg forestgreen # CSS color name
# Change just the opacity of current background
wsh setbg --opacity 0.7
# Remove background
wsh setbg --clear
# Preview the metadata
wsh setbg --print "#ff0000"
```
The command validates that:
- Color values are valid hex codes or CSS color names
- Image paths point to accessible, supported image files
- The opacity value is between 0.0 and 1.0
- The center and tile options are not used together
:::tip
Use `--print` to preview the metadata for any background configuration without applying it. You can then copy this JSON representation to use as a [Background Preset](/presets#background-configurations)
:::
---
## run
The `run` command creates a new terminal command block and executes a specified command within it. The command can be provided either as arguments after `--` or using the `-c` flag. Unless the `-x` or `-X` flags are passed, commands can be re-executed by pressing `Enter` once the command has finished running.