Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ title: Changelog

## [Unreleased](https://github.com/lets-cli/lets/releases/tag/v0.0.X)

* `[Fixed]` Add spacing between the `EXAMPLES` help title and its examples.
* `[Fixed]` Align styled error output to the left while preserving the padded error badge.
* `[Docs]` Convert design specs into ADRs.
* `[Refactoring]` Rename the internal download progress package to progressbar.
* `[Added]` Show interactive download progress for `lets self upgrade`. Issue [#367](https://github.com/lets-cli/lets/issues/367)
Expand Down
8 changes: 4 additions & 4 deletions internal/cmd/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,12 @@ func (o errorOutput) blank() {

// header writes the styled error heading.
func (o errorOutput) header() {
o.writeln(o.styles.ErrorHeader.String())
o.writeln(o.styles.ErrorHeader.UnsetMarginLeft().String())
}

// commandTreeTitle writes the dependency tree section heading.
func (o errorOutput) commandTreeTitle() {
title := o.styles.Title.Margin(0, 0).MarginLeft(2).Padding(0, 0)
title := o.styles.Title.Margin(0, 0).Padding(0, 0)
o.writeln(title.Render("command tree:"))
}

Expand All @@ -68,7 +68,7 @@ func (r errorRenderer) Render() {
return
}

errorText := r.styles.ErrorText
errorText := r.styles.ErrorText.UnsetMarginLeft()

r.out.header()
r.renderMessage(errorText)
Expand Down Expand Up @@ -132,7 +132,7 @@ func (r errorRenderer) renderDependencyTree(depErr *executor.DependencyError) {
r.out.commandTreeTitle()

for i, name := range depErr.Chain {
line := strings.Repeat(" ", i+2) + joint + r.styles.Program.Command.Render(name)
line := strings.Repeat(" ", i+1) + joint + r.styles.Program.Command.Render(name)
if i == len(depErr.Chain)-1 {
line += " " + failed
}
Expand Down
1 change: 1 addition & 0 deletions internal/cmd/help.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ func (r helpRenderer) renderUsageAndExamples() {
cw := blockStyle.GetWidth() - blockStyle.GetHorizontalPadding()

r.out.sectionTitle("examples")
r.out.blank()

for i, example := range examples {
if lipgloss.Width(example) > cw {
Expand Down
19 changes: 17 additions & 2 deletions internal/cmd/help_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,12 @@ Example:
if !strings.Contains(out, "OPTIONS") {
t.Fatalf("expected options title in output: %q", out)
}
if !strings.Contains(out, "EXAMPLES\n\n") {
t.Fatalf("expected blank line after examples title in output: %q", out)
}
if !strings.Contains(out, `lets release 1.0.0 -m "Release 1.0.0"`) {
t.Fatalf("expected example in output: %q", out)
}
argIdx := strings.Index(out, "<version>")
flagIdx := strings.Index(out, "--message=<message>, -m")
if argIdx == -1 {
Expand Down Expand Up @@ -177,11 +183,11 @@ func TestHelpRendererDoesNotDuplicateDocoptUsageCommandPath(t *testing.T) {
}
}

func TestErrorHandlerRemovesErrorHeaderLeftPadding(t *testing.T) {
func TestErrorHandlerRemovesErrorTextLeftMargin(t *testing.T) {
var stderr bytes.Buffer
styles := fang.Styles{
ErrorHeader: lipgloss.NewStyle().Padding(0, 1).SetString("ERROR"),
ErrorText: lipgloss.NewStyle(),
ErrorText: lipgloss.NewStyle().MarginLeft(2),
Program: fang.Program{
Flag: lipgloss.NewStyle(),
},
Expand All @@ -193,9 +199,18 @@ func TestErrorHandlerRemovesErrorHeaderLeftPadding(t *testing.T) {
if !strings.Contains(out, "ERROR") {
t.Fatalf("expected error header in output: %q", out)
}
if !strings.HasPrefix(out, " ERROR") && !strings.Contains(out, "\n ERROR") {
t.Fatalf("expected error header padding to start at column zero: %q", out)
}
if strings.Contains(out, "\n ERROR") {
t.Fatalf("expected error header outer margin to be removed: %q", out)
}
if !strings.Contains(out, "\nTry --help for usage.") {
t.Fatalf("expected usage hint in output: %q", out)
}
if strings.Contains(out, "\n unknown command") || strings.Contains(out, "\n Try --help") {
t.Fatalf("expected error text to start at column zero: %q", out)
}
}

func TestErrorHandlerSplitsExecuteErrorCause(t *testing.T) {
Expand Down
10 changes: 5 additions & 5 deletions internal/cmd/testdata/TestErrorGolden/command_not_found.golden
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
ERROR
Unknown command "zzzznotacommand" for "lets".

ERROR

Unknown command "zzzznotacommand" for "lets".

Try --help for usage.
Try --help for usage.

Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
ERROR
Unknown command "slef" for "lets"
Did you mean this?
self
.

ERROR

Unknown command "slef" for "lets"

Did you mean this?
self
.

Try --help for usage.
Try --help for usage.

16 changes: 8 additions & 8 deletions internal/cmd/testdata/TestErrorGolden/dependency_chain.golden
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
ERROR
Exit status 1.

ERROR

Exit status 1.

COMMAND TREE:
└─ deploy
└─ build
└─ lint <-- failed here
COMMAND TREE:
└─ deploy
└─ build
└─ lint <-- failed here

12 changes: 6 additions & 6 deletions internal/cmd/testdata/TestErrorGolden/dependency_single.golden
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
ERROR
Exit status 1.

ERROR

Exit status 1.

COMMAND TREE:
└─ lint <-- failed here
COMMAND TREE:
└─ lint <-- failed here

2 changes: 1 addition & 1 deletion internal/executor/execute_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ func TestAfterScriptErrorDoesNotOverrideMainError(t *testing.T) {
mainErr := fmt.Errorf("main script failed")

r := newRecordingRunner()
r.failOn(0, mainErr) // main script fails
r.failOn(0, mainErr) // main script fails
r.failOn(1, fmt.Errorf("after script failed")) // after script also fails (logged, not returned)
ex := NewExecutor(cfg, r.run)

Expand Down
15 changes: 9 additions & 6 deletions internal/theme/theme.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,14 +73,15 @@ func ProgressColors(scheme fang.ColorScheme) (color.Color, color.Color) {
// DefaultColorScheme is the default colorscheme.
func DefaultColorScheme(c lipgloss.LightDarkFunc) fang.ColorScheme {
baseCyan := charmtone.Turtle
baseCyanLighter := lipgloss.Color("#0BF4F1")
baseWhite := charmtone.Ash
baseGray := charmtone.Oyster

return fang.ColorScheme{
Base: c(charmtone.Charcoal, baseCyan),
Title: baseWhite,
Base: c(charmtone.Charcoal, baseCyanLighter),
Title: baseCyanLighter,
Codeblock: c(charmtone.Salt, lipgloss.Color("#2F2E36")),
Program: c(charmtone.Malibu, baseWhite),
Program: c(charmtone.Malibu, baseCyan),
Command: c(charmtone.Pony, baseCyan),
DimmedArgument: c(charmtone.Squid, baseGray),
Comment: c(charmtone.Squid, lipgloss.Color("#747282")),
Expand Down Expand Up @@ -118,15 +119,17 @@ func AnsiColorScheme(c lipgloss.LightDarkFunc) fang.ColorScheme {
}

func SynthwaveColorScheme(c lipgloss.LightDarkFunc) fang.ColorScheme {
basePink := lipgloss.Color("#f24db8")

return fang.ColorScheme{
Base: c(charmtone.Charcoal, charmtone.Cheeky),
Base: c(charmtone.Charcoal, basePink),
Title: charmtone.Grape,
Codeblock: c(charmtone.Salt, lipgloss.Color("#2F2E36")),
Program: c(charmtone.Malibu, charmtone.Grape),
Command: c(charmtone.Pony, charmtone.Cheeky),
Command: c(charmtone.Pony, basePink),
DimmedArgument: c(charmtone.Squid, charmtone.Oyster),
Comment: c(charmtone.Squid, lipgloss.Color("#747282")),
Flag: c(lipgloss.Color("#0CB37F"), charmtone.Cheeky),
Flag: c(lipgloss.Color("#0CB37F"), basePink),
Argument: c(charmtone.Charcoal, charmtone.Ash),
Description: c(charmtone.Charcoal, charmtone.Ash),
FlagDefault: c(charmtone.Smoke, charmtone.Squid),
Expand Down
10 changes: 6 additions & 4 deletions internal/theme/theme_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"github.com/charmbracelet/x/exp/charmtone"
)

var defaultTitleColor = lipgloss.Color("#0BF4F1")

func TestValidName(t *testing.T) {
for _, name := range []string{DefaultName, ANSIName, SynthwaveName} {
if !ValidName(name) {
Expand All @@ -20,8 +22,8 @@ func TestValidName(t *testing.T) {
}

func TestColorSchemeByName(t *testing.T) {
if got := ColorSchemeByName(DefaultName)(lipgloss.LightDark(true)).Title; got != charmtone.Ash {
t.Fatalf("expected default theme title color %v, got %v", charmtone.Ash, got)
if got := ColorSchemeByName(DefaultName)(lipgloss.LightDark(true)).Title; got != defaultTitleColor {
t.Fatalf("expected default theme title color %v, got %v", defaultTitleColor, got)
}

if got := ColorSchemeByName(ANSIName)(lipgloss.LightDark(true)).ErrorDetails; got != lipgloss.Red {
Expand All @@ -32,8 +34,8 @@ func TestColorSchemeByName(t *testing.T) {
t.Fatalf("expected synthwave theme title color %v, got %v", charmtone.Grape, got)
}

if got := ColorSchemeByName("unknown")(lipgloss.LightDark(true)).Title; got != charmtone.Ash {
t.Fatalf("expected unknown theme to fall back to %v, got %v", charmtone.Ash, got)
if got := ColorSchemeByName("unknown")(lipgloss.LightDark(true)).Title; got != defaultTitleColor {
t.Fatalf("expected unknown theme to fall back to %v, got %v", defaultTitleColor, got)
}
}

Expand Down
Loading