package drivers import ( "bufio" "fmt" "os" "strconv" "strings" ) type MemInfoDriver struct{} func NewMemInfoDriver() (*MemInfoDriver, error) { r := MemInfoDriver{} _, err := r.Read() return &r, err } func (r *MemInfoDriver) Render(console *strings.Builder) error { u, err := r.Read() if err != nil { return err } usage := u.(MemoryUsage) fmt.Fprintf(console, "--- Usage ---\033[K\n") fmt.Fprintf(console, "%-16s | %.2f GiB\033[K\n", "Total", usage.TotalGB) fmt.Fprintf(console, "%-16s | %.2f GiB (%.2f%%) \033[K\n", "Used", usage.UsedGB, usage.UsedPercent) fmt.Fprintf(console, "%-16s | %.2f GiB\033[K\n", "Avail", usage.AvailableGB) return nil } // Read /proc/meminfo for active system memory statistics func (r *MemInfoDriver) Read() (any, error) { usage := MemoryUsage{} file, err := os.Open("/proc/meminfo") if err != nil { return usage, err } defer file.Close() var memTotal, memAvailable float64 scanner := bufio.NewScanner(file) for scanner.Scan() { line := scanner.Text() fields := strings.Fields(line) if len(fields) < 2 { continue } val, err := strconv.ParseFloat(fields[1], 64) if err != nil { continue } switch fields[0] { case "MemTotal:": memTotal = val // stored in kB case "MemAvailable:": memAvailable = val // stored in kB } } if err := scanner.Err(); err != nil { return usage, err } used := memTotal - memAvailable usedPct := (used / memTotal) * 100 usage = MemoryUsage{ TotalGB: memTotal / (1024 * 1024), AvailableGB: memAvailable / (1024 * 1024), UsedGB: used / (1024 * 1024), UsedPercent: usedPct, } return usage, nil }