Published on

Scripting = Configuration

4 min read - 644 words
Authors
  • avatar
    Name
    Florian Bellmann
    Twitter
Scripting = Configuration

Overview

Common ways of configuring software

Over the years we have seen many ways of configuring software products. Most of the time, these products can either be run with environment variables or through loading a configuration file. These files have formats like .xml, .yml, .json, .toml and so on.

One advantage that .yml files have, is that they can use placeholders and allow for substitution of default values. More complex scenarios oftentimes require to have the logic inside of the software product itself though. The configuration files hold flags and values to that behavior.

Scripting as configuration

A modern approach when building software for developers, is to configure them by using a scripting language. This is a powerful approach, as it allows to use the full capabilities of a programming language. In practise one builds a configuration object inside the scripting language and returns it to the software at hand.

Lua

Neovim and WezTerm chose to use Lua for that and Lua is continuing to gain market share. Lua is a small and fast scripting language. It is very easy to learn and has a small footprint. Additionally, Lua has the concept of a Lua table which is basically a key value object.

local config = {
  name = "John Doe",
  age = 42,
  address = {
    street = "Main Street",
    city = "New York",
    country = "USA"
  }
}

return config

The config object is such a table. This small file returns it to whoever consumes the output. It could already be a configuration that a software program could read.

Utilizing the power

To give an example on where the scripting is useful, let's take a look at the following configuration file.

local config = {
  name = "Great software product", 
  theme = "Github light",
  update_interval = 1000
}

return config

Say we want to deploy our software on both MacOS and Windows which require a different update_interval. With a small scripting function we can automate this.

  -- Function to execute a shell command and capture its output
local function execute(command)
  local handle = io.popen(command)
  local result = handle:read("*a")
  handle:close()
  return result
end

local is_macos = execute("uname -s") == "Darwin"

local config = {
  name = "Great software product", 
  theme = "Github light",
  update_interval = is_macos and 1000 or 5000 -- Ternary if in lua
} 

return config

What if we want to provide our users the option to choose between light and dark themes in the application. Traditionally, one would implement a theme switcher inside the app itself. With the same helper function execute() we can achieve an automatic switcher in the config file. This example is build for MacOS, it can be done in a similar way for Windows.

local function is_macos_dark_theme()
  -- Check MacOS system theme
  local command = "defaults read -g AppleInterfaceStyle"
  local theme = execute(command)

  -- Remove leading/trailing white space and line breaks from the theme
  theme = theme:gsub("^%s*(.-)%s*$", "%1")

  -- Determine and return the theme
  if theme == "Dark" then
    return true
  else
    return false
  end
end

local config = {
  name = "Great software product", 
  theme = is_macos_dark_theme() and "Github dark" or "Github light",
  update_interval = is_macos and 1000 or 5000
} 

return config

Extensibility of software

By providing the possibility to script, it encourages users of the software to do so. This allows for a high degree of extensibility. The users can write their own plugins and share them with the community. It fosters experimenting and a new level of engagement with the software.

To be fair, this is mainly possible with software that is targeting software developers or people that have some knowledge of scripting.

I anyhow think it's a great approach that supports a fun way to interact with the software at hand.

Cheers
Flo