Add utils.readFile and utils.interpolateFile, use them in xmonad config

- Add utils.readFile which reads a file and evaluates any nix in ${{null}}
  brackets like that, returning a string. This should be a drop-in replacement
  for builtins.readFile
- Add utils.interpolateFile which does the same as readFile but also writes to
  the store and returns a store path for the new file. This should be a drop-in
  wrapper for a path
- Use utils.interpolateFile on the xmonad config file
- Use a relative file path contained in nix interpolation brackets in the xmonad
  config file
- Use package paths inside the included file (all included paths are also
  interpolated)
- Update xmonad to have better volume change support
- Update xmonad to have better multi-display support (actually start polybar,
  display different colors for second displays)
diff --git a/modules/xmonad/vol_change.py b/modules/xmonad/vol_change.py
new file mode 100644
index 0000000..6629995
--- /dev/null
+++ b/modules/xmonad/vol_change.py
@@ -0,0 +1,30 @@
+#!${{pkgs.python3}}/bin/python3
+
+import sys
+import os
+import subprocess
+
+args = sys.argv
+
+device_argument = "--default-source" if "-i" in args else ""
+
+control_argument = ""
+control_argument += "-i" if "-u" in args else ""
+control_argument += "-d" if "-d" in args else ""
+control_argument += "-t" if "-m" in args else " 5"
+
+os.system(
+    f"${{pkgs.pamixer}}/bin/pamixer {device_argument} {control_argument} --set-limit 150"
+)
+mute_char = (
+    "!"
+    if subprocess.getoutput(f"${{pkgs.pamixer}}/bin/pamixer {device_argument} --get-mute")
+    == "true"
+    else ""
+)
+volume = subprocess.getoutput(f"${{pkgs.pamixer}}/bin/pamixer {device_argument} --get-volume")
+
+socket_path = f"{os.environ['XDG_RUNTIME_DIR']}/xob.sock"
+
+with open(socket_path, "w") as socket:
+    socket.write(f"{volume}{mute_char}\n")