_|                
_|_|_|    _|_|_|      _|_|_|    _|_|_|      
_|    _|  _|    _|  _|    _|  _|    _|      
_|    _|  _|    _|  _|    _|  _|    _|      
_|_|_|    _|    _|    _|_|_|    _|_|_|  _|  
_|                                          
_|                                            
                    _|  _|                      
  _|_|    _|_|_|    _|      _|_|_|      _|_|    
_|    _|  _|    _|  _|  _|  _|    _|  _|_|_|_|  
_|    _|  _|    _|  _|  _|  _|    _|  _|        
  _|_|    _|    _|  _|  _|  _|    _|    _|_|_|  

Home

Posts

Shell arguments with getopts

I have been updating my dwm setup recently while stuck at home with covid and decided to update my status bar script to make it a bit nicer to use. This consists of a "main" script which imports several modules that each output their own thing (show the date, volume, etc.) before displaying it on dwm's status bar with xsetroot. This works fine but it's a little annoying for people to have to edit the source code (especially each module) to change some basic stuff like formatting or style.

To make this a little easier, I am now using the getopts shell built-in which allows me to define flags that can be called to change what and how information is displayed per-module. This is better than using positional arguments as it lets me mix and match optional settings and those that require data. The date module, for example, should let you specify the format used and what to display before it

date_module -f "%d %b %T" -s  -i "📅"

With these settings, the module should output something like

📅 14 Mar 20:30:01 |

If we remove the -i flag, it should just display the date alone and if we do not provide a format with -f it should default to the standard format used by the date command. The -s flag doesn't take an argument but dictates if we end the module with a '|' to separate it from other modules

To do this, we must process all the provided flags and their arguments to change what we write to the output:

#!/bin/sh

date_module() {
    DATE=$(date) # Use this if no date format is provided

    while getopts "f:si:" OPT; do
        case "$OPT"
            f) # Get the date with the provided format
                DATE=$(date "+$OPTARG")
                ;;
            s) # The module should end with a '|'
                SEP="|"
                ;;
            i) # What to display before the date
                ICON="$OPTARG"
                ;;
        esac
    done

    printf "%s %s %s" "$ICON" "$DATE" "$SEP"
}

We provide getopts with some information about the flags we use. In this example, f and i expect a value so they are followed by a colon while s does not. It will then loop though each flag given to it and run it's appropriate command. Finally, the finished result is output so it can be used by the main script to display in the bar.

Unfortunately there is not a way to use long flag names with getopts so youre stuck with single charachters. Confusingly the "getopt" utility does allow this but it isn't portable so you'll be stuck on Linux.

So far I've updated two of my modules to use this method, with additional values read from a .conf file to support changing colors (thanks to status2d), icons, formatting, and separators. It's going to take a long time to update everything but it's a good excuse to fix some of my old hacky code.

My bar so far

                                                    ██████
                                  ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒██
                              â–’â–’â–’â–’â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–‘â–’â–’â–’â–’
                            â–’â–’â–‘â–‘â–‘â–‘                      â–‘â–‘â–‘â–‘â–’â–’â–’â–’
                        ████████████████████▒▒░░            ░░░░▒▒
                      ██████████████████████████░░░░░░░░      ░░▒▒
      ██████████  ████▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒██████████████░░      ░░▒▒
    ████████████▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░▒▒▒▒▒▒██████████░░    ████
    ████████▒▒▒▒░░░░░░                    ░░░░░░▒▒▒▒██████░░    ████████
    ██████▒▒░░░░                                ░░░░▒▒████░░    ██████████
        ▒▒░░░░██████████              ████████      ░░▒▒██░░    ██████████
        ▒▒████████▒▒████              ██▒▒▒▒██████  ░░▒▒██░░░░░░▒▒██████
  ██████░░████▒▒▒▒██████              ██████▒▒████  ░░▒▒██████▒▒▒▒
████████░░██████████        ████        ██████████  ░░▒▒████████
████████░░    ░░░░░░░░░░  ░░░░░░░░░░  ░░░░░░░░░░    ░░▒▒████████
  ██████▒▒░░░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒░░░░░░░░░░░░░░░░▒▒████████
          â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’          â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’â–’