77
88 "github.com/atotto/clipboard"
99 tea "github.com/charmbracelet/bubbletea"
10+ "github.com/charmbracelet/lipgloss"
1011 "github.com/voocel/codebot/internal/config"
1112 "github.com/voocel/codebot/internal/cron"
1213 "github.com/voocel/codebot/internal/policy"
@@ -22,7 +23,7 @@ func (a *App) handleCommand(input string) tea.Cmd {
2223 cmd , ok := a .registry .Lookup (inv .Name )
2324 if ! ok {
2425 return tui .SendCommandResult (tui .CommandStyle .Render (
25- fmt .Sprintf ("Unknown command: /%s. Type /help for available commands. " , inv .Name )))
26+ fmt .Sprintf ("Unknown command: /%s. 输入 / 浏览命令,或用 /help 查看完整列表。 " , inv .Name )))
2627 }
2728
2829 spec := cmd .Spec ()
@@ -143,7 +144,7 @@ func (a *App) builtinCommands() []Command {
143144 NewSimple (CommandSpec {
144145 Name : "loop" , Usage : "/loop <interval|cron> <prompt>" ,
145146 Description : "Schedule recurring prompts" ,
146- Risk : policy .RiskLow , Kind : CommandKindBuiltin ,
147+ Risk : policy .RiskLow , Kind : CommandKindBuiltin ,
147148 }, func (ctx * CommandContext , inv CommandInvocation ) tea.Cmd {
148149 return ctx .App .cmdLoop (inv .RawArgs )
149150 }),
@@ -171,31 +172,40 @@ func (a *App) helpText() string {
171172 groups [spec .Kind ] = append (groups [spec .Kind ], cmd )
172173 }
173174
175+ headerStyle := lipgloss .NewStyle ().Foreground (lipgloss .Color ("247" ))
176+ sectionStyle := lipgloss .NewStyle ().Foreground (lipgloss .Color ("249" ))
174177 var sb strings.Builder
175- sb .WriteString ("Available commands: \n " )
178+ sb .WriteString (headerStyle . Render ( "Available commands (/ opens the command palette):" ) )
176179 a .renderCommandGroup (& sb , "Built-in" , groups [CommandKindBuiltin ])
177180 a .renderCommandGroup (& sb , "Custom commands" , groups [CommandKindCustom ])
178181 a .renderCommandGroup (& sb , "Skills" , groups [CommandKindSkill ])
179182
180- sb .WriteString (strings .TrimSpace (`
183+ sb .WriteString ("\n \n " )
184+ sb .WriteString (sectionStyle .Render ("Keyboard shortcuts:" ))
185+ sb .WriteString ("\n " )
186+ sb .WriteString (tui .MutedStyle .Render (strings .TrimSpace (`
181187
182- Keyboard shortcuts:
183188 Enter Send message
184189 Esc Abort running agent
185190 Ctrl+C Quit
186- ` ))
191+ ` )))
187192
188- return tui . CommandStyle . Render ( sb .String () )
193+ return sb .String ()
189194}
190195
191196func (a * App ) renderCommandGroup (sb * strings.Builder , title string , commands []Command ) {
192197 if len (commands ) == 0 {
193198 return
194199 }
195200
201+ sectionStyle := lipgloss .NewStyle ().Foreground (lipgloss .Color ("249" ))
202+ usageStyle := lipgloss .NewStyle ().Foreground (lipgloss .Color ("243" ))
203+ descStyle := lipgloss .NewStyle ().Foreground (lipgloss .Color ("247" ))
204+ metaStyle := lipgloss .NewStyle ().Foreground (lipgloss .Color ("250" ))
205+
196206 sb .WriteString ("\n \n " )
197- sb .WriteString (title )
198- sb .WriteString (": \n " )
207+ sb .WriteString (sectionStyle . Render ( title + ":" ) )
208+ sb .WriteString ("\n " )
199209
200210 for _ , cmd := range commands {
201211 spec := a .registry .EffectiveSpec (cmd )
@@ -224,7 +234,14 @@ func (a *App) renderCommandGroup(sb *strings.Builder, title string, commands []C
224234 if len (spec .Aliases ) > 0 {
225235 tags = append (tags , "aliases: " + strings .Join (spec .Aliases , "," ))
226236 }
227- fmt .Fprintf (sb , " %-24s %s [%s]\n " , usage , desc , strings .Join (tags , ", " ))
237+
238+ sb .WriteString (" " )
239+ sb .WriteString (usageStyle .Render (fmt .Sprintf ("%-24s" , usage )))
240+ sb .WriteString (" " )
241+ sb .WriteString (descStyle .Render (desc ))
242+ sb .WriteString (" " )
243+ sb .WriteString (metaStyle .Render ("[" + strings .Join (tags , ", " ) + "]" ))
244+ sb .WriteString ("\n " )
228245 }
229246}
230247
@@ -312,7 +329,6 @@ func (a *App) cmdNew() tea.Cmd {
312329 }
313330}
314331
315-
316332func (a * App ) cmdSettings () tea.Cmd {
317333 s := a .Session .Settings ()
318334 baseURL := a .Session .BaseURL ()
@@ -325,10 +341,42 @@ func (a *App) cmdSettings() tea.Cmd {
325341 }
326342 apiKey := a .Session .APIKey ()
327343 masked := maskKey (apiKey )
328- info := fmt .Sprintf ("Provider: %s\n Model: %s\n API Key: %s\n Base URL: %s\n Thinking level: %s\n Context window: %d\n Auto compaction: %v\n Max turns: %d\n Config: %s" ,
329- s .Provider , a .Session .ModelName (), masked , baseURL ,
330- thinking , s .ContextWindow , s .AutoCompaction , s .MaxTurns , config .SettingsPath (a .Cwd ))
331- return tui .SendCommandResult (tui .CommandStyle .Render (info ))
344+
345+ labelStyle := lipgloss .NewStyle ().Foreground (lipgloss .Color ("243" ))
346+ valueStyle := lipgloss .NewStyle ().Foreground (lipgloss .Color ("247" ))
347+ metaStyle := lipgloss .NewStyle ().Foreground (lipgloss .Color ("248" ))
348+
349+ autoCompact := "off"
350+ if s .AutoCompaction {
351+ autoCompact = "on"
352+ }
353+
354+ var sb strings.Builder
355+ renderRow := func (label , value string ) {
356+ sb .WriteString (labelStyle .Render (fmt .Sprintf ("%-16s" , label )))
357+ sb .WriteString (" " )
358+ sb .WriteString (valueStyle .Render (value ))
359+ sb .WriteString ("\n " )
360+ }
361+ renderMetaRow := func (label , value string ) {
362+ sb .WriteString (labelStyle .Render (fmt .Sprintf ("%-16s" , label )))
363+ sb .WriteString (" " )
364+ sb .WriteString (metaStyle .Render (value ))
365+ sb .WriteString ("\n " )
366+ }
367+
368+ renderRow ("Provider" , s .Provider )
369+ renderRow ("Model" , a .Session .ModelName ())
370+ renderRow ("API key" , masked )
371+ renderRow ("Base URL" , baseURL )
372+ sb .WriteString ("\n " )
373+ renderRow ("Thinking" , thinking )
374+ renderRow ("Context" , tui .FormatTokens (s .ContextWindow ))
375+ renderRow ("Auto compact" , autoCompact )
376+ renderRow ("Max turns" , fmt .Sprintf ("%d" , s .MaxTurns ))
377+ renderMetaRow ("Config" , config .SettingsPath (a .Cwd ))
378+
379+ return tui .SendCommandResult (strings .TrimRight (sb .String (), "\n " ))
332380}
333381
334382func maskKey (key string ) string {
0 commit comments