feat: Add gum style command

Style provides a shell script interface for Lip Gloss. It allows you to
use Lip Gloss to style text without needing to use Go. All of the
styling options are available as flags.

Let's make some text glamorous using bash:

```
gum style \
    --foreground "#FF06B7" --border "double" \
    --margin 2 --padding "2 4" --width 50 \
    "And oh gosh, how delicious the fabulous frizzy frobscottle" \
    "was! It was sweet and refreshing. It tasted of vanilla and" \
    "cream, with just the faintest trace of raspberries on the" \
    "edge of the flavour. And the bubbles were wonderful."
```

Output:

```
╔══════════════════════════════════════════════════╗
║                                                  ║
║                                                  ║
║    And oh gosh, how delicious the fabulous       ║
║    frizzy frobscottle was It was sweet and       ║
║    refreshing. It tasted of vanilla and          ║
║    cream, with just the faintest trace of        ║
║    raspberries on the edge of the flavour.       ║
║    And the bubbles were wonderful.               ║
║                                                  ║
║                                                  ║
╚══════════════════════════════════════════════════╝
```
This commit is contained in:
Maas Lalani 2022-07-06 12:09:35 -04:00
parent 2320f10278
commit 09feddcc61
No known key found for this signature in database
GPG key ID: 5A6ED5CBF1A0A000
6 changed files with 116 additions and 0 deletions

12
style/align.go Normal file
View file

@ -0,0 +1,12 @@
package style
import "github.com/charmbracelet/lipgloss"
// align maps strings to `lipgloss.Position`s
var align = map[string]lipgloss.Position{
"center": lipgloss.Center,
"left": lipgloss.Left,
"top": lipgloss.Top,
"bottom": lipgloss.Bottom,
"right": lipgloss.Right,
}

13
style/borders.go Normal file
View file

@ -0,0 +1,13 @@
package style
import "github.com/charmbracelet/lipgloss"
// border maps strings to `lipgloss.Border`s
var border map[string]lipgloss.Border = map[string]lipgloss.Border{
"double": lipgloss.DoubleBorder(),
"hidden": lipgloss.HiddenBorder(),
"none": {},
"normal": lipgloss.NormalBorder(),
"rounded": lipgloss.RoundedBorder(),
"thick": lipgloss.ThickBorder(),
}

28
style/command.go Normal file
View file

@ -0,0 +1,28 @@
package style
import (
"fmt"
"github.com/charmbracelet/lipgloss"
)
// Run provides a shell script interface for the Lip Gloss styling.
// https://github.com/charmbracelet/lipgloss
func (o Options) Run() {
fmt.Println(lipgloss.NewStyle().
Foreground(lipgloss.Color(o.Foreground)).
Background(lipgloss.Color(o.Background)).
BorderBackground(lipgloss.Color(o.BorderBackground)).
BorderForeground(lipgloss.Color(o.BorderForeground)).
Align(align[o.Align]).
Bold(o.Bold).
Border(border[o.Border]).
Margin(parseMargin(o.Margin)).
Padding(parsePadding(o.Padding)).
Height(o.Height).
Width(o.Width).
Faint(o.Faint).
Italic(o.Italic).
Strikethrough(o.Strikethrough).
Render(o.Text))
}

21
style/options.go Normal file
View file

@ -0,0 +1,21 @@
package style
// Options is the customization options for the style command.
type Options struct {
Text string `arg:"" optional:"" help:"Text to style"`
Background string `help:"Background color"`
Foreground string `help:"Foreground color"`
BorderBackground string `help:"Border background color"`
BorderForeground string `help:"Border foreground color"`
Align string `help:"Text alignment" enum:"left,center,right,bottom,middle,top" default:"left"`
Border string `help:"Border style to apply" enum:"none,hidden,normal,rounded,thick,double" default:"none"`
Height int `help:"Height of output"`
Width int `help:"Width of output"`
Margin string `help:"Margin to apply around the text."`
Padding string `help:"Padding to apply around the text."`
Bold bool `help:"Apply bold formatting"`
Faint bool `help:"Apply faint formatting"`
Italic bool `help:"Apply italic formatting"`
Strikethrough bool `help:"Apply strikethrough formatting"`
}

41
style/spacing.go Normal file
View file

@ -0,0 +1,41 @@
package style
import (
"strconv"
"strings"
)
// parsePadding parses 1 - 4 integers from a string and returns them in a top,
// right, bottom, left order for use in the lipgloss.Padding() method
func parsePadding(s string) (int, int, int, int) {
var ints []int
tokens := strings.Split(s, " ")
// All tokens must be an integer
for _, token := range tokens {
parsed, err := strconv.Atoi(token)
if err != nil {
return 0, 0, 0, 0
}
ints = append(ints, parsed)
}
if len(tokens) == 1 {
return ints[0], ints[0], ints[0], ints[0]
}
if len(tokens) == 2 {
return ints[0], ints[1], ints[0], ints[1]
}
if len(tokens) == 4 {
return ints[0], ints[1], ints[2], ints[3]
}
return 0, 0, 0, 0
}
// parseMargin is an alias for parsePadding since they involve the same logic
// to parse integers to the same format.
var parseMargin = parsePadding

1
style/style.go Normal file
View file

@ -0,0 +1 @@
package style