summaryrefslogtreecommitdiffstats
path: root/tv
diff options
context:
space:
mode:
authorjeschli <jeschli@gmail.com>2018-12-04 19:27:27 +0100
committerjeschli <jeschli@gmail.com>2018-12-04 19:27:27 +0100
commit5030b74cc5c578bb82619a24592504a6008f1a10 (patch)
tree0551e3ddb94353b7438bec02174bf3379bc89b87 /tv
parent78b289201987675844aa37abeb4279eb4051ebe0 (diff)
parent82988de84c177c247ebbe80940c4d50b9f073b4e (diff)
Merge branch 'master' of prism.r:stockholm
Diffstat (limited to 'tv')
-rw-r--r--tv/1systems/mu/config.nix13
-rw-r--r--tv/1systems/querel/config.nix3
-rw-r--r--tv/2configs/bash/default.nix22
-rw-r--r--tv/2configs/default.nix5
-rw-r--r--tv/2configs/gitrepos.nix1
-rw-r--r--tv/2configs/pulse.nix2
-rw-r--r--tv/2configs/urlwatch.nix5
-rw-r--r--tv/2configs/vim.nix83
-rw-r--r--tv/2configs/xp-332.nix4
-rw-r--r--tv/2configs/xserver/Xresources.nix5
-rw-r--r--tv/2configs/xserver/default.nix37
-rw-r--r--tv/3modules/default.nix2
-rw-r--r--tv/3modules/dnsmasq.nix57
-rw-r--r--tv/3modules/ejabberd/config.nix1
-rw-r--r--tv/3modules/slock.nix71
-rw-r--r--tv/5pkgs/haskell/default.nix20
-rw-r--r--tv/5pkgs/haskell/xmonad-tv/default.nix15
-rw-r--r--tv/5pkgs/haskell/xmonad-tv/shell.nix78
-rw-r--r--tv/5pkgs/haskell/xmonad-tv/src/Helpers/Path.hs15
-rw-r--r--tv/5pkgs/haskell/xmonad-tv/src/Paths.hs25
-rw-r--r--tv/5pkgs/haskell/xmonad-tv/src/main.hs206
-rw-r--r--tv/5pkgs/haskell/xmonad-tv/src/xmonad-tv.cabal25
-rw-r--r--tv/5pkgs/simple/default.nix8
-rw-r--r--tv/5pkgs/simple/disko.nix13
-rwxr-xr-xtv/5pkgs/simple/fzmenu/bin/otpmenu41
-rwxr-xr-xtv/5pkgs/simple/fzmenu/bin/passmenu41
-rw-r--r--tv/5pkgs/simple/fzmenu/default.nix34
-rw-r--r--tv/5pkgs/simple/hc.nix37
-rw-r--r--tv/5pkgs/simple/otpmenu.nix15
-rw-r--r--tv/5pkgs/simple/q/default.nix6
-rw-r--r--tv/5pkgs/simple/xmonad-tv/default.nix295
-rw-r--r--tv/default.nix10
-rw-r--r--tv/krops.nix2
33 files changed, 822 insertions, 375 deletions
diff --git a/tv/1systems/mu/config.nix b/tv/1systems/mu/config.nix
index c26d4ab30..a653ce40d 100644
--- a/tv/1systems/mu/config.nix
+++ b/tv/1systems/mu/config.nix
@@ -15,7 +15,7 @@ with import <stockholm/lib>;
# hardware configuration
boot.initrd.luks.devices.muca = {
- device = "/dev/disk/by-uuid/a8796bb3-6c03-4ddf-b2e4-c2e44c51d352";
+ device = "/dev/disk/by-uuid/7b24a931-40b6-44a6-ba22-c805cf164e91";
};
boot.initrd.luks.cryptoModules = [ "aes" "sha512" "xts" ];
boot.initrd.availableKernelModules = [ "ahci" ];
@@ -25,16 +25,17 @@ with import <stockholm/lib>;
fileSystems = {
"/" = {
device = "/dev/mapper/muvga-root";
- fsType = "btrfs";
- options = ["defaults" "noatime" "ssd" "compress=lzo"];
+ fsType = "ext4";
+ options = [ "defaults" "discard" ];
};
"/home" = {
device = "/dev/mapper/muvga-home";
- fsType = "btrfs";
- options = ["defaults" "noatime" "ssd" "compress=lzo"];
+ fsType = "ext4";
+ options = [ "defaults" "discard" ];
};
"/boot" = {
- device = "/dev/disk/by-uuid/DC38-F165";
+ device = "/dev/disk/by-uuid/CEB1-9743";
+ fsType = "vfat";
};
};
diff --git a/tv/1systems/querel/config.nix b/tv/1systems/querel/config.nix
index 01d67b5f5..6e7944cdf 100644
--- a/tv/1systems/querel/config.nix
+++ b/tv/1systems/querel/config.nix
@@ -25,7 +25,6 @@ with import <stockholm/lib>;
};
environment.systemPackages = with pkgs; [
- chromium
firefoxWrapper
gimp
kate
@@ -63,8 +62,6 @@ with import <stockholm/lib>;
networking.networkmanager.enable = true;
- nixpkgs.config.chromium.enablePepperFlash = true;
-
programs.ssh.startAgent = false;
services.xserver.enable = true;
diff --git a/tv/2configs/bash/default.nix b/tv/2configs/bash/default.nix
index b75ad8bfc..d7673931c 100644
--- a/tv/2configs/bash/default.nix
+++ b/tv/2configs/bash/default.nix
@@ -13,6 +13,20 @@ with import <stockholm/lib>;
shopt -s histappend histreedit histverify
shopt -s no_empty_cmd_completion
complete -d cd
+
+ case $UID in
+ ${shell.escape (toString config.krebs.users.tv.uid)})
+ if test ''${SHLVL-1} = 1; then
+ case ''${XMONAD_SPAWN_WORKSPACE-} in
+ stockholm)
+ cd ~/stockholm
+ ;;
+ esac
+ fi
+
+ export NIX_PATH="stockholm=$HOME/stockholm:$NIX_PATH"
+ ;;
+ esac
'';
promptInit = /* sh */ ''
case $UID in
@@ -32,14 +46,6 @@ with import <stockholm/lib>;
if test -n "$SSH_AGENT_PID"; then
PS1="ssh-agent[$SSH_AGENT_PID] $PS1"
fi
-
- if test ''${SHLVL-1} = 1; then
- case ''${XMONAD_SPAWN_WORKSPACE-} in
- stockholm)
- cd ~/stockholm
- ;;
- esac
- fi
'';
};
}
diff --git a/tv/2configs/default.nix b/tv/2configs/default.nix
index d9ddc90d0..484a337b7 100644
--- a/tv/2configs/default.nix
+++ b/tv/2configs/default.nix
@@ -87,11 +87,6 @@ with import <stockholm/lib>;
export SYSTEM="$1"
exec nix-shell -I stockholm="$PWD" --run 'deploy --system="$SYSTEM"'
'';
- reload = "systemctl reload";
- restart = "systemctl restart";
- start = "systemctl start";
- status = "systemctl status";
- stop = "systemctl stop";
};
environment.variables = {
diff --git a/tv/2configs/gitrepos.nix b/tv/2configs/gitrepos.nix
index 62c90d4e9..a89d1302c 100644
--- a/tv/2configs/gitrepos.nix
+++ b/tv/2configs/gitrepos.nix
@@ -76,6 +76,7 @@ let {
};
} // mapAttrs (_: recursiveUpdate { cgit.section = "3. Haskell libraries"; }) {
blessings = {};
+ hc = {};
mime = {};
quipper = {};
scanner = {};
diff --git a/tv/2configs/pulse.nix b/tv/2configs/pulse.nix
index c051b4261..2e679bd14 100644
--- a/tv/2configs/pulse.nix
+++ b/tv/2configs/pulse.nix
@@ -95,7 +95,7 @@ in
users = {
groups.pulse.gid = config.users.users.pulse.uid;
users.pulse = {
- uid = genid "pulse";
+ uid = genid_uint31 "pulse";
group = "pulse";
extraGroups = [ "audio" ];
home = "${runDir}/home";
diff --git a/tv/2configs/urlwatch.nix b/tv/2configs/urlwatch.nix
index 77947dafa..7467e8e67 100644
--- a/tv/2configs/urlwatch.nix
+++ b/tv/2configs/urlwatch.nix
@@ -27,11 +27,6 @@ in {
# 2014-09-24 ref https://github.com/4z3/xintmap
http://www.mathstat.dal.ca/~selinger/quipper/
- ## other
-
- https://nixos.org/channels/nixos-18.03/git-revision
- https://nixos.org/channels/nixos-unstable/git-revision
-
## 2014-10-17
## TODO update ~/src/login/default.nix
#http://hackage.haskell.org/package/bcrypt
diff --git a/tv/2configs/vim.nix b/tv/2configs/vim.nix
index 2ac7f7518..3794628c1 100644
--- a/tv/2configs/vim.nix
+++ b/tv/2configs/vim.nix
@@ -14,8 +14,25 @@ let {
};
extra-runtimepath = concatMapStringsSep "," (pkg: "${pkg.rtp}") [
+ # cannot use pkgs.vimPlugins.fzf-vim as it's missing :Rg
+ (pkgs.vimUtils.buildVimPlugin {
+ name = "fzf-2018-11-14";
+ src = pkgs.fetchgit {
+ url = https://github.com/junegunn/fzf.vim;
+ rev = "ad1833ecbc9153b6e34a4292dc089a58c4bcb8dc";
+ sha256 = "1z2q71q6l9hq9fqfqpj1svhyk4yk1bzw1ljhksx4bnpz8gkfbx2m";
+ };
+ })
+ pkgs.vimPlugins.fzfWrapper
pkgs.vimPlugins.undotree
- pkgs.vimPlugins.vim-elixir
+ (pkgs.vimUtils.buildVimPlugin {
+ name = "vim-elixir-2018-08-17";
+ src = pkgs.fetchgit {
+ url = https://github.com/elixir-editors/vim-elixir;
+ rev = "0a847f0faed5ba2d94bb3d51f355c50f37ba025b";
+ sha256 = "1jl85wpgywhcvhgw02y8zpvqf0glr4i8522kxpvhsiacb1v1xh04";
+ };
+ })
(pkgs.vimUtils.buildVimPlugin {
name = "vim-syntax-jq";
src = pkgs.fetchgit {
@@ -112,7 +129,7 @@ let {
command! -n=0 -bar ShowSyntax :call ShowSyntax()
'';
})))
- ((rtp: rtp // { inherit rtp; }) (pkgs.write "vim-tv" {
+ ((rtp: rtp // { inherit rtp; }) (pkgs.write "vim-syntax-nix-nested" {
"/syntax/haskell.vim".text = /* vim */ ''
syn region String start=+\[[[:alnum:]]*|+ end=+|]+
@@ -222,26 +239,58 @@ let {
" This is required because containedin isn't transitive.
syn cluster nix_has_dollar_curly
\ add=@nix_${lang}_syntax
- '') {
+ '') (let
+
+ capitalize = s: let
+ xs = stringToCharacters s;
+ in
+ toUpper (head xs) + concatStrings (tail xs);
+
+ alts = xs: ''\(${concatStringsSep ''\|'' xs}\)'';
+ def = k: ''${k}[ \t\r\n]*='';
+ writer = k: ''write${k}[^ \t\r\n]*[ \t\r\n]*\("[^"]*"\|[a-z]\+\)'';
+
+ in {
c = {};
cabal = {};
diff = {};
haskell = {};
- jq.extraStart = concatStringsSep ''\|'' [
- ''writeJq.*''
+ jq.extraStart = alts [
+ (writer "Jq")
''write[^ \t\r\n]*[ \t\r\n]*"[^"]*\.jq"''
];
+ javascript.extraStart = ''/\* js \*/'';
lua = {};
- sed.extraStart = ''writeSed[^ \t\r\n]*[ \t\r\n]*"[^"]*"'';
- sh.extraStart = concatStringsSep ''\|'' [
- ''write\(A\|Ba\|Da\)sh[^ \t\r\n]*[ \t\r\n]*\("[^"]*"\|[a-z]\+\)''
- ''[a-z]*Phase[ \t\r\n]*=''
+ python.extraStart = ''/\* py \*/'';
+ sed.extraStart = writer "Sed";
+ sh.extraStart = let
+ phases = [
+ "unpack"
+ "patch"
+ "configure"
+ "build"
+ "check"
+ "install"
+ "fixup"
+ "installCheck"
+ "dist"
+ ];
+ shells = [
+ "ash"
+ "bash"
+ "dash"
+ ];
+ in alts [
+ (def "shellHook")
+ (def "${alts phases}Phase")
+ (def "${alts ["pre" "post"]}${alts (map capitalize phases)}")
+ (writer (alts (map capitalize shells)))
];
yaml = {};
vim.extraStart =
''write[^ \t\r\n]*[ \t\r\n]*"\(\([^"]*\.\)\?vimrc\|[^"]*\.vim\)"'';
xdefaults = {};
- })}
+ }))}
" Clear syntax that interferes with nixINSIDE_DOLLAR_CURLY.
syn clear shVarAssign
@@ -309,6 +358,11 @@ let {
paths = [
(pkgs.writeDashBin "vim" ''
set -efu
+ export FZF_DEFAULT_COMMAND='${pkgs.ripgrep}/bin/rg --files'
+ export PATH=$PATH:${makeBinPath [
+ pkgs.fzf
+ pkgs.ripgrep
+ ]}
(umask 0077; exec ${pkgs.coreutils}/bin/mkdir -p ${toString need-dirs})
exec ${pkgs.vim}/bin/vim "$@"
'')
@@ -333,6 +387,7 @@ let {
set shortmess+=I
set showcmd
set showmatch
+ set timeoutlen=0
set ttimeoutlen=0
set undodir=${dirs.undodir}
set undofile
@@ -385,5 +440,13 @@ let {
noremap <esc>[c <nop> | noremap! <esc>[c <nop>
noremap <esc>[d <nop> | noremap! <esc>[d <nop>
vnoremap u <nop>
+
+ " fzf
+ nnoremap <esc>q :Files<cr>
+ nnoremap <esc>w :Rg<cr>
+
+ " edit alternate buffer
+ " For some reason neither putting <ctrl>6 nor <ctrl>^ works here...
+ nnoremap <esc>a 
'';
}
diff --git a/tv/2configs/xp-332.nix b/tv/2configs/xp-332.nix
index 627401dc6..4a0b0ae16 100644
--- a/tv/2configs/xp-332.nix
+++ b/tv/2configs/xp-332.nix
@@ -11,7 +11,7 @@ with import <stockholm/lib>;
hardware.sane = {
enable = true;
extraBackends = [
- pkgs.utsushi
+ pkgs.utsushi-customized
];
};
@@ -19,7 +19,7 @@ with import <stockholm/lib>;
elem (parseDrvName pkg.name).name [ "imagescan-plugin-networkscan" ];
nixpkgs.overlays = singleton (self: super: {
- utsushi = super.utsushi.override {
+ utsushi-customized = self.utsushi.override {
guiSupport = false;
jpegSupport = false;
networkSupport = true;
diff --git a/tv/2configs/xserver/Xresources.nix b/tv/2configs/xserver/Xresources.nix
index 1d4044480..d032efc7d 100644
--- a/tv/2configs/xserver/Xresources.nix
+++ b/tv/2configs/xserver/Xresources.nix
@@ -50,4 +50,9 @@ pkgs.writeText "Xresources" /* xdefaults */ ''
root-urxvt*foreground: #e0c0c0
root-urxvt*BorderColor: #400000
root-urxvt*color0: #800000
+
+ fzmenu-urxvt*background: rgb:42/23/42
+ fzmenu-urxvt*externalBorder: 1
+ fzmenu-urxvt*geometry: 70x9
+ fzmenu-urxvt*internalBorder: 1
''
diff --git a/tv/2configs/xserver/default.nix b/tv/2configs/xserver/default.nix
index dbfa804d2..8d4b13fad 100644
--- a/tv/2configs/xserver/default.nix
+++ b/tv/2configs/xserver/default.nix
@@ -24,17 +24,6 @@ in {
pkgs.xlibs.fontschumachermisc
];
- # TODO dedicated group, i.e. with a single user [per-user-setuid]
- # TODO krebs.setuid.slock.path vs /run/wrappers/bin
- krebs.setuid.slock = {
- filename = "${pkgs.slock}/bin/slock";
- group = "wheel";
- envp = {
- DISPLAY = ":${toString config.services.xserver.display}";
- USER = cfg.user.name;
- };
- };
-
services.xserver = {
# Don't install feh into systemPackages
@@ -57,12 +46,19 @@ in {
systemd.services.display-manager.enable = false;
- systemd.services.xmonad = {
+ systemd.services.xmonad = let
+ xmonad = "${pkgs.haskellPackages.xmonad-tv}/bin/xmonad";
+ in {
wantedBy = [ "graphical.target" ];
requires = [ "xserver.service" ];
environment = {
DISPLAY = ":${toString config.services.xserver.display}";
+ FZMENU_FZF_DEFAULT_OPTS = toString [
+ "--color=dark,border:126,bg+:090"
+ "--inline-info"
+ ];
+
XMONAD_CACHE_DIR = cfg.cacheDir;
XMONAD_CONFIG_DIR = cfg.configDir;
XMONAD_DATA_DIR = cfg.dataDir;
@@ -88,6 +84,14 @@ in {
"za" "zh" "zj" "zs"
]);
};
+ path = [
+ config.tv.slock.package
+ pkgs.fzmenu
+ pkgs.pulseaudioLight.out
+ pkgs.rxvt_unicode
+ pkgs.xcalib
+ "/run/wrappers" # for su
+ ];
serviceConfig = {
SyslogIdentifier = "xmonad";
ExecStartPre = "${pkgs.coreutils}/bin/mkdir -p ${toString [
@@ -95,8 +99,8 @@ in {
"\${XMONAD_CONFIG_DIR}"
"\${XMONAD_DATA_DIR}"
]}";
- ExecStart = "${pkgs.xmonad-tv}/bin/xmonad";
- ExecStop = "${pkgs.xmonad-tv}/bin/xmonad --shutdown";
+ ExecStart = "@${xmonad} xmonad-${currentSystem} ";
+ ExecStop = "@${xmonad} xmonad-${currentSystem} --shutdown";
User = cfg.user.name;
WorkingDirectory = cfg.user.home;
};
@@ -142,4 +146,9 @@ in {
User = cfg.user.name;
};
};
+
+ tv.slock = {
+ enable = true;
+ user = cfg.user;
+ };
}
diff --git a/tv/3modules/default.nix b/tv/3modules/default.nix
index 493cc8b72..f53a58e9a 100644
--- a/tv/3modules/default.nix
+++ b/tv/3modules/default.nix
@@ -1,10 +1,12 @@
{
imports = [
./charybdis
+ ./dnsmasq.nix
./ejabberd
./hosts.nix
./iptables.nix
./nixpkgs-overlays.nix
+ ./slock.nix
./x0vncserver.nix
];
}
diff --git a/tv/3modules/dnsmasq.nix b/tv/3modules/dnsmasq.nix
new file mode 100644
index 000000000..ec927f98a
--- /dev/null
+++ b/tv/3modules/dnsmasq.nix
@@ -0,0 +1,57 @@
+with import <stockholm/lib>;
+{ config, ... }: let
+ cfg = config.tv.dnsmasq;
+in {
+
+ options.tv.dnsmasq = {
+ enable = mkEnableOption "tv.dnsmasq";
+ dhcp-range = mkOption {
+ type = types.str;
+ };
+ interface = mkOption {
+ type = types.str;
+ };
+ address = mkOption {
+ type = types.str;
+ };
+ prefixLength = mkOption {
+ type = types.addCheck types.int (x: x >= 0 && x <= 32);
+ };
+ };
+
+ config = mkIf cfg.enable (mkMerge [
+ {
+ networking.dhcpcd.denyInterfaces = [ cfg.interface ];
+ services.dnsmasq.resolveLocalQueries = false;
+ networking.interfaces.${cfg.interface} = {
+ ipv4.addresses = singleton {
+ address = cfg.address;
+ prefixLength = cfg.prefixLength;
+ };
+ };
+ services.dnsmasq.enable = true;
+ services.dnsmasq.extraConfig = ''
+ dhcp-range=${cfg.dhcp-range}
+ interface=${cfg.interface}
+ '';
+ tv.iptables.extra.filter.INPUT = [
+ "-i ${cfg.interface} -p tcp -m tcp --dport bootps -j ACCEPT"
+ "-i ${cfg.interface} -p udp -m udp --dport bootps -j ACCEPT"
+ "-i ${cfg.interface} -p tcp -m tcp --dport domain -j ACCEPT"
+ "-i ${cfg.interface} -p udp -m udp --dport domain -j ACCEPT"
+ ];
+ }
+ {
+ # enable forwarding
+ boot.kernel.sysctl."net.ipv4.ip_forward" = true;
+ tv.iptables.extra.filter.FORWARD = [
+ "-m state --state RELATED,ESTABLISHED -j ACCEPT"
+ "-i ${cfg.interface} -j ACCEPT"
+ ];
+ tv.iptables.extra.nat.POSTROUTING = [
+ "-j MASQUERADE"
+ ];
+ }
+ ]);
+
+}
diff --git a/tv/3modules/ejabberd/config.nix b/tv/3modules/ejabberd/config.nix
index 68bcfa340..a0631e226 100644
--- a/tv/3modules/ejabberd/config.nix
+++ b/tv/3modules/ejabberd/config.nix
@@ -87,7 +87,6 @@ in /* yaml */ ''
mod_configure: {}
mod_disco: {}
mod_echo: {}
- mod_irc: {}
mod_bosh: {}
mod_last: {}
mod_offline:
diff --git a/tv/3modules/slock.nix b/tv/3modules/slock.nix
new file mode 100644
index 000000000..1c84b1e9e
--- /dev/null
+++ b/tv/3modules/slock.nix
@@ -0,0 +1,71 @@
+with import <stockholm/lib>;
+{ config, pkgs, ... }: let
+ cfg = config.tv.slock;
+in {
+ options.tv.slock = {
+ enable = mkEnableOption "tv.slock";
+ package = mkOption {
+ default = pkgs.execBin "slock" rec {
+ filename = "${pkgs.systemd}/bin/systemctl";
+ argv = [ filename "start" "slock-${cfg.user.name}.service" ];
+ };
+ type = types.package;
+ };
+ user = mkOption {
+ type = types.user;
+ };
+ };
+ config = mkIf cfg.enable {
+ security.polkit.extraConfig = /* js */ ''
+ polkit.addRule(function(action, subject) {
+ if (action.id == "org.freedesktop.systemd1.manage-units" &&
+ action.lookup("unit") == "slock-${cfg.user.name}.service" &&
+ subject.user == ${toJSON cfg.user.name}) {
+ return polkit.Result.YES;
+ }
+ });
+ '';
+ systemd.services."slock-${cfg.user.name}" = {
+ environment = {
+ DISPLAY = ":${toString config.services.xserver.display}";
+ LD_PRELOAD = pkgs.runCommandCC "slock-${cfg.user.name}.so" {
+ passAsFile = ["text"];
+ text = /* c */ ''
+ #include <shadow.h>
+ #include <unistd.h>
+
+ static struct spwd entry = {
+ .sp_namp = "",
+ .sp_pwdp =
+ ${toC config.users.users.${cfg.user.name}.hashedPassword},
+ .sp_lstchg = 0,
+ .sp_min = 0,
+ .sp_max = 0,
+ .sp_warn = 0,
+ .sp_inact = 0,
+ .sp_expire = 0,
+ .sp_flag = 0,
+ };
+
+ extern struct spwd *getspnam(const char *name) { return &entry; }
+ extern int setgroups(size_t size, const gid_t *list) { return 0; }
+ extern int setgid(gid_t gid) { return 0; }
+ extern int setuid(uid_t uid) { return 0; }
+ '';
+ } /* sh */ ''
+ gcc -Wall -shared -o $out -xc "$textPath"
+ '';
+ };
+ restartIfChanged = false;
+ serviceConfig = {
+ ExecStart = "${pkgs.slock}/bin/slock";
+ OOMScoreAdjust = -1000;
+ Restart = "on-failure";
+ RestartSec = "100ms";
+ StartLimitBurst = 0;
+ SyslogIdentifier = "slock";
+ User = cfg.user.name;
+ };
+ };
+ };
+}
diff --git a/tv/5pkgs/haskell/default.nix b/tv/5pkgs/haskell/default.nix
new file mode 100644
index 000000000..fcede2f9c
--- /dev/null
+++ b/tv/5pkgs/haskell/default.nix
@@ -0,0 +1,20 @@
+with import <stockholm/lib>;
+let
+ overrides = self: super:
+ mapNixDir (path: self.callPackage path {}) [
+ <stockholm/krebs/5pkgs/haskell>
+ ./.
+ ];
+in
+ self: super: {
+ haskell = super.haskell // {
+ packages = mapAttrs (name: value:
+ if hasAttr "override" value
+ then value.override { inherit overrides; }
+ else value
+ ) super.haskell.packages;
+ };
+ haskellPackages = super.haskellPackages.override {
+ inherit overrides;
+ };
+ }
diff --git a/tv/5pkgs/haskell/xmonad-tv/default.nix b/tv/5pkgs/haskell/xmonad-tv/default.nix
new file mode 100644
index 000000000..42eb13d41
--- /dev/null
+++ b/tv/5pkgs/haskell/xmonad-tv/default.nix
@@ -0,0 +1,15 @@
+{ mkDerivation, base, containers, directory, extra, stdenv, unix
+, X11, xmonad, xmonad-contrib, xmonad-stockholm
+}:
+mkDerivation {
+ pname = "xmonad-tv";
+ version = "1.0.0";
+ src = ./src;
+ isLibrary = false;
+ isExecutable = true;
+ executableHaskellDepends = [
+ base containers directory extra unix X11 xmonad xmonad-contrib
+ xmonad-stockholm
+ ];
+ license = stdenv.lib.licenses.mit;
+}
diff --git a/tv/5pkgs/haskell/xmonad-tv/shell.nix b/tv/5pkgs/haskell/xmonad-tv/shell.nix
new file mode 100644
index 000000000..936e69627
--- /dev/null
+++ b/tv/5pkgs/haskell/xmonad-tv/shell.nix
@@ -0,0 +1,78 @@
+{ compiler ? "default" }: let
+
+ stockholm = import <stockholm>;
+
+ inherit (stockholm.systems.${lib.krops.getHostName}) config pkgs;
+ inherit (stockholm) lib;
+
+ haskellPackages =
+ if compiler == "default"
+ then pkgs.haskellPackages
+ else pkgs.haskell.packages.${compiler};
+
+ xmonadDrv = haskellPackages.callPackage (import ./.) {};
+
+in
+
+ lib.overrideDerivation xmonadDrv.env (oldAttrs: {
+ shellHook = ''
+ pkg_name=${lib.shell.escape (lib.baseNameOf (toString ./.))}
+
+ WORKDIR=${toString ./src}
+ CACHEDIR=$HOME/tmp/$pkg_name
+ HISTFILE=$CACHEDIR/bash_history
+
+ mkdir -p "$CACHEDIR"
+
+ config_XMONAD_CACHE_DIR=${lib.shell.escape
+ config.systemd.services.xmonad.environment.XMONAD_CACHE_DIR
+ }
+
+ xmonad=$CACHEDIR/xmonad-${lib.currentSystem}
+
+ xmonad_build() {(
+ set -efu
+ cd "$WORKDIR"
+ options=$(
+ ${pkgs.cabal-read}/bin/ghc-options "$WORKDIR/$pkg_name.cabal" xmonad
+ )
+ ghc $options \
+ -odir "$CACHEDIR" \
+ -hidir "$CACHEDIR" \
+ -o "$xmonad" \
+ main.hs
+ )}
+
+ xmonad_restart() {(
+ set -efu
+ cd "$WORKDIR"
+ if systemctl is-active xmonad; then
+ sudo systemctl stop xmonad
+ cp -b "$config_XMONAD_CACHE_DIR"/xmonad.state "$CACHEDIR"/
+ echo "xmonad.state: $(cat "$CACHEDIR"/xmonad.state)"
+ else
+ "$xmonad" --shutdown || :
+ fi
+ "$xmonad" &
+ echo xmonad pid: $! >&2
+ )}
+
+ xmonad_yield() {(
+ set -efu
+ "$xmonad" --shutdown
+ cp -b "$CACHEDIR"/xmonad.state "$config_XMONAD_CACHE_DIR"/
+ sudo systemctl start xmonad
+ )}
+
+ export PATH=${config.systemd.services.xmonad.path}:$PATH
+ export SHELL=/run/current-system/sw/bin/bash
+
+ export XMONAD_CACHE_DIR="$CACHEDIR"
+ export XMONAD_DATA_DIR="$CACHEDIR"
+ export XMONAD_CONFIG_DIR=/var/empty
+
+ unset XMONAD_STARTUP_HOOK
+
+ cd "$WORKDIR"
+ '';
+ })
diff --git a/tv/5pkgs/haskell/xmonad-tv/src/Helpers/Path.hs b/tv/5pkgs/haskell/xmonad-tv/src/Helpers/Path.hs
new file mode 100644
index 000000000..1029d60be
--- /dev/null
+++ b/tv/5pkgs/haskell/xmonad-tv/src/Helpers/Path.hs
@@ -0,0 +1,15 @@
+module Helpers.Path where
+
+import qualified Data.List
+import qualified System.Directory
+import qualified System.IO.Unsafe
+
+
+findExecutable :: String -> FilePath
+findExecutable =
+ System.IO.Unsafe.unsafePerformIO . find
+ where
+ find name =
+ maybe failure id <$> System.Directory.findExecutable name
+ where
+ failure = error (Data.List.intercalate " " [name, "not found"])
diff --git a/tv/5pkgs/haskell/xmonad-tv/src/Paths.hs b/tv/5pkgs/haskell/xmonad-tv/src/Paths.hs
new file mode 100644
index 000000000..3a879b5d0
--- /dev/null
+++ b/tv/5pkgs/haskell/xmonad-tv/src/Paths.hs
@@ -0,0 +1,25 @@
+module Paths where
+
+import Helpers.Path
+
+
+otpmenu :: FilePath
+otpmenu = findExecutable "otpmenu"
+
+pactl :: FilePath
+pactl = findExecutable "pactl"
+
+passmenu :: FilePath
+passmenu = findExecutable "passmenu"
+
+slock :: FilePath
+slock = findExecutable "slock"
+
+su :: FilePath
+su = findExecutable "su"
+
+urxvtc :: FilePath
+urxvtc = findExecutable "urxvtc"
+
+xcalib :: FilePath
+xcalib = findExecutable "xcalib"
diff --git a/tv/5pkgs/haskell/xmonad-tv/src/main.hs b/tv/5pkgs/haskell/xmonad-tv/src/main.hs
new file mode 100644
index 000000000..b7d4e9bca
--- /dev/null
+++ b/tv/5pkgs/haskell/xmonad-tv/src/main.hs
@@ -0,0 +1,206 @@
+{-# LANGUAGE DeriveDataTypeable #-} -- for XS
+{-# LANGUAGE FlexibleContexts #-} -- for xmonad'
+{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+
+module Main (main) where
+
+import System.Exit (exitFailure)
+
+import Control.Exception
+import Control.Monad.Extra (whenJustM)
+import Graphics.X11.ExtraTypes.XF86
+import Text.Read (readEither)
+import XMonad
+import System.IO (hPutStrLn, stderr)
+import System.Environment (getArgs, getEnv, getEnvironment, lookupEnv)
+import System.Posix.Process (executeFile)
+import XMonad.Actions.DynamicWorkspaces ( addWorkspacePrompt, renameWorkspace
+ , removeEmptyWorkspace)
+import XMonad.Actions.CycleWS (toggleWS)
+import XMonad.Layout.N