package tui import ( "fmt" "get-container/cmd/hytop/backend" "maps" "strings" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" ) type ModelProcessInfo struct { Title string DoubleMiddleLine string MiddleLine string BottomLine string NoProceseLine string // 没有进程时显示的行 Cache map[int][]backend.DCUProcessInfo width int style lipgloss.Style modMsg *ModelMsg } const ( Processes = " Processes:" ModelProcessInfoTitle = " DCU PID USER DCU-MEM SDMA %CPU %MEM TIME Docker Command" ModelProcessInfoNoPro = " No running processes found" ) func NewModelProcessInfo(width int) *ModelProcessInfo { result := ModelProcessInfo{width: width, Cache: make(map[int][]backend.DCUProcessInfo), style: lipgloss.NewStyle()} return &result } func (m *ModelProcessInfo) Init() tea.Cmd { sb := strings.Builder{} sb.WriteString(myBorder.Left) sb.WriteString(Processes) uah := fmt.Sprintf("%s@%s ", m.style.Foreground(lipgloss.Color("#edff2cff")).SetString(backend.User).String(), m.style.Foreground(lipgloss.Color("#a3ff2bff")).SetString(backend.HostName).String()) space := strings.Repeat(" ", m.width-lipgloss.Width(Processes)-lipgloss.Width(uah)-2) sb.WriteString(space) sb.WriteString(uah) sb.WriteString(myBorder.Right) sb.WriteByte('\n') sb.WriteString(myBorder.Left) sb.WriteString(ModelProcessInfoTitle) sb.WriteString(strings.Repeat(" ", m.width-2-lipgloss.Width(ModelProcessInfoTitle))) sb.WriteString(myBorder.Right) sb.WriteByte('\n') m.Title = sb.String() m.DoubleMiddleLine = "╞" + strings.Repeat("═", m.width-2) + "╡\n" m.MiddleLine = myBorder.MiddleLeft + strings.Repeat("─", m.width-2) + myBorder.MiddleRight + "\n" m.BottomLine = myBorder.BottomLeft + strings.Repeat("═", m.width-2) + myBorder.BottomRight m.NoProceseLine = myBorder.Left + ModelProcessInfoNoPro + strings.Repeat(" ", m.width-2-lipgloss.Width(ModelProcessInfoNoPro)) + myBorder.Right + "\n" return nil } func (m *ModelProcessInfo) View() string { haveProcess := false lines := make([]string, 0) sb := strings.Builder{} for index := range 64 { processes, have := m.Cache[index] if !have { continue } for _, process := range processes { haveProcess = true sb.WriteString(myBorder.Left) sb.WriteString(FormatStr(fmt.Sprintf("%d", process.DCU), 4, lipgloss.Right)) sb.WriteByte(' ') sb.WriteString(FormatStr(fmt.Sprintf("%d", process.Info.Pid), 7, lipgloss.Right)) sb.WriteByte(' ') sb.WriteString(FormatStr(process.Info.User, 8, lipgloss.Right)) sb.WriteByte(' ') sb.WriteString(FormatStr(process.DCUMem, 8, lipgloss.Right)) sb.WriteByte(' ') sb.WriteString(FormatStr(fmt.Sprintf("%d", process.SDMA), 4, lipgloss.Right)) sb.WriteByte(' ') sb.WriteString(FormatStr(fmt.Sprintf("%.1f", process.Info.CPU), 5, lipgloss.Right)) sb.WriteByte(' ') sb.WriteString(FormatStr(fmt.Sprintf("%.1f", process.Info.Mem), 5, lipgloss.Right)) sb.WriteByte(' ') sb.WriteString(FormatStr(process.Info.Time, 9, lipgloss.Right)) sb.WriteByte(' ') if process.Info.ContInfo != nil { sb.WriteString(FormatStr(process.Info.ContInfo.Name, 20, lipgloss.Left)) } else { sb.WriteString(FormatStr(" - ", 20, lipgloss.Right)) } sb.WriteByte(' ') w := m.width - lipgloss.Width(sb.String()) - 2 tw := lipgloss.Width(process.Info.Cmd) if w >= tw { sb.WriteString(process.Info.Cmd) sb.WriteString(strings.Repeat(" ", w-tw)) } else { sb.WriteString(FormatStr(process.Info.Cmd, w-2, lipgloss.Left)) sb.WriteString("..") } sb.WriteByte(' ') sb.WriteString(myBorder.Right) sb.WriteByte('\n') lines = append(lines, sb.String()) sb.Reset() } lines = append(lines, m.MiddleLine) } sb.WriteString(m.Title) sb.WriteString(m.DoubleMiddleLine) if !haveProcess { sb.WriteString(m.NoProceseLine) } else { for _, v := range lines[:len(lines)-1] { sb.WriteString(v) } } sb.WriteString(m.BottomLine) return sb.String() } func (m *ModelProcessInfo) Update(inputMsg tea.Msg) (tea.Model, tea.Cmd) { switch msg := inputMsg.(type) { case *ModelMsg: clear(m.Cache) maps.Copy(m.Cache, msg.DCUPidInfo) m.modMsg = msg return m, nil } return m, nil }