diff --git a/cmd/melt/main.go b/cmd/melt/main.go index df4692c..cede90b 100644 --- a/cmd/melt/main.go +++ b/cmd/melt/main.go @@ -8,7 +8,6 @@ import ( "io" "os" "strings" - "sync" "github.com/caarlos0/sshmarshal" "github.com/charmbracelet/lipgloss" @@ -16,7 +15,9 @@ import ( "github.com/mattn/go-isatty" "github.com/muesli/coral" mcoral "github.com/muesli/mango-coral" + "github.com/muesli/reflow/wordwrap" "github.com/muesli/roff" + "github.com/muesli/termenv" "golang.org/x/crypto/ssh" "golang.org/x/term" ) @@ -27,20 +28,21 @@ const ( ) var ( - widthOnce sync.Once - terminalWidth int - docStyle = lipgloss.NewStyle().Margin(1, 2) - baseStyle = lipgloss.NewStyle().Margin(0, 0, 1, 2) - headerStyle = lipgloss.NewStyle() - lineStyle = lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{Light: "", Dark: "237"}) - backslashStyle = lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{Light: "", Dark: "239"}) - mnemonicStyle = baseStyle.Copy(). - Foreground(lipgloss.Color("204")). - Background(lipgloss.Color("234")). + terminalWidth int + + docStyle = lipgloss.NewStyle().Margin(1, 2) + baseStyle = lipgloss.NewStyle().Margin(0, 0, 1, 2) + violet = lipgloss.Color(completeColor("#6B50FF", "63", "12")) + cmdStyle = lipgloss.NewStyle(). + Foreground(lipgloss.AdaptiveColor{Light: "#FF5E8E", Dark: "#FF5E8E"}). + Background(lipgloss.AdaptiveColor{Light: completeColor("#ECECEC", "255", "7"), Dark: "#1F1F1F"}). + Padding(0, 1) + mnemonicStyle = baseStyle.Copy(). + Foreground(violet). + Background(lipgloss.AdaptiveColor{Light: completeColor("#EEEBFF", "255", "7"), Dark: completeColor("#1B1731", "235", "8")}). Padding(1, 2) - cmdStyle = baseStyle.Copy() - restoreStyle = lipgloss.NewStyle().Bold(true).Margin(1) - keyStyle = lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{Light: "", Dark: "36"}) + borderStyle = lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{Light: "", Dark: "236"}) + keyPathStyle = lipgloss.NewStyle().Foreground(violet) rootCmd = &coral.Command{ Use: "melt", @@ -64,28 +66,23 @@ You can use that seed to restore your public and private keys.`, w := getWidth(maxWidth) b.WriteRune('\n') - header := headerStyle.Render("Success! ") - headerGap := w - lipgloss.Width(header) - line := lineStyle.Render(strings.Repeat("─", headerGap)) - renderBlock(&b, baseStyle, w, header+line) - - renderBlock(&b, baseStyle, w, "Your key has been melted down to the seed words below. Store them somewhere safe. You can use melt to recover your key at any time.") + meltCmd := cmdStyle.Render(os.Args[0]) + renderBlock(&b, baseStyle, w, fmt.Sprintf("OK! Your key has been melted down to the seed words below. Store them somewhere safe. You can use %s to recover your key at any time.", meltCmd)) renderBlock(&b, mnemonicStyle, w, mnemonic) renderBlock(&b, baseStyle, w, "To recreate this key run:") - // Restore command - cmdEOL := backslashStyle.Render(" \\") - const cmdIndent = 4 - cmd := cmdStyle.Copy(). - Width(w - lipgloss.Width(cmdEOL) - cmdIndent - 4). - Render(os.Args[0] + " restore ./key --seed \"" + mnemonic + "\"") + // Build formatted restore command + const cmdEOL = " \\" + cmd := wordwrap.String( + os.Args[0]+` restore ./my-key --seed "`+mnemonic+`"`, + w-lipgloss.Width(cmdEOL)-baseStyle.GetHorizontalFrameSize()*2, + ) + leftPad := strings.Repeat(" ", baseStyle.GetMarginLeft()) cmdLines := strings.Split(cmd, "\n") for i, l := range cmdLines { - if i > 0 { - b.WriteString(strings.Repeat(" ", cmdIndent)) - } - b.WriteString(strings.TrimRight(l, " ")) - if i < len(cmdLines)-2 { + b.WriteString(leftPad) + b.WriteString(l) + if i < len(cmdLines)-1 { b.WriteString(cmdEOL) b.WriteRune('\n') } @@ -104,7 +101,7 @@ You can use that seed to restore your public and private keys.`, restoreCmd = &coral.Command{ Use: "restore", Short: "Recreate a key using the given seed words", - Example: ` melt restore --seed \"list of words\" ./restored_id25519 + Example: ` melt restore --seed "list of words" ./restored_id25519 melt restore ./restored_id25519 < seed`, Aliases: []string{"res", "r"}, Args: coral.ExactArgs(1), @@ -113,9 +110,9 @@ You can use that seed to restore your public and private keys.`, return err } - pub := keyStyle.Render(args[0]) - priv := keyStyle.Render(args[0] + ".pub") - fmt.Println(baseStyle.Render(fmt.Sprintf("\nSuccessfully restored keys to %s and %s!", pub, priv))) + pub := keyPathStyle.Render(args[0]) + priv := keyPathStyle.Render(args[0] + ".pub") + fmt.Println(baseStyle.Render(fmt.Sprintf("\nSuccessfully restored keys to %s and %s", pub, priv))) return nil }, } @@ -227,9 +224,7 @@ func restore(mnemonic, path string) error { func getWidth(max int) int { var err error - widthOnce.Do(func() { - terminalWidth, _, err = term.GetSize(int(os.Stdout.Fd())) - }) + terminalWidth, _, err = term.GetSize(int(os.Stdout.Fd())) if err != nil || terminalWidth > maxWidth { return maxWidth } @@ -240,3 +235,13 @@ func renderBlock(w io.Writer, s lipgloss.Style, width int, str string) { io.WriteString(w, s.Copy().Width(width).Render(str)) io.WriteString(w, "\n") } + +func completeColor(truecolor, ansi256, ansi string) string { + switch lipgloss.ColorProfile() { + case termenv.TrueColor: + return truecolor + case termenv.ANSI256: + return ansi256 + } + return ansi +} diff --git a/go.mod b/go.mod index ff49856..c867b43 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,7 @@ require ( github.com/muesli/coral v1.0.0 github.com/muesli/mango-coral v1.0.1 github.com/muesli/roff v0.1.0 + github.com/muesli/termenv v0.11.1-0.20220204035834-5ac8409525e0 github.com/tyler-smith/go-bip39 v1.1.0 golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 @@ -22,7 +23,6 @@ require ( github.com/muesli/mango v0.1.0 // indirect github.com/muesli/mango-pflag v0.1.0 // indirect github.com/muesli/reflow v0.2.1-0.20210115123740-9e1d0d53df68 // indirect - github.com/muesli/termenv v0.11.1-0.20220204035834-5ac8409525e0 // indirect github.com/rivo/uniseg v0.2.0 // indirect github.com/spf13/pflag v1.0.5 // indirect golang.org/x/sys v0.0.0-20220307203707-22a9840ba4d7 // indirect diff --git a/go.sum b/go.sum index 562676b..1cca3f7 100644 --- a/go.sum +++ b/go.sum @@ -50,7 +50,6 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220307203707-22a9840ba4d7 h1:8IVLkfbr2cLhv0a/vKq4UFUcJym8RmDoDboxCFWEjYE= golang.org/x/sys v0.0.0-20220307203707-22a9840ba4d7/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=