返回 DeepSeek-Reasonix
status_labels.go
根目录 / internal / cli / status_labels.go
1 package cli
2
3 import (
4 "fmt"
5 "path/filepath"
6 "slices"
7 "strings"
8
9 "reasonix/internal/event"
10 "reasonix/internal/i18n"
11 )
12
13 type readStatusState struct {
14 readStatusLabel string
15 frames map[string]event.ReadStatusPayload
16 }
17
18 func (s *readStatusState) ingest(incoming *event.ReadStatusPayload) {
19 if incoming == nil || incoming.ReadID == "" {
20 return
21 }
22 if previous, ok := s.frames[incoming.ReadID]; ok {
23 if incoming.Generation < previous.Generation || (incoming.Generation == previous.Generation && incoming.Sequence <= previous.Sequence) {
24 return
25 }
26 }
27 if s.frames == nil {
28 s.frames = map[string]event.ReadStatusPayload{}
29 }
30 s.frames[incoming.ReadID] = *incoming
31 keys := make([]string, 0, len(s.frames))
32 for key := range s.frames {
33 keys = append(keys, key)
34 }
35 slices.Sort(keys)
36 var labels []string
37 for _, key := range keys {
38 frame := s.frames[key]
39 if label := readStatusLabelText(&frame); label != "" {
40 labels = append(labels, label)
41 }
42 }
43 s.readStatusLabel = strings.Join(labels, " · ")
44 }
45
46 // readStatusLabelText renders the host's structured read status for the live
47 // status line; an inactive or unnamed frame clears it.
48 func readStatusLabelText(rs *event.ReadStatusPayload) string {
49 if rs == nil || !rs.Active || strings.TrimSpace(rs.Path) == "" {
50 return ""
51 }
52 file := filepath.Base(rs.Path)
53 covered := ""
54 if len(rs.Covered) > 0 {
55 parts := make([]string, 0, len(rs.Covered))
56 for _, r := range rs.Covered {
57 parts = append(parts, fmt.Sprintf("%d-%d", r[0]+1, r[1]))
58 }
59 covered = strings.Join(parts, ", ")
60 }
61 switch {
62 case rs.State == "blocked" || rs.State == "needs_scope":
63 return fmt.Sprintf(i18n.M.ReadStatusPausedFmt, file) + "; " + i18n.M.ReadStatusRecovery
64 case rs.HasMore && covered != "":
65 return fmt.Sprintf(i18n.M.ReadStatusCoveredFmt, file, covered)
66 case rs.HasMore:
67 return fmt.Sprintf(i18n.M.ReadStatusReadingFmt, file)
68 case covered != "":
69 return fmt.Sprintf(i18n.M.ReadStatusDoneFmt, file, covered)
70 default:
71 return fmt.Sprintf(i18n.M.ReadStatusReadingFmt, file)
72 }
73 }
74
74 lines GO