summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile12
-rw-r--r--krebs/3modules/setuid.nix6
-rw-r--r--krebs/4lib/types.nix13
-rw-r--r--krebs/5pkgs/builders.nix113
-rw-r--r--tv/1systems/xu.nix1
-rw-r--r--tv/2configs/xserver/default.nix4
-rw-r--r--tv/5pkgs/default.nix1
-rw-r--r--tv/5pkgs/q/default.nix193
-rw-r--r--tv/5pkgs/xmonad-tv.nix25
9 files changed, 336 insertions, 32 deletions
diff --git a/Makefile b/Makefile
index a74e3a877..6e09559b6 100644
--- a/Makefile
+++ b/Makefile
@@ -48,6 +48,14 @@ $(if $(target_user),,$(error unbound variable: target_user))
$(if $(target_port),,$(error unbound variable: target_port))
$(if $(target_path),,$(error unbound variable: target_path))
+build = \
+ nix-build \
+ --no-out-link \
+ --show-trace \
+ -I nixos-config=$(nixos-config) \
+ -I stockholm=$(stockholm) \
+ -E "let build = import <stockholm>; in $(1)"
+
evaluate = \
nix-instantiate \
--eval \
@@ -74,6 +82,10 @@ deploy:
env STOCKHOLM_VERSION="$$STOCKHOLM_VERSION" \
nixos-rebuild switch --show-trace -I $(target_path)
+# usage: make build.pkgs.get
+build build.:;@$(call build,$${expr-eval})
+build.%:;@$(call build,$@)
+
# usage: make LOGNAME=shared system=wolf eval.config.krebs.build.host.name
eval eval.:;@$(call evaluate,$${expr-eval})
eval.%:;@$(call evaluate,$@)
diff --git a/krebs/3modules/setuid.nix b/krebs/3modules/setuid.nix
index cfb8382e8..65a4abe1c 100644
--- a/krebs/3modules/setuid.nix
+++ b/krebs/3modules/setuid.nix
@@ -20,6 +20,10 @@ let
type = types.filename;
default = config._module.args.name;
};
+ envp = mkOption {
+ type = types.attrsOf types.str;
+ default = {};
+ };
filename = mkOption {
type = mkOptionType {
# TODO unyuck string and merge with toC
@@ -57,7 +61,7 @@ let
};
config.activate = let
src = pkgs.execve config.name {
- inherit (config) filename;
+ inherit (config) envp filename;
};
dst = "${wrapperDir}/${config.name}";
in ''
diff --git a/krebs/4lib/types.nix b/krebs/4lib/types.nix
index 56d1d55c3..66191d0b3 100644
--- a/krebs/4lib/types.nix
+++ b/krebs/4lib/types.nix
@@ -286,6 +286,19 @@ types // rec {
};
};
+ haskell.conid = mkOptionType {
+ name = "Haskell constructor identifier";
+ check = x:
+ isString x && match "[[:upper:]][[:lower:]_[:upper:]0-9']*" x != null;
+ merge = mergeOneOption;
+ };
+
+ haskell.modid = mkOptionType {
+ name = "Haskell module identifier";
+ check = x: isString x && all haskell.conid.check (splitString "." x);
+ merge = mergeOneOption;
+ };
+
# RFC952, B. Lexical grammar, <hname>
hostname = mkOptionType {
name = "hostname";
diff --git a/krebs/5pkgs/builders.nix b/krebs/5pkgs/builders.nix
index 39b91d144..f60bbc9d0 100644
--- a/krebs/5pkgs/builders.nix
+++ b/krebs/5pkgs/builders.nix
@@ -1,4 +1,4 @@
-{ config, lib, pkgs, ... }:
+{ config, pkgs, ... }:
with config.krebs.lib;
rec {
execve = name: { filename, argv ? null, envp ? {}, destination ? "" }: let
@@ -28,6 +28,21 @@ rec {
execveBin = name: cfg: execve name (cfg // { destination = "/bin/${name}"; });
+ writeBash = name: text: pkgs.writeScript name ''
+ #! ${pkgs.bash}/bin/bash
+ ${text}
+ '';
+
+ writeBashBin = name: text: pkgs.writeTextFile {
+ executable = true;
+ destination = "/bin/${name}";
+ name = name;
+ text = ''
+ #! ${pkgs.bash}/bin/bash
+ ${text}
+ '';
+ };
+
writeC = name: { destination ? "" }: src: pkgs.runCommand name {} ''
PATH=${makeBinPath (with pkgs; [
binutils
@@ -66,50 +81,112 @@ rec {
mv "$textPath" $out
'';
- writeHaskellBin =
+ writeHaskell =
k:
let
k' = parseDrvName k;
name = k'.name;
version = if k'.version != "" then k'.version else "0";
in
- { build-depends ? ["base"] ++ depends
- , depends ? []
+ { base-depends ? ["base"]
+ , executables ? {}
, ghc-options ? ["-Wall" "-O3" "-threaded" "-rtsopts"]
, haskellPackages ? pkgs.haskellPackages
+ , library ? null
, license ? "WTFPL"
}:
- main-text:
let
+ isExecutable = executables != {};
+ isLibrary = library != null;
+
cabal-file = pkgs.writeText "${name}-${version}.cabal" ''
build-type: Simple
cabal-version: >= 1.2
name: ${name}
version: ${version}
-
- executable ${name}
- build-depends: ${concatStringsSep "," build-depends}
- ghc-options: ${toString ghc-options}
- main-is: ${main-file.name}
+ ${concatStringsSep "\n" (mapAttrsToList exe-section executables)}
+ ${optionalString isLibrary (lib-section library)}
'';
- main-file = pkgs.writeText "${name}-${version}.hs" main-text;
+
+ exe-install =
+ exe-name:
+ { file ? pkgs.writeText "${name}-${exe-name}.hs" text
+ , relpath ? "${exe-name}.hs"
+ , text
+ , ... }:
+ if types.filename.check exe-name
+ then "install -D ${file} $out/${relpath}"
+ else throw "argument ‘exe-name’ is not a ${types.filename.name}";
+
+ exe-section =
+ exe-name:
+ { build-depends ? base-depends ++ extra-depends
+ , extra-depends ? []
+ , file ? pkgs.writeText "${name}-${exe-name}.hs" text
+ , relpath ? "${exe-name}.hs"
+ , text
+ , ... }: ''
+ executable ${exe-name}
+ build-depends: ${concatStringsSep "," build-depends}
+ ghc-options: ${toString ghc-options}
+ main-is: ${relpath}
+ '';
+
+ get-depends =
+ { build-depends ? base-depends ++ extra-depends
+ , extra-depends ? []
+ , ...
+ }:
+ build-depends;
+
+ lib-install =
+ { exposed-modules
+ , ... }:
+ concatStringsSep "\n" (mapAttrsToList mod-install exposed-modules);
+
+ lib-section =
+ { build-depends ? base-depends ++ extra-depends
+ , extra-depends ? []
+ , exposed-modules
+ , ... }: ''
+ library
+ build-depends: ${concatStringsSep "," build-depends}
+ ghc-options: ${toString ghc-options}
+ exposed-modules: ${concatStringsSep "," (attrNames exposed-modules)}
+ '';
+
+ mod-install =
+ mod-name:
+ { file ? pkgs.writeText "${name}-${mod-name}.hs" text
+ , relpath ? "${replaceStrings ["."] ["/"] mod-name}.hs"
+ , text
+ , ... }:
+ if types.haskell.modid.check mod-name
+ then "install -D ${file} $out/${relpath}"
+ else throw "argument ‘mod-name’ is not a ${types.haskell.modid.name}";
in
- haskellPackages.mkDerivation rec {
- inherit license version;
- executableHaskellDepends = attrVals build-depends haskellPackages;
- isExecutable = true;
- isLibrary = false;
+ haskellPackages.mkDerivation {
+ inherit isExecutable isLibrary license version;
+ executableHaskellDepends =
+ attrVals
+ (concatMap get-depends (attrValues executables))
+ haskellPackages;
+ libraryHaskellDepends =
+ attrVals
+ (optionals isLibrary (get-depends library))
+ haskellPackages;
pname = name;
src = pkgs.runCommand "${name}-${version}-src" {} ''
install -D ${cabal-file} $out/${cabal-file.name}
- install -D ${main-file} $out/${main-file.name}
+ ${optionalString isLibrary (lib-install library)}
+ ${concatStringsSep "\n" (mapAttrsToList exe-install executables)}
'';
};
writeNixFromCabal =
trace (toString [
"The function `writeNixFromCabal` has been deprecated in favour of"
- "`writeHaskellBin'."
+ "`writeHaskell`."
])
(name: path: pkgs.runCommand name {} ''
${pkgs.cabal2nix}/bin/cabal2nix ${path} > $out
diff --git a/tv/1systems/xu.nix b/tv/1systems/xu.nix
index 96a0545a7..a79ae498b 100644
--- a/tv/1systems/xu.nix
+++ b/tv/1systems/xu.nix
@@ -60,6 +60,7 @@ with config.krebs.lib;
nmap
p7zip
pass
+ q
qrencode
texLive
tmux
diff --git a/tv/2configs/xserver/default.nix b/tv/2configs/xserver/default.nix
index 965c3bbe1..c41c0a81e 100644
--- a/tv/2configs/xserver/default.nix
+++ b/tv/2configs/xserver/default.nix
@@ -74,8 +74,8 @@ in {
};
serviceConfig = {
SyslogIdentifier = "xmonad";
- ExecStart = "${pkgs.xmonad-tv}/bin/xmonad-tv";
- ExecStop = "${pkgs.xmonad-tv}/bin/xmonad-tv --shutdown";
+ ExecStart = "${pkgs.xmonad-tv}/bin/xmonad";
+ ExecStop = "${pkgs.xmonad-tv}/bin/xmonad --shutdown";
User = user.name;
WorkingDirectory = user.home;
};
diff --git a/tv/5pkgs/default.nix b/tv/5pkgs/default.nix
index 05dc02887..da3c914b8 100644
--- a/tv/5pkgs/default.nix
+++ b/tv/5pkgs/default.nix
@@ -17,6 +17,7 @@
erlang = pkgs.erlangR16;
};
ff = pkgs.callPackage ./ff {};
+ q = pkgs.callPackage ./q {};
viljetic-pages = pkgs.callPackage ./viljetic-pages {};
xmonad-tv = import ./xmonad-tv.nix { inherit pkgs; };
};
diff --git a/tv/5pkgs/q/default.nix b/tv/5pkgs/q/default.nix
new file mode 100644
index 000000000..1d08a5447
--- /dev/null
+++ b/tv/5pkgs/q/default.nix
@@ -0,0 +1,193 @@
+{ pkgs, ... }:
+let
+ q-cal = let
+ # XXX 23 is the longest line of cal's output
+ pad = ''{
+ ${pkgs.gnused}/bin/sed '
+ # rtrim
+ s/ *$//
+
+ # delete last empty line
+ ''${/^$/d}
+ ' \
+ | ${pkgs.gawk}/bin/awk '{printf "%-23s\n", $0}' \
+ | ${pkgs.gnused}/bin/sed '
+ # colorize header
+ 1,2s/.*/&/
+
+ # colorize week number
+ s/^[ 1-9][0-9]/&/
+ '
+ }'';
+ in ''
+ ${pkgs.coreutils}/bin/paste \
+ <(${pkgs.utillinux}/bin/cal -mw \
+ $(${pkgs.coreutils}/bin/date +'%m %Y' -d 'last month') \
+ | ${pad}
+ ) \
+ <(${pkgs.utillinux}/bin/cal -mw \
+ | ${pkgs.gnused}/bin/sed '
+ # colorize day of month
+ s/\(^\| \)'"$(${pkgs.coreutils}/bin/date +%e)"'\>/&/
+ ' \
+ | ${pad}
+ ) \
+ <(${pkgs.utillinux}/bin/cal -mw \
+ $(${pkgs.coreutils}/bin/date +'%m %Y' -d 'next month') \
+ | ${pad}
+ ) \
+ | ${pkgs.gnused}/bin/sed 's/\t/ /g'
+ '';
+
+ q-isodate = ''
+ ${pkgs.coreutils}/bin/date \
+ '+%Y-%m-%dT%H:%M:%S%:z'
+ '';
+
+ # Singapore's red is #ED2E38
+ q-sgtdate = ''
+ TZ=Asia/Singapore \
+ ${pkgs.coreutils}/bin/date \
+ '+%Y-%m-%dT%H:%M:%S%:z'
+ '';
+
+ q-gitdir = ''
+ if test -d .git; then
+ #git status --porcelain
+ branch=$(
+ ${pkgs.git}/bin/git branch \
+ | ${pkgs.gnused}/bin/sed -rn 's/^\* (.*)/\1/p'
+ )
+ echo "± $LOGNAME@''${HOSTNAME-$(${pkgs.nettools}/bin/hostname)}:$PWD .git $branch"
+ fi
+ '';
+
+ q-power_supply = ''
+ for uevent in /sys/class/power_supply/*/uevent; do
+ if test -f $uevent; then
+ eval "$(${pkgs.gnused}/bin/sed -n '
+ s/^\([A-Z_]\+=\)\(.*\)/\1'\'''\2'\'''/p
+ ' $uevent)"
+
+ if test "x''${POWER_SUPPLY_CHARGE_NOW-}" = x; then
+ continue
+ fi
+
+ charge_percentage=$(echo "
+ scale=2
+ $POWER_SUPPLY_CHARGE_NOW / $POWER_SUPPLY_CHARGE_FULL
+ " | ${pkgs.bc}/bin/bc)
+
+ lfc=$POWER_SUPPLY_CHARGE_FULL
+ rc=$POWER_SUPPLY_CHARGE_NOW
+ #rc=2800
+ N=78; N=76
+ N=10
+ n=$(echo $N-1 | ${pkgs.bc}/bin/bc)
+ centi=$(echo "$rc*100/$lfc" | ${pkgs.bc}/bin/bc)
+ deci=$(echo "$rc*$N/$lfc" | ${pkgs.bc}/bin/bc)
+ energy_evel=$(
+ echo -n '☳ ' # TRIGRAM FOR THUNDER
+ if test $centi -ge 42; then echo -n ''
+ elif test $centi -ge 23; then echo -n ''
+ elif test $centi -ge 11; then echo -n ''
+ else echo -n ''; fi
+ for i in $(${pkgs.coreutils}/bin/seq 1 $deci); do
+ echo -n ■
+ done
+ echo -n ''
+ for i in $(${pkgs.coreutils}/bin/seq $deci $n); do
+ echo -n ■
+ done
+ echo '' $rc #/ $lfc
+ )
+ echo "$energy_evel $charge_percentage"
+ fi
+ done
+ '';
+
+ q-virtualization = ''
+ echo "VT: $(${pkgs.systemd}/bin/systemd-detect-virt)"
+ '';
+
+ q-wireless = ''
+ for dev in $(
+ ${pkgs.iw}/bin/iw dev \
+ | ${pkgs.gnused}/bin/sed -n 's/^\s*Interface\s\+\([0-9a-z]\+\)$/\1/p'
+ ); do
+ inet=$(${pkgs.iproute}/bin/ip addr show $dev \
+ | ${pkgs.gnused}/bin/sed -n '
+ s/.*inet \([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+\).*/\1/p
+ ') \
+ || unset inet
+ ssid=$(${pkgs.iw}/bin/iw dev $dev link \
+ | ${pkgs.gnused}/bin/sed -n '
+ s/.*\tSSID: \(.*\)/\1/p
+ ') \
+ || unset ssid
+ echo "$dev''${inet+ $inet}''${ssid+ $ssid}"
+ done
+ '';
+
+ q-online = ''
+ if ${pkgs.curl}/bin/curl -s google.com >/dev/null; then
+ echo 'online'
+ else
+ echo offline
+ fi
+ '';
+
+ q-thermal_zone = ''
+ for i in /sys/class/thermal/thermal_zone*; do
+ type=$(${pkgs.coreutils}/bin/cat $i/type)
+ temp=$(${pkgs.coreutils}/bin/cat $i/temp)
+ printf '%s %s°C\n' $type $(echo $temp / 1000 | ${pkgs.bc}/bin/bc)
+ done
+ '';
+
+ q-todo = ''
+ TODO_file=$HOME/TODO
+ if test -e "$TODO_file"; then
+ ${pkgs.coreutils}/bin/cat "$TODO_file" \
+ | ${pkgs.gawk}/bin/gawk -v now=$(${pkgs.coreutils}/bin/date +%s) '
+ BEGIN { print "remind=0" }
+ /^[0-9]/{
+ x = $1
+ gsub(".", "\\\\&", x)
+ rest = substr($0, index($0, " "))
+ rest = $0
+ sub(" *", "", rest)
+ gsub(".", "\\\\&", rest)
+ print "test $(${pkgs.coreutils}/bin/date +%s -d"x") -lt "now" && \
+ echo \"\x1b[38;5;208m\""rest esc "\"\x1b[m\" && \
+ (( remind++ ))"
+ }
+ END { print "test $remind = 0 && echo \"nothing to remind\"" }
+ ' \
+ | {
+ # bash needed for (( ... ))
+ ${pkgs.bash}/bin/bash
+ }
+ else
+ echo "$TODO_file: no such file or directory"
+ fi
+ '';
+
+in
+# bash needed for <(...)
+pkgs.writeBashBin "q" ''
+ set -eu
+ export PATH=/var/empty
+ ${q-cal}
+ echo
+ ${q-isodate}
+ ${q-sgtdate}
+ (${q-gitdir}) &
+ (${q-power_supply}) &
+ (${q-virtualization}) &
+ (${q-wireless}) &
+ (${q-online}) &
+ (${q-thermal_zone}) &
+ wait
+ ${q-todo}
+''
diff --git a/tv/5pkgs/xmonad-tv.nix b/tv/5pkgs/xmonad-tv.nix
index 74e43dc79..04e7e8359 100644
--- a/tv/5pkgs/xmonad-tv.nix
+++ b/tv/5pkgs/xmonad-tv.nix
@@ -1,14 +1,15 @@
{ pkgs, ... }:
-pkgs.writeHaskellBin "xmonad-tv" {
- depends = [
- "containers"
- "unix"
- "X11"
- "xmonad"
- "xmonad-contrib"
- "xmonad-stockholm"
- ];
-} ''
+pkgs.writeHaskell "xmonad-tv" {
+ executables.xmonad = {
+ extra-depends = [
+ "containers"
+ "unix"
+ "X11"
+ "xmonad"
+ "xmonad-contrib"
+ "xmonad-stockholm"
+ ];
+ text = ''
{-# LANGUAGE DeriveDataTypeable #-} -- for XS
{-# LANGUAGE FlexibleContexts #-} -- for xmonad'
{-# LANGUAGE LambdaCase #-}
@@ -299,4 +300,6 @@ wGSConfig = def
allWorkspaceNames :: W.StackSet i l a sid sd -> X [i]
allWorkspaceNames ws =
return $ map W.tag (W.hidden ws) ++ [W.tag $ W.workspace $ W.current ws]
-''
+ '';
+ };
+}