Skip to content

Small issue roundup #23

@sedlund

Description

@sedlund

Several UX / architectural issues discovered while debugging rgrc -c df

While trying to use a custom df config, I ran into several behaviors that appear to be bugs or unexpected UX in rgrc.

Environment

  • rgrc: 0.6.12
  • NixOS / Nix-style environment
  • WSL2
  • coreutils df
  • user config in ~/.config/rgrc

Example minimal config:

~/.config/rgrc/rgrc.conf

^df(\s|$)
conf.df

~/.config/rgrc/conf.df

regexp=.*
colours=magenta,bold

This confirms that configs load when running:

df -h | rgrc -c df

However several issues surfaced.


1. rgrc -c <config> <command> blocks waiting for stdin

Running:

rgrc -c df df -h

appears to hang.

Debug output:

rgrc: matched pattern '^df(\s|$)'
rgrc: found config file ~/.config/rgrc/conf.df

After that the program blocks.

Cause

-c mode switches rgrc into stdin filter mode and does not execute the command that follows.

So this command:

rgrc -c df df -h

waits forever for stdin.

This is surprising UX because the CLI syntax strongly suggests:

rgrc -c <config> <command> [args...]

should execute the command.

Suggested fix

Support both behaviors:

invocation behavior
rgrc -c df read stdin (current behavior)
rgrc -c df df -h execute command and colorize output

Implementation concept:

if args.config && args.command.is_empty():
    read stdin
else if args.config && !args.command.is_empty():
    spawn command and pipe output through colorizer

2. Command matching includes arguments

Rules in rgrc.conf match the full pseudo command string:

df -h

not just the command name.

Therefore:

^df$

does not match df -h.

Users must write:

^df(\s|$)

which is unintuitive and easy to miss.

Suggested fix

Attempt matching in two passes:

  1. match against the full pseudo command (current behavior)
  2. if no match is found, match against the command name only

This preserves compatibility while making simple rules behave as expected.


3. Config path handling ignores XDG environment variables

The code uses hardcoded paths such as:

~/.config/rgrc
~/.local/share/rgrc
/etc/rgrc.conf

instead of respecting the XDG Base Directory specification:

XDG_CONFIG_HOME
XDG_DATA_HOME
XDG_CONFIG_DIRS
XDG_DATA_DIRS

This causes unexpected behavior in environments such as:

  • NixOS
  • container environments
  • systems using custom XDG paths

Suggested fix

Construct search paths dynamically following the XDG Base Directory specification.

Example:

Config search order:

$XDG_CONFIG_HOME/rgrc
$XDG_CONFIG_DIRS/rgrc
/etc/rgrc

Data search order:

$XDG_DATA_HOME/rgrc
$XDG_DATA_DIRS/rgrc
/usr/share/rgrc

4. Dev path (share/) can override user configs

RESOURCE_PATHS includes a share directory which appears to be intended for development.

If a share/conf.* exists relative to the working directory, it can override user configs unexpectedly.

Example scenario:

./share/conf.df
~/.config/rgrc/conf.df

If rgrc searches share/ first, the user config will never be loaded.

Suggested fix

Either:

  • move share/ to the end of the search path
  • or only enable it behind a development flag or environment variable

Example:

RGRC_DEV_SHARE=1

5. df example config contains unnecessary lookaround

The shipped conf.df includes patterns like:

regexp=^(?!Filesystem)(\/[-\w\d.]+)+\s

The negative lookahead forces rgrc to use the enhanced regex engine.

This increases regex complexity and can slow matching on long paths such as:

/lib/modules/5.15.167.4-microsoft-standard-WSL2

The lookahead appears unnecessary because the Filesystem header does not start with /.

Suggested fix

Simplify the pattern to avoid lookaround:

regexp=^(\/[-\w\d.]+)+\s

This allows the faster regex engine and reduces potential backtracking cost.


Summary

Issues discovered:

  1. -c mode blocks when a command is provided instead of executing it
  2. command matching includes arguments, requiring unintuitive regex rules
  3. config search paths ignore XDG environment variables
  4. development share/ path can override user configs
  5. df config uses unnecessary lookaround that forces slower regex evaluation

I’m happy to submit PRs for these if the proposed direction aligns with the intended design.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions