sebastiano.tronto.net

Source files and build scripts for my personal website
git clone https://git.tronto.net/sebastiano.tronto.net
Download | Log | Files | Refs | README

tmux-battery.md (6020B)


      1 # tmux trick #1: battery status indicator
      2 
      3 *This post is part of a [series](../../series)*
      4 
      5 [tmux](https://github.com/tmux/tmux/wiki) is a program that allows
      6 you to create multiple virtual terminals in the same shell and keep
      7 your terminal sessions open even after the shell exits. A common
      8 use case for both of these features is connecting to a remote server:
      9 with *multiplexing* you can use multiple terminals with a single
     10 SSH connection, and the session persistence feature leaves the
     11 remote programs running even when you disconnect from the server.
     12 Having multiple virtual terminals open on the same screen and easily
     13 switching between windows is also useful when working locally.  In
     14 fact, tmux is the first command I use pretty much every time I use
     15 my [netbook](../2022-09-10-netbooks) - even though
     16 [one shell is all I need](../2023-02-25-job-control).
     17 
     18 Since tmux is quite a complex program, I never learned the details
     19 of how it works. I learned how to do the couple of things I need,
     20 and use the default settings for everything. But sometimes I do
     21 feel the need to improve my workfow a bit, and what better excuse
     22 for tinkering with a software tool than writing about it?
     23 
     24 In this post I have one simple goal: display the battery level in
     25 tmux's status bar. I am going to focus on OpenBSD, because this is
     26 the system where I need this: on my Linux laptop I use my window
     27 manager status bar to display this information, but on my underpowered
     28 OpenBSD laptop I rarely use a graphical environment, and I rely on
     29 tmux as a desktop environment.
     30 
     31 ## tmux commands
     32 
     33 tmux can be controlled using a variety of key bindings, all prefixed by
     34 a "prefix" key combination, which by default is `Ctrl+B`. For example,
     35 `Ctrl+B C` creates a new window and `Ctrl+B %` splits the screen
     36 vertically.
     37 
     38 Each key binding calls a *tmux command*. Not all commands are bound to
     39 a key combination, and there are other ways to call them, including:
     40 
     41 * Typing them in the tmux command line, invoked by pressing `Ctrl+B :`.
     42 * Calling them from any shell as `tmux command ...`.
     43 * Adding them to the tmux configuration file (by default `~/.tmux.conf`)
     44   to be called on startup.
     45 
     46 ## The tmux status bar
     47 
     48 tmux has a status bar, which can be any size between 0 (disabled)
     49 and 5 lines long. The default is 1 line with date, time and hostname
     50 displayed on the right, and some information on the current session
     51 on the left.
     52 
     53 My goal is to customize the status indicators on the right. After
     54 consulting the [man page](https://man.openbsd.org/tmux) for a while,
     55 I figured out that the command I need is:
     56 
     57 ```
     58 set status-right "Hello, World!"
     59 ```
     60 
     61 To show the output of a command one can use the `#()` notation:
     62 
     63 ```
     64 set status-right "#(date +'%H:%M')"
     65 ```
     66 
     67 This example is actually a bit redundant, because the string is
     68 passed through [strftime](https://man.openbsd.org/strftime) before
     69 displaying. So one could simply use `set status-right "%H:%M"` to
     70 specify a date in the HH:MM format.
     71 
     72 The status bar by default refreshes (and so re-runs the commands
     73 in `#()`) every 15 seconds, but this can be changed with the
     74 `status-interval` command.
     75 
     76 ## Battery information
     77 
     78 The next step is getting the battery status from a command. On Linux
     79 I wrote a little [script](https://git.tronto.net/scripts) to automate
     80 this, but I don't have one (yet!) for OpenBSD. On this OS, this
     81 information can be retrieved with `apm`:
     82 
     83 ```
     84 $ apm
     85 Battery state: high, 91% remaining, 367 minutes life estimate
     86 AC adapter state: not connected
     87 Performance adjustment mode: manual (1000 MHz)
     88 ```
     89 
     90 I am only interested in the `91%` part, so I should pass this through `grep`
     91 
     92 ```
     93 $ apm | grep -o '[^ ]*%'
     94 91%
     95 ```
     96 
     97 This command means "print the strings that consist of a % symbol
     98 preceded by any number of non-space characters". To learn more about
     99 `grep`, check out [my blog post](../2023-08-20-grep).
    100 
    101 ## Putting it all together
    102 
    103 We can get our status line to show the battery status with this
    104 tmux command:
    105 
    106 ```
    107 set status-right "#(apm | grep -o '[^ ]*%%')"
    108 ```
    109 
    110 Cool! But did you notice the double `%%`? That's because the string
    111 is formatted with `strftime`, as I mentioned before, so we must
    112 escape the `%`.  Tricky!
    113 
    114 ## More status info
    115 
    116 We reached our goal, but in doing so we also got rid of all the information
    117 that was already part of the status. I would like to have at least some of
    118 it back.
    119 
    120 One way to solve this is to use the `-a` flags for the `set` command,
    121 like this:
    122 
    123 ```
    124 set -a status-right " #(apm | grep -o '[^ ]*%%')"
    125 ```
    126 
    127 This will append the new string to the current status, instead of
    128 replacing it. Alternatively, we could declare exactly all the stuff
    129 that we want there:
    130 
    131 ```
    132 set status-right "#(apm | grep -o '[^ ]*%%') | %Y-%m-%d | %H:%M"
    133 ```
    134 
    135 But what if one wants even more information there? I don't want to have
    136 a cluttered status line, but for example being able to see at a glance if
    137 I am connected to wifi or not would be convenient.
    138 
    139 A simple solution is writing a shell script that prints out all this
    140 information, save it somewhere in the `$PATH`, and then use
    141 `set status-right "#(status_script)"`. I already have such a script
    142 for Linux, and now I added one for OpenBSD in my
    143 [scripts repository](https://git.tronto.net/scripts).
    144 
    145 ## Configuration file
    146 
    147 Finally, we can have our status bar set on startup by adding the
    148 following line to our configuration file:
    149 
    150 ```
    151 set -g status-right "#(status_script)"
    152 ```
    153 
    154 ...wait a minute, that is the `-g` flag about? Witout it, I get the
    155 following error on startup:
    156 
    157 ```
    158 /home/sebastiano/.tmux.conf:1 no current session
    159 ```
    160 
    161 Apparently, commands run *without* `-g` only apply to the current
    162 "session", but the configuration file is sourced *before* a session
    163 is created. The `-g` is used to apply this command globally. My
    164 understanding of this is still superficial, but for now I am happy
    165 that the battery status is there.  Maybe I'll learn about sessions
    166 at some point, and I'll write a new blog post about them :)
    167 
    168 *Next in the series: [copy to clipboard](../2026-05-17-tmux-clipboard)*