grafana-alloy: don't build the frontend twice
[NixPkgs.git] / nixos / modules / services / x11 / window-managers / xmonad.nix
blob7feb3a0b520faf186a334040dba7ba4ffbd7ddc0
1 {pkgs, lib, config, ...}:
3 with lib;
4 let
5   inherit (lib) mkOption mkIf optionals literalExpression optionalString;
6   cfg = config.services.xserver.windowManager.xmonad;
8   ghcWithPackages = cfg.haskellPackages.ghcWithPackages;
9   packages = self: cfg.extraPackages self ++
10                    optionals cfg.enableContribAndExtras
11                    [ self.xmonad-contrib self.xmonad-extras ];
13   xmonad-vanilla = pkgs.xmonad-with-packages.override {
14     inherit ghcWithPackages packages;
15   };
17   xmonad-config =
18     let
19       xmonadAndPackages = self: [ self.xmonad ] ++ packages self;
20       xmonadEnv = ghcWithPackages xmonadAndPackages;
21       configured = pkgs.writers.writeHaskellBin "xmonad" {
22         ghc = cfg.haskellPackages.ghc;
23         libraries = xmonadAndPackages cfg.haskellPackages;
24         inherit (cfg) ghcArgs;
25       } cfg.config;
26     in
27       pkgs.runCommandLocal "xmonad" {
28         nativeBuildInputs = [ pkgs.makeWrapper ];
29       } (''
30         install -D ${xmonadEnv}/share/man/man1/xmonad.1.gz $out/share/man/man1/xmonad.1.gz
31         makeWrapper ${configured}/bin/xmonad $out/bin/xmonad \
32       '' + optionalString cfg.enableConfiguredRecompile ''
33           --set XMONAD_GHC "${xmonadEnv}/bin/ghc" \
34       '' + ''
35           --set XMONAD_XMESSAGE "${pkgs.xorg.xmessage}/bin/xmessage"
36       '');
38   xmonad = if (cfg.config != null) then xmonad-config else xmonad-vanilla;
39 in {
40   meta.maintainers = with maintainers; [ lassulus xaverdh ivanbrennan slotThe ];
42   options = {
43     services.xserver.windowManager.xmonad = {
44       enable = mkEnableOption "xmonad";
46       haskellPackages = mkOption {
47         default = pkgs.haskellPackages;
48         defaultText = literalExpression "pkgs.haskellPackages";
49         example = literalExpression "pkgs.haskell.packages.ghc810";
50         type = types.attrs;
51         description = ''
52           haskellPackages used to build Xmonad and other packages.
53           This can be used to change the GHC version used to build
54           Xmonad and the packages listed in
55           {var}`extraPackages`.
56         '';
57       };
59       extraPackages = mkOption {
60         type = types.functionTo (types.listOf types.package);
61         default = self: [];
62         defaultText = literalExpression "self: []";
63         example = literalExpression ''
64           haskellPackages: [
65             haskellPackages.xmonad-contrib
66             haskellPackages.monad-logger
67           ]
68         '';
69         description = ''
70           Extra packages available to ghc when rebuilding Xmonad. The
71           value must be a function which receives the attrset defined
72           in {var}`haskellPackages` as the sole argument.
73         '';
74       };
76       enableContribAndExtras = mkOption {
77         default = false;
78         type = lib.types.bool;
79         description = "Enable xmonad-{contrib,extras} in Xmonad.";
80       };
82       config = mkOption {
83         default = null;
84         type = with lib.types; nullOr (either path str);
85         description = ''
86           Configuration from which XMonad gets compiled. If no value is
87           specified, a vanilla xmonad binary is put in PATH, which will
88           attempt to recompile and exec your xmonad config from $HOME/.xmonad.
89           This setup is then analogous to other (non-NixOS) linux distributions.
91           If you do set this option, you likely want to use "launch" as your
92           entry point for xmonad (as in the example), to avoid xmonad's
93           recompilation logic on startup. Doing so will render the default
94           "mod+q" restart key binding dysfunctional though, because that attempts
95           to call your binary with the "--restart" command line option, unless
96           you implement that yourself. You way mant to bind "mod+q" to
97           `(restart "xmonad" True)` instead, which will just restart
98           xmonad from PATH. This allows e.g. switching to the new xmonad binary
99           after rebuilding your system with nixos-rebuild.
100           For the same reason, ghc is not added to the environment when this
101           option is set, unless {option}`enableConfiguredRecompile` is
102           set to `true`.
104           If you actually want to run xmonad with a config specified here, but
105           also be able to recompile and restart it from a copy of that source in
106           $HOME/.xmonad on the fly, set {option}`enableConfiguredRecompile`
107           to `true` and implement something like "compileRestart"
108           from the example.
109           This should allow you to switch at will between the local xmonad and
110           the one NixOS puts in your PATH.
111         '';
112         example = ''
113           import XMonad
114           import XMonad.Util.EZConfig (additionalKeys)
115           import Control.Monad (when)
116           import Text.Printf (printf)
117           import System.Posix.Process (executeFile)
118           import System.Info (arch,os)
119           import System.Environment (getArgs)
120           import System.FilePath ((</>))
122           compiledConfig = printf "xmonad-%s-%s" arch os
124           myConfig = defaultConfig
125             { modMask = mod4Mask -- Use Super instead of Alt
126             , terminal = "urxvt" }
127             `additionalKeys`
128             [ ( (mod4Mask,xK_r), compileRestart True)
129             , ( (mod4Mask,xK_q), restart "xmonad" True ) ]
131           compileRestart resume = do
132             dirs  <- asks directories
133             whenX (recompile dirs True) $ do
134               when resume writeStateToFile
135               catchIO
136                   ( do
137                       args <- getArgs
138                       executeFile (cacheDir dirs </> compiledConfig) False args Nothing
139                   )
141           main = getDirectories >>= launch myConfig
143           --------------------------------------------
144           {- For versions before 0.17.0 use this instead -}
145           --------------------------------------------
146           -- compileRestart resume =
147           --   whenX (recompile True) $
148           --     when resume writeStateToFile
149           --       *> catchIO
150           --         ( do
151           --             dir <- getXMonadDataDir
152           --             args <- getArgs
153           --             executeFile (dir </> compiledConfig) False args Nothing
154           --         )
155           --
156           -- main = launch myConfig
157           --------------------------------------------
159         '';
160       };
162       enableConfiguredRecompile = mkOption {
163         default = false;
164         type = lib.types.bool;
165         description = ''
166           Enable recompilation even if {option}`config` is set to a
167           non-null value. This adds the necessary Haskell dependencies (GHC with
168           packages) to the xmonad binary's environment.
169         '';
170       };
172       xmonadCliArgs = mkOption {
173         default = [];
174         type = with lib.types; listOf str;
175         description = ''
176           Command line arguments passed to the xmonad binary.
177         '';
178       };
180       ghcArgs = mkOption {
181         default = [];
182         type = with lib.types; listOf str;
183         description = ''
184           Command line arguments passed to the compiler (ghc)
185           invocation when xmonad.config is set.
186         '';
187       };
189     };
190   };
191   config = mkIf cfg.enable {
192     services.xserver.windowManager = {
193       session = [{
194         name = "xmonad";
195         start = ''
196            systemd-cat -t xmonad -- ${xmonad}/bin/xmonad ${lib.escapeShellArgs cfg.xmonadCliArgs} &
197            waitPID=$!
198         '';
199       }];
200     };
202     environment.systemPackages = [ xmonad ];
203   };