Skip to content

Commit

Permalink
Merge pull request #1212 from nicktate/feature/appdev-charm-cleanup
Browse files Browse the repository at this point in the history
appdev: charm framework cleanup
  • Loading branch information
Kamal Nasser authored Aug 22, 2022
2 parents e7a9db8 + 92acda4 commit 18eb542
Show file tree
Hide file tree
Showing 21 changed files with 601 additions and 345 deletions.
47 changes: 30 additions & 17 deletions cmd/charm-test/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,42 @@ import (
"time"

"github.com/MakeNowJust/heredoc"
"github.com/davecgh/go-spew/spew"
"github.com/digitalocean/doctl/commands/charm"
"github.com/digitalocean/doctl/commands/charm/confirm"
"github.com/digitalocean/doctl/commands/charm/input"
"github.com/digitalocean/doctl/commands/charm/template"
"github.com/digitalocean/doctl/commands/charm/text"
"github.com/digitalocean/doctl/commands/charm/textbox"
)

func main() {
p, err := confirm.New("proceed?", confirm.WithDefaultChoice(confirm.Yes)).Prompt()
spew.Dump(p, err)
var err error
choice, err := confirm.New("wanna see a magic trick?",
confirm.WithDefaultChoice(confirm.Yes),
confirm.WithPersistPrompt(confirm.PersistPromptIfNo),
).Prompt()
if err != nil {
fmt.Println(err)
}
if choice == confirm.Yes {
fmt.Println("👻")
}
os.Exit(1)
i := input.New("app name:", input.WithRequired())
res, err := i.Prompt()
spew.Dump(res, err)
os.Exit(0)
_, err = i.Prompt()
if err != nil {
fmt.Println(err)
}

fmt.Println(
charm.Checkmark, charm.CheckmarkSuccess,
text.Checkmark,
text.Checkmark.Inherit(text.Success),
)

fmt.Println(
charm.TextSuccess.WithString("woo!"), charm.TextSuccess.S("woo 2!"),
text.Success.WithString("woo!"), text.Success.S("woo 2!"),
)

if err := charm.TemplatePrintE(heredoc.Doc(`
if err := template.PrintE(heredoc.Doc(`
--- template ---
This is an example template.
Expand All @@ -38,7 +51,7 @@ func main() {
{{ success checkmark }} just the checkmark.
{{ success (join " " (checkmark) "good job!") }}
{{ error (join " " (checkmark) "we're both confused.") }}
{{ warning "try again?" }}
{{ warning (print promptPrefix " try again?") }}
{{ error (join " " (crossmark) "there we go.") }}
{{ success (bold "full send let's go!!!!") }}
Expand All @@ -58,14 +71,14 @@ func main() {
img := "yeet/yote:dev"
dur := 23*time.Minute + 37*time.Second
fmt.Fprintf(
charm.NewTextBox().Success(),
textbox.New().Success(),
"%s Successfully built %s in %s",
charm.CheckmarkSuccess,
charm.TextSuccess.S(img),
charm.TextWarning.S(dur.Truncate(time.Second).String()),
text.Checkmark.Success(),
text.Success.S(img),
text.Warning.S(dur.Truncate(time.Second).String()),
)

if err := charm.TemplateBufferedE(charm.NewTextBox().Success(), heredoc.Doc(`
if err := template.BufferedE(textbox.New().Success(), heredoc.Doc(`
{{ success checkmark }} Successfully built {{ success .img }} in {{ warning (duration .dur) }}`,
), map[string]any{
"img": img,
Expand All @@ -74,7 +87,7 @@ func main() {
panic(err)
}

charm.TemplateBuffered(charm.NewTextBox().Success(), heredoc.Doc(`
template.Buffered(textbox.New().Success(), heredoc.Doc(`
{{ success checkmark }} Successfully built {{ success .img }} in {{ warning (duration .dur) }}`,
), map[string]any{
"img": img,
Expand Down
3 changes: 2 additions & 1 deletion commands/apps_charm.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"strings"

"github.com/digitalocean/doctl/commands/charm"
"github.com/digitalocean/doctl/commands/charm/template"
"github.com/digitalocean/godo"
)

Expand All @@ -22,7 +23,7 @@ func (i componentListItem) Description() string {

if buildable, ok := i.spec.(godo.AppBuildableComponentSpec); ok {
if sourceDir := buildable.GetSourceDir(); sourceDir != "" {
desc = append(desc, "located in ./"+charm.TextHighlight.S(sourceDir))
desc = append(desc, template.String(`located in ./{{highlight .}}`, sourceDir))
}
}

Expand Down
52 changes: 34 additions & 18 deletions commands/apps_dev.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ import (

"github.com/MakeNowJust/heredoc"
"github.com/digitalocean/doctl"
"github.com/digitalocean/doctl/commands/charm"
"github.com/digitalocean/doctl/commands/charm/confirm"
"github.com/digitalocean/doctl/commands/charm/list"
"github.com/digitalocean/doctl/commands/charm/pager"
"github.com/digitalocean/doctl/commands/charm/template"
"github.com/digitalocean/doctl/commands/charm/textbox"
"github.com/digitalocean/doctl/commands/displayers"
"github.com/digitalocean/doctl/internal/apps/builder"

"github.com/charmbracelet/bubbles/list"
"github.com/digitalocean/godo"
"github.com/joho/godotenv"
"github.com/spf13/cobra"
Expand Down Expand Up @@ -97,7 +99,11 @@ func AppsDev() *Command {
// RunAppsDevBuild builds an app component locally.
func RunAppsDevBuild(c *CmdConfig) error {
ctx := context.Background()
if timeout, _ := c.Doit.GetDuration(c.NS, doctl.ArgTimeout); timeout > 0 {
timeout, err := c.Doit.GetDuration(c.NS, doctl.ArgTimeout)
if err != nil {
return err
}
if timeout > 0 {
var cancel context.CancelFunc
ctx, cancel = context.WithTimeout(ctx, timeout)
defer cancel()
Expand Down Expand Up @@ -133,7 +139,7 @@ func RunAppsDevBuild(c *CmdConfig) error {
if appSpecPath == "" {
if _, err := os.Stat(AppsDevDefaultSpecPath); err == nil {
appSpecPath = AppsDevDefaultSpecPath
charm.TemplatePrint(heredoc.Doc(`
template.Print(heredoc.Doc(`
{{success checkmark}} using app spec at {{highlight .}}{{nl}}`,
), AppsDevDefaultSpecPath)
}
Expand Down Expand Up @@ -170,8 +176,7 @@ func RunAppsDevBuild(c *CmdConfig) error {
components = append(components, componentListItem{c})
return nil
})
list := charm.NewList(components)
list.Fullscreen = true
list := list.New(components)
list.Model().Title = "select a component"
list.Model().SetStatusBarItemName("component", "components")
selected, err := list.Select()
Expand All @@ -198,6 +203,12 @@ func RunAppsDevBuild(c *CmdConfig) error {
if err != nil {
return err
}

buildingComponentLine := template.String(heredoc.Doc(`
building {{lower (snakeToTitle .GetType)}} {{highlight .GetName}}`,
), componentSpec)
template.Print(`{{success checkmark}} {{.}}{{nl 2}}`, buildingComponentLine)

if componentSpec.GetSourceDir() != "" {
sd := componentSpec.GetSourceDir()
stat, err := os.Stat(sd)
Expand Down Expand Up @@ -241,6 +252,7 @@ func RunAppsDevBuild(c *CmdConfig) error {
choice, err := confirm.New(
"start build?",
confirm.WithDefaultChoice(confirm.Yes),
confirm.WithPersistPrompt(confirm.PersistPromptIfNo),
).Prompt()
if err != nil {
return err
Expand All @@ -263,8 +275,8 @@ func RunAppsDevBuild(c *CmdConfig) error {
logWriter io.Writer
)
if Interactive {
pager, err := charm.NewPager(
charm.PagerWithTitle("Building " + component),
logPager, err := pager.New(
pager.WithTitle(buildingComponentLine),
)
if err != nil {
return fmt.Errorf("starting log pager: %w", err)
Expand All @@ -273,20 +285,16 @@ func RunAppsDevBuild(c *CmdConfig) error {
go func() {
defer cancel()
defer wg.Done()
err := pager.Start(ctx)
err := logPager.Start(ctx)
if err != nil {
fmt.Fprintf(os.Stderr, "pager error: %v\n", err)
}
}()
logWriter = pager
logWriter = logPager
} else {
logWriter = os.Stdout
}

charm.TemplatePrint(heredoc.Doc(`
{{success checkmark}} building {{lower (snakeToTitle .GetType)}} {{highlight .GetName}}{{nl}}{{nl}}`,
), componentSpec)

var res builder.ComponentBuilderResult
err = func() error {
defer cancel()
Expand All @@ -310,20 +318,28 @@ func RunAppsDevBuild(c *CmdConfig) error {
// allow the pager to exit cleanly
wg.Wait()

// TODO: differentiate between user-initiated cancel and cancel due to build failure
// if err == nil {
// err = ctx.Err()
// if errors.Is(err, context.Canceled) {
// err = fmt.Errorf("cancelled")
// }
// }

if err != nil {
return err
} else if res.ExitCode == 0 {
charm.TemplateBuffered(
charm.NewTextBox().Success(),
template.Buffered(
textbox.New().Success(),
`{{success checkmark}} successfully built {{success .img}} in {{warning (duration .dur)}}`,
map[string]any{
"img": res.Image,
"dur": res.BuildDuration,
},
)
} else {
charm.TemplateBuffered(
charm.NewTextBox().Error(),
template.Buffered(
textbox.New().Error(),
`{{error crossmark}} build container exited with code {{highlight .code}} after {{warning (duration .dur)}}`,
map[string]any{
"code": res.ExitCode,
Expand Down
30 changes: 13 additions & 17 deletions commands/charm/charm.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,21 +34,23 @@ func (s Style) Copy() Style {

// Inherit returns a copy of the original style with the properties from another style inherited.
// This follows lipgloss's inheritance behavior so margins, padding, and underlying string values are not inherited.
func (s Style) Inherit(o Style) Style {
func (s Style) Inherit(styles ...Style) Style {
c := s.Copy()
c.style = c.style.Inherit(o.style)
for _, style := range styles {
c.style = c.style.Inherit(style.style)
}
return c
}

// NOTE is this actually needed
// // Inherit inherits properties from another style in-place.
// // This follows lipgloss's inheritance behavior so margins, padding, and underlying string values are not inherited.
// //
// // NOTE: this is an internal method that overwrites the original style.
// func (s *Style) inherit(o Style) *Style {
// s.style = s.style.Inherit(o.style)
// return s
// }
// Inherit returns a copy of the original style with the properties from a lipgloss.Style inherited.
// This follows lipgloss's inheritance behavior so margins, padding, and underlying string values are not inherited.
func (s Style) InheritLipgloss(styles ...lipgloss.Style) Style {
c := s.Copy()
for _, style := range styles {
c.style = c.style.Inherit(style)
}
return c
}

// Sprintf formats the specified text with the style applied.
func (s Style) Sprintf(format string, a ...any) string {
Expand Down Expand Up @@ -88,9 +90,3 @@ func (s Style) WithString(str string) Style {
func (s Style) String() string {
return s.style.String()
}

func factory[T any](x T) func() T {
return func() T {
return x
}
}
Loading

0 comments on commit 18eb542

Please sign in to comment.