From dc83d0b7204cf66315471e980729490813b7d915 Mon Sep 17 00:00:00 2001
From: Ryan Voots <simcop2387@simcop2387.info>
Date: Thu, 7 Oct 2021 15:16:30 -0400
Subject: [PATCH] fix(battery): support `acpitool` and multiple batteries under
 Linux (#9609)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: Marc Cornellà <hello@mcornella.com>
---
 plugins/battery/battery.plugin.zsh | 54 ++++++++++++++++++------------
 1 file changed, 32 insertions(+), 22 deletions(-)

diff --git a/plugins/battery/battery.plugin.zsh b/plugins/battery/battery.plugin.zsh
index a525fd7da..24bff8ae6 100644
--- a/plugins/battery/battery.plugin.zsh
+++ b/plugins/battery/battery.plugin.zsh
@@ -12,15 +12,12 @@
 ###########################################
 
 if [[ "$OSTYPE" = darwin* ]]; then
-
   function battery_is_charging() {
     ioreg -rc AppleSmartBattery | command grep -q '^.*"ExternalConnected"\ =\ Yes'
   }
-
   function battery_pct() {
     pmset -g batt | grep -Eo "\d+%" | cut -d% -f1
   }
-
   function battery_pct_remaining() {
     if battery_is_charging; then
       echo "External Power"
@@ -28,7 +25,6 @@ if [[ "$OSTYPE" = darwin* ]]; then
       battery_pct
     fi
   }
-
   function battery_time_remaining() {
     local smart_battery_status="$(ioreg -rc "AppleSmartBattery")"
     if [[ $(echo $smart_battery_status | command grep -c '^.*"ExternalConnected"\ =\ No') -eq 1 ]]; then
@@ -42,7 +38,6 @@ if [[ "$OSTYPE" = darwin* ]]; then
       echo "∞"
     fi
   }
-
   function battery_pct_prompt () {
     local battery_pct color
     if ioreg -rc AppleSmartBattery | command grep -q '^.*"ExternalConnected"\ =\ No'; then
@@ -61,17 +56,14 @@ if [[ "$OSTYPE" = darwin* ]]; then
   }
 
 elif [[ "$OSTYPE" = freebsd* ]]; then
-
   function battery_is_charging() {
     [[ $(sysctl -n hw.acpi.battery.state) -eq 2 ]]
   }
-
   function battery_pct() {
     if (( $+commands[sysctl] )); then
       sysctl -n hw.acpi.battery.life
     fi
   }
-
   function battery_pct_remaining() {
     if ! battery_is_charging; then
       battery_pct
@@ -79,7 +71,6 @@ elif [[ "$OSTYPE" = freebsd* ]]; then
       echo "External Power"
     fi
   }
-
   function battery_time_remaining() {
     local remaining_time
     remaining_time=$(sysctl -n hw.acpi.battery.time)
@@ -89,7 +80,6 @@ elif [[ "$OSTYPE" = freebsd* ]]; then
       printf %02d:%02d $hour $minute
     fi
   }
-
   function battery_pct_prompt() {
     local battery_pct color
     battery_pct=$(battery_pct_remaining)
@@ -106,19 +96,42 @@ elif [[ "$OSTYPE" = freebsd* ]]; then
       echo "%{$fg[$color]%}${battery_pct}%%%{$reset_color%}"
     fi
   }
-
 elif [[ "$OSTYPE" = linux*  ]]; then
-
   function battery_is_charging() {
-    ! acpi 2>/dev/null | command grep -v "rate information unavailable" | command grep -q '^Battery.*Discharging'
-  }
-
-  function battery_pct() {
-    if (( $+commands[acpi] )); then
-      acpi 2>/dev/null | command grep -v "rate information unavailable" | command grep -E '^Battery.*(Full|(Disc|C)harging)' | cut -f2 -d ',' | tr -cd '[:digit:]'
+    if (( $+commands[acpitool] )); then
+      ! acpitool 2>/dev/null | command grep -qE '^\s+Battery.*Discharging'
+    elif (( $+commands[acpi] )); then
+      ! acpi 2>/dev/null | command grep -v "rate information unavailable" | command grep -q '^Battery.*Discharging'
+    fi
+  }
+  function battery_pct() {
+    if (( $+commands[acpitool] )); then
+      # Sample output:
+      #   Battery #1     : Unknown, 99.55%
+      #   Battery #2     : Discharging, 49.58%, 01:12:05
+      #   All batteries  : 62.60%, 02:03:03
+      acpitool 2>/dev/null | command awk -F, '
+        /^\s+All batteries/ {
+          gsub(/[^0-9.]/, "", $1)
+          pct=$1
+          exit
+        }
+        !pct && /^\s+Battery/ {
+          gsub(/[^0-9.]/, "", $2)
+          pct=$2
+        }
+        END { print pct }
+        '
+    elif (( $+commands[acpi] )); then
+      # Sample output:
+      # Battery 0: Discharging, 0%, rate information unavailable
+      # Battery 1: Full, 100%
+      acpi 2>/dev/null | command awk -F, '
+        /rate information unavailable/ { next }
+        /^Battery.*: /{ gsub(/[^0-9]/, "", $2); print $2; exit }
+      '
     fi
   }
-
   function battery_pct_remaining() {
     if ! battery_is_charging; then
       battery_pct
@@ -126,13 +139,11 @@ elif [[ "$OSTYPE" = linux*  ]]; then
       echo "External Power"
     fi
   }
-
   function battery_time_remaining() {
     if ! battery_is_charging; then
       acpi 2>/dev/null | command grep -v "rate information unavailable" | cut -f3 -d ','
     fi
   }
-
   function battery_pct_prompt() {
     local battery_pct color
     battery_pct=$(battery_pct_remaining)
@@ -149,7 +160,6 @@ elif [[ "$OSTYPE" = linux*  ]]; then
       echo "%{$fg[$color]%}${battery_pct}%%%{$reset_color%}"
     fi
   }
-
 else
   # Empty functions so we don't cause errors in prompts
   function battery_is_charging { false }