refactor(cli): move the custom status-line command into its own file

chat_tui.go crossed its repolint file-size budget once #11114 and #11062
landed together. The status-line command runner is self-contained, so it
moves verbatim to chat_tui_statusline.go; no behaviour changes.

The freed budget is reclaimed for chat_tui.go only (file-size 4112 -> 4067,
function-size 1056 -> 1030, complexity 274 -> 271, essay 77 -> 75) and the
repo-wide limits drop by the same amounts.
This commit is contained in:
esengine committed 2026-09-27 22:03:08 -07:00
1 parent 52f465e4f5
commit 790c6be08e
3 files changed
+74 -63

No files matched your search

-55
View File
@@ -2,7 +2,6 @@ package cli
import (
"context"
"encoding/json"
"errors"
"fmt"
"os"
@@ -30,7 +29,6 @@ import (
"reasonix/internal/control"
"reasonix/internal/event"
"reasonix/internal/gitcmd"
"reasonix/internal/hook"
"reasonix/internal/i18n"
"reasonix/internal/memory"
"reasonix/internal/migration"
@@ -539,63 +537,10 @@ type elapsedTickMsg struct{ generation uint64 }
// formatted readout ("" when none/failed).
type balanceMsg struct{ text string }
// statuslineMsg carries the latest custom status-line output (one line, ""
// when none/failed).
type statuslineMsg struct{ out string }
// gitStatusMsg carries the latest lightweight git readout for the built-in
// status line. Empty means "not a git worktree" or "git unavailable".
type gitStatusMsg struct{ status gitStatus }
// runStatusline runs the user's custom status-line command off the event loop,
// feeding it a small JSON context on stdin and returning its first stdout line.
// A no-op (nil) when no command is configured. Tight timeout so a slow script
// can't stall the UI; failures collapse to an empty line rather than an error.
func (m chatTUI) runStatusline() tea.Cmd {
cmd := m.statuslineCmd
if cmd == "" {
return nil
}
used, window := m.ctrl.ContextSnapshot()
cwd, _ := os.Getwd()
payload, _ := json.Marshal(map[string]any{
"model": m.label,
"contextUsed": used,
"contextWindow": window,
"cwd": cwd,
})
return func() tea.Msg { return statuslineMsg{out: runStatuslineCmd(cmd, string(payload))} }
}
const statuslineCommandTimeout = 2 * time.Second
// runStatuslineCmd runs a status-line command with the JSON context on stdin and
// returns its first stdout line (status lines are a single row). A tight timeout
// keeps a slow script from stalling the UI; any failure collapses to "".
func runStatuslineCmd(cmd, stdinPayload string) string {
return runStatuslineCmdWithTimeout(cmd, stdinPayload, statuslineCommandTimeout)
}
func runStatuslineCmdWithTimeout(cmd, stdinPayload string, timeout time.Duration) string {
return runStatuslineCmdWith(hook.DefaultSpawner, cmd, stdinPayload, timeout)
}
// runStatuslineCmdWith spawns from the workspace, which the user does not
// author, so a bare command name resolves through PATH alone.
func runStatuslineCmdWith(spawn hook.Spawner, cmd, stdinPayload string, timeout time.Duration) string {
res := spawn(context.Background(), hook.SpawnInput{
Command: cmd,
Stdin: stdinPayload + "\n",
Env: map[string]string{hook.NoCwdCommandSearchEnv: "1"},
Timeout: timeout,
})
out := strings.TrimSpace(res.Stdout)
if i := strings.IndexByte(out, '\n'); i >= 0 {
out = strings.TrimSpace(out[:i])
}
return out
}
func (m chatTUI) refreshGitStatus() tea.Cmd {
if m.statuslineCmd != "" {
return nil
+66
View File
@@ -0,0 +1,66 @@
package cli
import (
"context"
"encoding/json"
"os"
"strings"
"time"
tea "charm.land/bubbletea/v2"
"reasonix/internal/hook"
)
// statuslineMsg carries the latest custom status-line output (one line, ""
// when none/failed).
type statuslineMsg struct{ out string }
// runStatusline runs the user's custom status-line command off the event loop,
// feeding it a small JSON context on stdin and returning its first stdout line.
// A no-op (nil) when no command is configured. Tight timeout so a slow script
// can't stall the UI; failures collapse to an empty line rather than an error.
func (m chatTUI) runStatusline() tea.Cmd {
cmd := m.statuslineCmd
if cmd == "" {
return nil
}
used, window := m.ctrl.ContextSnapshot()
cwd, _ := os.Getwd()
payload, _ := json.Marshal(map[string]any{
"model": m.label,
"contextUsed": used,
"contextWindow": window,
"cwd": cwd,
})
return func() tea.Msg { return statuslineMsg{out: runStatuslineCmd(cmd, string(payload))} }
}
const statuslineCommandTimeout = 2 * time.Second
// runStatuslineCmd runs a status-line command with the JSON context on stdin and
// returns its first stdout line (status lines are a single row). A tight timeout
// keeps a slow script from stalling the UI; any failure collapses to "".
func runStatuslineCmd(cmd, stdinPayload string) string {
return runStatuslineCmdWithTimeout(cmd, stdinPayload, statuslineCommandTimeout)
}
func runStatuslineCmdWithTimeout(cmd, stdinPayload string, timeout time.Duration) string {
return runStatuslineCmdWith(hook.DefaultSpawner, cmd, stdinPayload, timeout)
}
// runStatuslineCmdWith spawns from the workspace, which the user does not
// author, so a bare command name resolves through PATH alone.
func runStatuslineCmdWith(spawn hook.Spawner, cmd, stdinPayload string, timeout time.Duration) string {
res := spawn(context.Background(), hook.SpawnInput{
Command: cmd,
Stdin: stdinPayload + "\n",
Env: map[string]string{hook.NoCwdCommandSearchEnv: "1"},
Timeout: timeout,
})
out := strings.TrimSpace(res.Stdout)
if i := strings.IndexByte(out, '\n'); i >= 0 {
out = strings.TrimSpace(out[:i])
}
return out
}
+8 -8
View File
@@ -2,10 +2,10 @@
"limits": {
"banner": 13,
"commented-code": 0,
"complexity": 1878,
"essay": 1915,
"file-size": 100466,
"function-size": 8031,
"complexity": 1875,
"essay": 1913,
"file-size": 100421,
"function-size": 8005,
"layering": 1,
"marker": 0,
"narrative": 63,
@@ -661,10 +661,10 @@
"essay": 6
},
"internal/cli/chat_tui.go": {
"complexity": 274,
"essay": 77,
"file-size": 4112,
"function-size": 1056
"complexity": 271,
"essay": 75,
"file-size": 4067,
"function-size": 1030
},
"internal/cli/chat_tui_paste.go": {
"essay": 6,