detached f13a4f4

cli: print styled config-open errors without ANSI returns

commit
f13a4f40678a5188d5b3a751f94c14bb3a2a948d
author
bnema · · 2026-02-11 19:55 UTC
parent
3a4e250
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
1 file · +12 -4
M internal/cli/cmd/config.go +12 -4
@@ -118,18 +118,24 @@ func runConfigOpen(_ *cobra.Command, _ []string) error {
118118
119119 configFile, err := config.GetConfigFile()
120120 if err != nil {
121- return fmt.Errorf("%s", strings.TrimRight(renderer.RenderError(fmt.Errorf("get config file: %w", err)), "\n"))
121+ wrappedErr := fmt.Errorf("get config file: %w", err)
122+ fmt.Fprintln(os.Stderr, strings.TrimRight(renderer.RenderError(wrappedErr), "\n"))
123+ return wrapPrintedError(wrappedErr)
122124 }
123125
124126 // Check if config file exists
125127 if _, statErr := os.Stat(configFile); os.IsNotExist(statErr) {
126- return fmt.Errorf("%s", strings.TrimRight(renderer.RenderError(fmt.Errorf("config file does not exist: %s", configFile)), "\n"))
128+ err := fmt.Errorf("config file does not exist: %s", configFile)
129+ fmt.Fprintln(os.Stderr, strings.TrimRight(renderer.RenderError(err), "\n"))
130+ return wrapPrintedError(err)
127131 }
128132
129133 editor := getEditor()
130134 if editor == "" {
131135 const msg = "no editor found: set $EDITOR or $VISUAL environment variable"
132- return fmt.Errorf("%s", strings.TrimRight(renderer.RenderError(fmt.Errorf("%s", msg)), "\n"))
136+ err := fmt.Errorf("%s", msg)
137+ fmt.Fprintln(os.Stderr, strings.TrimRight(renderer.RenderError(err), "\n"))
138+ return wrapPrintedError(err)
133139 }
134140
135141 // Keep this a simple, non-interactive message; the actual editor takes over the terminal.
@@ -141,7 +147,9 @@ func runConfigOpen(_ *cobra.Command, _ []string) error {
141147 cmd.Stderr = os.Stderr
142148
143149 if err := cmd.Run(); err != nil {
144- return fmt.Errorf("%s", strings.TrimRight(renderer.RenderError(fmt.Errorf("open config: %w", err)), "\n"))
150+ wrappedErr := fmt.Errorf("open config: %w", err)
151+ fmt.Fprintln(os.Stderr, strings.TrimRight(renderer.RenderError(wrappedErr), "\n"))
152+ return wrapPrintedError(wrappedErr)
145153 }
146154 return nil
147155 }
@@ -118,18 +118,24 @@ func runConfigOpen(_ *cobra.Command, _ []string) error {
118 118
119 configFile, err := config.GetConfigFile()119 configFile, err := config.GetConfigFile()
120 if err != nil {120 if err != nil {
121- return fmt.Errorf("%s", strings.TrimRight(renderer.RenderError(fmt.Errorf("get config file: %w", err)), "\n"))121+ wrappedErr := fmt.Errorf("get config file: %w", err)
122+ fmt.Fprintln(os.Stderr, strings.TrimRight(renderer.RenderError(wrappedErr), "\n"))
123+ return wrapPrintedError(wrappedErr)
122 }124 }
123 125
124 // Check if config file exists126 // Check if config file exists
125 if _, statErr := os.Stat(configFile); os.IsNotExist(statErr) {127 if _, statErr := os.Stat(configFile); os.IsNotExist(statErr) {
126- return fmt.Errorf("%s", strings.TrimRight(renderer.RenderError(fmt.Errorf("config file does not exist: %s", configFile)), "\n"))128+ err := fmt.Errorf("config file does not exist: %s", configFile)
129+ fmt.Fprintln(os.Stderr, strings.TrimRight(renderer.RenderError(err), "\n"))
130+ return wrapPrintedError(err)
127 }131 }
128 132
129 editor := getEditor()133 editor := getEditor()
130 if editor == "" {134 if editor == "" {
131 const msg = "no editor found: set $EDITOR or $VISUAL environment variable"135 const msg = "no editor found: set $EDITOR or $VISUAL environment variable"
132- return fmt.Errorf("%s", strings.TrimRight(renderer.RenderError(fmt.Errorf("%s", msg)), "\n"))136+ err := fmt.Errorf("%s", msg)
137+ fmt.Fprintln(os.Stderr, strings.TrimRight(renderer.RenderError(err), "\n"))
138+ return wrapPrintedError(err)
133 }139 }
134 140
135 // Keep this a simple, non-interactive message; the actual editor takes over the terminal.141 // Keep this a simple, non-interactive message; the actual editor takes over the terminal.
@@ -141,7 +147,9 @@ func runConfigOpen(_ *cobra.Command, _ []string) error {
141 cmd.Stderr = os.Stderr147 cmd.Stderr = os.Stderr
142 148
143 if err := cmd.Run(); err != nil {149 if err := cmd.Run(); err != nil {
144- return fmt.Errorf("%s", strings.TrimRight(renderer.RenderError(fmt.Errorf("open config: %w", err)), "\n"))150+ wrappedErr := fmt.Errorf("open config: %w", err)
151+ fmt.Fprintln(os.Stderr, strings.TrimRight(renderer.RenderError(wrappedErr), "\n"))
152+ return wrapPrintedError(wrappedErr)
145 }153 }
146 return nil154 return nil
147 }155 }

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 8

Tags 42

↑↓ moveenter openesc close