process.go 6.19 KB
Newer Older
1
2
3
4
package tui

import (
	"fmt"
5
	"get-container/cmd/hytop/backend"
6
7
8
9
10
11
12
13
	"maps"
	"strings"

	tea "github.com/charmbracelet/bubbletea"
	"github.com/charmbracelet/lipgloss"
)

type ModelProcessInfo struct {
14
	Title            [2]string
15
16
17
18
19
20
21
	DoubleMiddleLine string
	MiddleLine       string
	BottomLine       string
	NoProceseLine    string // 没有进程时显示的行
	Cache            map[int][]backend.DCUProcessInfo
	width            int
	style            lipgloss.Style
22
	modMsg           *ModelMsg
liming6's avatar
liming6 committed
23
	actionMsg        *ActionMsg
24
25
26
27
}

const (
	Processes             = " Processes:"
28
	ModelProcessInfoTitle = " DCU     PID     USER  DCU-MEM SDMA  %CPU  %MEM      TIME Docker               Command"
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
	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')
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
	m.Title[0] = sb.String()
	sb.Reset()

	sb.WriteString(myBorder.Left)
	sb.WriteString(Processes)
	uah = fmt.Sprintf("%s@%s ", backend.User, backend.HostName)
	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)
	m.Title[1] = LowLeightStyle.Render(sb.String()) + "\n"
71
72
73
74
75
76
77
78
	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 {
79
	darkMode := false
liming6's avatar
liming6 committed
80
	if m.actionMsg != nil && m.actionMsg.Action != nil && m.actionMsg.VM == VMMain {
81
82
		darkMode = true
	}
83
	haveProcess := false
liming6's avatar
liming6 committed
84
85
86
87
	var heightLightPid int32 = 0
	if m.actionMsg != nil && m.actionMsg.PointPid != nil {
		heightLightPid = *m.actionMsg.PointPid
	}
88
89
	lines := make([]string, 0)
	sb := strings.Builder{}
liming6's avatar
liming6 committed
90
	sbInner := strings.Builder{}
91
92
93
94
95
96
97
98
	for index := range 64 {
		processes, have := m.Cache[index]
		if !have {
			continue
		}
		for _, process := range processes {
			haveProcess = true
			sb.WriteString(myBorder.Left)
liming6's avatar
liming6 committed
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115

			sbInner.WriteString(FormatStr(fmt.Sprintf("%d", process.DCU), 4, lipgloss.Right))
			sbInner.WriteByte(' ')
			sbInner.WriteString(FormatStr(fmt.Sprintf("%d", process.Info.Pid), 7, lipgloss.Right))
			sbInner.WriteByte(' ')
			sbInner.WriteString(FormatStr(process.Info.User, 8, lipgloss.Right))
			sbInner.WriteByte(' ')
			sbInner.WriteString(FormatStr(process.DCUMem, 8, lipgloss.Right))
			sbInner.WriteByte(' ')
			sbInner.WriteString(FormatStr(fmt.Sprintf("%d", process.SDMA), 4, lipgloss.Right))
			sbInner.WriteByte(' ')
			sbInner.WriteString(FormatStr(fmt.Sprintf("%.1f", process.Info.CPU), 5, lipgloss.Right))
			sbInner.WriteByte(' ')
			sbInner.WriteString(FormatStr(fmt.Sprintf("%.1f", process.Info.Mem), 5, lipgloss.Right))
			sbInner.WriteByte(' ')
			sbInner.WriteString(FormatStr(process.Info.Time, 9, lipgloss.Right))
			sbInner.WriteByte(' ')
116
			if process.Info.ContInfo != nil {
liming6's avatar
liming6 committed
117
				sbInner.WriteString(FormatStr(process.Info.ContInfo.Name, 20, lipgloss.Left))
118
			} else {
liming6's avatar
liming6 committed
119
				sbInner.WriteString(FormatStr("  -  ", 20, lipgloss.Right))
120
			}
liming6's avatar
liming6 committed
121
122
			sbInner.WriteByte(' ')
			w := m.width - lipgloss.Width(sbInner.String()) - 3
123
124
			tw := lipgloss.Width(process.Info.Cmd)
			if w >= tw {
liming6's avatar
liming6 committed
125
126
				sbInner.WriteString(process.Info.Cmd)
				sbInner.WriteString(strings.Repeat(" ", w-tw))
127
			} else {
liming6's avatar
liming6 committed
128
129
				sbInner.WriteString(FormatStr(process.Info.Cmd, w-1, lipgloss.Left))
				sbInner.WriteString("..")
130
			}
liming6's avatar
liming6 committed
131
132
133
134
135
136
137
138
			sbInner.WriteByte(' ')
			selected := false
			if m.actionMsg != nil && m.actionMsg.SelectPids != nil {
				b, have := m.actionMsg.SelectPids[process.Info.Pid]
				if have && b {
					selected = true
				}
			}
139
140
141
142
			if darkMode {
				selected = false
			}
			if heightLightPid == process.Info.Pid && !darkMode {
liming6's avatar
liming6 committed
143
144
145
146
147
148
149
150
151
152
153
154
155
				if selected {
					sb.WriteString(HeightSelectedStyle.Render(sbInner.String()))
				} else {
					sb.WriteString(HeightLightStyle.Render(sbInner.String()))
				}
			} else {
				if selected {
					sb.WriteString(SelectedStyle.Render(sbInner.String()))
				} else {
					sb.WriteString(sbInner.String())
				}
			}
			sbInner.Reset()
156
157
158
159
160
161
162
			sb.WriteString(myBorder.Right)
			sb.WriteByte('\n')
			lines = append(lines, sb.String())
			sb.Reset()
		}
		lines = append(lines, m.MiddleLine)
	}
163

164
165
166
167
168
169
170
171
172
173
174
175
	if darkMode {
		sb.WriteString(m.Title[1])
		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 LowLeightStyle.Render(sb.String())
176
	} else {
177
178
179
180
181
182
183
184
		sb.WriteString(m.Title[0])
		sb.WriteString(m.DoubleMiddleLine)
		if !haveProcess {
			sb.WriteString(m.NoProceseLine)
		} else {
			for _, v := range lines[:len(lines)-1] {
				sb.WriteString(v)
			}
185
		}
186
187
		sb.WriteString(m.BottomLine)
		return sb.String()
188
189
190
191
192
193
194
195
	}
}

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)
196
197
		m.modMsg = msg
		return m, nil
liming6's avatar
liming6 committed
198
199
200
	case *ActionMsg:
		m.actionMsg = msg
		return m, nil
201
202
203
	}
	return m, nil
}