Merge remote-tracking branch 'cd/master' into pre-merge

This commit is contained in:
makefu 2015-11-14 01:50:39 +01:00
commit a0fbe917ac
37 changed files with 394 additions and 1516 deletions

View File

@ -13,40 +13,36 @@ let stockholm = {
krebs = import ./krebs (args // { inherit lib stockholm; });
lib =
let
lib = import <nixpkgs/lib>;
klib = import ./krebs/4lib { inherit lib; };
#ulib = import (./. + "/${current-user-name}/4lib") { lib = lib // klib; };
ulib = {}; # TODO
in
builtins // lib // klib // ulib // rec {
# TODO move this stuff
lib = let
nlib = import <nixpkgs/lib>;
klib = import (slib.kpath "4lib") { lib = nlib; };
slib = rec {
stockholm-path = ./.;
nspath = ns: p: stockholm-path + "/${ns}/${p}";
kpath = nspath "krebs";
upath = nspath current-user-name;
};
ulib = let p = slib.upath "4lib"; in
nlib.optionalAttrs (klib.dir.has-default-nix p)
(import p { lib = nlib // klib; });
in nlib // klib // slib // ulib // builtins;
inherit (eval {}) pkgs;
kpath = lib.nspath "krebs";
upath = lib.nspath current-user-name;
base-module = { config, ... }: {
imports = builtins.filter builtins.pathExists (lib.concatLists [
(map (f: f "2configs") [ upath ])
(map (f: f "3modules") [ kpath upath ])
imports = builtins.filter lib.dir.has-default-nix (lib.concatLists [
(map (f: f "2configs") [ lib.upath ])
(map (f: f "3modules") [ lib.kpath lib.upath ])
]);
krebs.current.enable = true;
krebs.current.host = config.krebs.hosts.${current-host-name};
krebs.current.user = config.krebs.users.${current-user-name};
nixpkgs.config.packageOverrides = pkgs:
let
kpkgs = import (kpath "5pkgs") { inherit lib pkgs; };
upkgs = import (upath "5pkgs") { inherit lib; pkgs = pkgs // kpkgs; };
in
kpkgs // upkgs;
nixpkgs.config.packageOverrides = pkgs: let
kpkgs = import (lib.kpath "5pkgs") { inherit lib pkgs; };
upkgs = import (lib.upath "5pkgs") { inherit lib; pkgs = pkgs // kpkgs; };
in kpkgs // upkgs;
};
eval = config: import <nixpkgs/nixos/lib/eval-config.nix> {

View File

@ -96,8 +96,8 @@ in {
'';
};
};
ssh.privkey.path = <secrets/ssh.id_ed25519>;
ssh.pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINKVjJrM7fHfHpvZXEA3hmX4JliHl6h6Q8AGOPcu+9fF";
ssh.privkey.path = <secrets/ssh.id_rsa>;
ssh.pubkey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQChm4sqQ2bUZj+2YnTf6G5HHRTpSe1jTUhJRnwcYPYZKF+CBqBncipRpuGlGXEsptNa+7ZMcQC0ySsz5SUOMt3Ih+NehVe/qt3VtRz0l0MgOWmH2qBwKK9Y4IuxrJQzUmP4UGlOGlFj9DORssSMOyFIG4eZ9k2qMn3xal0NVRfGTShKlouWsiUILZ8I+sDNE00z8DAYesgc1yazvRnjzvLkRxdNdpYiAFBbmXMpPKK95McRJaWsuNSeal9kd5p5PagWcgN4DZ6+ebzz3NKnmzk4j+vuHX0U9lTXBqKMlzzmM2YNLRtDPfrtJNyHqLpZUpFhJKqZCD+4/0zdrzRfC7Th+5czzUCSvHiKPVsqw5eOdiQX6EyzNAF5zpkpRp//QdUNNXC5/Ku6GKCO491+TuA8VCha0fOwBONccTLUI/hGNmCh88mLbukVoeGJrbYNCOA/6kEz7ZLEveU4i+TT7okhDElMsNk+AWCZ8/NdJQNX3/K6+JJ9qAn+/yC8LdjgYYJ2oU/aw5/HyOgiQ0z4n9UfQ7j+nHysY9CQb1b3guX7yjJoc3KpNXCXEztuIRHjFD1EP8NRTSmGjsa/VjLmTLSsqjD+7IE5mT0tO5RJvmagDgdJSr/iR5D9zjW7hx7ttvektrlp9g0v3CiCFVaW4l95hGYT0HaNBLJ5R0YHm0lD+Q==";
};
fastpoke = {
dc = "lass";

View File

@ -159,7 +159,7 @@ with lib;
};
secure = true;
ssh.privkey.path = <secrets/ssh.id_ed25519>;
ssh.pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILMPMh3nHxVcPqM+LrkK7eYxNJY1ShBXOTg1vlSR45wx";
ssh.pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMIHmwXHV7E9UGuk4voVCADjlLkyygqNw054jvrsPn5t root@nomic";
};
ok = {
nets = {
@ -277,7 +277,8 @@ with lib;
};
};
secure = true;
ssh.pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAID554niVFWomJjuSuQoiCdMUYrCFPpPzQuaoXXYYDxlw";
ssh.privkey.path = <secrets/ssh.id_ed25519>;
ssh.pubkey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPnjfceKuHNQu7S4eYFN1FqgzMqiL7haNZMh2ZLhvuhK root@xu";
};
};
users = addNames rec {

View File

@ -3,7 +3,7 @@
with builtins;
with lib;
rec {
let out = rec {
eq = x: y: x == y;
@ -14,7 +14,10 @@ rec {
types = import ./types.nix { inherit lib; };
dir.has-default-nix = path: pathExists (path + "/default.nix");
dns = import ./dns.nix { inherit lib; };
git = import ./git.nix { lib = lib // out; };
listset = import ./listset.nix { inherit lib; };
shell = import ./shell.nix { inherit lib; };
tree = import ./tree.nix { inherit lib; };
@ -28,4 +31,8 @@ rec {
subdirsOf = path:
mapAttrs (name: _: path + "/${name}")
(filterAttrs (_: eq "directory") (readDir path));
}
mapAttrValues = f: mapAttrs (_: f);
setAttr = name: value: set: set // { ${name} = value; };
}; in out

42
krebs/4lib/git.nix Normal file
View File

@ -0,0 +1,42 @@
{ lib, ... }:
let
inherit (lib) addNames escapeShellArg makeSearchPath optionalString;
commands = addNames {
git-receive-pack = {};
git-upload-pack = {};
};
receive-modes = addNames {
fast-forward = {};
non-fast-forward = {};
create = {};
delete = {};
merge = {}; # TODO implement in git.nix
};
permissions = {
fetch = {
allow-commands = [
commands.git-upload-pack
];
};
push = ref: extra-modes: {
allow-commands = [
commands.git-receive-pack
commands.git-upload-pack
];
allow-receive-ref = ref;
allow-receive-modes = [ receive-modes.fast-forward ] ++ extra-modes;
};
};
refs = {
master = "refs/heads/master";
all-heads = "refs/heads/*";
};
in
commands // receive-modes // permissions // refs

View File

@ -0,0 +1,168 @@
{ lib, pkgs, ... }:
with lib;
let
out = {
inherit irc-announce;
};
# TODO irc-announce should return a derivation
irc-announce = { nick, channel, server, port ? 6667, verbose ? false }: ''
#! /bin/sh
set -euf
export PATH=${makeSearchPath "bin" (with pkgs; [
coreutils
git
gnused
])}
green() { printf '\x0303,99%s\x0F' "$1"; }
red() { printf '\x0304,99%s\x0F' "$1"; }
orange() { printf '\x0307,99%s\x0F' "$1"; }
pink() { printf '\x0313,99%s\x0F' "$1"; }
gray() { printf '\x0314,99%s\x0F' "$1"; }
unset message
add_message() {
message="''${message+$message
}$*"
}
nick=${escapeShellArg nick}
channel=${escapeShellArg channel}
server=${escapeShellArg server}
port=${toString port}
host=$nick
cgit_endpoint=http://cgit.$host
empty=0000000000000000000000000000000000000000
while read oldrev newrev ref; do
if [ $oldrev = $empty ]; then
receive_mode=create
elif [ $newrev = $empty ]; then
receive_mode=delete
elif [ "$(git merge-base $oldrev $newrev)" = $oldrev ]; then
receive_mode=fast-forward
else
receive_mode=non-fast-forward
fi
h=$(echo $ref | sed 's:^refs/heads/::')
# empty_tree=$(git hash-object -t tree /dev/null)
empty_tree=4b825dc6
id=$(echo $newrev | cut -b-7)
id2=$(echo $oldrev | cut -b-7)
if [ $newrev = $empty ]; then id=$empty_tree; fi
if [ $oldrev = $empty ]; then id2=$empty_tree; fi
case $receive_mode in
create)
link="$cgit_endpoint/$GIT_SSH_REPO/?h=$h"
;;
delete)
link="$cgit_endpoint/$GIT_SSH_REPO/ ($h)"
;;
fast-forward|non-fast-forward)
link="$cgit_endpoint/$GIT_SSH_REPO/diff/?h=$h&id=$id&id2=$id2"
;;
esac
#$host $GIT_SSH_REPO $ref $link
add_message $(pink push) $link $(gray "($receive_mode)")
${optionalString verbose ''
add_message "$(
git log \
--format="$(orange %h) %s $(gray '(%ar)')" \
--reverse \
$id2..$id
git diff --stat $id2..$id \
| sed '$!s/\(+*\)\(-*\)$/'$(green '\1')$(red '\2')'/'
)"
''}
done
if test -n "''${message-}"; then
exec ${irc-announce-script} \
"$server" \
"$port" \
"$nick" \
"$channel" \
"$message"
fi
'';
irc-announce-script = pkgs.writeScript "irc-announce-script" ''
#! /bin/sh
set -euf
export PATH=${makeSearchPath "bin" (with pkgs; [
coreutils
gawk
gnused
netcat
nettools
])}
IRC_SERVER=$1
IRC_PORT=$2
IRC_NICK=$3$$
IRC_CHANNEL=$4
message=$5
export IRC_CHANNEL # for privmsg_cat
# echo2 and cat2 are used output to both, stdout and stderr
# This is used to see what we send to the irc server. (debug output)
echo2() { echo "$*"; echo "$*" >&2; }
cat2() { tee /dev/stderr; }
# privmsg_cat transforms stdin to a privmsg
privmsg_cat() { awk '{ print "PRIVMSG "ENVIRON["IRC_CHANNEL"]" :"$0 }'; }
# ircin is used to feed the output of netcat back to the "irc client"
# so we can implement expect-like behavior with sed^_^
# XXX mkselfdestructingtmpfifo would be nice instead of this cruft
tmpdir="$(mktemp -d irc-announce_XXXXXXXX)"
cd "$tmpdir"
mkfifo ircin
trap "
rm ircin
cd '$OLDPWD'
rmdir '$tmpdir'
trap - EXIT INT QUIT
" EXIT INT QUIT
{
echo2 "USER $LOGNAME 0 * :$LOGNAME@$(hostname)"
echo2 "NICK $IRC_NICK"
# wait for MODE message
sed -n '/^:[^ ]* MODE /q'
echo2 "JOIN $IRC_CHANNEL"
printf '%s' "$message" \
| privmsg_cat \
| cat2
echo2 "PART $IRC_CHANNEL"
# wait for PART confirmation
sed -n '/:'"$IRC_NICK"'![^ ]* PART /q'
echo2 'QUIT :Gone to have lunch'
} < ircin \
| nc "$IRC_SERVER" "$IRC_PORT" | tee -a ircin
'';
in out

View File

@ -0,0 +1,16 @@
{ mkDerivation, base, containers, fetchgit, stdenv, X11, X11-xshape
, xmonad, xmonad-contrib
}:
mkDerivation {
pname = "xmonad-stockholm";
version = "1.0.0";
src = fetchgit {
url = "http://cgit.cd/xmonad-stockholm";
sha256 = "35dda5d16acc90af94ae2fae10ab5cc2d5b450c3f1ff2e7f515ac53877269abf";
rev = "2dbefe42fc5cfe9093465bf3e22ba8f82feeef6e";
};
libraryHaskellDepends = [
base containers X11 X11-xshape xmonad xmonad-contrib
];
license = stdenv.lib.licenses.mit;
}

View File

@ -9,12 +9,12 @@
, ... }:
stdenv.mkDerivation {
name = "push-1.1.0";
name = "push-1.1.1";
src = fetchgit {
url = http://cgit.cd.retiolum/push;
rev = "c5f4bda5bd00bad7778bbd5a9af8d476de0de920";
sha256 = "d335b644b791214263cee5c6659538c8e45326531b0588e5e7eb3bd9ef969800";
rev = "ea8b76569c6b226fe148e559477669b095408472";
sha256 = "c305a1515d30603f6ed825d44487e863fdc7d90400620ceaf2c335a3b5d1e221";
};
phases = [
@ -45,4 +45,3 @@ stdenv.mkDerivation {
chmod +x $out/bin/push
'';
}

View File

@ -156,6 +156,7 @@
get
genid
teamspeak_client
hashPassword
];
#TODO: fix this shit

View File

@ -8,6 +8,8 @@ in {
imports = [
../2configs/base.nix
../2configs/downloading.nix
../2configs/git.nix
../2configs/ts3.nix
{
users.extraGroups = {
# ● systemd-tmpfiles-setup.service - Create Volatile Files and Directories
@ -82,6 +84,9 @@ in {
#workaround for server dying after 6-7h
boot.kernelPackages = pkgs.linuxPackages_4_2;
}
{
nixpkgs.config.allowUnfree = true;
}
];
krebs.build.host = config.krebs.hosts.prism;

View File

@ -15,8 +15,8 @@ with lib;
{
users.extraUsers = {
root = {
openssh.authorizedKeys.keys = map readFile [
../../krebs/Zpubkeys/lass.ssh.pub
openssh.authorizedKeys.keys = [
config.krebs.users.lass.pubkey
];
};
mainUser = {
@ -28,8 +28,8 @@ with lib;
useDefaultShell = true;
extraGroups = [
];
openssh.authorizedKeys.keys = map readFile [
../../krebs/Zpubkeys/lass.ssh.pub
openssh.authorizedKeys.keys = [
config.krebs.users.lass.pubkey
];
};
};

View File

@ -1,7 +1,10 @@
{ config, lib, pkgs, ... }:
with lib;
{
let
rpc-password = import <secrets/transmission-pw.nix>;
in {
imports = [
../3modules/folderPerms.nix
];
@ -15,8 +18,8 @@ with lib;
extraGroups = [
"download"
];
openssh.authorizedKeys.keys = map readFile [
../../krebs/Zpubkeys/lass.ssh.pub
openssh.authorizedKeys.keys = [
config.krebs.users.lass.pubkey
];
};
@ -46,8 +49,7 @@ with lib;
rpc-authentication-required = true;
rpc-whitelist-enabled = false;
rpc-username = "download";
#add rpc-password in secrets
rpc-password = "test123";
inherit rpc-password;
peer-port = 51413;
};
};

19
lass/2configs/ts3.nix Normal file
View File

@ -0,0 +1,19 @@
{ config, ... }:
{
services.teamspeak3 = {
enable = true;
};
krebs.iptables.tables.filter.INPUT.rules = [
#voice port
{ predicate = "-p tcp --dport 9987"; target = "ACCEPT"; }
{ predicate = "-p udp --dport 9987"; target = "ACCEPT"; }
##file transfer port
#{ predicate = "-p tcp --dport 30033"; target = "ACCEPT"; }
#{ predicate = "-p udp --dport 30033"; target = "ACCEPT"; }
##query port
#{ predicate = "-p tcp --dport 10011"; target = "ACCEPT"; }
#{ predicate = "-p udp --dport 10011"; target = "ACCEPT"; }
];
}

1
null/default.nix Normal file
View File

@ -0,0 +1 @@
_:{}

View File

@ -4,23 +4,8 @@ with lib;
{
krebs.build.host = config.krebs.hosts.cd;
krebs.build.user = config.krebs.users.tv;
krebs.build.target = "root@cd.internet";
krebs.build.source = {
git.nixpkgs = {
url = https://github.com/NixOS/nixpkgs;
rev = "c44a593aa43bba6a0708f6f36065a514a5110613";
};
dir.secrets = {
path = "/home/tv/secrets/cd";
};
dir.stockholm = {
path = "/home/tv/stockholm";
};
};
imports = [
../2configs/hw/CAC-Developer-2.nix
../2configs/fs/CAC-CentOS-7-64bit.nix
@ -115,7 +100,6 @@ with lib;
iftop
iotop
iptables
mutt # for mv
nethogs
ntp # ntpate
rxvt_unicode.terminfo
@ -126,17 +110,4 @@ with lib;
SystemMaxUse=1G
RuntimeMaxUse=128M
'';
users.extraUsers = {
mv = {
uid = 1338;
group = "users";
home = "/home/mv";
createHome = true;
useDefaultShell = true;
openssh.authorizedKeys.keys = [
config.krebs.users.mv.pubkey
];
};
};
}

View File

@ -17,23 +17,8 @@ in
{
krebs.build.host = config.krebs.hosts.mkdir;
krebs.build.user = config.krebs.users.tv;
krebs.build.target = "root@${primary-addr4}";
krebs.build.source = {
git.nixpkgs = {
url = https://github.com/NixOS/nixpkgs;
rev = "c44a593aa43bba6a0708f6f36065a514a5110613";
};
dir.secrets = {
path = "/home/tv/secrets/mkdir";
};
dir.stockholm = {
path = "/home/tv/stockholm";
};
};
imports = [
../2configs/hw/CAC-Developer-1.nix
../2configs/fs/CAC-CentOS-7-64bit.nix

View File

@ -4,23 +4,9 @@ with lib;
{
krebs.build.host = config.krebs.hosts.nomic;
krebs.build.user = config.krebs.users.tv;
krebs.build.target = "root@nomic.gg23";
krebs.build.source = {
git.nixpkgs = {
url = https://github.com/NixOS/nixpkgs;
rev = "c44a593aa43bba6a0708f6f36065a514a5110613";
};
dir.secrets = {
path = "/home/tv/secrets/nomic";
};
dir.stockholm = {
path = "/home/tv/stockholm";
};
};
imports = [
../2configs/hw/AO753.nix
#../2configs/consul-server.nix

View File

@ -17,23 +17,9 @@ in
{
krebs.build.host = config.krebs.hosts.rmdir;
krebs.build.user = config.krebs.users.tv;
krebs.build.target = "root@rmdir.internet";
krebs.build.source = {
git.nixpkgs = {
url = https://github.com/NixOS/nixpkgs;
rev = "c44a593aa43bba6a0708f6f36065a514a5110613";
};
dir.secrets = {
path = "/home/tv/secrets/rmdir";
};
dir.stockholm = {
path = "/home/tv/stockholm";
};
};
imports = [
../2configs/hw/CAC-Developer-1.nix
../2configs/fs/CAC-CentOS-7-64bit.nix

View File

@ -4,24 +4,6 @@ with lib;
{
krebs.build.host = config.krebs.hosts.wu;
krebs.build.user = config.krebs.users.tv;
krebs.build.target = "root@wu";
krebs.build.source = {
git.nixpkgs = {
url = https://github.com/NixOS/nixpkgs;
rev = "c44a593aa43bba6a0708f6f36065a514a5110613";
target-path = "/var/src/nixpkgs";
};
dir.secrets = {
path = "/home/tv/secrets/wu";
};
dir.stockholm = {
path = "/home/tv/stockholm";
target-path = "/var/src/stockholm";
};
};
imports = [
../2configs/hw/w110er.nix
@ -29,7 +11,6 @@ with lib;
../2configs/git.nix
../2configs/mail-client.nix
../2configs/xserver
../2configs/z.nix
{
environment.systemPackages = with pkgs; [
@ -62,31 +43,24 @@ with lib;
bind # dig
cac
dic
ff
file
get
gitAndTools.qgit
gnupg21
haskellPackages.hledger
htop
jq
manpages
mkpasswd
mpv
netcat
nix-repl
nmap
nq
p7zip
pavucontrol
posix_man_pages
pssh
push
qrencode
sxiv
texLive
tmux
zathura
#ack
#apache-httpd
@ -145,6 +119,8 @@ with lib;
#xkill
#xl2tpd
#xsel
unison
];
}
{
@ -180,122 +156,6 @@ with lib;
];
};
}
{
users.extraGroups = {
tv.gid = 1337;
slaves.gid = 3799582008; # genid slaves
};
users.extraUsers =
mapAttrs (name: user@{ extraGroups ? [], ... }: user // {
inherit name;
home = "/home/${name}";
createHome = true;
useDefaultShell = true;
group = "tv";
extraGroups = ["slaves"] ++ extraGroups;
}) {
ff = {
uid = 13378001;
extraGroups = [
"audio"
"video"
];
};
cr = {
uid = 13378002;
extraGroups = [
"audio"
"video"
];
};
fa = {
uid = 2300001;
};
rl = {
uid = 2300002;
};
tief = {
uid = 2300702;
};
btc-bitcoind = {
uid = 2301001;
};
btc-electrum = {
uid = 2301002;
};
ltc-litecoind = {
uid = 2301101;
};
eth = {
uid = 2302001;
};
emse-hsdb = {
uid = 4200101;
};
wine = {
uid = 13370400;
extraGroups = [
"audio"
"video"
];
};
df = {
uid = 13370401;
extraGroups = [
"audio"
"video"
];
};
xr = {
uid = 13370061;
extraGroups = [
"audio"
"video"
];
};
"23" = {
uid = 13370023;
};
electrum = {
uid = 13370102;
};
skype = {
uid = 6660001;
extraGroups = [
"audio"
];
};
onion = {
uid = 6660010;
};
};
security.sudo.extraConfig =
let
isSlave = u: elem "slaves" u.extraGroups;
masterOf = u: u.group;
slaves = filterAttrs (_: isSlave) config.users.extraUsers;
toSudoers = u: "${masterOf u} ALL=(${u.name}) NOPASSWD: ALL";
in
concatMapStringsSep "\n" toSudoers (attrValues slaves);
}
];
boot.initrd.luks = {

View File

@ -4,22 +4,9 @@ with lib;
{
krebs.build.host = config.krebs.hosts.xu;
krebs.build.user = config.krebs.users.tv;
krebs.build.target = "root@xu";
krebs.build.source = {
git.nixpkgs = {
url = https://github.com/NixOS/nixpkgs;
rev = "c44a593aa43bba6a0708f6f36065a514a5110613";
};
dir.secrets = {
path = "/home/tv/secrets/xu";
};
dir.stockholm = {
path = "/home/tv/stockholm";
};
};
krebs.build.source.git.nixpkgs.rev =
"7ae05edcdd14f6ace83ead9bf0d114e97c89a83a";
imports = [
../2configs/hw/x220.nix
@ -27,7 +14,6 @@ with lib;
../2configs/git.nix
../2configs/mail-client.nix
../2configs/xserver
../2configs/z.nix
{
environment.systemPackages = with pkgs; [
@ -60,29 +46,23 @@ with lib;
bind # dig
#cac
dic
ff
file
gitAndTools.qgit #xserver
gnupg21
haskellPackages.hledger
htop
jq
manpages
mkpasswd
mpv #xserver
netcat
nix-repl
nmap
nq
p7zip
pavucontrol #xserver
pass
posix_man_pages
#pssh
qrencode
sxiv #xserver
texLive
tmux
zathura #xserver
#ack
#apache-httpd
@ -140,6 +120,8 @@ with lib;
#xkill
#xl2tpd
#xsel
unison
];
}
{
@ -176,125 +158,6 @@ with lib;
];
};
}
{
users.extraGroups = {
tv.gid = 1337;
slaves.gid = 3799582008; # genid slaves
};
users.extraUsers =
mapAttrs (name: user@{ extraGroups ? [], ... }: user // {
inherit name;
home = "/home/${name}";
createHome = true;
useDefaultShell = true;
group = "tv";
extraGroups = ["slaves"] ++ extraGroups;
}) {
ff = {
uid = 13378001;
extraGroups = [
"audio"
"video"
];
};
cr = {
uid = 13378002;
extraGroups = [
"audio"
"video"
"bumblebee"
];
};
fa = {
uid = 2300001;
};
rl = {
uid = 2300002;
};
tief = {
uid = 2300702;
};
btc-bitcoind = {
uid = 2301001;
};
btc-electrum = {
uid = 2301002;
};
ltc-litecoind = {
uid = 2301101;
};
eth = {
uid = 2302001;
};
emse-hsdb = {
uid = 4200101;
};
wine = {
uid = 13370400;
extraGroups = [
"audio"
"video"
"bumblebee"
];
};
df = {
uid = 13370401;
extraGroups = [
"audio"
"video"
"bumblebee"
];
};
xr = {
uid = 13370061;
extraGroups = [
"audio"
"video"
];
};
"23" = {
uid = 13370023;
};
electrum = {
uid = 13370102;
};
skype = {
uid = 6660001;
extraGroups = [
"audio"
];
};
onion = {
uid = 6660010;
};
};
security.sudo.extraConfig =
let
isSlave = u: elem "slaves" u.extraGroups;
masterOf = u: u.group;
slaves = filterAttrs (_: isSlave) config.users.extraUsers;
toSudoers = u: "${masterOf u} ALL=(${u.name}) NOPASSWD: ALL";
in
concatMapStringsSep "\n" toSudoers (attrValues slaves);
}
];
boot.initrd.luks = {
@ -349,7 +212,6 @@ with lib;
security.setuidPrograms = [
"sendmail" # for cron
#"slock"
];
services.printing.enable = true;

View File

@ -5,9 +5,29 @@ with lib;
{
krebs.enable = true;
krebs.build = {
user = config.krebs.users.tv;
target = mkDefault "root@${config.krebs.build.host.name}";
source = {
git.nixpkgs = {
url = mkDefault https://github.com/NixOS/nixpkgs;
rev = mkDefault "c44a593aa43bba6a0708f6f36065a514a5110613";
target-path = mkDefault "/var/src/nixpkgs";
};
dir.secrets = {
path = mkDefault "/home/tv/secrets/${config.krebs.build.host.name}";
};
dir.stockholm = {
path = mkDefault "/home/tv/stockholm";
target-path = mkDefault "/var/src/stockholm";
};
};
};
networking.hostName = config.krebs.build.host.name;
imports = [
<secrets>
./vim.nix
{
# stockholm dependencies
@ -16,40 +36,14 @@ with lib;
];
}
{
# TODO never put hashedPassword into the store
users.extraUsers =
mapAttrs (_: h: { hashedPassword = h; })
(import <secrets/hashedPasswords.nix>);
}
{
users.groups.subusers.gid = 1093178926; # genid subusers
}
{
users.defaultUserShell = "/run/current-system/sw/bin/bash";
users.mutableUsers = false;
}
{
users.extraUsers = {
root = {
openssh.authorizedKeys.keys = [
config.krebs.users.tv.pubkey
config.krebs.users.tv_xu.pubkey
];
};
users = {
defaultUserShell = "/run/current-system/sw/bin/bash";
mutableUsers = false;
users = {
tv = {
isNormalUser = true;
uid = 1337;
group = "users";
home = "/home/tv";
createHome = true;
useDefaultShell = true;
extraGroups = [
"audio"
"video"
"wheel"
];
openssh.authorizedKeys.keys = [
config.krebs.users.tv.pubkey
];
};
};
};
}
@ -94,6 +88,21 @@ with lib;
ls = "ls -h --color=auto --group-directories-first";
dmesg = "dmesg -L --reltime";
view = "vim -R";
reload = "systemctl reload";
restart = "systemctl restart";
start = "systemctl start";
status = "systemctl status";
stop = "systemctl stop";
};
environment.variables = {
NIX_PATH =
with config.krebs.build.source; with dir; with git;
mkForce (concatStringsSep ":" [
"nixpkgs=${nixpkgs.target-path}"
"secrets=${stockholm.target-path}/null"
]);
};
programs.bash = {
@ -164,5 +173,13 @@ with lib;
"sendmail" # for sudo
];
}
{
systemd.tmpfiles.rules = let
forUsers = flip map users;
isUser = { group, ... }: hasSuffix "users" group;
users = filter isUser (mapAttrsToList (_: id) config.users.users);
in forUsers (u: "d /run/xdg/${u.name} 0700 ${u.name} ${u.group} -");
environment.variables.XDG_RUNTIME_DIR = "/run/xdg/$LOGNAME";
}
];
}

View File

@ -1,6 +1,7 @@
{ config, lib, pkgs, ... }:
with import ../4lib { inherit lib pkgs; };
with lib;
let
out = {
@ -20,26 +21,22 @@ let
rules = concatMap make-rules (attrValues repos);
public-repos = mapAttrs make-public-repo ({
} // mapAttrValues (setAttr "section" "1. Miscellaneous") {
cac = {
desc = "CloudAtCost command line interface";
};
cgserver = {};
crude-mail-setup = {};
dot-xmonad = {};
get = {};
hack = {};
load-env = {};
make-snapshot = {};
much = {};
nixos-infest = {};
nixpkgs = {};
painload = {};
push = {};
regfish = {};
stockholm = {
desc = "take all the computers hostage, they'll love you!";
};
} // mapAttrs (_: repo: repo // { section = "Haskell libraries"; }) {
} // mapAttrValues (setAttr "section" "2. Haskell libraries") {
blessings = {};
mime = {};
quipper = {};
@ -47,6 +44,13 @@ let
wai-middleware-time = {};
web-routes-wai-custom = {};
xintmap = {};
xmonad-stockholm = {};
} // mapAttrValues (setAttr "section" "3. Museum") {
cgserver = {};
crude-mail-setup = {};
dot-xmonad = {};
nixos-infest = {};
painload = {};
});
restricted-repos = mapAttrs make-restricted-repo (
@ -63,7 +67,7 @@ let
inherit name desc section;
public = true;
hooks = {
post-receive = git.irc-announce {
post-receive = pkgs.git-hooks.irc-announce {
# TODO make nick = config.krebs.build.host.name the default
nick = config.krebs.build.host.name;
channel = "#retiolum";
@ -82,7 +86,7 @@ let
with git // config.krebs.users;
repo:
singleton {
user = tv;
user = [ tv tv_xu ];
repo = [ repo ];
perm = push "refs/*" [ non-fast-forward create delete merge ];
} ++

View File

@ -64,6 +64,10 @@ let
\ | hi TrailingSpace ctermbg=88
\ | hi Normal ctermfg=White
au BufRead,BufNewFile *.hs so ${pkgs.writeText "hs.vim" ''
syn region String start=+\[[^|]*|+ end=+|]+
''}
au BufRead,BufNewFile *.nix so ${pkgs.writeText "nix.vim" ''
setf nix
set isk=@,48-57,_,192-255,-,'

View File

@ -34,7 +34,14 @@ let
};
environment.systemPackages = [
pkgs.ff
pkgs.gitAndTools.qgit
pkgs.mpv
pkgs.pavucontrol
pkgs.slock
pkgs.sxiv
pkgs.xsel
pkgs.zathura
];
security.setuidPrograms = [

View File

@ -1,40 +0,0 @@
{ config, lib, pkgs, ... }:
with lib;
{
krebs.per-user.z.packages = [
(pkgs.writeScriptBin "cr" ''
#! /bin/sh
set -efu
export LC_TIME=de_DE.utf8
exec ${pkgs.chromium}/bin/chromium \
--ssl-version-min=tls1 \
--disk-cache-dir=/tmp/chromium-disk-cache_"$LOGNAME" \
--disk-cache-size=50000000 \
"%@"
'')
];
programs.bash.interactiveShellInit = ''
case ''${XMONAD_SPAWN_WORKSPACE-} in
za|zh|zj|zs)
exec sudo -u z -i
;;
esac
'';
security.sudo.extraConfig = "tv ALL=(z) NOPASSWD: ALL";
users.users.z = {
extraGroups = [
"audio"
"vboxusers"
"video"
];
group = "subusers";
home = "/home/z";
uid = 3043726074; # genid z
useDefaultShell = true;
};
}

View File

@ -1,11 +0,0 @@
{ lib, pkgs, ... }:
lib // rec {
git = import ./git.nix {
inherit lib pkgs;
};
# TODO deprecate shell-escape for lass
shell-escape = lib.shell.escape;
}

View File

@ -1,202 +0,0 @@
{ lib, pkgs, ... }:
let
inherit (lib) addNames escapeShellArg makeSearchPath optionalString;
commands = addNames {
git-receive-pack = {};
git-upload-pack = {};
};
receive-modes = addNames {
fast-forward = {};
non-fast-forward = {};
create = {};
delete = {};
merge = {}; # TODO implement in git.nix
};
permissions = {
fetch = {
allow-commands = [
commands.git-upload-pack
];
};
push = ref: extra-modes: {
allow-commands = [
commands.git-receive-pack
commands.git-upload-pack
];
allow-receive-ref = ref;
allow-receive-modes = [ receive-modes.fast-forward ] ++ extra-modes;
};
};
refs = {
master = "refs/heads/master";
all-heads = "refs/heads/*";
};
irc-announce-script = pkgs.writeScript "irc-announce-script" ''
#! /bin/sh
set -euf
export PATH=${makeSearchPath "bin" (with pkgs; [
coreutils
gawk
gnused
netcat
nettools
])}
IRC_SERVER=$1
IRC_PORT=$2
IRC_NICK=$3$$
IRC_CHANNEL=$4
message=$5
export IRC_CHANNEL # for privmsg_cat
# echo2 and cat2 are used output to both, stdout and stderr
# This is used to see what we send to the irc server. (debug output)
echo2() { echo "$*"; echo "$*" >&2; }
cat2() { tee /dev/stderr; }
# privmsg_cat transforms stdin to a privmsg
privmsg_cat() { awk '{ print "PRIVMSG "ENVIRON["IRC_CHANNEL"]" :"$0 }'; }
# ircin is used to feed the output of netcat back to the "irc client"
# so we can implement expect-like behavior with sed^_^
# XXX mkselfdestructingtmpfifo would be nice instead of this cruft
tmpdir="$(mktemp -d irc-announce_XXXXXXXX)"
cd "$tmpdir"
mkfifo ircin
trap "
rm ircin
cd '$OLDPWD'
rmdir '$tmpdir'
trap - EXIT INT QUIT
" EXIT INT QUIT
{
echo2 "USER $LOGNAME 0 * :$LOGNAME@$(hostname)"
echo2 "NICK $IRC_NICK"
# wait for MODE message
sed -n '/^:[^ ]* MODE /q'
echo2 "JOIN $IRC_CHANNEL"
printf '%s' "$message" \
| privmsg_cat \
| cat2
echo2 "PART $IRC_CHANNEL"
# wait for PART confirmation
sed -n '/:'"$IRC_NICK"'![^ ]* PART /q'
echo2 'QUIT :Gone to have lunch'
} < ircin \
| nc "$IRC_SERVER" "$IRC_PORT" | tee -a ircin
'';
hooks = {
# TODO make this a package?
irc-announce = { nick, channel, server, port ? 6667, verbose ? false }: ''
#! /bin/sh
set -euf
export PATH=${makeSearchPath "bin" (with pkgs; [
coreutils
git
gnused
])}
green() { printf '\x0303,99%s\x0F' "$1"; }
red() { printf '\x0304,99%s\x0F' "$1"; }
orange() { printf '\x0307,99%s\x0F' "$1"; }
pink() { printf '\x0313,99%s\x0F' "$1"; }
gray() { printf '\x0314,99%s\x0F' "$1"; }
unset message
add_message() {
message="''${message+$message
}$*"
}
nick=${escapeShellArg nick}
channel=${escapeShellArg channel}
server=${escapeShellArg server}
port=${toString port}
host=$nick
cgit_endpoint=http://cgit.$host
empty=0000000000000000000000000000000000000000
while read oldrev newrev ref; do
if [ $oldrev = $empty ]; then
receive_mode=create
elif [ $newrev = $empty ]; then
receive_mode=delete
elif [ "$(git merge-base $oldrev $newrev)" = $oldrev ]; then
receive_mode=fast-forward
else
receive_mode=non-fast-forward
fi
h=$(echo $ref | sed 's:^refs/heads/::')
# empty_tree=$(git hash-object -t tree /dev/null)
empty_tree=4b825dc6
id=$(echo $newrev | cut -b-7)
id2=$(echo $oldrev | cut -b-7)
if [ $newrev = $empty ]; then id=$empty_tree; fi
if [ $oldrev = $empty ]; then id2=$empty_tree; fi
case $receive_mode in
create)
link="$cgit_endpoint/$GIT_SSH_REPO/?h=$h"
;;
delete)
link="$cgit_endpoint/$GIT_SSH_REPO/ ($h)"
;;
fast-forward|non-fast-forward)
link="$cgit_endpoint/$GIT_SSH_REPO/diff/?h=$h&id=$id&id2=$id2"
;;
esac
#$host $GIT_SSH_REPO $ref $link
add_message $(pink push) $link $(gray "($receive_mode)")
${optionalString verbose ''
add_message "$(
git log \
--format="$(orange %h) %s $(gray '(%ar)')" \
--reverse \
$id2..$id
git diff --stat $id2..$id \
| sed '$!s/\(+*\)\(-*\)$/'$(green '\1')$(red '\2')'/'
)"
''}
done
if test -n "''${message-}"; then
exec ${irc-announce-script} \
"$server" \
"$port" \
"$nick" \
"$channel" \
"$message"
fi
'';
};
in
commands // receive-modes // permissions // refs // hooks

View File

@ -1,21 +0,0 @@
let
pkgs = import <nixpkgs> {};
inherit (pkgs.lib) concatMap hasAttr;
in rec {
no-touch-args = {
config = throw "no-touch-args: can't touch config!";
lib = throw "no-touch-args: can't touch lib!";
pkgs = throw "no-touch-args: can't touch pkgs!";
};
# list-imports : path -> [path]
# Return a module's transitive list of imports.
# XXX duplicates won't get eliminated from the result.
list-imports = path:
let module = import path no-touch-args;
imports = if hasAttr "imports" module
then concatMap list-imports module.imports
else [];
in [path] ++ imports;
}

View File

@ -1,6 +1,16 @@
{ pkgs, ... }:
{
cr = pkgs.writeScriptBin "cr" ''
#! /bin/sh
set -efu
export LC_TIME=de_DE.utf8
exec ${pkgs.chromium}/bin/chromium \
--ssl-version-min=tls1 \
--disk-cache-dir=/tmp/chromium-disk-cache_"$LOGNAME" \
--disk-cache-size=50000000 \
"%@"
'';
ff = pkgs.callPackage ./ff {};
viljetic-pages = pkgs.callPackage ./viljetic-pages {};
xmonad-tv =

View File

@ -35,9 +35,9 @@ import XMonad.Layout.PerWorkspace (onWorkspace)
--import XMonad.Layout.BinarySpacePartition
--import XMonad.Actions.Submap
import Util.Pager
import Util.Rhombus
import Util.Shutdown
import XMonad.Stockholm.Pager
import XMonad.Stockholm.Rhombus
import XMonad.Stockholm.Shutdown
myTerm :: String

View File

@ -1,123 +0,0 @@
{-# LANGUAGE CPP #-}
module Util.Font
( printStringCentered
, printStringXMF'
) where
import XMonad
import XMonad.Util.Font
printStringCentered :: (Functor m, MonadIO m)
=> Display -> Drawable -> XMonadFont
-> GC -> Rectangle -> String
-> m ()
printStringCentered d p xmf gc r s = do
let x = rect_x r
y = rect_y r
w = rect_width r
h = rect_height r
text_w <- textWidthXMF d xmf s
(text_ascent, _) <- textExtentsXMF xmf s
let text_x = x + round ((fi w - fi text_w) / 2)
text_y = y + round ((fi h + fi text_h) / 2)
text_h = text_ascent
printStringXMF' d p xmf gc "" "" text_x text_y s
-- from xmonad-contrib's XMonad.Util.Font, (c) 2007 Andrea Rossato and Spencer Janssen
printStringXMF' :: (Functor m, MonadIO m) => Display -> Drawable -> XMonadFont -> GC -> String -> String
-> Position -> Position -> String -> m ()
printStringXMF' d p (Core fs) gc fc bc x y s = io $ do
setFont d gc $ fontFromFontStruct fs
--tv [fc',bc'] <- mapM (stringToPixel d) [fc,bc]
--tv setForeground d gc fc'
--tv setBackground d gc bc'
drawImageString d p gc x y s
printStringXMF' d p (Utf8 fs) gc fc bc x y s = io $ do
--tv [fc',bc'] <- mapM (stringToPixel d) [fc,bc]
--tv setForeground d gc fc'
--tv setBackground d gc bc'
io $ wcDrawImageString d p fs gc x y s
#ifdef XFT
printStringXMF' dpy drw fs@(Xft font) gc fc bc x y s = do
let screen = defaultScreenOfDisplay dpy
colormap = defaultColormapOfScreen screen
visual = defaultVisualOfScreen screen
--tv bcolor <- stringToPixel dpy bc
(a,d) <- textExtentsXMF fs s
gi <- io $ xftTextExtents dpy font s
--tv io $ setForeground dpy gc bcolor
io $ fillRectangle dpy drw gc (x - fi (xglyphinfo_x gi))
(y - fi a)
(fi $ xglyphinfo_xOff gi)
(fi $ a + d)
io $ withXftDraw dpy drw visual colormap $
\draw -> withXftColorName dpy visual colormap fc $
\color -> xftDrawString draw color font x y s
#endif
-- --my_printStringXMF :: (Functor m, MonadIO m) => Display -> Drawable -> XMonadFont -> GC -> String -> String
-- -- -> Position -> Position -> String -> m ()
-- my_printStringXMF (Core fs) d p gc x y s = do
-- setFont d gc $ fontFromFontStruct fs
-- -- [fc',bc'] <- mapM (stringToPixel d) [fc,bc]
-- -- setForeground d gc fc'
-- -- setBackground d gc bc'
-- drawImageString d p gc x y s
-- my_printStringXMF (Utf8 fs) d p gc x y s = do
-- -- [fc',bc'] <- mapM (stringToPixel d) [fc,bc]
-- -- setForeground d gc fc'
-- -- setBackground d gc bc'
-- wcDrawImageString d p fs gc x y s
-- #ifdef XFT
-- my_printStringXMF dpy drw fs@(Xft font) gc fc bc x y s = do
-- let screen = defaultScreenOfDisplay dpy
-- colormap = defaultColormapOfScreen screen
-- visual = defaultVisualOfScreen screen
-- bcolor <- stringToPixel dpy bc
-- (a,d) <- textExtentsXMF fs s
-- gi <- io $ xftTextExtents dpy font s
-- io $ setForeground dpy gc bcolor
-- io $ fillRectangle dpy drw gc (x - fromIntegral (xglyphinfo_x gi))
-- (y - fromIntegral a)
-- (fromIntegral $ xglyphinfo_xOff gi)
-- (fromIntegral $ a + d)
-- io $ withXftDraw dpy drw visual colormap $
-- \draw -> withXftColorName dpy visual colormap fc $
-- \color -> xftDrawString draw color font x y s
-- #endif
-- --textWidthXMF :: MonadIO m => Display -> XMonadFont -> String -> m Int
-- my_textWidthXMF _ (Utf8 fs) s = return $ fromIntegral $ wcTextEscapement fs s
-- my_textWidthXMF _ (Core fs) s = return $ fromIntegral $ textWidth fs s
-- #ifdef XFT
-- my_TextWidthXMF dpy (Xft xftdraw) s = liftIO $ do
-- gi <- xftTextExtents dpy xftdraw s
-- return $ xglyphinfo_xOff gi
-- #endif
--
-- my_textExtentsXMF :: MonadIO m => XMonadFont -> String -> m (Int32,Int32)
-- my_textExtentsXMF (Utf8 fs) s = do
-- let (_,rl) = wcTextExtents fs s
-- ascent = fromIntegral $ - (rect_y rl)
-- descent = fromIntegral $ rect_height rl + (fromIntegral $ rect_y rl)
-- return (ascent, descent)
-- my_textExtentsXMF (Core fs) s = do
-- let (_,a,d,_) = textExtents fs s
-- return (a,d)
-- #ifdef XFT
-- my_textExtentsXMF (Xft xftfont) _ = io $ do
-- ascent <- fromIntegral `fmap` xftfont_ascent xftfont
-- descent <- fromIntegral `fmap` xftfont_descent xftfont
-- return (ascent, descent)
-- #endif

View File

@ -1,172 +0,0 @@
module Util.Pager
( defaultPagerConfig
, defaultWindowColors
, defaultWorkspaceColors
, MatchMethod(..)
, pager
, PagerConfig(..)
) where
import Data.List ( find )
import Data.Maybe ( catMaybes )
import Graphics.X11
import Util.Rhombus
import XMonad
import qualified XMonad.StackSet as W
import XMonad.Hooks.UrgencyHook
import XMonad.Util.Font ( fi, stringToPixel )
data PagerConfig = PagerConfig
{ pc_font :: String
, pc_cellwidth :: Dimension
, pc_margin :: Dimension
, pc_matchmethod :: MatchMethod
, pc_wrap :: Bool
, pc_workspaceColors :: Bool -> Bool -> Bool -> (String, String, String)
, pc_windowColors :: Bool -> Bool -> Bool -> Bool -> Bool -> (String, String)
}
defaultPagerConfig :: PagerConfig
defaultPagerConfig = PagerConfig "xft:Sans-8" 100 0 MatchInfix True defaultWorkspaceColors defaultWindowColors
pager :: PagerConfig -> (String -> X ()) -> [String] -> X ()
pager pc = rhombus defaultRhombusConfig
{ rc_font = pc_font pc
, rc_cellwidth = pc_cellwidth pc
, rc_margin = pc_margin pc
, rc_matchmethod = pc_matchmethod pc
, rc_wrap = pc_wrap pc
, rc_colors = pc_workspaceColors pc
, rc_paint = pagerPaint pc
}
defaultWorkspaceColors :: Bool -- workspace has focus
-> Bool -- workspace name matches incremental search
-> Bool -- workspace is the current one
-> (String, String, String) -- workspace border, background color, and foreground color
defaultWorkspaceColors False False False = ("#101010","#050505","#202020")
defaultWorkspaceColors False False True = ("#101010","#050505","#202020")
defaultWorkspaceColors False True False = ("#404040","#202020","#b0b0b0")
defaultWorkspaceColors False True True = ("#101010","#050505","#505050")
defaultWorkspaceColors True _ False = ("#808020","#404010","#f0f0b0")
defaultWorkspaceColors True _ True = ("#404010","#202005","#909050")
defaultWindowColors :: Bool -- window's workspace has focus
-> Bool -- window's workspace name matches incremental search
-> Bool -- window's workspace the current one
-> Bool -- window is urgent
-> Bool -- window has focus
-> (String, String) -- window border and background color
defaultWindowColors wsf m c u True = ("#802020", snd $ defaultWindowColors wsf m c u False)
defaultWindowColors False False False False _ = ("#111111","#060606")
defaultWindowColors False False False True _ = ("#802020","#401010")
defaultWindowColors False False True False _ = ("#101010","#050505")
defaultWindowColors False False True True _ = ("#401010","#200505")
defaultWindowColors False True False False _ = ("#202080","#101040")
defaultWindowColors False True False True _ = ("#802080","#401040")
defaultWindowColors False True True False _ = ("#101040","#100520")
defaultWindowColors False True True True _ = ("#401040","#200520")
defaultWindowColors True False False False _ = ("#208020","#104010")
defaultWindowColors True False False True _ = ("#808020","#404010")
defaultWindowColors True False True False _ = ("#104010","#052005")
defaultWindowColors True False True True _ = ("#404010","#202005")
defaultWindowColors True True False False _ = ("#208080","#104040")
defaultWindowColors True True False True _ = ("#808080","#404040")
defaultWindowColors True True True False _ = ("#104040","#102020")
defaultWindowColors True True True True _ = ("#404040","#202020")
pagerPaint ::
PagerConfig
-> RhombusConfig
-> Display
-> Drawable
-> GC
-> WorkspaceId
-> Rectangle
-> Bool
-> Bool
-> Bool
-> X ()
pagerPaint pc rc d p gc t r focus match current = do
ss <- gets windowset
let x = rect_x r
y = rect_y r
urgents <- readUrgents
let foci = map W.focus $ catMaybes $ map W.stack $ W.workspaces ss
let color = pc_windowColors pc focus match current -- :: Bool -> (String, String)
(_, _, _fg_color) = pc_workspaceColors pc focus match current
fg_color <- stringToPixel d _fg_color
let r = screenRect $ W.screenDetail $ W.current ss
let a = fi (rect_width r) / fi (rect_height r)
let scale = fi (rc_cellwidth rc) / fi (rect_width r)
-- TODO whenNothing print error
whenJust (findWorkspace t ss) $ \ ws -> do
whenJust (W.stack ws) $ \ s ->
withDisplay $ \ d -> io $ do
let color' w = color (w `elem` urgents) (w `elem` foci)
-- TODO painting of floating windows is broken
mapM_ (drawMiniWindow d p gc x y color' scale) (W.down s)
drawMiniWindow d p gc x y color' scale (W.focus s)
mapM_ (drawMiniWindow d p gc x y color' scale) (W.up s)
drawMiniWindow
:: RealFrac a
=> Display
-> Drawable
-> GC
-> Position
-> Position
-> (Window -> (String, String))
-> a
-> Window
-> IO ()
drawMiniWindow d p gc ox oy color s win = do
let scale x = round $ fi x * s
wa <- getWindowAttributes d win
let x = ox + (scale $ wa_x wa)
y = oy + (scale $ wa_y wa)
w = (scale $ wa_width wa)
h = (scale $ wa_height wa)
let (fg, bg) = color win
fg' <- stringToPixel d fg
bg' <- stringToPixel d bg
setForeground d gc bg'
fillRectangle d p gc (x + 1) (y + 1) (w - 2) (h - 2)
setForeground d gc fg'
drawLines d p gc
[ Point x y
, Point (fi w - 1) 0
, Point 0 (fi h - 2)
, Point (- fi w + 1) 0
, Point 0 (- fi h + 2)
]
coordModePrevious
-- TODO externalize findWorkspace
findWorkspace :: (Eq i) => i -> W.StackSet i l a sid sd -> Maybe (W.Workspace i l a)
findWorkspace t ss = find ((==)t . W.tag) (W.workspaces ss)

View File

@ -1,369 +0,0 @@
module Util.Rhombus
( defaultRhombusConfig
, MatchMethod(..)
, rhombus
, RhombusConfig(..)
, RhombusState(..)
) where
import Control.Monad ( forM_, zipWithM_ )
import Data.Char
import Data.List
import Data.Ord
import Data.Map ( fromList )
import Data.Maybe ( isJust, fromJust )
import XMonad
import XMonad.StackSet hiding ( filter )
import XMonad.Util.Font
import XMonad.Util.Image ( drawIcon )
import XMonad.Util.XUtils
import Util.Submap
import Util.XUtils
import Util.Font
data MatchMethod = MatchInfix | MatchPrefix
data RhombusConfig = RhombusConfig
{ rc_font :: String
, rc_cellwidth :: Dimension
, rc_margin :: Dimension
, rc_matchmethod :: MatchMethod
, rc_wrap :: Bool
, rc_colors :: Bool -> Bool -> Bool -> (String, String, String)
, rc_paint :: RhombusConfig -> Display -> Pixmap -> GC -> String -> Rectangle -> Bool -> Bool -> Bool -> X ()
}
-- TODO currently xft is broken
defaultRhombusConfig = RhombusConfig "xft:Sans-8" 100 0 MatchInfix True stupidColors noPaint
where
stupidColors _ _ _ = ("red", "magenta", "yellow")
noPaint _ _ _ _ _ _ _ _ _ = return ()
data RhombusState = RhombusState
{ rs_window :: Window
, rs_search :: String
, rs_font :: XMonadFont
, rs_focus :: (Position, Position)
, rs_strings :: [String]
}
reachableCoords :: RhombusState -> [(Position, Position)]
reachableCoords RhombusState{rs_strings=xs} = take (length xs) wave
matchingReachableCoords :: RhombusConfig -> RhombusState -> [(Position, Position)]
matchingReachableCoords rc rs =
snd $ unzip
$ filter (isXOf (rc_matchmethod rc) (rs_search rs) . fst)
$ zip (rs_strings rs) (reachableCoords rs)
match :: MatchMethod -> String -> [String] -> Maybe String
match m s ws = do
let cands = filter (isXOf m s) ws
if length cands == 1
then Just $ head cands
else Nothing
rhombus :: RhombusConfig -> (String -> X ()) -> [String] -> X ()
rhombus rc viewFunc as = withGrabbedKeyboard $ do
rs <- newRhombus rc as
--redraw rc rs
showWindow (rs_window rs)
rhombusMode viewFunc rc rs
rhombusMode :: (String -> X ()) -> RhombusConfig -> RhombusState -> X ()
rhombusMode viewFunc rc rs =
case match (rc_matchmethod rc) (rs_search rs) (init $ rs_strings rs) of
Nothing -> redraw rc rs >> submapString def keys
Just i -> removeRhombus rs >> viewFunc i
where
def (ch:[]) | isPrint ch =
incSearchPushChar ch rs >>= rhombusMode viewFunc rc
def _ =
failbeep >> rhombusMode viewFunc rc rs
keys = fromList $
[ ((0 , xK_BackSpace ), incSearchPopChar rs >>= rhombusMode viewFunc rc)
, ((0 , xK_Escape ), removeRhombus rs)
, ((0 , xK_Menu ), removeRhombus rs)
, ((0 , xK_Left ), goto rc (-1, 0) rs >>= rhombusMode viewFunc rc)
, ((0 , xK_Right ), goto rc ( 1, 0) rs >>= rhombusMode viewFunc rc)
, ((0 , xK_Up ), goto rc ( 0,-1) rs >>= rhombusMode viewFunc rc)
, ((0 , xK_Down ), goto rc ( 0, 1) rs >>= rhombusMode viewFunc rc)
, ((0 , xK_Tab ), gotoNextMatch rc rs >>= rhombusMode viewFunc rc)
, ((_S , xK_Tab ), gotoPrevMatch rc rs >>= rhombusMode viewFunc rc)
, ((0 , xK_Return ), removeRhombus rs >> return (selectFocused rs) >>= viewFunc)
]
_S = shiftMask
-- TODO make failbeep configurable
failbeep = spawn "beep -l 100 -f 500"
goto :: RhombusConfig -> (Position, Position) -> RhombusState -> X RhombusState
goto RhombusConfig{rc_wrap=True} xy rs = maybe (failbeep >> return rs) return $ wrapFocus xy rs
goto RhombusConfig{rc_wrap=False} xy rs = maybe (failbeep >> return rs) return $ moveFocus xy rs
moveFocus :: (Position, Position) -> RhombusState -> Maybe RhombusState
moveFocus (dx, dy) rs@RhombusState{rs_focus=(x,y)} = do
let focus' = (x + dx, y + dy)
if elem focus' (reachableCoords rs)
then Just rs { rs_focus = focus' }
else Nothing
wrapFocus :: (Position, Position) -> RhombusState -> Maybe RhombusState
wrapFocus (0, dy) rs@RhombusState{rs_focus=focus} = do
let column = sortBy (comparing snd) $ filter ((==) (fst focus) . fst) (reachableCoords rs)
i <- elemIndex focus column
return rs { rs_focus = column `modIndex` (i + fromIntegral dy) }
wrapFocus (dx, 0) rs@RhombusState{rs_focus=focus} = do
let column = sortBy (comparing fst) $ filter ((==) (snd focus) . snd) (reachableCoords rs)
i <- elemIndex focus column
return rs { rs_focus = column `modIndex` (i + fromIntegral dx) }
wrapFocus _ _ = Nothing
gotoPrevMatch :: RhombusConfig -> RhombusState -> X RhombusState
gotoPrevMatch rc rs@RhombusState{rs_focus=focus} = do
case reverse (matchingReachableCoords rc rs) of
[] -> failbeep >> return rs
xs -> return rs
{ rs_focus = maybe (head xs)
(modIndex xs . (+1))
(focus `elemIndex` xs)
}
gotoNextMatch :: RhombusConfig -> RhombusState -> X RhombusState
gotoNextMatch rc rs@RhombusState{rs_focus=focus} = do
case matchingReachableCoords rc rs of
[] -> failbeep >> return rs
xs -> return rs
{ rs_focus = maybe (head xs)
(modIndex xs . (+1))
(focus `elemIndex` xs)
}
selectFocused :: RhombusState -> String
selectFocused rs =
-- TODO the rhombus must never "focus" something inexistent
fromJust $ lookup (rs_focus rs) $ zip wave (rs_strings rs)
incSearchPushChar :: Char -> RhombusState -> X RhombusState
incSearchPushChar c rs = return rs { rs_search = rs_search rs ++ [c] }
incSearchPopChar :: RhombusState -> X RhombusState
-- only rubout if we have at least one char
incSearchPopChar rs@RhombusState{rs_search=xs@(_:_)} =
return rs { rs_search = init xs }
incSearchPopChar rs = return rs
redraw :: RhombusConfig -> RhombusState -> X ()
redraw rc rs = do
ss <- gets windowset
let Screen _ _ (SD (Rectangle _ _ s_width s_height)) = current ss
-- TODO this let is duplicated in newRhombus
let scale x = x * cell_w `div` s_width -- TODO use bw
cell_w = rc_cellwidth rc
cell_h = scale s_height
-- txy is the top-left corner of the first (center) cell
-- XXX div and (-) are not distributive
-- we could round $ (s_* - cell_*) / 2, though...
tx = fi $ s_width `div` 2 - cell_w `div` 2
ty = fi $ s_height `div` 2 - cell_h `div` 2
margin = rc_margin rc
-- dxy are the outer cell dimensions (i.e. including the border)
dx = fi $ cell_w + 2 + margin
dy = fi $ cell_h + 2 + margin
paint = rc_paint rc
xmf = rs_font rs
tags = rs_strings rs
--currentTag = last tags
withDisplay $ \ d -> do
-- XXX we cannot use withPixmapAndGC because rc_paint is an X monad
p <- io $ createPixmap d (rs_window rs) s_width s_height (defaultDepthOfScreen $ defaultScreenOfDisplay d)
g <- io $ createGC d p
-- TODO fixme
color_black <- stringToPixel d "black"
forZipWithM_ tags (reachableCoords rs) $ \ tag oxy@(ox, oy) -> do
let focus = oxy == rs_focus rs
match = isXOf (rc_matchmethod rc) (rs_search rs) tag
current = tag == last tags
(_b_color, _bg_color, _fg_color) = rc_colors rc focus match current
--cell_x = (ox * dx) + x - fi (cell_w `div` 2)
--cell_y = (oy * dy) + y - fi (cell_h `div` 2)
cell_x = (ox * dx) + tx + 1
cell_y = (oy * dy) + ty + 1
b_color <- stringToPixel d _b_color
bg_color <- stringToPixel d _bg_color
fg_color <- stringToPixel d _fg_color
-- draw background
io $ setForeground d g bg_color
io $ fillRectangle d p g cell_x cell_y cell_w cell_h
-- draw border
io $ setForeground d g b_color
io $ drawLines d p g
[ Point (cell_x - 1) (cell_y - 1)
, Point (fi cell_w + 1) 0
, Point 0 (fi cell_h + 1)
, Point (-(fi cell_w + 1)) 0
, Point 0 (-(fi cell_h + 1))
]
coordModePrevious
-- custom draw
paint rc d p g tag (Rectangle cell_x cell_y cell_w cell_h) focus match current
-- paint text
-- TODO custom paint text?
-- TODO withCopyArea
io $ withPixmapAndGC d p s_width s_height (defaultDepthOfScreen $ defaultScreenOfDisplay d) $ \ f_pm f_gc -> do
withPixmapAndGC d f_pm s_width s_height 1 $ \ clip_mask clip_gc -> do
setForeground d clip_gc 0
setBackground d clip_gc 0
fillRectangle d clip_mask clip_gc 0 0 s_width s_height
setForeground d clip_gc 1
let r = Rectangle cell_x cell_y cell_w cell_h
printStringCentered d clip_mask xmf clip_gc r tag
setForeground d f_gc fg_color
setBackground d f_gc color_black -- TODO
printStringCentered d f_pm xmf f_gc r tag
setClipMask d f_gc clip_mask
copyArea d f_pm p f_gc 0 0 s_width s_height 0 0
io $ copyArea d p (rs_window rs) g 0 0 s_width s_height 0 0
io $ freePixmap d p
io $ freeGC d g
newRhombus :: RhombusConfig -> [String] -> X RhombusState
newRhombus rc tags = do
ss <- gets windowset
let Screen _ _ (SD (Rectangle _ _ s_width s_height)) = current ss
(_, def_win_bg, _) = rc_colors rc False True False
-- TODO this let is duplicated in redraw
let scale x = x * cell_w `div` s_width -- TODO use bw
cell_w = rc_cellwidth rc
cell_h = scale s_height
-- TODO don't delete this let but use it instead of s_{width,height}
-- (xcoords, ycoords) = unzip $ take (length tags) wave -- this is reachableCoords
-- win_width = (maximum xcoords - minimum xcoords) * dx
-- win_height = (maximum ycoords - minimum ycoords) * dy
-- txy is the top-left corner of the first (center) cell
-- XXX div and (-) are not distributive
-- we could round $ (s_* - cell_*) / 2, though...
tx = fi $ s_width `div` 2 - cell_w `div` 2
ty = fi $ s_height `div` 2 - cell_h `div` 2
margin = rc_margin rc
-- dxy are the outer cell dimensions (i.e. including the border)
dx = fi $ cell_w + 2 + margin
dy = fi $ cell_h + 2 + margin
fn <- initXMF (rc_font rc)
win <- createNewWindow (Rectangle 0 0 s_width s_height) Nothing def_win_bg True
withDisplay $ \ d ->
io $ shapeWindow d win $ \ p g ->
forZipWithM_ tags wave $ \ _ (ox, oy) ->
fillRectangle d p g (tx + ox * dx) (ty + oy * dy) (fi cell_w + 2) (fi cell_h + 2)
return $ RhombusState win "" fn (0,0) tags
removeRhombus :: RhombusState -> X ()
removeRhombus (RhombusState w _ fn _ _) = do
deleteWindow w
releaseXMF fn
wave :: [(Position, Position)]
wave = zip (0:(concat $ map (\i -> [0..i]++[i-1,i-2..1] ++ [0,-1..(-i)]++[-i,-i+1..(-1)]) [1..])) (concat $ map (\i -> [0..i]++[i-1,i-2..1] ++ [0,-1..(-i)]++[-i+1,-i+2..(-1)]) [1..])
where
wave1 = 0:(concat $ map (\i -> [0..i]++[i-1,i-2..1] ++ [0,-1..(-i)]++[-i,-i+1..(-1)]) [1..])
wave2 = concat $ map (\i -> [0..i]++[i-1,i-2..1] ++ [0,-1..(-i)]++[-i+1,-i+2..(-1)]) [1..]
commonPrefix (x:xs) (y:ys) | x == y = x:commonPrefix xs ys
commonPrefix _ _ = []
isXOf :: MatchMethod -> String -> String -> Bool
isXOf MatchInfix = isInfixOf
isXOf MatchPrefix = isPrefixOf
findXIndex :: (Eq a) => MatchMethod -> [a] -> [a] -> Maybe Int
findXIndex MatchInfix = findInfixIndex
findXIndex MatchPrefix = findPrefixIndex
findInfixIndex :: (Eq a) => [a] -> [a] -> Maybe Int
findInfixIndex needle haystack
= (\x -> if null x then Nothing else Just (fst $ head x))
. dropWhile (\(_,x) -> not $ isPrefixOf needle x)
$ zip [0..] (tails haystack)
findPrefixIndex :: (Eq a) => [a] -> [a] -> Maybe Int
findPrefixIndex needle haystack =
if isPrefixOf needle haystack
then Just 0
else Nothing
modIndex :: Integral i => [a] -> i -> a
modIndex xs i = xs `genericIndex` (i `mod` genericLength xs)
forZipWithM_ a b f = zipWithM_ f a b
withGrabbedKeyboard f = do
XConf { theRoot = root, display = d } <- ask
catchX (io (grabKeyboard d root False grabModeAsync grabModeAsync currentTime) >> f)
(return ())
io $ ungrabKeyboard d currentTime

View File

@ -1,53 +0,0 @@
{-# LANGUAGE LambdaCase #-}
module Util.Shutdown
( sendShutdownEvent
, handleShutdownEvent
, shutdown
)
where
import Control.Monad
import Data.Monoid
import Data.Maybe (catMaybes)
import qualified Data.Map as Map
import System.Environment (getEnv)
import System.Exit (exitSuccess)
import XMonad
import qualified XMonad.StackSet as W
sendShutdownEvent :: IO ()
sendShutdownEvent = do
dpy <- openDisplay ""
rw <- rootWindow dpy $ defaultScreen dpy
a <- internAtom dpy "XMONAD_SHUTDOWN" False
allocaXEvent $ \e -> do
setEventType e clientMessage
setClientMessageEvent e rw a 32 0 currentTime
sendEvent dpy rw False structureNotifyMask e
sync dpy False
handleShutdownEvent :: Event -> X All
handleShutdownEvent = \case
ClientMessageEvent { ev_message_type = mt } -> do
c <- (mt ==) <$> getAtom "XMONAD_SHUTDOWN"
when c shutdown
return (All c)
_ ->
return (All True)
shutdown :: X ()
shutdown = do
broadcastMessage ReleaseResources
io . flush =<< asks display
let wsData = show . W.mapLayout show . windowset
maybeShow (t, Right (PersistentExtension ext)) = Just (t, show ext)
maybeShow (t, Left str) = Just (t, str)
maybeShow _ = Nothing
extState =
return . show . catMaybes . map maybeShow . Map.toList . extensibleState
s <- gets (\s -> (wsData s : extState s))
_ <- io $ do
path <- getEnv "XMONAD_STATE"
writeFile path (unlines s)
exitSuccess
return ()

View File

@ -1,31 +0,0 @@
-- This module is based on Jason Creighton's XMonad.Actions.Submap
module Util.Submap
( submapString
) where
import Data.Bits
import XMonad hiding (keys)
import qualified Data.Map as M
import Control.Monad.Fix (fix)
-- | Like 'XMonad.Actions.Submap.submapDefault', but provides the looked up string to the default action.
submapString :: (String -> X ()) -> M.Map (KeyMask, KeySym) (X ()) -> X ()
submapString def keys = do
XConf { theRoot = root, display = d } <- ask
(m, s, str) <- io $ allocaXEvent $ \p -> fix $ \nextkey -> do
maskEvent d keyPressMask p
KeyEvent { ev_keycode = code, ev_state = m } <- getEvent p
keysym <- keycodeToKeysym d code 0
if isModifierKey keysym
then nextkey
else do
(mbKeysym, str) <- lookupString (asKeyEvent p)
return (m, keysym, str)
-- Remove num lock mask and Xkb group state bits
m' <- cleanMask $ m .&. ((1 `shiftL` 12) - 1)
maybe (def str) id (M.lookup (m', s) keys)

View File

@ -1,47 +0,0 @@
module Util.XUtils
( shapeWindow
, withGC
, withPixmap
, withPixmapAndGC
) where
import Control.Exception ( bracket )
import Foreign.C.Types ( CInt )
import Graphics.X11.Xlib
import Graphics.X11.Xlib.Extras
import Graphics.X11.Xshape
shapeWindow :: Display -> Window -> (Pixmap -> GC -> IO ()) -> IO ()
shapeWindow d w f = do
wa <- getWindowAttributes d w
let width = fromIntegral $ wa_width wa
height = fromIntegral $ wa_height wa
withPixmapAndGC d w width height 1 $ \ p g -> do
setForeground d g 0
fillRectangle d p g 0 0 width height
setForeground d g 1
f p g
xshapeCombineMask d w shapeBounding 0 0 p shapeSet
withGC :: Display -> Drawable -> (GC -> IO ()) -> IO ()
withGC d p =
bracket (createGC d p) (freeGC d)
withPixmap :: Display -> Drawable -> Dimension -> Dimension -> CInt -> (Pixmap -> IO ()) -> IO ()
withPixmap d p w h depth =
bracket (createPixmap d p w h depth) (freePixmap d)
withPixmapAndGC :: Display -> Drawable -> Dimension -> Dimension -> CInt -> (Pixmap -> GC -> IO ()) -> IO ()
withPixmapAndGC d w width height depth f =
withPixmap d w width height depth $ \ p ->
withGC d p $ \ g -> f p g

View File

@ -9,11 +9,9 @@ Executable xmonad
Build-Depends:
base,
containers,
filepath,
unix,
X11,
X11-xshape,
xmonad,
xmonad-contrib
xmonad-contrib,
xmonad-stockholm
GHC-Options: -Wall -O3 -threaded -rtsopts
Main-Is: Main.hs