I'm attempting to create a dynamic prompt that uses colour-encodings for providing visual cues of the battery situation.
I will be using pmset -g batt
to get all of this information.
So far I'm working with the fetching of
Number 1 can be fetched by pmset -g batt | egrep '([0-9]+\%).*' -o --colour=auto | cut -f1 -d';'
, and the result will be 100%
(well, currently, since my battery is fully charged).
Number 2 can be fetched by pmset -g batt | awk '/charging|discharging|charged/ {print $4}' | cut -f1 -d';'
, but for it to work properly in the prompt, you'll have to modify it to be pmset -g batt | awk '/charging|discharging|charged/ {print $4}' | cut -f2 -d';'
- which will then show an awkward empty space before the word. so " charged"
instead of "charged"
, " discharging"
instead of "discharging"
and " charging"
instead of "charging"
. That's fine, I guess, but I'm thinking this could be taken further.
Number 3 can be fetched by pmset -g batt | grep -Eo '([0-9][0-9]|[0-9]):[0-5][0-9]'
- but, if your battery is fully charged, you will get a cool 0:00
, which makes no sense.
Okay, we've established that this kind of information can be fetched out, and can be displayed at least in the terminal itself, what about the dynamic prompt issue?
Well, here's what I have right now:
[100%] [] [ charged] [Sat Nov 10 21:24:34] [~] >>
This is not perfectly ideal. For instance, the []
doesn't need to show at all, considering the info it would show is 0:00
. the [ charged]
is also a bit needless.
So here's what I propose to ask how to do:
[time left / time to charge]
" and no "[ charged]
[time left]
(percentage colour could be.. modified?).[time left]
(percentage could be yellow).Now, I got this far:
export PS1="[\$(pmset -g batt | egrep '([0-9]+\%).*' -o --colour=auto | cut -f1 -d';')] [\$(pmset -g batt | grep -Eo '([0-9][0-9]|[0-9]):[0-5][0-9]')] [\$(pmset -g batt | awk '/charging|discharging|charged/ {print $4}' | cut -f2 -d';')] [\d \t]"
which gives me [100%] [0:00] [ charged] [Sat Nov 10 21:32:38]
Anyway, back to that weird cut -f1
vs. cut -f2
difference between terminal and prompt. If I put cut -f1
into the export PS1
prompt, I get this:
[100%] [0:00] [ -InternalBattery-0 (id=4194403) 100%] [Sat Nov 10 21:34:44]
Anyway, I'm thinking there has got to be a way of going "oh, 0:00? don't display this segment of the prompt at all" - but I'm not sure how to do that.
So, to recap, I'm trying to utilise "Charged,Charging,Discharging" to set the battery percentage colour, charged = regular color, charging = yellow, discharging = ..green?, less than 20% = panic red color. 5% blink? :D
I'm also trying to use the "time left to charge" and "time left of charge" time to be displayed in the prompt itself, dynamically.
Any advice would be much appreciated.
p.s. extra bonus points for showing [estimating] if pmset -g batt
results in (no estimate)
on the time-left-of-charge
p.p.s. extra bonus points#2 for figuring out what to do with (i.e. this is a state that isn't (no estimate)
but will sometimes occur.
Now drawing from 'AC Power'
-InternalBattery-0 (id=4194403) 89%; AC attached; not charging present: true
Your question is really about how to handle complex prompts. The actually complicated question here is how to handle conditional use of ANSI colors in a prompt.
The sub-questions are 'normal' string chomping, conditional, and ANSI code. All of this I handle in my dotfiles, in profile
and functions_colors.sh
.
What you really want is
export PS1="[\$(__batt_pct)]\$(__batt_time) [\$(__batt_state)] [\d \t] "
and then
yellow=$(tput setaf 184)
green=$(tput setaf 120)
red=$(tput setaf 160)
reset=$(tput init)
function __batt_pct() {
bpct=$(pmset -g batt | egrep '([0-9]+)%.*' -o | cut -f1 -d';')
bpct=${bpct%?} # remove last char (%)
case 1 in
$(($bpct <= 15))) echo "$red$bpct%$reset" ;;
$(($bpct <= 65))) echo "$yellow$bpct%$reset" ;;
*) echo "$green$bpct%$reset" ;;
esac
}
# now, as a function, we can easily handle a conditional
function __batt_time() {
btime=$(pmset -g batt | grep -Eo '([0-9][0-9]|[0-9]):[0-5][0-9]')
if [[ "$btime" == "0:00" ]]; then echo ''; else echo " [$btime]"; fi
}
# I need to cut field-1 for this to trim evenly
function __batt_state() {
bstate=$(pmset -g batt | awk '/charging|discharging|charged/ {print $4}' | cut -f1 -d';')
}
We use __
because to follow a unix convention for function names that won't need to be manually used at the CLI.
For the colors, just follow any ANSI color guide, e.g. the ones I linked in my dotfiles. Then change that __batt_state
function
# I need to cut field-1 for this to trim evenly
function __batt_state() {
bstate=$(pmset -g batt | awk '/charging|discharging|charged/ {print $4}' | cut -f1 -d';')
case "$bstate" in
charged)
echo "$green$bstate$reset"
;;
charging)
echo "$yellow$bstate$reset"
;;
discharging)
echo "$red$bstate$reset"
;;
*)
echo $bstate
exit
esac
}
I decided to drop all of this in a repo, so that I can use it easier.