about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.editorconfig20
-rw-r--r--.gitignore2
-rw-r--r--.gitlab-ci.yml27
-rw-r--r--default.nix6
-rw-r--r--flake.lock57
-rw-r--r--flake.nix126
-rw-r--r--package.yaml10
-rwxr-xr-xscripts/nsp-console.sh7
-rwxr-xr-xscripts/toggle-compton.sh7
-rwxr-xr-xscripts/toggle-redshift.sh8
-rwxr-xr-xscripts/toggle-touchpad.sh10
-rwxr-xr-xscripts/toggle-trackpoint.sh10
-rwxr-xr-xscripts/xmobar/fcitx.sh13
-rwxr-xr-xscripts/xshot-select-upload.sh7
-rwxr-xr-xscripts/xshot-select.sh5
-rwxr-xr-xscripts/xshot-upload.sh7
-rwxr-xr-xscripts/xshot.sh5
-rw-r--r--shell.nix6
-rw-r--r--src/exe/Main.hs8
-rw-r--r--src/lib/XMonad/Custom/Bindings.hs159
-rw-r--r--src/lib/XMonad/Custom/Config.hs35
-rw-r--r--src/lib/XMonad/Custom/Event.hs22
-rw-r--r--src/lib/XMonad/Custom/Layout.hs54
-rw-r--r--src/lib/XMonad/Custom/Log.hs78
-rw-r--r--src/lib/XMonad/Custom/Manage.hs20
-rw-r--r--src/lib/XMonad/Custom/Misc.hs21
-rw-r--r--src/lib/XMonad/Custom/Navigation.hs4
-rw-r--r--src/lib/XMonad/Custom/Projects.hs14
-rw-r--r--src/lib/XMonad/Custom/Prompt.hs4
-rw-r--r--src/lib/XMonad/Custom/Scratchpads.hs16
-rw-r--r--src/lib/XMonad/Custom/Startup.hs52
-rw-r--r--src/lib/XMonad/Custom/Theme.hs4
-rw-r--r--src/lib/XMonad/Custom/Workspaces.hs15
-rw-r--r--stack.yaml2
-rw-r--r--stack.yaml.lock16
-rw-r--r--treefmt.toml24
-rw-r--r--xmonad-ng.cabal20
37 files changed, 240 insertions, 661 deletions
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..a4a2eed
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,20 @@
+[*]
+charset = utf-8
+end_of_line = lf
+indent_size = 4
+indent_style = space
+insert_final_newline = true
+max_line_length = 80
+trim_trailing_whitespace = true
+
+[*.nix]
+indent_size = 2
+indent_style = space
+
+[*.hs]
+indent_size = 2
+indent_style = space
+
+[*.{yaml,yml}]
+indent_size = 2
+indent_style = space
diff --git a/.gitignore b/.gitignore
index 39c8a93..f564999 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,6 @@
 .direnv/
-.pre-commit-config.yaml
 .stack-work/
 cabal.project.local
 dist-newstyle/
 result
+state/
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 2242e13..2626dd7 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,19 +1,16 @@
 ---
-image: nixpkgs/nix-flakes:nixos-21.11
-
-before_script:
-  - nix --version
-  - nix flake metadata
+image: nixpkgs/nix:nixos-22.05
 
 stages:
   - info
   - check
-  - cachix
+  - publish
 
 info:
   stage: info
   script:
-    - env
+    - nix --version
+    - nix flake metadata
     - nix show-config
     - nix show-derivation
 
@@ -21,19 +18,11 @@ check:
   stage: check
   script:
     - nix flake check --show-trace
-  allow_failure: true
 
-cachix:
-  stage: cachix
+publish:
+  stage: publish
   script:
     - set -o pipefail
     - nix build --print-build-logs --show-trace --json |
-      nix shell nixpkgs#jq
-      --command jq -r '.[].outputs | to_entries[].value' |
-      nix shell nixpkgs#cachix
-      --command cachix push $CACHIX_CACHE_NAME
-  artifacts:
-    paths:
-      - result
-    expire_in: 1 week
-    when: on_success
+      nix run nixpkgs#jq -- -r '.[].outputs | to_entries[].value' |
+      nix run nixpkgs#cachix -- push $CACHIX_CACHE_NAME
diff --git a/default.nix b/default.nix
deleted file mode 100644
index 80aeb43..0000000
--- a/default.nix
+++ /dev/null
@@ -1,6 +0,0 @@
-(import (let lock = builtins.fromJSON (builtins.readFile ./flake.lock);
-in fetchTarball {
-  url =
-    "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
-  sha256 = lock.nodes.flake-compat.locked.narHash;
-}) { src = ./.; }).defaultNix
diff --git a/flake.lock b/flake.lock
index a3610e9..1591d5d 100644
--- a/flake.lock
+++ b/flake.lock
@@ -1,29 +1,12 @@
 {
   "nodes": {
-    "flake-compat": {
-      "flake": false,
-      "locked": {
-        "lastModified": 1641205782,
-        "narHash": "sha256-4jY7RCWUoZ9cKD8co0/4tFARpWB+57+r1bLLvXNJliY=",
-        "owner": "edolstra",
-        "repo": "flake-compat",
-        "rev": "b7547d3eed6f32d06102ead8991ec52ab0a4f1a7",
-        "type": "github"
-      },
-      "original": {
-        "owner": "edolstra",
-        "ref": "master",
-        "repo": "flake-compat",
-        "type": "github"
-      }
-    },
     "flake-utils": {
       "locked": {
-        "lastModified": 1644229661,
-        "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=",
+        "lastModified": 1659877975,
+        "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
         "owner": "numtide",
         "repo": "flake-utils",
-        "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797",
+        "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
         "type": "github"
       },
       "original": {
@@ -35,11 +18,11 @@
     },
     "nixpkgs": {
       "locked": {
-        "lastModified": 1645013224,
-        "narHash": "sha256-b7OEC8vwzJv3rsz9pwnTX2LQDkeOWz2DbKypkVvNHXc=",
+        "lastModified": 1660551188,
+        "narHash": "sha256-a1LARMMYQ8DPx1BgoI/UN4bXe12hhZkCNqdxNi6uS0g=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "b66b39216b1fef2d8c33cc7a5c72d8da80b79970",
+        "rev": "441dc5d512153039f19ef198e662e4f3dbb9fd65",
         "type": "github"
       },
       "original": {
@@ -49,36 +32,10 @@
         "type": "github"
       }
     },
-    "pre-commit-hooks": {
-      "inputs": {
-        "flake-utils": [
-          "flake-utils"
-        ],
-        "nixpkgs": [
-          "nixpkgs"
-        ]
-      },
-      "locked": {
-        "lastModified": 1639823344,
-        "narHash": "sha256-jlsQb2y6A5dB1R0wVPLOfDGM0wLyfYqEJNzMtXuzCXw=",
-        "owner": "cachix",
-        "repo": "pre-commit-hooks.nix",
-        "rev": "ff9c0b459ddc4b79c06e19d44251daa8e9cd1746",
-        "type": "github"
-      },
-      "original": {
-        "owner": "cachix",
-        "ref": "master",
-        "repo": "pre-commit-hooks.nix",
-        "type": "github"
-      }
-    },
     "root": {
       "inputs": {
-        "flake-compat": "flake-compat",
         "flake-utils": "flake-utils",
-        "nixpkgs": "nixpkgs",
-        "pre-commit-hooks": "pre-commit-hooks"
+        "nixpkgs": "nixpkgs"
       }
     }
   },
diff --git a/flake.nix b/flake.nix
index 38edac0..c3561cd 100644
--- a/flake.nix
+++ b/flake.nix
@@ -16,98 +16,58 @@
       ref = "master";
       inputs.nixpkgs.follows = "nixpkgs";
     };
-
-    flake-compat = {
-      type = "github";
-      owner = "edolstra";
-      repo = "flake-compat";
-      ref = "master";
-      flake = false;
-    };
-
-    pre-commit-hooks = {
-      type = "github";
-      owner = "cachix";
-      repo = "pre-commit-hooks.nix";
-      ref = "master";
-      inputs = {
-        nixpkgs.follows = "nixpkgs";
-        flake-utils.follows = "flake-utils";
-      };
-    };
   };
 
   outputs = inputs:
-    with inputs;
-    let name = "xmonad-ng";
-    in flake-utils.lib.eachSystem [ "x86_64-linux" ] (system:
-      let
-        pkgs = import nixpkgs {
-          inherit system;
-          inputs = null;
-          nixpkgs = nixpkgs.legacyPackages.${system};
-        };
+    with inputs; let
+      name = "xmonad-ng";
+    in
+      flake-utils.lib.eachSystem ["x86_64-linux"] (system: let
+        pkgs = import nixpkgs {inherit system;};
 
-        package = { returnShellEnv ? false }:
-          with pkgs;
-          haskellPackages.developPackage {
-            inherit name returnShellEnv;
-            root = ./.;
-            overrides = _: _:
-              with haskellPackages; {
-                xmonad = xmonad_0_17_0;
-                xmonad-contrib = xmonad-contrib_0_17_0;
-              };
-            modifier = drv:
-              haskell.lib.addBuildTools drv (with haskellPackages; [
-                brittany
-                cabal-install
-                haskell-language-server
-                hlint
-                hpack
-                stack
-              ]);
+        haskellPackages = pkgs.haskellPackages.override {
+          overrides = _: super: {
+            ${name} = with pkgs.haskell.lib;
+              justStaticExecutables (
+                failOnAllWarnings (
+                  disableExecutableProfiling (
+                    disableLibraryProfiling (
+                      (pkgs.haskellPackages.developPackage {
+                        inherit name;
+                        root = inputs.self;
+                      })
+                      .overrideAttrs (_: _: {
+                        postInstall = ''
+                          rm -rf $out/share
+                        '';
+                      })
+                    )
+                  )
+                )
+              );
           };
+        };
       in {
-        packages.${name} = package { };
-        defaultPackage = self.packages.${system}.${name};
+        packages.default = haskellPackages.${name};
 
-        checks.preCommit = pre-commit-hooks.lib.${system}.run {
-          src = ./.;
-          hooks = {
-            nix-linter.enable = true;
-            nixfmt.enable = true;
-            hpack.enable = true;
-            hlint.enable = true;
-            yamllint.enable = true;
-            brittany.enable = true;
-            shellcheck.enable = true;
-            shfmt = {
-              enable = true;
-              name = "shfmt";
-              entry = "${pkgs.shfmt}/bin/shfmt -s -w";
-              types = [ "shell" ];
-            };
-            prettier = {
-              enable = true;
-              types = [ ];
-              files = "\\.((yaml)|\\d)$";
-            };
+        devShells.default = with haskellPackages;
+          shellFor {
+            nativeBuildInputs = [
+              brittany
+              cabal-install
+              haskell-language-server
+              hpack
+              stack
+            ];
+            packages = p: [p.${name}];
           };
-        };
 
-        devShells = {
-          ${name} = package { returnShellEnv = true; };
-          preCommit = pkgs.mkShell {
-            inherit (self.checks.${system}.preCommit) shellHook;
-          };
+        formatter = pkgs.alejandra;
+      })
+      // {
+        overlays.default = final: prev: {
+          # TODO Figure out how to generalise the system here.
+          ${name} = packages.default."x86_64-linux";
         };
-        devShell = self.devShells.${system}.${name};
-      }) // {
-        # FIXME This exposes an attribute set of "system.package" thus making
-        # importing this package from the overlay to look like this
-        # "pkgs.xmonad-ng.${system}" which is fucking stupid. I have to fix that
-        # somehow.
-        overlay = _: _: { ${name} = self.defaultPackage; };
       };
 }
diff --git a/package.yaml b/package.yaml
index 30a47f9..445f7d5 100644
--- a/package.yaml
+++ b/package.yaml
@@ -1,15 +1,13 @@
 ---
 name: xmonad-ng
-version: 2.0.1.0
+version: 2.1.0.0
 synopsis: Personal XMonad configuration
 description: I hope no one will read this description. It's awful.
 category: System
-author: Azat Bahawi <azahi@teknik.io>
-copyright: (c) Azat Bahawi 2018-2021
+author: Azat Bahawi <azat@bahawi.net>
+copyright: (c) Azat Bahawi 2018-2022
 license: GPL-3.0-or-later
 
-github: azahi/xmonad-ng
-
 ghc-options:
   - -Wall
   - -Wcompat
@@ -19,7 +17,7 @@ ghc-options:
 
 dependencies:
   - base == 4.*
-  - flow == 1.0.*
+  - flow == 2.0.*
   - xmonad == 0.17.*
   - xmonad-contrib == 0.17.*
 
diff --git a/scripts/nsp-console.sh b/scripts/nsp-console.sh
deleted file mode 100755
index 4ac9e32..0000000
--- a/scripts/nsp-console.sh
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/bin/sh
-
-if tmux list-sessions | grep "scratchpad"; then
-	tmux attach-session -t "scratchpad"
-else
-	tmux new-session -s "scratchpad" -n "scratchpad" -c "$HOME"
-fi
diff --git a/scripts/toggle-compton.sh b/scripts/toggle-compton.sh
deleted file mode 100755
index 0fcb1bf..0000000
--- a/scripts/toggle-compton.sh
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/bin/sh
-
-if ! pgrep compton >/dev/null 2>&1; then
-	compton -b
-else
-	pkill compton
-fi
diff --git a/scripts/toggle-redshift.sh b/scripts/toggle-redshift.sh
deleted file mode 100755
index 2af8258..0000000
--- a/scripts/toggle-redshift.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/usr/bin/env bash
-
-if ! pgrep redshift >/dev/null 2>&1; then
-	redshift &
-	disown redshift
-else
-	pkill redshift
-fi
diff --git a/scripts/toggle-touchpad.sh b/scripts/toggle-touchpad.sh
deleted file mode 100755
index 2a1c061..0000000
--- a/scripts/toggle-touchpad.sh
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/sh
-
-ID=$(xinput list | grep -Eo 'TouchPad\s*id\=[0-9]{1,2}' | grep -Eo '[0-9]{1,2}')
-STATE=$(xinput list-props "$ID" | awk '/Device Enabled/ {print $4}')
-
-if [ "$STATE" = 1 ]; then
-	xinput disable "$ID"
-else
-	xinput enable "$ID"
-fi
diff --git a/scripts/toggle-trackpoint.sh b/scripts/toggle-trackpoint.sh
deleted file mode 100755
index d385553..0000000
--- a/scripts/toggle-trackpoint.sh
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/sh
-
-ID=$(xinput list | grep -Eo 'TrackPoint\s*id\=[0-9]{1,2}' | grep -Eo '[0-9]{1,2}')
-STATE=$(xinput list-props "$ID" | awk '/Device Enabled/ {print $4}')
-
-if [ "$STATE" = 1 ]; then
-	xinput disable "$ID"
-else
-	xinput enable "$ID"
-fi
diff --git a/scripts/xmobar/fcitx.sh b/scripts/xmobar/fcitx.sh
deleted file mode 100755
index f159c41..0000000
--- a/scripts/xmobar/fcitx.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/sh
-
-STATUS="$(fcitx-remote)"
-
-if [ "$STATUS" = 0 ]; then
-	OUT="Off"
-elif [ "$STATUS" = 1 ]; then
-	OUT="Disabled"
-else
-	OUT="Enabled"
-fi
-
-echo "$OUT"
diff --git a/scripts/xshot-select-upload.sh b/scripts/xshot-select-upload.sh
deleted file mode 100755
index 70c08c4..0000000
--- a/scripts/xshot-select-upload.sh
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/bin/sh
-
-PIC="$HOME/pictures/screenshots/$(date +%Y-%m-%d_%H-%M-%S).png"
-
-maim --format=png --hidecursor --quality 8 --select "$PIC" &&
-	curl --form "file=@$PIC" "https://0x0.st" |
-	xclip -quiet
diff --git a/scripts/xshot-select.sh b/scripts/xshot-select.sh
deleted file mode 100755
index a0913a5..0000000
--- a/scripts/xshot-select.sh
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/sh
-
-PIC="$HOME/pictures/screenshots/$(date +%Y-%m-%d_%H-%M-%S).png"
-
-maim --format=png --hidecursor --quality 8 --select "$PIC"
diff --git a/scripts/xshot-upload.sh b/scripts/xshot-upload.sh
deleted file mode 100755
index 17b614a..0000000
--- a/scripts/xshot-upload.sh
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/bin/sh
-
-PIC="$HOME/pictures/screenshots/$(date +%Y-%m-%d_%H-%M-%S).png"
-
-maim --format=png --hidecursor --quality 8 "$PIC" &&
-	curl --form "file=@$PIC" "https://0x0.st" |
-	xclip -quiet
diff --git a/scripts/xshot.sh b/scripts/xshot.sh
deleted file mode 100755
index 046315d..0000000
--- a/scripts/xshot.sh
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/sh
-
-PIC="$HOME/pictures/screenshots/$(date +%Y-%m-%d_%H-%M-%S).png"
-
-maim --format=png --hidecursor --quality 8 "$PIC"
diff --git a/shell.nix b/shell.nix
deleted file mode 100644
index fa2a56c..0000000
--- a/shell.nix
+++ /dev/null
@@ -1,6 +0,0 @@
-(import (let lock = builtins.fromJSON (builtins.readFile ./flake.lock);
-in fetchTarball {
-  url =
-    "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
-  sha256 = lock.nodes.flake-compat.locked.narHash;
-}) { src = ./.; }).shellNix
diff --git a/src/exe/Main.hs b/src/exe/Main.hs
index 7b08f2a..f64c3c5 100644
--- a/src/exe/Main.hs
+++ b/src/exe/Main.hs
@@ -3,15 +3,15 @@
 -- Description             : Application entrypoint
 -- Copyright               : (c) Azat Bahawi 2018-2021
 -- SPDX-License-Identifier : GPL-3.0-or-later
--- Maintainer              : azahi@teknik.io
+-- Maintainer              : azat@bahawi.net
 -- Stability               : experimental
 -- Portability             : non-portable
 --
 
 module Main where
 
-import           XMonad
-import           XMonad.Custom.Config
+import           XMonad                         ( xmonad )
+import           XMonad.Custom.Config           ( ngConfig )
 
 main :: IO ()
-main = myConfig >>= xmonad
+main = ngConfig >>= xmonad
diff --git a/src/lib/XMonad/Custom/Bindings.hs b/src/lib/XMonad/Custom/Bindings.hs
index 208ccdf..e9498ca 100644
--- a/src/lib/XMonad/Custom/Bindings.hs
+++ b/src/lib/XMonad/Custom/Bindings.hs
@@ -1,28 +1,24 @@
-{-# LANGUAGE LambdaCase #-}
+{-# OPTIONS_GHC -Wno-name-shadowing #-}
 
 -- |
 -- Module                  : XMonad.Custom.Bindings
 -- Description             : Key bindings and keys configuration
--- Copyright               : (c) Azat Bahawi 2018-2021
+-- Copyright               : (c) Azat Bahawi 2018-2022
 -- SPDX-License-Identifier : GPL-3.0-or-later
--- Maintainer              : azahi@teknik.io
+-- Maintainer              : azat@bahawi.net
 -- Stability               : experimental
 -- Portability             : non-portable
 --
 
 module XMonad.Custom.Bindings
-  ( keys
-  , rawKeys
-  , modMask
-  , mouseBindings
+  ( ngKeys
+  , ngModMask
+  , ngMouseBindings
   ) where
 
 import qualified Data.Map                      as M
 import           System.Exit
-import           XMonad                  hiding ( keys
-                                                , modMask
-                                                , mouseBindings
-                                                )
+import           XMonad
 import           XMonad.Actions.CopyWindow
 import           XMonad.Actions.CycleWS
 import           XMonad.Actions.DynamicProjects
@@ -35,16 +31,12 @@ import           XMonad.Actions.Navigation2D
 import           XMonad.Actions.Promote
 import           XMonad.Actions.UpdatePointer
 import           XMonad.Actions.WithAll
-import           XMonad.Custom.Layout
 import qualified XMonad.Custom.Misc            as C
 import           XMonad.Custom.Scratchpads
 import           XMonad.Custom.Theme
 import           XMonad.Hooks.UrgencyHook
 import           XMonad.Layout.BinarySpacePartition
 import           XMonad.Layout.Hidden
-import           XMonad.Layout.MultiToggle
-import           XMonad.Layout.MultiToggle.Instances
-import           XMonad.Layout.Reflect
 import           XMonad.Layout.ResizableTile
 import           XMonad.Layout.SubLayouts
 import           XMonad.Prompt.ConfirmPrompt
@@ -54,18 +46,30 @@ import           XMonad.Prompt.Workspace
 import qualified XMonad.StackSet               as S
 import           XMonad.Util.EZConfig
 import           XMonad.Util.NamedScratchpad
-import           XMonad.Util.WorkspaceCompare
 
-modMask :: KeyMask
-modMask = mod4Mask
+ngModMask :: KeyMask
+ngModMask = mod4Mask
 
-directions :: [Direction2D]
-directions = [D, U, L, R]
+ngKeys :: XConfig Layout -> M.Map (KeyMask, KeySym) (X ())
+ngKeys c = mkKeymap c (rawKeys c)
 
-arrowKeys, directionKeys, wsKeys :: [String]
-arrowKeys = ["<D>", "<U>", "<L>", "<R>"]
-directionKeys = ["j", "k", "h", "l"]
-wsKeys = map show [1 .. 9 :: Int]
+ngMouseBindings :: XConfig Layout -> M.Map (KeyMask, Button) (Window -> X ())
+ngMouseBindings XConfig { XMonad.modMask = ngModMask } = M.fromList
+  [ ( (ngModMask, button1)
+    , \w ->
+      focus w
+        >> F.mouseWindow F.position w
+        >> ifClick (snapMagicMove (Just 50) (Just 50) w)
+        >> windows S.shiftMaster
+    )
+  , ( (ngModMask, button3)
+    , \w ->
+      focus w
+        >> F.mouseWindow F.linear w
+        >> ifClick (snapMagicResize [L, R, U, D] (Just 50) (Just 50) w)
+        >> windows S.shiftMaster
+    )
+  ]
 
 zipKeys :: [a] -> [[a]] -> [t1] -> (t1 -> b) -> [([a], b)]
 zipKeys m ks as f = zipWith (\k d -> (m ++ k, f d)) ks as
@@ -73,42 +77,6 @@ zipKeys m ks as f = zipWith (\k d -> (m ++ k, f d)) ks as
 zipKeys' :: [a] -> [[a]] -> [t1] -> (t1 -> t2 -> b) -> t2 -> [([a], b)]
 zipKeys' m ks as f b = zipWith (\k d -> (m ++ k, f d b)) ks as
 
-tryMessageR_ :: (Message a, Message b) => a -> b -> X ()
-tryMessageR_ x y = sequence_ [tryMessageWithNoRefreshToCurrent x y, refresh]
-
-toggleCopyToAll :: X ()
-toggleCopyToAll = wsContainingCopies >>= \case
-  [] -> windows copyToAll
-  _  -> killAllOtherCopies
-
-getSortByIndexNonSP :: X ([WindowSpace] -> [WindowSpace])
-getSortByIndexNonSP = (. namedScratchpadFilterOutWorkspace) <$> getSortByIndex
-
-nextNonEmptyWS, prevNonEmptyWS :: X ()
-nextNonEmptyWS = findWorkspace getSortByIndexNonSP Next HiddenNonEmptyWS 1
-  >>= \t -> windows . S.view $ t
-prevNonEmptyWS = findWorkspace getSortByIndexNonSP Prev HiddenNonEmptyWS 1
-  >>= \t -> windows . S.view $ t
-
-toggleFloat :: Window -> X ()
-toggleFloat w = windows
-  (\s -> if M.member w (S.floating s)
-    then S.sink w s
-    else S.float
-      w
-      (S.RationalRect (1 / 2 - 1 / 4) (1 / 2 - 1 / 4) (1 / 2) (1 / 2))
-      s
-  )
-
-withUpdatePointer :: [(String, X ())] -> [(String, X ())]
-withUpdatePointer = map addAction
- where
-  addAction :: (String, X ()) -> (String, X ())
-  addAction (key, action) = (key, action >> updatePointer (0.98, 0.01) (0, 0))
-
-keys :: XConfig Layout -> M.Map (KeyMask, KeySym) (X ())
-keys c = mkKeymap c (rawKeys c)
-
 rawKeys :: XConfig Layout -> [(String, X ())]
 rawKeys c = withUpdatePointer $ concatMap ($ c) keymaps
  where
@@ -122,32 +90,25 @@ rawKeys c = withUpdatePointer $ concatMap ($ c) keymaps
     , keysLayout
     , keysResize
     ]
+  withUpdatePointer :: [(String, X ())] -> [(String, X ())]
+  withUpdatePointer = map addAction
+   where
+    addAction :: (String, X ()) -> (String, X ())
+    addAction (key, action) =
+      (key, action >> updatePointer (0.98, 0.01) (0, 0))
 
 keysBase :: XConfig Layout -> [(String, X ())]
 keysBase _ =
-  [ ("M-S-q", confirmPrompt hotPromptTheme "Quit XMonad?" $ io exitSuccess)
-  , ("M-q"  , spawn "xmonad --restart")
-  , -- TODO Replace with interal calls
-    ("M-C-q", spawn "xmonad --recompile && xmonad --restart")
+  [ ("M-S-q", confirmPrompt hotPromptTheme "Quit?" $ io exitSuccess)
   , ("M-x"  , shellPrompt promptTheme)
   , ("M-w"  , windowPrompt promptTheme Goto allWindows)
   , ("M-S-w", windowPrompt promptTheme Bring allWindows)
   ]
 
 keysSystem :: XConfig Layout -> [(String, X ())]
-keysSystem _ =
-  [ ("M-C-g"            , return ())
-  , -- TODO Replace scripts with internal functions
-    ("<XF86ScreenSaver>", spawn "~/.xmonad/scripts/screenlock.sh")
-  , ("M-<Print>", spawn "~/.xmonad/scripts/xshot-upload.sh")
-  , ("M-S-<Print>", spawn "~/.xmonad/scripts/xshot-select-upload.sh")
-  , ("M-C-c", spawn "~/.xmonad/scripts/toggle-compton.sh")
-  , ("M-C-r", spawn "~/.xmonad/scripts/toggle-redshift.sh")
-  , ("M-C-p", spawn "~/.xmonad/scripts/toggle-touchpad.sh")
-  , ("M-C-t", spawn "~/.xmonad/scripts/toggle-trackpoint.sh")
-  ]
+keysSystem _ = [("M-C-g", return ())]
 
-keysMedia :: XConfig Layout -> [(String, X ())] -- TODO Make audio keys compatible with ALSA/PA at the same time
+keysMedia :: XConfig Layout -> [(String, X ())]
 keysMedia _ =
   [ ("<XF86AudioMicMute>", spawn "pactl set-source-mute 1 toggle")
   , ("<XF86AudioMute>"   , spawn "pactl set-sink-mute 0 toggle")
@@ -167,19 +128,17 @@ keysWorkspaces :: XConfig Layout -> [(String, X ())]
 keysWorkspaces _ =
   [ ("M-S-o", switchProjectPrompt promptTheme)
     , ("M-S-p", shiftToProjectPrompt promptTheme)
-    , ("M-,"  , nextNonEmptyWS)
-    , ("M-."  , prevNonEmptyWS)
     , ("M-i"  , toggleWS' ["NSP"])
-    , ("M-n", workspacePrompt promptTheme $ windows . S.shift)
+    , ("M-n"  , workspacePrompt promptTheme $ windows . S.shift)
     ]
     ++ zipKeys "M-"     wsKeys [0 ..] (withNthWorkspace S.greedyView)
     ++ zipKeys "M-S-"   wsKeys [0 ..] (withNthWorkspace S.shift)
     ++ zipKeys "M-C-S-" wsKeys [0 ..] (withNthWorkspace copy)
+  where wsKeys = map show [1 .. 9 :: Int]
 
 keysSpawnables :: XConfig Layout -> [(String, X ())]
 keysSpawnables _ =
   [ ("M-<Return>", spawn (C.term C.applications))
-  , ("M-b"       , spawn (C.browser C.applications))
   , ("M-c"       , namedScratchpadAction scratchpads "console")
   , ("M-m"       , namedScratchpadAction scratchpads "music")
   , ("M-t"       , namedScratchpadAction scratchpads "top")
@@ -190,7 +149,6 @@ keysWindows :: XConfig Layout -> [(String, X ())]
 keysWindows _ =
   [ ("M-d"  , kill)
     , ("M-S-d", confirmPrompt hotPromptTheme "Kill all" killAll)
-    , ("M-a"  , toggleCopyToAll)
     , ("M-e"  , withFocused hideWindow)
     , ("M-S-e", popOldestHiddenWindow)
     , ("M-p"  , promote)
@@ -201,28 +159,24 @@ keysWindows _ =
     , ("M-S-'", windows S.swapDown)
     , ("M-S-;", windows S.swapUp)
     ]
-    ++ zipKeys' "M-"   directionKeys directions windowGo   True -- TODO W moving
-    ++ zipKeys' "M-S-" directionKeys directions windowSwap True
-    ++ zipKeys "M-C-" directionKeys directions (sendMessage . pullGroup)
+    ++ zipKeys' "M-"   vimKeys directions windowGo   True -- TODO W moving
+    ++ zipKeys' "M-S-" vimKeys directions windowSwap True
+    ++ zipKeys "M-C-" vimKeys directions (sendMessage . pullGroup)
     ++ zipKeys' "M-"   arrowKeys directions screenGo       True
     ++ zipKeys' "M-S-" arrowKeys directions windowToScreen True
     ++ zipKeys' "M-C-" arrowKeys directions screenSwap     True
+ where
+  directions = [D, U, L, R]
+  arrowKeys  = ["<D>", "<U>", "<L>", "<R>"]
+  vimKeys    = ["j", "k", "h", "l"]
 
 keysLayout :: XConfig Layout -> [(String, X ())]
 keysLayout c =
   [ ("M-<Tab>"  , sendMessage NextLayout)
   , ("M-C-<Tab>", toSubl NextLayout)
   , ("M-S-<Tab>", setLayout $ XMonad.layoutHook c)
-  , ("M-o"      , withFocused toggleFloat)
-  , ("M-S-o"    , sinkAll)
   , ("M-S-,"    , sendMessage $ IncMasterN (-1))
   , ("M-S-."    , sendMessage $ IncMasterN 1)
-  , ("M-r"      , tryMessageR_ Rotate (Toggle REFLECTX))
-  , ("M-S-r"    , sendMessage $ Toggle REFLECTX)
-  , ( "M-f"
-    , sequence_ [withFocused $ windows . S.sink, sendMessage $ Toggle NBFULL]
-    )
-  , ("M-C-g", sendMessage $ Toggle GAPS) -- FIXME Breaks merged tabbed layout
   ]
 
 keysResize :: XConfig Layout -> [(String, X ())]
@@ -236,21 +190,6 @@ keysResize _ =
   , ("M-S-C-[", tryMessageR_ (ShrinkFrom D) MirrorShrink)
   , ("M-S-C-]", tryMessageR_ (ShrinkFrom U) MirrorExpand)
   ]
-
-mouseBindings :: XConfig Layout -> M.Map (KeyMask, Button) (Window -> X ())
-mouseBindings XConfig{} = M.fromList
-  [ ( (modMask, button1)
-    , \w ->
-      focus w
-        >> F.mouseWindow F.position w
-        >> ifClick (snapMagicMove (Just 50) (Just 50) w)
-        >> windows S.shiftMaster
-    )
-  , ( (modMask, button3)
-    , \w ->
-      focus w
-        >> F.mouseWindow F.linear w
-        >> ifClick (snapMagicResize [L, R, U, D] (Just 50) (Just 50) w)
-        >> windows S.shiftMaster
-    )
-  ]
+ where
+  tryMessageR_ :: (Message a, Message b) => a -> b -> X ()
+  tryMessageR_ x y = sequence_ [tryMessageWithNoRefreshToCurrent x y, refresh]
diff --git a/src/lib/XMonad/Custom/Config.hs b/src/lib/XMonad/Custom/Config.hs
index 4a4af2d..2936363 100644
--- a/src/lib/XMonad/Custom/Config.hs
+++ b/src/lib/XMonad/Custom/Config.hs
@@ -3,20 +3,20 @@
 -- |
 -- Module                  : XMonad.Custom.Config
 -- Description             : Configuration entrypoint to be passed to executable
--- Copyright               : (c) Azat Bahawi 2018-2021
+-- Copyright               : (c) Azat Bahawi 2018-2022
 -- SPDX-License-Identifier : GPL-3.0-or-later
--- Maintainer              : azahi@teknik.io
+-- Maintainer              : azat@bahawi.net
 -- Stability               : experimental
 -- Portability             : non-portable
 --
 
 module XMonad.Custom.Config
-  ( myConfig
+  ( ngConfig
   ) where
 
 import           Flow
 import           XMonad
-import           XMonad.Actions.Navigation2D
+import           XMonad.Actions.Navigation2D    ( withNavigation2DConfig )
 import qualified XMonad.Custom.Bindings        as C
 import qualified XMonad.Custom.Event           as C
 import qualified XMonad.Custom.Layout          as C
@@ -25,24 +25,29 @@ import qualified XMonad.Custom.Misc            as C
 import qualified XMonad.Custom.Navigation      as C
 import qualified XMonad.Custom.Theme           as C
 import qualified XMonad.Custom.Workspaces      as C
-import           XMonad.Hooks.EwmhDesktops
-import           XMonad.Hooks.ManageDocks
-import           XMonad.Hooks.UrgencyHook
+import           XMonad.Hooks.EwmhDesktops      ( ewmh
+                                                , ewmhFullscreen
+                                                )
+import           XMonad.Hooks.ManageDocks       ( docks )
+import           XMonad.Hooks.UrgencyHook       ( borderUrgencyHook
+                                                , withUrgencyHook
+                                                )
 import           XMonad.Layout.IndependentScreens
+                                                ( countScreens )
 
-myConfig = do
+ngConfig = do
   screens <- countScreens
   def { borderWidth        = C.border
-      , workspaces         = C.myWorkspaces screens
-      , layoutHook         = C.layoutHook
+      , workspaces         = C.ngWorkspaces screens
+      , layoutHook         = C.ngLayoutHook
       , terminal           = C.term C.applications
       , normalBorderColor  = C.colorN
       , focusedBorderColor = C.colorF
-      , modMask            = C.modMask
-      , keys               = C.keys
-      , mouseBindings      = C.mouseBindings
-      , manageHook         = C.manageHook
-      , handleEventHook    = C.handleEventHook
+      , modMask            = C.ngModMask
+      , keys               = C.ngKeys
+      , mouseBindings      = C.ngMouseBindings
+      , manageHook         = C.ngManageHook
+      , handleEventHook    = C.ngHandleEventHook
       , focusFollowsMouse  = False
       , clickJustFocuses   = False
       }
diff --git a/src/lib/XMonad/Custom/Event.hs b/src/lib/XMonad/Custom/Event.hs
index 9ff2552..4e5a598 100644
--- a/src/lib/XMonad/Custom/Event.hs
+++ b/src/lib/XMonad/Custom/Event.hs
@@ -1,24 +1,24 @@
 -- |
 -- Module                  : XMonad.Custom.Event
 -- Description             : Event hooks and stuff
--- Copyright               : (c) Azat Bahawi 2018-2021
+-- Copyright               : (c) Azat Bahawi 2018-2022
 -- SPDX-License-Identifier : GPL-3.0-or-later
--- Maintainer              : azahi@teknik.io
+-- Maintainer              : azat@bahawi.net
 -- Stability               : experimental
 -- Portability             : non-portable
 --
 
 module XMonad.Custom.Event
-  ( handleEventHook
+  ( ngHandleEventHook
   ) where
 
-import           Data.Monoid
-import           XMonad                  hiding ( handleEventHook )
-import           XMonad.Custom.Scratchpads
-import           XMonad.Hooks.EwmhDesktops
-import           XMonad.Hooks.ManageDocks
+import           Data.Monoid                    ( All )
+import           XMonad                         ( Event
+                                                , X
+                                                )
+import           XMonad.Custom.Scratchpads      ( scratchpads )
 import           XMonad.Util.Loggers.NamedScratchpad
+                                                ( nspTrackHook )
 
-handleEventHook :: Event -> X All
-handleEventHook =
-  mconcat [nspTrackHook scratchpads, docksEventHook, fullscreenEventHook]
+ngHandleEventHook :: Event -> X All
+ngHandleEventHook = mconcat [nspTrackHook scratchpads]
diff --git a/src/lib/XMonad/Custom/Layout.hs b/src/lib/XMonad/Custom/Layout.hs
index 8ed7d08..0ca3761 100644
--- a/src/lib/XMonad/Custom/Layout.hs
+++ b/src/lib/XMonad/Custom/Layout.hs
@@ -1,60 +1,22 @@
-{-# LANGUAGE DeriveDataTypeable #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE TypeSynonymInstances #-}
 {-# OPTIONS_GHC -Wno-missing-signatures #-}
 
 -- |
 -- Module                  : XMonad.Custom.Layout
 -- Description             : Layouts and such
--- Copyright               : (c) Azat Bahawi 2018-2021
+-- Copyright               : (c) Azat Bahawi 2018-2022
 -- SPDX-License-Identifier : GPL-3.0-or-later
--- Maintainer              : azahi@teknik.io
+-- Maintainer              : azat@bahawi.net
 -- Stability               : experimental
 -- Portability             : non-portable
 --
 
 module XMonad.Custom.Layout
-  ( layoutHook
-  , CustomTransformers(..)
+  ( ngLayoutHook
   ) where
 
-import           XMonad                  hiding ( layoutHook )
-import           XMonad.Custom.Theme
-import           XMonad.Hooks.ManageDocks
-import           XMonad.Layout.Accordion
-import           XMonad.Layout.BinarySpacePartition
-import           XMonad.Layout.Fullscreen
-import           XMonad.Layout.Hidden
-import           XMonad.Layout.LayoutModifier
-import           XMonad.Layout.MultiToggle
-import           XMonad.Layout.MultiToggle.Instances
-import           XMonad.Layout.NoBorders
-import           XMonad.Layout.Reflect
-import           XMonad.Layout.Simplest
-import           XMonad.Layout.Spacing
-import           XMonad.Layout.SubLayouts
-import           XMonad.Layout.Tabbed
-import           XMonad.Layout.WindowNavigation
+import           XMonad                         ( Full(Full)
+                                                , Tall(Tall)
+                                                , (|||)
+                                                )
 
-applySpacing :: l a -> ModifiedLayout Spacing l a
-applySpacing = spacingRaw False (Border 6 6 6 6) True (Border 6 6 6 6) True
-
-data CustomTransformers = GAPS
-  deriving (Read, Show, Eq, Typeable)
-
-instance Transformer CustomTransformers Window where
-  transform GAPS x k = k (avoidStruts $ applySpacing x) (const x)
-
-layoutHook =
-  fullscreenFloat
-    $ lessBorders OnlyLayoutFloat
-    $ mkToggle (single NBFULL)
-    $ avoidStruts
-    $ applySpacing
-    $ mkToggle (single GAPS)
-    $ mkToggle (single REFLECTX)
-    $ mkToggle (single REFLECTY)
-    $ windowNavigation
-    $ addTabs shrinkText tabTheme
-    $ hiddenWindows
-    $ subLayout [] (Simplest ||| Accordion) emptyBSP
+ngLayoutHook = Tall 1 (1 / 2) (3 / 100) ||| Full
diff --git a/src/lib/XMonad/Custom/Log.hs b/src/lib/XMonad/Custom/Log.hs
index e9d3c1a..5e1e1b1 100644
--- a/src/lib/XMonad/Custom/Log.hs
+++ b/src/lib/XMonad/Custom/Log.hs
@@ -1,82 +1,20 @@
 -- |
 -- Module                  : XMonad.Custom.Log
 -- Description             : Loggers and statusbar configuration
--- Copyright               : (c) Azat Bahawi 2018-2021
+-- Copyright               : (c) Azat Bahawi 2018-2022
 -- SPDX-License-Identifier : GPL-3.0-or-later
--- Maintainer              : azahi@teknik.io
+-- Maintainer              : azat@bahawi.net
 -- Stability               : experimental
 -- Portability             : non-portable
 --
 
 module XMonad.Custom.Log
-  ( logHook
+  ( ngLogHook
   ) where
 
-import           System.IO
-import           XMonad                  hiding ( logHook )
-import           XMonad.Actions.CopyWindow
-import           XMonad.Custom.Theme
-import           XMonad.Hooks.CurrentWorkspaceOnTop
-import           XMonad.Hooks.DynamicLog
-import           XMonad.Hooks.EwmhDesktops
-import           XMonad.Util.NamedScratchpad
-import           XMonad.Util.SpawnNamedPipe
-import           XMonad.Util.WorkspaceCompare
+import           XMonad                         ( X )
+import           XMonad.Hooks.DynamicLog        ( dynamicLog )
 
-xmobarFont :: Int -> String -> String
-xmobarFont f = wrap (concat ["<fn=", show f, ">"]) "</fn>"
-
-topBarPP :: PP
-topBarPP = def
-  { ppCurrent         = xmobarColor white2 "" . xmobarFont 2 . wrap "=" "="
-  , ppVisible         = xmobarColor white1 "" . wrap "~" "~"
-  , ppHidden          = xmobarColor white1 "" . wrap "-" "-"
-  , ppHiddenNoWindows = xmobarColor white1 "" . wrap "_" "_"
-  , ppUrgent          = xmobarColor red2 "" . wrap "!" "!"
-  , ppSep             = " / "
-  , ppWsSep           = " "
-  , ppTitle           = xmobarColor white1 "" . shorten 50
-  , ppTitleSanitize   = xmobarStrip
-  , ppLayout          = xmobarColor white1 ""
-  , ppOrder           = id
-  , ppSort            = (namedScratchpadFilterOutWorkspace .) <$> getSortByIndex
-  , ppExtras          = []
-  }
-
-botBarPP :: PP
-botBarPP = topBarPP { ppCurrent         = const ""
-                    , ppVisible         = const ""
-                    , ppHidden          = const ""
-                    , ppHiddenNoWindows = const ""
-                    , ppUrgent          = const ""
-                    , ppTitle           = const ""
-                    , ppLayout          = const ""
-                    }
-
-safePrintToPipe :: Maybe Handle -> String -> IO ()
-safePrintToPipe = maybe (\_ -> return ()) hPutStrLn
-
-logHook :: X ()
-logHook = do
-  currentWorkspaceOnTop
-  ewmhDesktopsLogHook
-  t <- getNamedPipe "xmobarTop"
-  b <- getNamedPipe "xmobarBot"
-  c <- wsContainingCopies
-  let copiesCurrent ws
-        | ws `elem` c
-        = xmobarColor yellow2 "" . xmobarFont 2 . wrap "*" "=" $ ws
-        | otherwise
-        = xmobarColor white2 "" . xmobarFont 2 . wrap "=" "=" $ ws
-  let copiesHidden ws
-        | ws `elem` c = xmobarColor yellow1 "" . wrap "*" "-" $ ws
-        | otherwise   = xmobarColor white1 "" . wrap "-" "-" $ ws
-  let copiesUrgent ws
-        | ws `elem` c = xmobarColor yellow2 "" . wrap "*" "!" $ ws
-        | otherwise   = xmobarColor white2 "" . wrap "!" "!" $ ws
-  dynamicLogWithPP $ topBarPP { ppCurrent = copiesCurrent
-                              , ppHidden  = copiesHidden
-                              , ppUrgent  = copiesUrgent
-                              , ppOutput  = safePrintToPipe t
-                              }
-  dynamicLogWithPP $ botBarPP { ppOutput = safePrintToPipe b }
+ngLogHook :: X ()
+ngLogHook = do
+  dynamicLog
diff --git a/src/lib/XMonad/Custom/Manage.hs b/src/lib/XMonad/Custom/Manage.hs
index dbc560e..fcda9c1 100644
--- a/src/lib/XMonad/Custom/Manage.hs
+++ b/src/lib/XMonad/Custom/Manage.hs
@@ -3,13 +3,13 @@
 -- Description             : Window management hooks and scratchpads
 -- Copyright               : (c) Azat Bahawi 2018-2021
 -- SPDX-License-Identifier : GPL-3.0-or-later
--- Maintainer              : azahi@teknik.io
+-- Maintainer              : azat@bahawi.net
 -- Stability               : experimental
 -- Portability             : non-portable
 --
 
 module XMonad.Custom.Manage
-  ( manageHook
+  ( ngManageHook
   ) where
 
 import           XMonad                  hiding ( manageHook )
@@ -20,6 +20,14 @@ import           XMonad.Hooks.ManageHelpers
 import           XMonad.Layout.Fullscreen
 import           XMonad.Util.NamedScratchpad
 
+ngManageHook :: ManageHook
+ngManageHook = mconcat
+  [ manageDocks
+  , fullscreenManageHook
+  , namedScratchpadManageHook scratchpads
+  , composeOne composeActions
+  ]
+
 composeActions :: [MaybeManageHook]
 composeActions =
   [ appName =? "emacs-popup" -?> tileBelowNoFocus
@@ -44,11 +52,3 @@ composeActions =
   tileNormal       = insertPosition Above Newer
   tileBelow        = insertPosition Below Newer
   tileBelowNoFocus = insertPosition Below Older
-
-manageHook :: ManageHook
-manageHook = mconcat
-  [ manageDocks
-  , fullscreenManageHook
-  , namedScratchpadManageHook scratchpads
-  , composeOne composeActions
-  ]
diff --git a/src/lib/XMonad/Custom/Misc.hs b/src/lib/XMonad/Custom/Misc.hs
index 366c01f..2511cbc 100644
--- a/src/lib/XMonad/Custom/Misc.hs
+++ b/src/lib/XMonad/Custom/Misc.hs
@@ -3,9 +3,9 @@
 -- |
 -- Module                  : XMonad.Custom.Misc
 -- Description             : Miscellaneous functions and constants
--- Copyright               : (c) Azat Bahawi 2018-2021
+-- Copyright               : (c) Azat Bahawi 2018-2022
 -- SPDX-License-Identifier : GPL-3.0-or-later
--- Maintainer              : azahi@teknik.io
+-- Maintainer              : azat@bahawi.net
 -- Stability               : experimental
 -- Portability             : non-portable
 --
@@ -15,22 +15,11 @@ module XMonad.Custom.Misc
   , applications
   ) where
 
-data Applications = Applications
-  { browser :: !String
-  , mixer   :: !String
-  , notify  :: !String
-  , player  :: !String
-  , term    :: !String
-  , top     :: !String
+newtype Applications = Applications
+  { term :: String
   }
   deriving (Eq, Show)
 
 
 applications :: Applications
-applications = Applications { browser = "qutebrowser"
-                            , mixer   = "pulsemixer"
-                            , notify  = "notify-send"
-                            , player  = "ncmpcpp"
-                            , term    = "alacritty"
-                            , top     = "htop"
-                            }
+applications = Applications { term = "alacritty" }
diff --git a/src/lib/XMonad/Custom/Navigation.hs b/src/lib/XMonad/Custom/Navigation.hs
index cf96ab7..d033389 100644
--- a/src/lib/XMonad/Custom/Navigation.hs
+++ b/src/lib/XMonad/Custom/Navigation.hs
@@ -1,9 +1,9 @@
 -- |
 -- Module                  : XMonad.Custom.Navigation
 -- Description             : Window navigation and layouts
--- Copyright               : (c) Azat Bahawi 2018-2021
+-- Copyright               : (c) Azat Bahawi 2018-2022
 -- SPDX-License-Identifier : GPL-3.0-or-later
--- Maintainer              : azahi@teknik.io
+-- Maintainer              : azat@bahawi.net
 -- Stability               : experimental
 -- Portability             : non-portable
 --
diff --git a/src/lib/XMonad/Custom/Projects.hs b/src/lib/XMonad/Custom/Projects.hs
index 9fa7a37..c57b4e3 100644
--- a/src/lib/XMonad/Custom/Projects.hs
+++ b/src/lib/XMonad/Custom/Projects.hs
@@ -1,9 +1,9 @@
 -- |
 -- Module                  : XMonad.Custom.Projects
 -- Description             : Per-project workspaces
--- Copyright               : (c) Azat Bahawi 2018-2021
+-- Copyright               : (c) Azat Bahawi 2018-2022
 -- SPDX-License-Identifier : GPL-3.0-or-later
--- Maintainer              : azahi@teknik.io
+-- Maintainer              : azat@bahawi.net
 -- Stability               : experimental
 -- Portability             : non-portable
 --
@@ -13,8 +13,6 @@ module XMonad.Custom.Projects
   ) where
 
 import           XMonad.Actions.DynamicProjects
-import           XMonad.Actions.SpawnOn
-import qualified XMonad.Custom.Misc            as C
 
 projects :: [Project]
 projects =
@@ -22,12 +20,4 @@ projects =
             , projectDirectory = "~/"
             , projectStartHook = Nothing
             }
-  , Project { projectName      = "Emacs"
-            , projectDirectory = "~/"
-            , projectStartHook = Just $ spawnOn "Emacs" "emacsclient"
-            }
-  , Project { projectName      = "WWW"
-            , projectDirectory = "~/"
-            , projectStartHook = Just $ spawnOn "WWW" (C.browser C.applications)
-            }
   ]
diff --git a/src/lib/XMonad/Custom/Prompt.hs b/src/lib/XMonad/Custom/Prompt.hs
index c54a00f..d8610eb 100644
--- a/src/lib/XMonad/Custom/Prompt.hs
+++ b/src/lib/XMonad/Custom/Prompt.hs
@@ -1,9 +1,9 @@
 -- |
 -- Module                  : XMonad.Custom.Prompt
 -- Description             : Prompt configuration
--- Copyright               : (c) Azat Bahawi 2018-2021
+-- Copyright               : (c) Azat Bahawi 2018-2022
 -- SPDX-License-Identifier : GPL-3.0-or-later
--- Maintainer              : azahi@teknik.io
+-- Maintainer              : azat@bahawi.net
 -- Stability               : experimental
 -- Portability             : non-portable
 --
diff --git a/src/lib/XMonad/Custom/Scratchpads.hs b/src/lib/XMonad/Custom/Scratchpads.hs
index 5570435..4aaaf94 100644
--- a/src/lib/XMonad/Custom/Scratchpads.hs
+++ b/src/lib/XMonad/Custom/Scratchpads.hs
@@ -1,9 +1,9 @@
 -- |
 -- Module                  : XMonad.Custom.Scratchpads
 -- Description             : Scratchpads configuration
--- Copyright               : (c) Azat Bahawi 2018-2021
+-- Copyright               : (c) Azat Bahawi 2018-2022
 -- SPDX-License-Identifier : GPL-3.0-or-later
--- Maintainer              : azahi@teknik.io
+-- Maintainer              : azat@bahawi.net
 -- Stability               : experimental
 -- Portability             : non-portable
 --
@@ -35,16 +35,4 @@ scratchpads =
        (spawnTerminalWith "NSPConsole" "~/.xmonad/scripts/nsp-console.sh")
        (title =? "NSPConsole")
        floatingNSP
-  , NS "volume"
-       (spawnTerminalWith "NSPVolume" (C.mixer C.applications))
-       (title =? "NSPVolume")
-       floatingNSP
-  , NS "music"
-       (spawnTerminalWith "NSPMusic" (C.player C.applications))
-       (title =? "NSPMusic")
-       floatingNSP
-  , NS "top"
-       (spawnTerminalWith "NSPTop" (C.top C.applications))
-       (title =? "NSPTop")
-       floatingNSP
   ]
diff --git a/src/lib/XMonad/Custom/Startup.hs b/src/lib/XMonad/Custom/Startup.hs
index 935d08f..3c9379e 100644
--- a/src/lib/XMonad/Custom/Startup.hs
+++ b/src/lib/XMonad/Custom/Startup.hs
@@ -1,58 +1,20 @@
 -- |
 -- Module                  : XMonad.Custom.Startup
 -- Description             : Startup hooks
--- Copyright               : (c) Azat Bahawi 2018-2021
+-- Copyright               : (c) Azat Bahawi 2018-2022
 -- SPDX-License-Identifier : GPL-3.0-or-later
--- Maintainer              : azahi@teknik.io
+-- Maintainer              : azat@bahawi.net
 -- Stability               : experimental
 -- Portability             : non-portable
 --
 
 module XMonad.Custom.Startup
-  ( startupHook
+  ( ngStartupHook
   ) where
 
-import           Control.Monad
-import           Data.Maybe
-import           XMonad                  hiding ( startupHook )
-import           XMonad.Hooks.ManageDocks
-import           XMonad.Hooks.SetWMName
-import           XMonad.Util.Cursor
-import           XMonad.Util.SpawnNamedPipe
+import           XMonad                         ( X )
+import           XMonad.Hooks.SetWMName         ( setWMName )
 
-atomsToFullscreen :: [String]
-atomsToFullscreen =
-  [ "_NET_ACTIVE_WINDOW"
-  , "_NET_CLIENT_LIST"
-  , "_NET_CLIENT_LIST_STACKING"
-  , "_NET_DESKTOP_NAMES"
-  , "_NET_WM_DESKTOP"
-  , "_NET_WM_STATE"
-  , "_NET_WM_STATE_FULLSCREEN"
-  , "_NET_WM_STATE_HIDDEN"
-  , "_NET_WM_STRUT"
-  ]
-
-addNETSupported :: Atom -> X ()
-addNETSupported x = withDisplay $ \d -> do
-  r <- asks theRoot
-  n <- getAtom "_NET_SUPPORTED"
-  a <- getAtom "ATOM"
-  liftIO $ do
-    p <- join . maybeToList <$> getWindowProperty32 d n r
-    when (fromIntegral x `notElem` p)
-      $ changeProperty32 d r n a propModeAppend [fromIntegral x]
-
-addEWMHFullscreen :: X ()
-addEWMHFullscreen = do
-  s <- mapM getAtom atomsToFullscreen
-  mapM_ addNETSupported s
-
-startupHook :: X ()
-startupHook = do
-  -- spawnNamedPipe "xmobar ~/.xmonad/xmobarrc/top.hs" "xmobarTop"
-  -- spawnNamedPipe "xmobar ~/.xmonad/xmobarrc/bot.hs" "xmobarBot"
-  docksStartupHook
-  addEWMHFullscreen
-  setDefaultCursor xC_left_ptr
+ngStartupHook :: X ()
+ngStartupHook = do
   setWMName "xmonad"
diff --git a/src/lib/XMonad/Custom/Theme.hs b/src/lib/XMonad/Custom/Theme.hs
index cfcd176..be3bc67 100644
--- a/src/lib/XMonad/Custom/Theme.hs
+++ b/src/lib/XMonad/Custom/Theme.hs
@@ -1,9 +1,9 @@
 -- |
 -- Module                  : XMonad.Custom.Theme
 -- Description             : Theming and styles
--- Copyright               : (c) Azat Bahawi 2018-2021
+-- Copyright               : (c) Azat Bahawi 2018-2022
 -- SPDX-License-Identifier : GPL-3.0-or-later
--- Maintainer              : azahi@teknik.io
+-- Maintainer              : azat@bahawi.net
 -- Stability               : experimental
 -- Portability             : non-portable
 --
diff --git a/src/lib/XMonad/Custom/Workspaces.hs b/src/lib/XMonad/Custom/Workspaces.hs
index 43d8aa2..995fb9f 100644
--- a/src/lib/XMonad/Custom/Workspaces.hs
+++ b/src/lib/XMonad/Custom/Workspaces.hs
@@ -1,19 +1,22 @@
 -- |
 -- Module                  : XMonad.Custom.Workspaces
 -- Description             : General workspace configuration
--- Copyright               : (c) Azat Bahawi 2018-2021
+-- Copyright               : (c) Azat Bahawi 2018-2022
 -- SPDX-License-Identifier : GPL-3.0-or-later
--- Maintainer              : azahi@teknik.io
+-- Maintainer              : azat@bahawi.net
 -- Stability               : experimental
 -- Portability             : non-portable
 --
 
 module XMonad.Custom.Workspaces
-  ( myWorkspaces
+  ( ngWorkspaces
   ) where
 
-import           XMonad.Core
+import           XMonad.Core                    ( ScreenId )
 import           XMonad.Layout.IndependentScreens
+                                                ( PhysicalWorkspace
+                                                , withScreens
+                                                )
 
-myWorkspaces :: ScreenId -> [PhysicalWorkspace]
-myWorkspaces = flip withScreens $ map show [1 .. 9 :: Int]
+ngWorkspaces :: ScreenId -> [PhysicalWorkspace]
+ngWorkspaces = flip withScreens $ map show [1 .. 9 :: Int]
diff --git a/stack.yaml b/stack.yaml
index 3f06915..8e60f3a 100644
--- a/stack.yaml
+++ b/stack.yaml
@@ -1,5 +1,5 @@
 ---
-resolver: lts-18.18
+resolver: lts-19.19
 extra-deps:
   - xmonad-0.17.0
   - xmonad-contrib-0.17.0
diff --git a/stack.yaml.lock b/stack.yaml.lock
index 59970bc..e474320 100644
--- a/stack.yaml.lock
+++ b/stack.yaml.lock
@@ -5,22 +5,22 @@
 
 packages:
 - completed:
-    hackage: xmonad-0.17.0@sha256:fc90c8fa647390c68c902912a5a7417f04025dfe72f7de51b248217f7ca0d484,5533
     pantry-tree:
-      size: 2485
       sha256: 6fd7c6a64621a088fcbb2e5a66030a78b0832d7341e4c465d3aeb4e668d097a5
+      size: 2485
+    hackage: xmonad-0.17.0@sha256:fc90c8fa647390c68c902912a5a7417f04025dfe72f7de51b248217f7ca0d484,5533
   original:
     hackage: xmonad-0.17.0
 - completed:
-    hackage: xmonad-contrib-0.17.0@sha256:defd04a9ca0e031eb7280b734ccd6d6b73f757babfe4a561a7ff718e75211749,20357
     pantry-tree:
-      size: 21783
       sha256: 81a4589ef85fed434a852ba1324466b5ad8f4fd752cd88840aa4ea4348a16cec
+      size: 21783
+    hackage: xmonad-contrib-0.17.0@sha256:defd04a9ca0e031eb7280b734ccd6d6b73f757babfe4a561a7ff718e75211749,20357
   original:
     hackage: xmonad-contrib-0.17.0
 snapshots:
 - completed:
-    size: 586296
-    url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/18/18.yaml
-    sha256: 63539429076b7ebbab6daa7656cfb079393bf644971156dc349d7c0453694ac2
-  original: lts-18.18
+    sha256: a95a93bcb7132bf5f8ad3356998e223947852f57d4da63e0e145870ea90d9d18
+    size: 619170
+    url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/19/19.yaml
+  original: lts-19.19
diff --git a/treefmt.toml b/treefmt.toml
deleted file mode 100644
index ff039ef..0000000
--- a/treefmt.toml
+++ /dev/null
@@ -1,24 +0,0 @@
-[formatter.haskell]
-command = ""
-includes = ["*.hs"]
-
-[formatter.shell]
-command = "/bin/sh"
-options = [
-    "-euc",
-    """
-shellcheck "$@"
-shfmt -s -w "$@"
-    """,
-    "--",
-]
-includes = ["*.sh"]
-
-[formatter.prettier]
-command = "prettier"
-options = ["--write"]
-includes = ["*.yaml"]
-
-[formatter.nix]
-command = "nixfmt"
-includes = ["*.nix"]
diff --git a/xmonad-ng.cabal b/xmonad-ng.cabal
index 748fc8b..2e73752 100644
--- a/xmonad-ng.cabal
+++ b/xmonad-ng.cabal
@@ -1,27 +1,21 @@
 cabal-version: 2.2
 
--- This file has been generated from package.yaml by hpack version 0.34.5.
+-- This file has been generated from package.yaml by hpack version 0.34.7.
 --
 -- see: https://github.com/sol/hpack
 
 name:           xmonad-ng
-version:        2.0.1.0
+version:        2.1.0.0
 synopsis:       Personal XMonad configuration
 description:    I hope no one will read this description. It's awful.
 category:       System
-homepage:       https://github.com/azahi/xmonad-ng#readme
-bug-reports:    https://github.com/azahi/xmonad-ng/issues
-author:         Azat Bahawi <azahi@teknik.io>
-maintainer:     Azat Bahawi <azahi@teknik.io>
-copyright:      (c) Azat Bahawi 2018-2021
+author:         Azat Bahawi <azat@bahawi.net>
+maintainer:     Azat Bahawi <azat@bahawi.net>
+copyright:      (c) Azat Bahawi 2018-2022
 license:        GPL-3.0-or-later
 license-file:   LICENSE
 build-type:     Simple
 
-source-repository head
-  type: git
-  location: https://github.com/azahi/xmonad-ng
-
 library
   exposed-modules:
       XMonad.Custom.Bindings
@@ -45,7 +39,7 @@ library
       X11 ==1.10.*
     , base ==4.*
     , containers ==0.6.*
-    , flow ==1.0.*
+    , flow ==2.0.*
     , xmonad ==0.17.*
     , xmonad-contrib ==0.17.*
   default-language: Haskell2010
@@ -57,7 +51,7 @@ executable xmonad-ng
   ghc-options: -Wall -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wredundant-constraints -rtsopts -threaded -v0 -with-rtsopts=-N
   build-depends:
       base ==4.*
-    , flow ==1.0.*
+    , flow ==2.0.*
     , xmonad ==0.17.*
     , xmonad-contrib ==0.17.*
     , xmonad-ng

Consider giving Nix/NixOS a try! <3