Problems with integrating a script in configuration.nix

Hello everyone,

I’m running into an issue whilst adding a script into my configuration.nix file.
When I add this script to my Autostart section in Budgie on NixOS it just works as expected. However in the vain of reproducibility I’d like to add it to my configuration.nix (or a separate file I could include), but when I add it as systemd.user.services.autorotate-sam as a linked file (because the file itself works, so why not just link to it?) it throws errors at me. And when I copy in the content of the script into my config only the screen rotation works, the pointer matrices aren’t changing. Below I’ll paste both versions to help diagnose the issue (sorry for the long post in advance!);

# Autorotate S.A.M. as NixOS script
  # WIP!!!
  systemd.user.services.autorotate-sam = {
    enable = true;
    after = [ "network-online.target" ];
    wantedBy = [ "multi-user.target" ];
    description = "Automatically rotate the display orientation and pointer matrixes";
    script = [ "/home/ryukurisu/SDcard/.bin/autorotate-sam.sh" ];
  };
  # Autorotate S.A.M. as NixOS script
  # WIP!!!
  systemd.user.services.autorotate-sam = {
    enable = true;
    after = [ "network-online.target" ];
    wantedBy = [ "multi-user.target" ];
    description = "Automatically rotate the display orientation and pointer matrixes";
    script = with pkgs; ''
    #!/bin/sh
    # Use multistage grep to find the display connector (VGA-1/eDP-1/etc)
    SCREEN=$(xrandr | grep 'connected' | grep -v 'disconnected' | grep -oE '[a-zA-Z]+[\-]+[^ ]')
        
    function Mice {
      for i in $(xinput list | grep -e "slave  pointer" | grep -Po 'id=\K[0-9]+') ; do
      	xinput set-prop "$i" "Coordinate Transformation Matrix" $MATRIX #1 0 0 0 1 0 0 0 1
      done
      }
        
    # Launch monitor-sensor - store output in a variable on tmpfs (RAM) to be parsed by the rest script
    #killall monitor-sensor
    monitor-sensor >> /dev/shm/sensor.log 2>&1 &
        
    # Parse output of monitor-sensor to get the new orientation whenever the log file is updated. Possibles are: normal, bottom-up, right-up, left-up. Light data will be ignored
    while inotifywait -e modify /dev/shm/sensor.log; do
      ORIENTATION=$(tail -n 1 /dev/shm/sensor.log | grep 'orientation' | grep -oE '[^ ]+$')  # Read the last line that was added to the file and get the orientation
      case "$ORIENTATION" in # Set the actions to be taken for each possible orientation
      normal)
        if [ ! -f /dev/shm/.rotation-lock ]; then
          xrandr --output $SCREEN --rotate normal
          MATRIX="1 0 0 0 1 0 0 0 1" ; Mice $?=$MATRIX;
        fi;;
      bottom-up)
        if [ ! -f /dev/shm/.rotation-lock ]; then
          xrandr --output $SCREEN --rotate inverted
          MATRIX="-1 0 1 0 -1 1 0 0 1" ; Mice $?=$MATRIX ;
        fi;;
      right-up)
        if [ ! -f /dev/shm/.rotation-lock ] ; then
          xrandr --output $SCREEN --rotate right
          MATRIX="0 1 0 -1 0 1 0 0 1" ; Mice $?=$MATRIX ;
        fi;;
      left-up)
        if [ ! -f /dev/shm/.rotation-lock ] ; then
          xrandr --output $SCREEN --rotate left
          MATRIX="0 -1 1 1 0 0 0 0 1" ; Mice $?=$MATRIX ;
        fi;;
      esac
    done    
    '';
  };

My preferred solution would be to link to an external file, maybe even a fetchFromGit(Hub?) (as Codeberg is a git repository).

1 Like

Try creating the script using Nixpkgs 23.05 manual | Nix & NixOS and add all of the utilities (xrandr,etc) as runtime inputs.

You probably want to package it. I wrote a post last summer that sketches out the main approaches and their merits:

I’ve tried creating writeScriptApplication but it keeps throwing errors;

pkgs.writeShellApplication = {
  	name = "autorotate-sam";
  	runtimeInputs = [ ];
  	text = ''
  	  #!/usr/bin/env sh
      # Use multistage grep to find the display connector (VGA-1/eDP-1/etc)
      SCREEN=$(xrandr | grep 'connected' | grep -v 'disconnected' | grep -oE '[a-zA-Z]+[\-]+[^ ]')
      
      function Mice {
      	for i in $(xinput list | grep -e "slave  pointer" | grep -Po 'id=\K[0-9]+') ; do
      		xinput set-prop "$i" "Coordinate Transformation Matrix" $MATRIX #1 0 0 0 1 0 0 0 1
      	done
      }
      
      # Launch monitor-sensor - store output in a variable on tmpfs (RAM) to be parsed by the rest script
      monitor-sensor >> /dev/shm/sensor.log 2>&1 &
      
      # Parse output of monitor-sensor to get the new orientation whenever the log file is updated. Possibles are: normal, bottom-up, right-up, left-up. Light data will be ignored
      while inotifywait -e modify /dev/shm/sensor.log; do
      	ORIENTATION=$(tail -n 1 /dev/shm/sensor.log | grep 'orientation' | grep -oE '[^ ]+$')  # Read the last line that was added to the file and get the orientation
      	case "$ORIENTATION" in # Set the actions to be taken for each possible orientation
      	normal)
      		if [ ! -f /dev/shm/.rotation-lock ]; then
      			xrandr --output $SCREEN --rotate normal
      			MATRIX="1 0 0 0 1 0 0 0 1"; Mice $?=$MATRIX;
      		fi;;
      	bottom-up)
      		if [ ! -f /dev/shm/.rotation-lock ]; then
      			xrandr --output $SCREEN --rotate inverted
      			MATRIX="-1 0 1 0 -1 1 0 0 1"; Mice $?=$MATRIX;
      		fi;;
      	right-up)
      		if [ ! -f /dev/shm/.rotation-lock ] ; then
      			xrandr --output $SCREEN --rotate right
      			MATRIX="0 1 0 -1 0 1 0 0 1"; Mice $?=$MATRIX;
      		fi;;
      	left-up)
      		if [ ! -f /dev/shm/.rotation-lock ] ; then
      			xrandr --output $SCREEN --rotate left
      			MATRIX="0 -1 1 1 0 0 0 0 1"; Mice $?=$MATRIX;
      		fi;;
      	esac
      done
    '';
    };

results in

sudo time nixos-rebuild switch
error: undefined variable 'xrandr'

       at /etc/nixos/configuration.nix:187:33:

          186|      name = "autorotate-sam";
          187|         runtimeInputs = with pkgs; [ xrandr grep xinput iio-sensor-proxy inotify-tools ];
             |                                 ^
          188|       text = ''
(use '--show-trace' to show detailed location information)
building Nix...

Whereas adding pkgs. in front of all the runtimeInputs results in this;

sudo time nixos-rebuild switch
error: attribute 'xrandr' missing

       at /etc/nixos/configuration.nix:187:22:

          186|       name = "autorotate-sam";
          187|         runtimeInputs = [ pkgs.xrandr pkgs.grep pkgs.xinput pkgs.iio-sensor-proxy pkgs.inotify-tools ];
             |                      ^
          188|    text = ''
       Did you mean one of arandr, lxrandr, oranda or srandrd?
(use '--show-trace' to show detailed location informat

Maybe this: Shell Scripts with Nix — ertt.ca will help you finding the dependencies?

There isn’t a 1-to-1 mapping between executable names and the top-level package namespace. For example, xrandr is pkgs.xorg.xrandr, and xinput will be the same way. grep will be pkgs.gnugrep.

1 Like