Skip to content

i3 Config Partials

Ken Gilmer edited this page Jun 26, 2021 · 3 revisions

NOTE: Deprecated

Most of this page is no longer relevant due to the coming change in i3 to enable config partials natively.

Overview

This page describes an approach to the decomposition of an i3-gaps config file into partials that are combined at session init.

octocat

Motivation

i3 and it's variations do not allow for the ability to discover and load configuration partials at start time. Rather, a complete file is defaulted or specified via command-line parameters. The i3 project does not see this as a feature they care about at this time, however for a project such as Regolith, a single config file presents problems at the packaging level. Linux package managers such as Debian's dpkg maintain consistency among packages partly by ensuring that only one given installed package "owns" a given file on the root file system. This means that multiple packages cannot contribute to a single file. There is a direct relationship between any installed file in the root filesystem and a package that installed it. However, as a single-file, Regolith integrates several smaller components to provide functionality such as color themes, advanced workspace management, and other features. Any feature that requires integration in the i3 config file essentially becomes a hard dependency in Regolith. A single config file must be provided by a single Debian package, and that package's control file must expose the dependency relationships found in that i3 config file.

A better approach from a package management perspective is to allow for configuration partials, or simply small pieces of a config file that can be composed together at runtime to form a single, complete file. This approach breaks the one-config-file, one-package problem. Any package may contribute a partial which can be managed independently from others. A nuance to this is that no single file can be relied upon as a top level description of all sub-files. For example, shipping a file with #include <> directives would suffer the same scaling issues as that file itself would need to be modified by multiple packages. Rather, a convention such as a conf.d directory is required. Discovery is enabled by simply specifying that all files within a conf.d directory shall be considered partials. Any package is free then to contribute it's file into this directory and not require further work to integrate into the host system.

Why Now?

When people open issues against i3 asking for functionality like this, a common response is to implement something like what is described here. Why has Regolith avoided doing so until now and why change? Regolith as a project strives to implement the least amount of code to provide a usable desktop environment. Many of the i3 config preprocessor schemes add additional logic, syntax, special cases, and caveats that would not exist in a "pure" i3 system. To avoid user friction and confusion regarding i3 configuration, these approaches have been avoided.

However, i3 is a key integration point in the Regolith desktop environment. Not only user actions but also background processes and various small UI programs are initialized via the i3 config file. Because of reasons stated above, it becomes difficult to add optional or system-dependent logic. Sometimes features and customization cannot be added as there is no simple way of making the functionality optional. Additionally, for Regolith to run on a variety of systems, the core dependencies should be as small as possible. With a monolithic file this is not possible. Lastly, while the Xresource facility provides a powerful way of extending i3 without changing the config file, it is verbose. This verbosity itself becomes an issue for users when trying to understand and modify Regolith's i3 config file.

Requirements

  1. Traditional configuration forms should not regress functionally in any way.
  2. Vanilla i3 users should not require knowledge of any new abstractions or procedures to configure (baseline i3 config files continue to work as expected, no surprises)
  3. Users have a clear understanding of the "concrete" i3 config file in all cases. In no case is the configuration obfuscated from the user.
  4. Config mode is either-or. i3 always consumes just a single config file, but where that config file comes from is based on the presence/absence of files in specific places on the file system. (i3 --moreversion) should be all it takes to know which "mode" a user is in.)
  5. In the config partial mode, the composite config file should contain comments (or other metadata) such that the exact set of partials used in the composite can be known in the config file itself.
  6. In the case that there is a unrecoverable error in a config partial, a package provided default is used. (opposed to omitting some partials if they fail, etc.. meaning: the partial evaluation is all-or-nothing)

Anti-requirements

  • There is no meta-language or additional commands added to the i3 config file syntax. All predication relies on filesystem semantics.
  • There is no complex logic regarding the source of partial files. They are either provided by the system in /etc/regolith/i3/conf.d (secondary) or specified by the user in ~/.config/regolith/i3/conf.d (primary) (in the case that user-configurable extension is enabled).

Files

  • /etc/regolith/i3/config: The i3 config file used in Regolith versions 1.2 - 1.5.1.
  • /etc/i3/config: The default i3 config file used by vanilla i3.
  • ~/.config/regolith/i3/config: The user-staged copy of the i3 config file in Regolith 1.2 - 1.5.1
  • ~/.config/regolith/i3/config-generated: The proposed config file generated at session init with partial mode on.
  • /etc/regolith/i3/config-baseline: A proposed default i3 config file for Regolith to fallback to in the case that an error occurs when generating the partial-versioned i3 config file. (This file would only exist if it's possible to catch a majority of user configuration issues such that the fallback would be useful.)

Heuristics

This section describes at a high level how the i3 config partial system works.

Mode Determination

  • By default, the i3 config partial mode is off.
  • The existence of a file at /etc/regolith/i3/config shall mean that the config partial mode is off. (S1)
  • The existence of an Xresource key/value pair of i3-wm.config.mode: default shall mean that the config partial mode is off. (S2)
  • The existence of an Xresource key/value pair of i3-wm.config.mode: partial shall mean that the config partial mode is on.
  • The existence of files within the directory (/etc/regolith/i3/conf.d || ~/.config/regolith/i3/conf.d) && !S1 && !S2 shall mean that the config partial mode is on.
  • Any ambiguity of states mentioned above shall result in i3 config partial mode as being off.

If partial config mode is off, the config file (~/.config/regolith/i3/config || /etc/regolith/i3/config) is passed to i3 in session init. If partial config mode is on, the complete config file is "compiled" from it's partials and staged in a user directory (~/.config/regolith/i3/config-generated) which is passed to i3-gaps during session init.

Partial Combination

  • ~/.config/regolith/i3/conf.d is evaluated first, if files do not exist here then /etc/regolith/i3/conf.d is evaluated. Either the user or the etc variant is used. They are not combined in any way.
  • If the file ~/.config/regolith/i3/config-generated exists, it is overwritten.
  • A static header comment is written to ~/.config/regolith/i3/config-generated describing that the file is generated and any manual edits will be lost, with links to the website for common desires such as disabling partial configs, where to put changes that stick, etc..
  • All files within the conf.d directory are read in filename descending sort order. The path of the file and a timestamp are appended as a comment to ~/.config/regolith/i3/config-generated and then the entire contents of the file is appended to ~/.config/regolith/i3/config-generated.
  • The generated config file is evaluated to ensure it is valid with i3 -C ~/.config/regolith/i3/config-generated. If the config file is invalid, the /etc/regolith/i3/config-baseline file is used. A notification is sent to the user noting the fallback event.
  • If the eval check passes, i3 is loaded with the config file ~/.config/regolith/i3/config-generated.

Observability

It should be obvious to users how a generated i3 config file was composed. In order to facilitate this (as described above), each partial, when appended to the generated config file will add it's full file path name and timestamp of when it was appended. The comment should use a unique string such that grepping the config file with said string would give a linear view of how the file was composed. Example, from a user overridden i3 config partial tree:

...
#+ /home/kgilmer/.config/regolith/i3/conf.d/10_workspaces (1609024812)
...

Debugging

In cases where the generated config file is somehow invalid (assuming such cases can be determined somehow), any error text of the error will be passed via a system notification to the user. The user may then inspect the generated config file and look for errors. Because of the comment headers for each section, finding each source file should be clear.

Error Handling

i3 has a config file evaluation function, triggered via the "-C" command-line parameter. This allows us to pre-check the config file before launching i3, and in the case of failure falling back to a known-good default and notifying the user of the issue.

Capabilities this Feature Enables

  • Ability to swap notification systems by installing packages
  • Ability to swap bar UI providers by installing packages
  • Remove the "init script" in the compositor packages to just i3 config partials.
  • The regolith-desktop-minimal metapackage should be able to remove several dependencies such as rofication and i3-snapshot.

Allowances for User Extension

Initially user extension by adding partials directly will not be supported. This is to evaluate the supportability of this method of configuring i3 for the general Regolith user base. At some point we may decided to enable user extension, and if so the following applies:

This approach to config partials can be utilized by users at two levels.  The "dotfiles" approach simply allows users to add files in their dotfiles for whatever partials they prefer in their system.  This approach is file based and would rely on the aspect of this system in which the user directory `~/.config/regolith/i3/conf.d` is checked first and has the top priority for user config paritals.

Secondly, users can create their own OS packages that can be hosted and installed by others.  This requires more care, development, and infrastructure support but would also enable the package management discovery, selection, and uniqueness logic of the package management system to be applied to config partials.  For example, `apt` guarantees that of the Regolith compositor packages, one and only one must be installed.

i3 Config file Decomposition Approach

The i3 config file needs to be decomposed into partials in such a way that packages can most easily add their own configuration bits without overlapping or having gaps with other config partials. For example, all i3bar configuration elements should be contributed in the same partial so that bar implementations can be cleanly swapped. Colors, background applications, special modes are other examples of extension by package.

Known Open Design Questions

  1. The ideal topology and granularity for i3 partial files such that package managers can cleanly integrate behaviors.
  2. The most appropriate notification tool to flag i3 config files as being invalid. i3-nagbar or notify-send or ...
  3. Rules of thumb where the line is drawn between "configure via package existence" vs "configure via Xresource kvp existence".
  4. Should system (/etc/regolith/...) vs user (~/.config/regolith/...) be EITHER/OR or combinational? (By nature, combinational does not make exclusion simple (omitting an installed file), so EITHER/OR seems safer.)

Proposed Changes in Regolith

Logic

  • The logic described in the Heuristics section will live in regolith-gnome-flashback which provides the session init logic, however this package name no longer accurately describes it's purpose. The package should be deprecated and another, named regolith-session should take it's place.
  • The package regolith-i3-gaps will no longer ship /etc/regolith/i3/config but rather /etc/regolith/i3/config-baseline as well as the subset of partials necessary for a working i3 install, but offering no functionality provided by other packages in regolith (for example rofication or the compositors).
  • Other packages that contribute some functionality that integrates into i3 will begin shipping their own partials (for example /etc/regolith/i3/conf.d/30_rofication).
  • regolith-desktop* meta packages will be refactored to remove hard dependencies given the new structure. regolith-desktop-minimal should require nothing i3-specific beyond regolith-i3-gaps-config and regolith-compositor-none.

Packaging (Volatile)

In the following proposed package structure, the term "i3 config partial" is reduced to i3cp in package names to denote packages that contribute config partials to Regolith. Virtual packages allow users to specify alternatives for defaults. For example, an alternative resize mode partial foo-i3cp-resize may use different sets of keys or have different UI treatments, and would provide the virtual package regolith-i3cp-resize-mode. This allows the package manager to ensure one and only one keybindings partial is installed.

Package Virtual Slot Partial File(s) Purpose
regolith-i3-gaps-config 01_documentation Comments for the user explaining how to read and configure the Regolith i3 file.
regolith-i3cp-workspaces 10_workspaces Specify the names of workspaces.
regolith-i3cp-primary-keybindings 15_primary-keybindings Specify keybindings for basic i3 workflow that has no external dependencies.
regolith-i3cp-resize-mode 50_resize-mode Default resize mode keybindings
regolith-i3cp-session 55_session_keybindings Default session keybindings (log out, etc.)
regolith-i3cp-config 60_config_keybindings Default configuration keybindings (Set wifi network, etc.)
regolith-i3cp-appearance 65_appearance Default appearance declarations (gap size, color mapping)
regolith-i3cp-network 67_network Default network keybindings and execs
regolith-i3cp-bar 70_bar Default bar declarations, should be possible use another bar implementation entirely with this partial.
... ... ... ...
regolith-ftue 15_first-time-user-experience Keybingings and execs for new users
regolith-unclutter 21_unclutter exec for unclutter
... ... ... ...
regolith-rofication regolith-i3cp-notification 80_notification Keybindings and execs for notification system.
regolith-i3-snapshot 75_i3-shapshot Keybindings for i3-snapshot.
... ... ... ...
regolith-compositor-none regolith-i3cp-compositor 30_compositor Exec for no compositor (pass-through)
regolith-compositor-xcompmgr regolith-i3cp-compositor 30_compositor Exec for compositor xcompmgr
regolith-compositor-compton-glx regolith-i3cp-compositor 30_compositor Exec for compositor compton with glx backend.
regolith-compositor-picom-glx regolith-i3cp-compositor 30_compositor Exec for compositor picom with glx backend.

Documentation

  • Rewrite all configuration documentation associated with the i3 config file. Clearly explain levels of evaluation and recommended approaches to over rides (Xresources, config partials, i3 config file)
  • Remove or reword all documentation advising against user-staged i3 config files.
  • Remove or reword all documentation referencing /etc/regolight/i3/config and ~/.config/regolith/i3/config.
  • Add a high-level description of this facility with steps for configuring (add a partial, remove a partial, stage partials, etc.)

Proof of Concept Implementation

Something like the following script may be called from within /usr/bin/regolith-session-init rather than calling i3 directly:

#!/bin/bash
# See https://github.com/regolith-linux/regolith-system/wiki/i3-config-partials

set -Eeu -o pipefail

DEFAULT_SYS_I3_CONFIG_FILE="/etc/regolith/i3/config"
DEFAULT_USER_I3_CONFIG_FILE="$HOME/.config/regolith/i3/config"
DEFAULT_USER_CONFIG_DIR="$HOME/.config/regolith/i3/conf.d"
DEFAULT_SYS_CONFIG_DIR="/etc/regolith/i3/conf.d"

# Determine partial or default config modes.
is_partial_mode() {
    # The existence of an Xresource key/value pair of i3-wm.config.mode: default shall mean that the config partial mode is off. 
    if [ "$(xrescat i3-wm.config.mode)" == "default" ]; then
        return 1
    fi

    # The existence of an Xresource key/value pair of i3-wm.config.mode: partial shall mean that the config partial mode is on.
    if [ "$(xrescat i3-wm.config.mode)" == "partial" ]; then
        return 0
    fi

    # The existence of a file at /etc/regolith/i3/config shall mean that the config partial mode is off
    if [ -f "$DEFAULT_SYS_I3_CONFIG_FILE" ]; then
        return 1
    fi

    # The existence of a file at /etc/regolith/i3/config shall mean that the config partial mode is off. 
    if [ -f "$DEFAULT_USER_I3_CONFIG_FILE" ]; then
        return 1
    else
        return 0 # true
    fi
}

# Determine which directory contains i3 config partials
# Sets I3_PARTIAL_DIR
resolve_partial_config_directory() {


    if [[ -d $DEFAULT_USER_CONFIG_DIR && -n "$(ls -A $DEFAULT_USER_CONFIG_DIR 2>/dev/null)" ]]; then
        I3_PARTIAL_DIR=$DEFAULT_USER_CONFIG_DIR
    else 
        I3_PARTIAL_DIR=$DEFAULT_SYS_CONFIG_DIR
    fi
}

# Determine where the default i3 config file is
# Sets I3_CONFIG_FILE
resolve_default_config_file() {
    if [ -f "$DEFAULT_USER_I3_CONFIG_FILE" ]; then
        I3_CONFIG_FILE="$DEFAULT_USER_I3_CONFIG_FILE"
    else
        I3_CONFIG_FILE="$DEFAULT_SYS_I3_CONFIG_FILE"
    fi
}

# Overwrite an existing file and add header
generate_partial_config_header() {
    SCRIPTPATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"    
    echo "# This config file was generated by $SCRIPTPATH at $(date)" > "$GENERATED_CONFIG_FILE"
    echo "# DO NOT make edits here, they will be lost.  Instead, see [TBD] for details." >> "$GENERATED_CONFIG_FILE"
}

# Launch i3 in default config file
start_i3_default_config_mode() {
    resolve_default_config_file
    echo "i3 -c $I3_CONFIG_FILE"
}

# Launch i3 in partial config file
start_i3_partial_config_mode() {
    resolve_partial_config_directory

    GENERATED_CONFIG_FILE="$HOME/.config/regolith/i3/config-generated"

    generate_partial_config_header

    for filename in "$I3_PARTIAL_DIR"/*; do
        echo "#+ $filename ($(date +%s))" >> "$GENERATED_CONFIG_FILE"
        cat $filename >> "$GENERATED_CONFIG_FILE"
    done

    echo "i3 -c $GENERATED_CONFIG_FILE"
}

if is_partial_mode; then
    start_i3_partial_config_mode
else    
    start_i3_default_config_mode
fi

Produces ~/.config/regolith/i3/config-generated:

# This config file was generated by /home/kgilmer/dev/repos/regolith-i3-gaps-config at Sat Dec 26 03:20:12 PM PST 2020
# DO NOT make edits here, they will be lost.  Instead, see [TBD] for details.
#+ /home/kgilmer/.config/regolith/i3/conf.d/01_meta-keybindings (1609024812)
###############################################################################
# i3-gaps config file for the Regolith Desktop Environment
#
# Please see http://i3wm.org/docs/userguide.html for a complete reference!
#
###############################################################################
#
# In this config file many values are taken from Xresources with the directive
# set_from_resource:
#
# set_from_resource <i3 variable name> <Xresources key> <default value>
#
# This configuration file utilizes Xresource variables to change configuration
# without having to make a copy of this config file.
# The benefit to not copying this file is easier upgrades in the future.
# To update a value in this config without making a copy, update the Xresource
# value in the file ~/.config/regolith/Xresources.
#
# For example, to change the bar position to the top of the screen this is the
# i3 config entry in this file:
# set_from_resource $i3-wm.bar.position i3-wm.bar.position bottom
#
# So add this line to ~/.config/regolith/Xresources to change it's value:
# i3-wm.bar.position: top
#
# Reload i3 after making Xresource changes.  Learn more at
# https://regolith-linux.org/docs/howto/override-xres/
#
###############################################################################
#
# This file uses a machine-parsable format for comments. The schema is:
# ## <Category> // <Action> // <Keybinding> ##
# Learn more at https://github.com/regolith-linux/remontoire
#
###############################################################################

###############################################################################
# Key Mappings
###############################################################################

# Meta Key - Alt key is Mod1, and Windows key is Mod4
set_from_resource $mod  i3-wm.mod Mod4
set_from_resource $alt  i3-wm.alt Mod1

set_from_resource $i3-wm.binding. i3-wm.binding.
#+ /home/kgilmer/.config/regolith/i3/conf.d/10_workspaces (1609024812)
###############################################################################
# Workspace Names
# These are the labels which define each i3 workspace.
###############################################################################

set_from_resource $ws1  i3-wm.workspace.01.name "1"
set_from_resource $ws2  i3-wm.workspace.02.name "2"
set_from_resource $ws3  i3-wm.workspace.03.name "3"
set_from_resource $ws4  i3-wm.workspace.04.name "4"
set_from_resource $ws5  i3-wm.workspace.05.name "5"
set_from_resource $ws6  i3-wm.workspace.06.name "6"
set_from_resource $ws7  i3-wm.workspace.07.name "7"
set_from_resource $ws8  i3-wm.workspace.08.name "8"
set_from_resource $ws9  i3-wm.workspace.09.name "9"
set_from_resource $ws10 i3-wm.workspace.10.name "10"
set_from_resource $ws11 i3-wm.workspace.11.name "11"
set_from_resource $ws12 i3-wm.workspace.12.name "12"
set_from_resource $ws13 i3-wm.workspace.13.name "13"
set_from_resource $ws14 i3-wm.workspace.14.name "14"
set_from_resource $ws15 i3-wm.workspace.15.name "15"
set_from_resource $ws16 i3-wm.workspace.16.name "16"
set_from_resource $ws17 i3-wm.workspace.17.name "17"
set_from_resource $ws18 i3-wm.workspace.18.name "18"
set_from_resource $ws19 i3-wm.workspace.19.name "19"

###############################################################################
# Workspace Keys
# These are the keys which will be used while binding workspace switching
###############################################################################

set_from_resource $ws1_key  i3-wm.workspace.01.key 1
set_from_resource $ws2_key  i3-wm.workspace.02.key 2
set_from_resource $ws3_key  i3-wm.workspace.03.key 3
set_from_resource $ws4_key  i3-wm.workspace.04.key 4
set_from_resource $ws5_key  i3-wm.workspace.05.key 5
set_from_resource $ws6_key  i3-wm.workspace.06.key 6
set_from_resource $ws7_key  i3-wm.workspace.07.key 7
set_from_resource $ws8_key  i3-wm.workspace.08.key 8
set_from_resource $ws9_key  i3-wm.workspace.09.key 9
set_from_resource $ws10_key i3-wm.workspace.10.key 0
#+ /home/kgilmer/.config/regolith/i3/conf.d/20_basic-keybindings (1609024812)

###############################################################################
# Launcher dialogs
###############################################################################

## Launch // Terminal // <> Enter ##
set_from_resource $i3-wm.binding.terminal i3-wm.binding.terminal Return
bindsym $mod+$i3-wm.binding.terminal exec /usr/bin/x-terminal-emulator

## Launch // Browser // <><Shift> Enter ##
set_from_resource $i3-wm.binding.browser i3-wm.binding.browser Shift+Return
bindsym $mod+$i3-wm.binding.browser exec gtk-launch $(xdg-settings get default-web-browser)

set_from_resource $rofiTheme rofi.theme /etc/regolith/styles/lascaille/rofi.rasi

## Launch // Application // <> Space ##
set_from_resource $i3-wm.binding.launcher.app i3-wm.binding.launcher.app space
set_from_resource $i3-wm.program.launcher.app i3-wm.program.launcher.app rofi -show drun -theme $rofiTheme
bindsym $mod+$i3-wm.binding.launcher.app exec $i3-wm.program.launcher.app

## Launch // Command // <><Shift> Space ##
set_from_resource $i3-wm.binding.launcher.cmd i3-wm.binding.launcher.cmd Shift+space
set_from_resource $i3-wm.program.launcher.cmd i3-wm.program.launcher.cmd rofi -show run -theme $rofiTheme
bindsym $mod+$i3-wm.binding.launcher.cmd exec $i3-wm.program.launcher.cmd

## Navigate // Window by Name // <><Ctrl> Space ##
set_from_resource $i3-wm.binding.launcher.window i3-wm.binding.launcher.window Ctrl+space
set_from_resource $i3-wm.program.launcher.window i3-wm.program.launcher.window rofi -show window -theme $rofiTheme
bindsym $mod+$i3-wm.binding.launcher.window exec $i3-wm.program.launcher.window

## Launch // This Dialog // <><Shift> ? ##
set_from_resource $i3-wm.binding.help i3-wm.binding.help Shift+question
set_from_resource $i3-wm.program.help i3-wm.program.help /usr/bin/remontoire-toggle
bindsym $mod+$i3-wm.binding.help exec --no-startup-id $i3-wm.program.help

## Launch // File Search // <><Alt> Space ##
set_from_resource $i3-wm.binding.file_search i3-wm.binding.file_search Mod1+space
set_from_resource $i3-wm.program.file_search i3-wm.program.file_search rofi -show find -modi find:/usr/share/rofi/modi/finder.sh
bindsym $mod+$i3-wm.binding.file_search exec $i3-wm.program.file_search

## Launch // Look Selector // <><Alt> l ##
set_from_resource $i3-wm.binding.look_selector i3-wm.binding.look_selector Mod1+l
set_from_resource $i3-wm.program.look_selector i3-wm.program.look_selector rofi -show look -modi look:/usr/share/rofi/modi/look-selector.sh
bindsym $mod+$i3-wm.binding.look_selector exec $i3-wm.program.look_selector

#+ /home/kgilmer/.config/regolith/i3/conf.d/70_resize-mode (1609024813)
###############################################################################
# Window Resize and Gaps
###############################################################################

set_from_resource $i3-wm.binding.inc_gaps i3-wm.binding.inc_gaps plus
set_from_resource $i3-wm.binding.dec_gaps i3-wm.binding.dec_gaps minus

set_from_resource $i3-wm.binding.inc_gaps_big i3-wm.binding.inc_gaps_big Shift+plus
set_from_resource $i3-wm.binding.dec_gaps_big i3-wm.binding.dec_gaps_big Shift+minus

## Resize // Enter Resize Mode // <> r ##
mode "Resize Mode" {
        # These bindings trigger as soon as you enter the resize mode

        ## Resize // Resize Window // ↑ ↓ ← → ##
        bindsym Left resize shrink width 6 px or 6 ppt
        bindsym Down resize grow height 6 px or 6 ppt
        bindsym Up resize shrink height 6 px or 6 ppt
        bindsym Right resize grow width 6 px or 6 ppt

        bindsym Shift+Left resize shrink width 12 px or 12 ppt
        bindsym Shift+Down resize grow height 12 px or 12 ppt
        bindsym Shift+Up resize shrink height 12 px or 12 ppt
        bindsym Shift+Right resize grow width 12 px or 12 ppt

        ## Resize // Resize Window // k j h l ##
        bindsym $i3-wm.binding.left resize shrink width 6 px or 6 ppt
        bindsym $i3-wm.binding.up resize grow height 6 px or 6 ppt
        bindsym $i3-wm.binding.down resize shrink height 6 px or 6 ppt
        bindsym $i3-wm.binding.right resize grow width 6 px or 6 ppt

        bindsym $i3-wm.binding.move_left resize shrink width 12 px or 12 ppt
        bindsym $i3-wm.binding.move_up resize grow height 12 px or 12 ppt
        bindsym $i3-wm.binding.move_down resize shrink height 12 px or 12 ppt
        bindsym $i3-wm.binding.move_right resize grow width 12 px or 12 ppt

        ## Resize // Window Gaps // + - ##
        bindsym $i3-wm.binding.dec_gaps gaps inner current minus 6
        bindsym $i3-wm.binding.inc_gaps gaps inner current plus 6
        bindsym $i3-wm.binding.dec_gaps_big gaps inner current minus 12
        bindsym $i3-wm.binding.inc_gaps_big gaps inner current plus 12

        ## Resize // Exit Resize Mode // Escape or Enter ##
        bindsym Return mode "default"
        bindsym Escape mode "default"
        bindsym $mod+r mode "default"
}
bindsym $mod+r mode "Resize Mode"
#+ /home/kgilmer/.config/regolith/i3/conf.d/80_default-external-programs (1609024813)
###############################################################################
# External programs launched with i3
###############################################################################

# Launch first time user experience script
set_from_resource $i3-wm.program.ftui i3-wm.program.ftui /usr/bin/regolith-ftue
exec --no-startup-id $i3-wm.program.ftui

To get a quick perspective regarding the components of a generated config file, grep the special comment sequence:

$ cat /home/kgilmer/.config/regolith/i3/config-generated | grep "#+"
#+ /home/kgilmer/.config/regolith/i3/conf.d/01_meta-keybindings (1609024812)
#+ /home/kgilmer/.config/regolith/i3/conf.d/10_workspaces (1609024812)
#+ /home/kgilmer/.config/regolith/i3/conf.d/20_basic-keybindings (1609024812)
#+ /home/kgilmer/.config/regolith/i3/conf.d/70_resize-mode (1609024813)
#+ /home/kgilmer/.config/regolith/i3/conf.d/80_default-external-programs (1609024813)

Development Plan

  1. create the regolith-session source package w/ regolith-session-flashback binary package to host scripts from regolith-gnome-session and some form of the code on this page.
  2. create an experimental branch in regolith-desktop that references regolith-session rather than regolith-gnome-flashback.
  3. create an experimental branch in regolith-i3-gaps-config that breaks apart config as specified in this document.
  4. test/iterate