From 9f1bad65714d47dbd8d16171aaef1979090032d7 Mon Sep 17 00:00:00 2001 From: Chris Cummer Date: Thu, 24 May 2018 22:00:40 -0700 Subject: [PATCH] Closes #52. Add Power module This module displaysw which source is providing power (AC or battery) and for the battery displays the current charge capacity, how long it will last, and the battery state. --- cmdrunner/widget.go | 1 - power/battery.go | 116 ++++++++++++++++++++++++++++++++++++++++++++ power/source.go | 25 ++++++++++ power/widget.go | 45 +++++++++++++++++ wtf.go | 3 ++ 5 files changed, 189 insertions(+), 1 deletion(-) create mode 100644 power/battery.go create mode 100644 power/source.go create mode 100644 power/widget.go diff --git a/cmdrunner/widget.go b/cmdrunner/widget.go index d9188a98..a489cd2c 100644 --- a/cmdrunner/widget.go +++ b/cmdrunner/widget.go @@ -21,7 +21,6 @@ type Widget struct { } func NewWidget() *Widget { - widget := Widget{ TextWidget: wtf.NewTextWidget(" 🏃 Runner ", "cmdrunner", false), diff --git a/power/battery.go b/power/battery.go new file mode 100644 index 00000000..c837b7f8 --- /dev/null +++ b/power/battery.go @@ -0,0 +1,116 @@ +package power + +import ( + "fmt" + "os/exec" + "regexp" + "strconv" + "strings" + + "github.com/senorprogrammer/wtf/wtf" +) + +const TimeRegExp = "^(?:\\d|[01]\\d|2[0-3]):[0-5]\\d" + +type Battery struct { + args []string + cmd string + result string + + Charge string + Remaining string +} + +func NewBattery() *Battery { + battery := Battery{ + args: []string{"-g", "batt"}, + cmd: "pmset", + } + + return &battery +} + +/* -------------------- Exported Functions -------------------- */ + +func (battery *Battery) Refresh() { + data := battery.execute() + battery.result = battery.parse(data) +} + +func (battery *Battery) String() string { + return battery.result +} + +/* -------------------- Unexported Functions -------------------- */ + +func (battery *Battery) execute() string { + cmd := exec.Command(battery.cmd, battery.args...) + return wtf.ExecuteCommand(cmd) +} + +func (battery *Battery) parse(data string) string { + lines := strings.Split(data, "\n") + if len(lines) < 2 { + return "unknown (1)" + } + + stats := strings.Split(lines[1], "\t") + if len(stats) < 2 { + return "unknown (2)" + } + + details := strings.Split(stats[1], "; ") + if len(details) < 3 { + return "unknown (3)" + } + + str := "" + str = str + fmt.Sprintf(" %10s: %s\n", "Charge", battery.formatCharge(details[0])) + str = str + fmt.Sprintf(" %10s: %s\n", "Remaining", battery.formatRemaining(details[2])) + str = str + fmt.Sprintf(" %10s: %s\n", "State", battery.formatState(details[1])) + + return str +} + +func (battery *Battery) formatCharge(data string) string { + percent, _ := strconv.ParseFloat(strings.Replace(data, "%", "", -1), 32) + + color := "" + + switch { + case percent >= 70: + color = "[green]" + case percent >= 35: + color = "[yellow]" + default: + color = "[red]" + } + + return color + data + "[white]" +} + +func (battery *Battery) formatRemaining(data string) string { + r, _ := regexp.Compile(TimeRegExp) + + result := r.FindString(data) + if result == "" { + result = "∞" + } + + return result +} + +func (battery *Battery) formatState(data string) string { + color := "" + + switch data { + case "charging": + color = "[green]" + case "discharging": + color = "[yellow]" + default: + color = "[white]" + } + + return color + data + "[white]" +} diff --git a/power/source.go b/power/source.go new file mode 100644 index 00000000..b5f0faff --- /dev/null +++ b/power/source.go @@ -0,0 +1,25 @@ +package power + +import ( + "os/exec" + "regexp" + "strings" + + "github.com/senorprogrammer/wtf/wtf" +) + +const SingleQuotesRegExp = "'(.*)'" + +// powerSource returns the name of the current power source, probably one of +// "AC Power" or "Battery Power" +func powerSource() string { + cmd := exec.Command("pmset", []string{"-g", "ps"}...) + result := wtf.ExecuteCommand(cmd) + + r, _ := regexp.Compile(SingleQuotesRegExp) + + source := r.FindString(result) + source = strings.Replace(source, "'", "", -1) + + return source +} diff --git a/power/widget.go b/power/widget.go new file mode 100644 index 00000000..f971bec8 --- /dev/null +++ b/power/widget.go @@ -0,0 +1,45 @@ +package power + +import ( + "fmt" + + "github.com/olebedev/config" + "github.com/senorprogrammer/wtf/wtf" +) + +// Config is a pointer to the global config object +var Config *config.Config + +type Widget struct { + wtf.TextWidget + + Battery *Battery +} + +func NewWidget() *Widget { + widget := Widget{ + TextWidget: wtf.NewTextWidget(" ⚡️ Power ", "power", false), + Battery: NewBattery(), + } + + widget.View.SetWrap(true) + + return &widget +} + +func (widget *Widget) Refresh() { + if widget.Disabled() { + return + } + + widget.UpdateRefreshedAt() + widget.Battery.Refresh() + widget.View.Clear() + + str := "" + str = str + fmt.Sprintf(" %10s: %s\n", "Source", powerSource()) + str = str + "\n" + str = str + widget.Battery.String() + + fmt.Fprintf(widget.View, "%s", str) +} diff --git a/wtf.go b/wtf.go index be8b5598..ade5982a 100644 --- a/wtf.go +++ b/wtf.go @@ -18,6 +18,7 @@ import ( "github.com/senorprogrammer/wtf/jira" "github.com/senorprogrammer/wtf/newrelic" "github.com/senorprogrammer/wtf/opsgenie" + "github.com/senorprogrammer/wtf/power" "github.com/senorprogrammer/wtf/security" "github.com/senorprogrammer/wtf/status" "github.com/senorprogrammer/wtf/system" @@ -157,6 +158,7 @@ func main() { jira.Config = Config newrelic.Config = Config opsgenie.Config = Config + power.Config = Config security.Config = Config status.Config = Config system.Config = Config @@ -175,6 +177,7 @@ func main() { jira.NewWidget(), newrelic.NewWidget(), opsgenie.NewWidget(), + power.NewWidget(), security.NewWidget(), status.NewWidget(), system.NewWidget(date, version),