diff --git a/README.md b/README.md index 8229bef..9d7fcbb 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,7 @@ The commands available directly from the shell are `clone`, `init`, `log`, `pull`, `fetch`, `status`, `diff`, `overview`, `config`, `count`, `login` and `cloneall`; every other command is interactive-only. -The interactive prompt is colored (Catppuccin Mocha) and shows the active +The interactive prompt is colored (Catppuccin-flavored) and shows the active project, its git branch and a `*` dirty marker: ``` diff --git a/alias.go b/alias.go index ef9d097..643ce21 100644 --- a/alias.go +++ b/alias.go @@ -241,7 +241,7 @@ func handleUnalias(name string) { func listAliases() { if len(aliases) == 0 { - fmt.Println(col(cGray, "no aliases defined")) + fmt.Println(col(cDark, "no aliases defined")) return } for _, n := range aliasNames() { @@ -251,7 +251,7 @@ func listAliases() { // formatAlias renders `name = 'body'` with color. func formatAlias(name, body string) string { - return col(cGreen, name) + col(cGray, " = ") + col(cYellow, "'"+body+"'") + return col(cGreen, name) + col(cDark, " = ") + col(cYellow, "'"+body+"'") } // expandAlias substitutes positional parameters in an alias body. With no diff --git a/assets.go b/assets.go index ad41ccc..b1a1ca5 100644 --- a/assets.go +++ b/assets.go @@ -114,8 +114,8 @@ func (r *remoteAPI) doUpload(method, endpoint, ctype string, body io.Reader, siz func (r *remoteAPI) uploadAssets(owner, repo string, ref releaseRef, assets []releaseAsset) error { failed := 0 for _, a := range assets { - fmt.Printf(" %s %s %s\n", col(cGray, "uploading"), - col(cGreen, padRight(a.name, 28)), col(cGray, humanSize(a.size))) + fmt.Printf(" %s %s %s\n", col(cDark, "uploading"), + col(cGreen, padRight(a.name, 28)), col(cDark, humanSize(a.size))) if err := r.uploadAsset(owner, repo, ref, a); err != nil { errorln(" " + a.name + ": " + err.Error()) failed++ diff --git a/colors.go b/colors.go index 5ae4a80..4379a59 100644 --- a/colors.go +++ b/colors.go @@ -7,21 +7,24 @@ import ( "unicode/utf8" ) -// Colors for the prompt, banner and output, using the Catppuccin Mocha palette -// as 24-bit truecolor escapes -// (https://terminalcolors.com/themes/catppuccin/mocha/). +// Colors for the prompt, banner and output, as 24-bit truecolor escapes: the +// Catppuccin Mocha accents with a warm white and three greys of its own. const ( cReset = "\033[0m" cBold = "\033[1m" cDim = "\033[2m" - cGreen = "\033[38;2;166;227;161m" // Green #a6e3a1 - cYellow = "\033[38;2;249;226;175m" // Yellow #f9e2af - cRed = "\033[38;2;243;139;168m" // Red #f38ba8 - cCyan = "\033[38;2;148;226;213m" // Teal #94e2d5 - cPurple = "\033[38;2;203;166;247m" // Mauve #cba6f7 - cWhite = "\033[38;2;205;214;244m" // Text #cdd6f4 - cGray = "\033[38;2;108;112;134m" // Overlay0 #6c7086 + cYellow = "\033[38;2;249;226;175m" // #f9e2af + cOrange = "\033[38;2;250;179;135m" // #fab387 + cRed = "\033[38;2;243;139;168m" // #f38ba8 + cGreen = "\033[38;2;148;226;213m" // #94e2d5 + cBlue = "\033[38;2;180;190;254m" // #b4befe + cPink = "\033[38;2;245;178;247m" // #f5b2f7 + cViolet = "\033[38;2;203;166;247m" // #cba6f7 + cWhite = "\033[38;2;240;240;234m" // #f0f0ea + cGrey = "\033[38;2;170;170;187m" // #aaaabb + cDark = "\033[38;2;119;119;136m" // #777788 + cDarker = "\033[38;2;68;68;85m" // #444455 ) // col wraps s in color c, but only when color output is enabled. @@ -66,7 +69,7 @@ func formatRepoList(entries []lsEntry, withSize bool) string { for _, e := range entries { fmt.Fprintf(&b, " %s %s", col(cGreen, padRight(e.name, width)), col(cYellow, e.date)) if withSize { - fmt.Fprintf(&b, " %s", col(cGray, fmt.Sprintf("%7s", humanSize(e.size)))) + fmt.Fprintf(&b, " %s", col(cDark, fmt.Sprintf("%7s", humanSize(e.size)))) } b.WriteByte('\n') } diff --git a/commands.go b/commands.go index 59816f8..499d7e8 100644 --- a/commands.go +++ b/commands.go @@ -282,7 +282,7 @@ func runCommandDepth(line string, depth int) bool { if pat != "" { what = "no " + many + " matching '" + word(words, 1) + "'" } - fmt.Println(col(cGray, what)) + fmt.Println(col(cDark, what)) break } // no size column when the server gave no usable sizes, rather than a @@ -296,7 +296,7 @@ func runCommandDepth(line string, depth int) bool { if total > 0 { summary += " · " + humanSize(total) } - fmt.Println(col(cGray, summary)) + fmt.Println(col(cDark, summary)) case "show": // show a repository's log directly on the server prj := PRJ @@ -610,7 +610,7 @@ func runCommandDepth(line string, depth int) bool { default: // unknown command — no longer forwarded to the shell fmt.Println(col(cRed, "unknown command: "+words[0]) + - col(cGray, " (prefix with '!' to run a shell command)")) + col(cDark, " (prefix with '!' to run a shell command)")) } return true @@ -671,9 +671,9 @@ func formatLog(lines []string, now time.Time) string { n++ } - fmt.Fprintf(&full, "%s %s %s\n", col(cPurple, hash), col(cYellow, z), subj) - fmt.Fprintf(&short, "%s %s %s\n", col(cPurple, hash), col(cYellow, zs), subj) - fmt.Fprintf(&tiny, "%s %s %s\n", col(cPurple, hash), col(cYellow, zss), subj) + fmt.Fprintf(&full, "%s %s %s\n", col(cViolet, hash), col(cYellow, z), subj) + fmt.Fprintf(&short, "%s %s %s\n", col(cViolet, hash), col(cYellow, zs), subj) + fmt.Fprintf(&tiny, "%s %s %s\n", col(cViolet, hash), col(cYellow, zss), subj) } switch { diff --git a/config.go b/config.go index 15930e8..2e8a73d 100644 --- a/config.go +++ b/config.go @@ -188,9 +188,9 @@ func migrateRemoteKeys(path, data string) { errorln("could not update " + path + ": " + err.Error()) return } - fmt.Println(col(cGray, path+": mirror settings renamed to the remote..* form")) + fmt.Println(col(cDark, path+": mirror settings renamed to the remote..* form")) for _, r := range renamed { - fmt.Println(col(cGray, " "+r)) + fmt.Println(col(cDark, " "+r)) } } diff --git a/mgsh_test.go b/mgsh_test.go index 60d25b8..7f4ce5a 100644 --- a/mgsh_test.go +++ b/mgsh_test.go @@ -109,7 +109,7 @@ func TestFormatRepoList(t *testing.T) { colored := formatRepoList(entries, false) useColor = false strip := func(s string) string { - for _, c := range []string{cReset, cGreen, cYellow, cGray} { + for _, c := range []string{cReset, cGreen, cYellow, cDark} { s = strings.ReplaceAll(s, c, "") } return s diff --git a/overview.go b/overview.go index b51f7e3..5ee8b70 100644 --- a/overview.go +++ b/overview.go @@ -82,7 +82,7 @@ func overviewAll() { }) if len(rows) == 0 { - fmt.Println(col(cGray, "nothing under "+BASE)) + fmt.Println(col(cDark, "nothing under "+BASE)) return } @@ -109,9 +109,9 @@ func overviewAll() { if initN > 0 { summary += fmt.Sprintf(" · %d to init", initN) } - fmt.Println(col(cGray, summary)) + fmt.Println(col(cDark, summary)) if srv.err != nil { - fmt.Println(col(cGray, " git server not reachable — local view only")) + fmt.Println(col(cDark, " git server not reachable — local view only")) } } @@ -301,7 +301,7 @@ func syncColor(s projStatus) string { case s.ahead > 0: return cGreen default: - return cGray + return cDark } } @@ -339,8 +339,8 @@ func formatProjStatus(s projStatus, w overviewWidths) string { if !s.lastWhen.IsZero() { age = shortAge(time.Since(s.lastWhen)) } - b.WriteString(" " + col(cGray, padRight(s.lastHost, w.host))) - b.WriteString(" " + col(cGray, fmt.Sprintf("%4s", age))) + b.WriteString(" " + col(cDark, padRight(s.lastHost, w.host))) + b.WriteString(" " + col(cDark, fmt.Sprintf("%4s", age))) } if w.hint { hint := "" @@ -350,7 +350,7 @@ func formatProjStatus(s projStatus, w overviewWidths) string { b.WriteString(" " + col(cYellow, padRight(hint, hintWidth))) } if len(s.mirrors) > 0 { - b.WriteString(col(cGray, " → "+strings.Join(s.mirrors, " "))) + b.WriteString(col(cDark, " → "+strings.Join(s.mirrors, " "))) } return strings.TrimRight(b.String(), " ") } diff --git a/prompt.go b/prompt.go index bd720b8..787e2a7 100644 --- a/prompt.go +++ b/prompt.go @@ -45,21 +45,21 @@ func plainPrompt() string { func coloredPrompt() string { var b strings.Builder - b.WriteString(cBold + cPurple + "< " + cReset) - b.WriteString(cCyan + filepath.Base(BASE) + cReset) + b.WriteString(cBold + cViolet + "< " + cReset) + b.WriteString(cBlue + filepath.Base(BASE) + cReset) if PRJ != "" && isDir(BASE+"/"+PRJ) { b.WriteString(cBold + cWhite + "/" + cReset + cBold + cGreen + PRJ + cReset) if BPLSTATE != "" { b.WriteString(cRed + BPLSTATE + cReset) } if BRANCH != "" { - b.WriteString(cGray + " (" + cReset + cCyan + BRANCH + cReset) + b.WriteString(cDark + " (" + cReset + cBlue + BRANCH + cReset) if DIRTY { b.WriteString(cRed + "*" + cReset) } - b.WriteString(cGray + ")" + cReset) + b.WriteString(cDark + ")" + cReset) } } - b.WriteString(" " + cBold + cPurple + ">" + cReset + " ") + b.WriteString(" " + cBold + cViolet + ">" + cReset + " ") return b.String() } diff --git a/release.go b/release.go index 72b66d6..3d7aded 100644 --- a/release.go +++ b/release.go @@ -193,8 +193,8 @@ func handleRelease(args string) { errorln("skipping " + s + ": another directory already contributes that name") } if len(assets) > 0 { - fmt.Printf("%s %s %s\n", col(cGray, "attaching"), col(cYellow, assetSummary(assets)), - col(cGray, "from "+strings.Join(assetDirList(DIR), " and "))) + fmt.Printf("%s %s %s\n", col(cDark, "attaching"), col(cYellow, assetSummary(assets)), + col(cDark, "from "+strings.Join(assetDirList(DIR), " and "))) } done := 0 @@ -204,7 +204,7 @@ func handleRelease(args string) { } } if len(targets) > 1 { - fmt.Printf("%s %d/%d remotes released\n", col(cGray, "release:"), done, len(targets)) + fmt.Printf("%s %d/%d remotes released\n", col(cDark, "release:"), done, len(targets)) } } @@ -303,8 +303,8 @@ func publishRelease(t RemoteTarget, repo, tag, body string, assets []releaseAsse if rel.Prerelease { what += " (pre-release)" } - fmt.Printf("%s %s %s %s\n", col(cGray, "remote"), col(cYellow, t.Name), - col(cGreen, what), col(cCyan, api.repoWebURL(owner, repo))) + fmt.Printf("%s %s %s %s\n", col(cDark, "remote"), col(cYellow, t.Name), + col(cGreen, what), col(cBlue, api.repoWebURL(owner, repo))) if len(assets) > 0 { if err := api.uploadAssets(owner, repo, ref, assets); err != nil { diff --git a/remote.go b/remote.go index 2553ab9..5ace454 100644 --- a/remote.go +++ b/remote.go @@ -296,7 +296,7 @@ func handlePushRemote(args string) { } } if len(targets) > 1 { - fmt.Printf("%s %d/%d remotes updated\n", col(cGray, "pushremote:"), done, len(targets)) + fmt.Printf("%s %d/%d remotes updated\n", col(cDark, "pushremote:"), done, len(targets)) } } @@ -313,7 +313,7 @@ func pushToRemote(t RemoteTarget, repo, description string) bool { return false } fmt.Printf("%s %s %s (as %s)\n", - col(cGray, "remote"), col(cYellow, t.Name), col(cCyan, api.url), col(cGreen, owner)) + col(cDark, "remote"), col(cYellow, t.Name), col(cBlue, api.url), col(cGreen, owner)) exists, err := api.repoExists(owner, repo) if err != nil { @@ -343,7 +343,7 @@ func pushToRemote(t RemoteTarget, repo, description string) bool { return false } gitPushHeader(DIR, t.Name, header, "--tags") - fmt.Println(col(cGreen, "pushed to ") + col(cCyan, web)) + fmt.Println(col(cGreen, "pushed to ") + col(cBlue, web)) return true } diff --git a/secrets.go b/secrets.go index 2e1519c..97c7f87 100644 --- a/secrets.go +++ b/secrets.go @@ -191,9 +191,9 @@ func secretsApproved(dir string) bool { where += ":" + strconv.Itoa(h.lineNo) } fmt.Printf(" %s %s\n %s\n", - col(cYellow, where), col(cGray, h.kind), col(cRed, ellipsis(strings.TrimSpace(h.text), 100))) + col(cYellow, where), col(cDark, h.kind), col(cRed, ellipsis(strings.TrimSpace(h.text), 100))) } - fmt.Println(col(cGray, " (set 'secretscan = off' to skip this check)")) + fmt.Println(col(cDark, " (set 'secretscan = off' to skip this check)")) return yesno("push anyway?", false) } diff --git a/show_config.go b/show_config.go index e916240..bbcd350 100644 --- a/show_config.go +++ b/show_config.go @@ -24,11 +24,11 @@ func showConfig() { project = DIR + "/" + projectRC } - fmt.Printf("%s %s\n", col(cGray, "global "), col(cCyan, global)) + fmt.Printf("%s %s\n", col(cDark, "global "), col(cBlue, global)) if project != "" { - fmt.Printf("%s %s\n", col(cGray, "project"), col(cCyan, project)) + fmt.Printf("%s %s\n", col(cDark, "project"), col(cBlue, project)) } else if PRJ != "" { - fmt.Printf("%s %s\n", col(cGray, "project"), col(cGray, "no "+projectRC+" in "+PRJ)) + fmt.Printf("%s %s\n", col(cDark, "project"), col(cDark, "no "+projectRC+" in "+PRJ)) } fmt.Println() @@ -72,13 +72,13 @@ func showConfig() { } if k := sshKeyPath(); k != "" { - fmt.Printf(" %s%s\n", col(cGray, padRight("ssh identity", 14)), col(cGray, k)) + fmt.Printf(" %s%s\n", col(cDark, padRight("ssh identity", 14)), col(cDark, k)) } - fmt.Printf(" %s%s\n", col(cGray, padRight("clone url", 14)), col(cGray, URL)) + fmt.Printf(" %s%s\n", col(cDark, padRight("clone url", 14)), col(cDark, URL)) // the project's real origin: it can differ from what the current settings // would produce, e.g. after moving the server or editing a project .mgshrc if o := originURL(); o != "" { - fmt.Printf(" %s%s\n", col(cGray, padRight("origin", 14)), col(cGray, o)) + fmt.Printf(" %s%s\n", col(cDark, padRight("origin", 14)), col(cDark, o)) } showRemotes() @@ -90,11 +90,11 @@ func showRemotes() { targets, incomplete := cfg.mirrorTargets() fmt.Println() if len(targets) == 0 && len(incomplete) == 0 { - fmt.Println(col(cGray, "no pushremote targets configured")) + fmt.Println(col(cDark, "no pushremote targets configured")) return } - fmt.Println(col(cGray, "pushremote targets (in push order):")) + fmt.Println(col(cDark, "pushremote targets (in push order):")) for _, t := range targets { vis := "private" if strings.EqualFold(strings.TrimSpace(t.Vis), "public") { @@ -106,7 +106,7 @@ func showRemotes() { } fmt.Printf(" %s%s %s\n", col(cGreen, padRight("@"+t.Name, 14)), t.URL, - col(cGray, kind+", "+vis+", key "+maskSecret(t.Key))) + col(cDark, kind+", "+vis+", key "+maskSecret(t.Key))) } for _, n := range incomplete { fmt.Printf(" %s%s\n", col(cRed, padRight("@"+n, 14)), col(cRed, "incomplete: url or key missing")) diff --git a/version.txt b/version.txt index 995d77e..8d9df19 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -4.0.58 +4.0.62