mirror of
https://github.com/tw93/Mole.git
synced 2026-02-04 13:16:47 +00:00
feat(status): persist cat visibility preference
- Add loadCatHidden/saveCatHidden functions - Save preference to ~/.config/mole/status_prefs - Load preference on startup
This commit is contained in:
@@ -9,15 +9,13 @@ run:
|
||||
modules-download-mode: readonly
|
||||
|
||||
linters:
|
||||
disable-all: true
|
||||
enable:
|
||||
# Default linters
|
||||
- govet
|
||||
- staticcheck
|
||||
- errcheck
|
||||
- ineffassign
|
||||
- unused
|
||||
# Additional useful linters
|
||||
- errcheck
|
||||
|
||||
linters-settings:
|
||||
govet:
|
||||
|
||||
@@ -74,6 +74,7 @@ mo purge --paths # Configure project scan directories
|
||||
- **Safety**: Built with strict protections. See [Security Audit](SECURITY_AUDIT.md). Preview changes with `mo clean --dry-run`.
|
||||
- **Debug Mode**: Use `--debug` for detailed logs (e.g., `mo clean --debug`). Combine with `--dry-run` for comprehensive preview including risk levels and file details.
|
||||
- **Navigation**: Supports arrow keys and Vim bindings (`h/j/k/l`).
|
||||
- **Status Shortcuts**: In `mo status`, press `k` to toggle cat visibility and save preference, `q` to quit.
|
||||
- **Configuration**: Run `mo touchid` for Touch ID sudo, `mo completion` for shell tab completion, `mo clean --whitelist` to manage protected paths.
|
||||
|
||||
## Features in Detail
|
||||
@@ -185,7 +186,7 @@ Up ▮▯▯▯▯ 0.8 MB/s Chrome ▮▮▮▯▯ 2
|
||||
Proxy HTTP · 192.168.1.100 Terminal ▮▯▯▯▯ 12.5%
|
||||
```
|
||||
|
||||
Health score based on CPU, memory, disk, temperature, and I/O load. Color-coded by range. Press `k` to hide/show cat, `q` to quit.
|
||||
Health score based on CPU, memory, disk, temperature, and I/O load. Color-coded by range.
|
||||
|
||||
### Project Artifact Purge
|
||||
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
// Package main provides the mo status command for real-time system monitoring.
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
@@ -37,10 +40,50 @@ type model struct {
|
||||
catHidden bool // true = hidden, false = visible
|
||||
}
|
||||
|
||||
// getConfigPath returns the path to the status preferences file.
|
||||
func getConfigPath() string {
|
||||
home, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return filepath.Join(home, ".config", "mole", "status_prefs")
|
||||
}
|
||||
|
||||
// loadCatHidden loads the cat hidden preference from config file.
|
||||
func loadCatHidden() bool {
|
||||
path := getConfigPath()
|
||||
if path == "" {
|
||||
return false
|
||||
}
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return strings.TrimSpace(string(data)) == "cat_hidden=true"
|
||||
}
|
||||
|
||||
// saveCatHidden saves the cat hidden preference to config file.
|
||||
func saveCatHidden(hidden bool) {
|
||||
path := getConfigPath()
|
||||
if path == "" {
|
||||
return
|
||||
}
|
||||
// Ensure directory exists
|
||||
dir := filepath.Dir(path)
|
||||
if err := os.MkdirAll(dir, 0755); err != nil {
|
||||
return
|
||||
}
|
||||
value := "cat_hidden=false"
|
||||
if hidden {
|
||||
value = "cat_hidden=true"
|
||||
}
|
||||
_ = os.WriteFile(path, []byte(value+"\n"), 0644)
|
||||
}
|
||||
|
||||
func newModel() model {
|
||||
return model{
|
||||
collector: NewCollector(),
|
||||
catHidden: false,
|
||||
catHidden: loadCatHidden(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,8 +98,9 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
case "q", "esc", "ctrl+c":
|
||||
return m, tea.Quit
|
||||
case "k":
|
||||
// Toggle cat visibility
|
||||
// Toggle cat visibility and persist preference
|
||||
m.catHidden = !m.catHidden
|
||||
saveCatHidden(m.catHidden)
|
||||
return m, nil
|
||||
}
|
||||
case tea.WindowSizeMsg:
|
||||
|
||||
@@ -286,9 +286,8 @@ func commandExists(name string) bool {
|
||||
return false
|
||||
}
|
||||
defer func() {
|
||||
if r := recover(); r != nil { //nolint:staticcheck
|
||||
// Treat LookPath panics as "missing".
|
||||
}
|
||||
_ = recover()
|
||||
}()
|
||||
_, err := exec.LookPath(name)
|
||||
return err == nil
|
||||
|
||||
@@ -32,7 +32,7 @@ func collectCPU() (CPUStatus, error) {
|
||||
}
|
||||
|
||||
// Two-call pattern for more reliable CPU usage.
|
||||
warmUpCpu()
|
||||
warmUpCPU()
|
||||
time.Sleep(cpuSampleInterval)
|
||||
percents, err := cpu.Percent(0, true)
|
||||
var totalPercent float64
|
||||
@@ -256,6 +256,6 @@ func fallbackCPUUtilization(logical int) (float64, []float64, error) {
|
||||
return avg, perCore, nil
|
||||
}
|
||||
|
||||
func warmUpCpu() {
|
||||
func warmUpCPU() {
|
||||
cpu.Percent(0, true) //nolint:errcheck
|
||||
}
|
||||
|
||||
@@ -134,15 +134,16 @@ func calculateHealthScore(cpu CPUStatus, mem MemoryStatus, disks []DiskStatus, d
|
||||
|
||||
// Build message.
|
||||
var msg string
|
||||
if score >= 90 {
|
||||
switch {
|
||||
case score >= 90:
|
||||
msg = "Excellent"
|
||||
} else if score >= 75 {
|
||||
case score >= 75:
|
||||
msg = "Good"
|
||||
} else if score >= 60 {
|
||||
case score >= 60:
|
||||
msg = "Fair"
|
||||
} else if score >= 40 {
|
||||
case score >= 40:
|
||||
msg = "Poor"
|
||||
} else {
|
||||
default:
|
||||
msg = "Critical"
|
||||
}
|
||||
|
||||
|
||||
@@ -187,15 +187,16 @@ func renderHeader(m MetricsSnapshot, errMsg string, animFrame int, termWidth int
|
||||
}
|
||||
|
||||
func getScoreStyle(score int) lipgloss.Style {
|
||||
if score >= 90 {
|
||||
switch {
|
||||
case score >= 90:
|
||||
return lipgloss.NewStyle().Foreground(lipgloss.Color("#87FF87")).Bold(true)
|
||||
} else if score >= 75 {
|
||||
case score >= 75:
|
||||
return lipgloss.NewStyle().Foreground(lipgloss.Color("#87D787")).Bold(true)
|
||||
} else if score >= 60 {
|
||||
case score >= 60:
|
||||
return lipgloss.NewStyle().Foreground(lipgloss.Color("#FFD75F")).Bold(true)
|
||||
} else if score >= 40 {
|
||||
case score >= 40:
|
||||
return lipgloss.NewStyle().Foreground(lipgloss.Color("#FFAF5F")).Bold(true)
|
||||
} else {
|
||||
default:
|
||||
return lipgloss.NewStyle().Foreground(lipgloss.Color("#FF6B6B")).Bold(true)
|
||||
}
|
||||
}
|
||||
@@ -707,11 +708,11 @@ func humanBytesCompact(v uint64) string {
|
||||
}
|
||||
}
|
||||
|
||||
func shorten(s string, max int) string {
|
||||
if len(s) <= max {
|
||||
func shorten(s string, maxLen int) string {
|
||||
if len(s) <= maxLen {
|
||||
return s
|
||||
}
|
||||
return s[:max-1] + "…"
|
||||
return s[:maxLen-1] + "…"
|
||||
}
|
||||
|
||||
func renderTwoColumns(cards []cardData, width int) string {
|
||||
|
||||
Reference in New Issue
Block a user