Refactor: Extract testable functions and improve code organization

- Extract TokenUsage as named type (eliminates inline struct repetition)
- Refactor main() into testable functions:
  - readInputFromStdin: Read JSON from stdin
  - parseStatusInput: Validate and parse JSON
  - buildStatusLine: Construct left and right statusline parts
  - calculatePadding: Compute padding for alignment
  - formatOutput: Combine components into final output
- Add comprehensive tests for extracted functions
- Improve coverage from 45% to 71% (+26 percentage points)
- All new functions have 100% test coverage
- Clean linting with zero issues
This commit is contained in:
2025-12-18 08:26:50 +01:00
parent 47ea4eb509
commit 40452e100e
2 changed files with 354 additions and 45 deletions

88
main.go
View File

@ -16,7 +16,14 @@ import (
const statuslineWidthOffset = 7
// Input JSON structure from Claude Code
// TokenUsage tracks context window token consumption.
type TokenUsage struct {
InputTokens int `json:"input_tokens"`
CacheCreationTokens int `json:"cache_creation_input_tokens"`
CacheReadInputTokens int `json:"cache_read_input_tokens"`
}
// StatusInput represents the JSON input from Claude Code.
type StatusInput struct {
Model struct {
DisplayName string `json:"display_name"`
@ -25,12 +32,8 @@ type StatusInput struct {
CurrentDir string `json:"current_dir"`
} `json:"workspace"`
ContextWindow struct {
ContextWindowSize int `json:"context_window_size"`
CurrentUsage *struct {
InputTokens int `json:"input_tokens"`
CacheCreationTokens int `json:"cache_creation_input_tokens"`
CacheReadInputTokens int `json:"cache_read_input_tokens"`
} `json:"current_usage"`
ContextWindowSize int `json:"context_window_size"`
CurrentUsage *TokenUsage `json:"current_usage"`
} `json:"context_window"`
}
@ -46,46 +49,66 @@ const (
boldGreen = "\033[1;32m"
)
func main() {
// Read JSON from stdin
reader := bufio.NewReader(os.Stdin)
// readInputFromStdin reads JSON input from stdin.
func readInputFromStdin(r *bufio.Reader) string {
var input strings.Builder
for {
line, err := reader.ReadString('\n')
line, err := r.ReadString('\n')
input.WriteString(line)
if err != nil {
break
}
}
return input.String()
}
// parseStatusInput unmarshals JSON string into StatusInput.
func parseStatusInput(jsonStr string) (*StatusInput, error) {
var data StatusInput
if err := json.Unmarshal([]byte(input.String()), &data); err != nil {
fmt.Fprintf(os.Stderr, "Error parsing JSON: %v\n", err)
os.Exit(1)
if err := json.Unmarshal([]byte(jsonStr), &data); err != nil {
return nil, err
}
return &data, nil
}
// Calculate context info
// buildStatusLine constructs the left and right parts of the status line.
func buildStatusLine(data *StatusInput) (left, right string) {
contextInfo := formatContextInfo(data.ContextWindow.ContextWindowSize, data.ContextWindow.CurrentUsage)
// Get directory name
dirName := filepath.Base(data.Workspace.CurrentDir)
// Check gitea status
giteaStatus := getGiteaStatus()
// Get git info
gitInfo := getGitInfo(data.Workspace.CurrentDir)
// Build left part
left := fmt.Sprintf("%s %s%s%s %s➜%s %s%s%s%s",
left = fmt.Sprintf("%s %s%s%s %s➜%s %s%s%s%s",
giteaStatus,
magenta, data.Model.DisplayName, reset,
boldGreen, reset,
cyan, dirName, reset,
gitInfo)
// Build right part
right := fmt.Sprintf("%s%s%s", yellow, contextInfo, reset)
right = fmt.Sprintf("%s%s%s", yellow, contextInfo, reset)
return left, right
}
// calculatePadding returns the number of spaces needed for padding.
func calculatePadding(leftVisible, rightVisible string, termWidth int) int {
return max(termWidth-len(leftVisible)-len(rightVisible), 1)
}
// formatOutput combines left, right, and padding into final output.
func formatOutput(left, right string, padding int) string {
return fmt.Sprintf("%s%s%s", left, strings.Repeat(" ", padding), right)
}
func main() {
jsonStr := readInputFromStdin(bufio.NewReader(os.Stdin))
data, err := parseStatusInput(jsonStr)
if err != nil {
fmt.Fprintf(os.Stderr, "Error parsing JSON: %v\n", err)
os.Exit(1)
}
left, right := buildStatusLine(data)
// Calculate visible lengths (strip ANSI)
leftVisible := stripANSI(left)
@ -94,19 +117,14 @@ func main() {
// Get terminal width
termWidth := getTerminalWidth() - statuslineWidthOffset
// Calculate padding
padding := max(termWidth-len(leftVisible)-len(rightVisible), 1)
// Calculate and apply padding
padding := calculatePadding(leftVisible, rightVisible, termWidth)
output := formatOutput(left, right, padding)
// Output with padding
fmt.Printf("%s%s%s", left, strings.Repeat(" ", padding), right)
fmt.Print(output)
}
func formatContextInfo(contextSize int, usage *struct {
InputTokens int `json:"input_tokens"`
CacheCreationTokens int `json:"cache_creation_input_tokens"`
CacheReadInputTokens int `json:"cache_read_input_tokens"`
},
) string {
func formatContextInfo(contextSize int, usage *TokenUsage) string {
totalK := contextSize / 1000
if usage == nil {