mirror of
https://github.com/nix-community/home-manager
synced 2024-11-26 06:30:28 +00:00
Initial import
This commit is contained in:
parent
e4c63eb66a
commit
d7d02c3ce8
26 changed files with 1749 additions and 0 deletions
2
default.nix
Normal file
2
default.nix
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
# Simply defer to the home-manager script derivation.
|
||||||
|
import ./home-manager
|
39
home-manager/default.nix
Normal file
39
home-manager/default.nix
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
{ pkgs }:
|
||||||
|
|
||||||
|
let
|
||||||
|
|
||||||
|
homeManagerExpr = pkgs.writeText "home-manager.nix" ''
|
||||||
|
{ pkgs ? import <nixpkgs> {}, confPath, modulesPath }:
|
||||||
|
|
||||||
|
let
|
||||||
|
env = import modulesPath {
|
||||||
|
configuration = import confPath;
|
||||||
|
pkgs = pkgs;
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
inherit (env) activation-script;
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
|
||||||
|
in
|
||||||
|
|
||||||
|
pkgs.stdenv.mkDerivation {
|
||||||
|
name = "home-manager";
|
||||||
|
|
||||||
|
phases = [ "installPhase" ];
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
install -v -D -m755 ${./home-manager} $out/bin/home-manager
|
||||||
|
|
||||||
|
substituteInPlace $out/bin/home-manager \
|
||||||
|
--subst-var-by bash "${pkgs.bash}" \
|
||||||
|
--subst-var-by HOME_MANAGER_EXPR_PATH "${homeManagerExpr}"
|
||||||
|
'';
|
||||||
|
|
||||||
|
meta = with pkgs.stdenv.lib; {
|
||||||
|
description = "A user environment configurator";
|
||||||
|
maintainers = [ maintainers.rycee ];
|
||||||
|
platforms = platforms.linux;
|
||||||
|
};
|
||||||
|
}
|
62
home-manager/home-manager
Normal file
62
home-manager/home-manager
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
#!@bash@/bin/bash
|
||||||
|
|
||||||
|
function doRebuild() {
|
||||||
|
if [[ -z "$1" ]] ; then
|
||||||
|
echo "Need to provide path to configuration file."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local wrkdir
|
||||||
|
wrkdir="$(mktemp -d)"
|
||||||
|
|
||||||
|
nix-build --show-trace \
|
||||||
|
"@HOME_MANAGER_EXPR_PATH@" \
|
||||||
|
--argstr modulesPath "$HOME/.nixpkgs/home-manager/modules" \
|
||||||
|
--argstr confPath "$1" \
|
||||||
|
-A activation-script \
|
||||||
|
-o "$wrkdir/activate"
|
||||||
|
|
||||||
|
"$wrkdir/activate/libexec/home-activate"
|
||||||
|
|
||||||
|
rm -rv "$wrkdir"
|
||||||
|
}
|
||||||
|
|
||||||
|
function doListGens() {
|
||||||
|
ls --color=yes -gG --sort time "/nix/var/nix/gcroots/per-user/$(whoami)" \
|
||||||
|
| cut -d' ' -f 4-
|
||||||
|
}
|
||||||
|
|
||||||
|
function doListPackages() {
|
||||||
|
local outPath
|
||||||
|
outPath="$(nix-env -q --out-path | grep -o '/.*home-manager-path$')"
|
||||||
|
nix-store -q --references "$outPath" | sed 's/[^-]*-//'
|
||||||
|
}
|
||||||
|
|
||||||
|
function doHelp() {
|
||||||
|
echo "Usage: $0 {help | rebuild CONF | generations | packages}"
|
||||||
|
echo
|
||||||
|
echo "Commands"
|
||||||
|
echo " help Print this help"
|
||||||
|
echo " rebuild Rebuild the current environment"
|
||||||
|
echo " generations List all home environment generations"
|
||||||
|
echo " packages List all packages installed in home-manager-path"
|
||||||
|
}
|
||||||
|
|
||||||
|
case $1 in
|
||||||
|
rebuild)
|
||||||
|
doRebuild "$2"
|
||||||
|
;;
|
||||||
|
generations)
|
||||||
|
doListGens
|
||||||
|
;;
|
||||||
|
packages)
|
||||||
|
doListPackages
|
||||||
|
;;
|
||||||
|
help|--help)
|
||||||
|
doHelp
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown command: $1"
|
||||||
|
doHelp
|
||||||
|
exit 1
|
||||||
|
esac
|
47
modules/default.nix
Normal file
47
modules/default.nix
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
{ configuration
|
||||||
|
, pkgs
|
||||||
|
, lib ? pkgs.stdenv.lib
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
|
||||||
|
modules = [
|
||||||
|
./home-environment.nix
|
||||||
|
./programs/bash.nix
|
||||||
|
./programs/beets.nix
|
||||||
|
./programs/eclipse.nix
|
||||||
|
./programs/emacs.nix
|
||||||
|
./programs/git.nix
|
||||||
|
./programs/gnome-terminal.nix
|
||||||
|
./programs/lesspipe.nix
|
||||||
|
./programs/texlive.nix
|
||||||
|
./services/dunst.nix
|
||||||
|
./services/gnome-keyring.nix
|
||||||
|
./services/gpg-agent.nix
|
||||||
|
./services/keepassx.nix
|
||||||
|
./services/network-manager-applet.nix
|
||||||
|
./services/random-background.nix
|
||||||
|
./services/taffybar.nix
|
||||||
|
./services/tahoe-lafs.nix
|
||||||
|
./services/udiskie.nix
|
||||||
|
./services/xscreensaver.nix
|
||||||
|
./systemd.nix
|
||||||
|
./xsession.nix
|
||||||
|
];
|
||||||
|
|
||||||
|
pkgsModule = {
|
||||||
|
config._module.args.pkgs = lib.mkForce pkgs;
|
||||||
|
};
|
||||||
|
|
||||||
|
module = lib.evalModules {
|
||||||
|
modules = [ configuration ] ++ modules ++ [ pkgsModule ];
|
||||||
|
};
|
||||||
|
|
||||||
|
in
|
||||||
|
|
||||||
|
{
|
||||||
|
inherit (module) options config;
|
||||||
|
|
||||||
|
activation-script = module.config.home.activationPackage;
|
||||||
|
home-path = module.config.home.path;
|
||||||
|
}
|
314
modules/home-environment.nix
Normal file
314
modules/home-environment.nix
Normal file
|
@ -0,0 +1,314 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
|
||||||
|
cfg = config.home;
|
||||||
|
|
||||||
|
languageSubModule = types.submodule {
|
||||||
|
options = {
|
||||||
|
base = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
description = ''
|
||||||
|
The language to use unless overridden by a more specific option.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
address = mkOption {
|
||||||
|
default = null;
|
||||||
|
type = types.nullOr types.str;
|
||||||
|
description = ''
|
||||||
|
The language to use for addresses.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
monetary = mkOption {
|
||||||
|
default = null;
|
||||||
|
type = types.nullOr types.str;
|
||||||
|
description = ''
|
||||||
|
The language to use for formatting currencies and money amounts.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
paper = mkOption {
|
||||||
|
default = null;
|
||||||
|
type = types.nullOr types.str;
|
||||||
|
description = ''
|
||||||
|
The language to use for paper sizes.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
time = mkOption {
|
||||||
|
default = null;
|
||||||
|
type = types.nullOr types.str;
|
||||||
|
description = ''
|
||||||
|
The language to use for formatting times.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
keyboardSubModule = types.submodule {
|
||||||
|
options = {
|
||||||
|
layout = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "us";
|
||||||
|
description = ''
|
||||||
|
Keyboard layout.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
model = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "pc104";
|
||||||
|
example = "presario";
|
||||||
|
description = ''
|
||||||
|
Keyboard model.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
options = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [];
|
||||||
|
example = ["grp:caps_toggle" "grp_led:scroll"];
|
||||||
|
description = ''
|
||||||
|
X keyboard options; layout switching goes here.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
variant = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "";
|
||||||
|
example = "colemak";
|
||||||
|
description = ''
|
||||||
|
X keyboard variant.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
in
|
||||||
|
|
||||||
|
{
|
||||||
|
options = {
|
||||||
|
home.file = mkOption {
|
||||||
|
description = "Attribute set of files to link into the user home.";
|
||||||
|
default = {};
|
||||||
|
type = types.loaOf (types.submodule (
|
||||||
|
{ name, config, ... }: {
|
||||||
|
options = {
|
||||||
|
target = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
description = "Path to target file relative to $HOME.";
|
||||||
|
};
|
||||||
|
|
||||||
|
text = mkOption {
|
||||||
|
default = null;
|
||||||
|
type = types.nullOr types.lines;
|
||||||
|
description = "Text of the file.";
|
||||||
|
};
|
||||||
|
|
||||||
|
source = mkOption {
|
||||||
|
type = types.path;
|
||||||
|
description = "Path of the source file.";
|
||||||
|
};
|
||||||
|
|
||||||
|
mode = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "444";
|
||||||
|
description = "The permissions to apply to the file.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = {
|
||||||
|
target = mkDefault name;
|
||||||
|
source = mkIf (config.text != null) (
|
||||||
|
let name' = "user-etc-" + baseNameOf name;
|
||||||
|
in mkDefault (pkgs.writeText name' config.text)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
})
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
home.language = mkOption {
|
||||||
|
type = languageSubModule;
|
||||||
|
default = {};
|
||||||
|
description = "Language configuration.";
|
||||||
|
};
|
||||||
|
|
||||||
|
home.keyboard = mkOption {
|
||||||
|
type = keyboardSubModule;
|
||||||
|
default = {};
|
||||||
|
description = "Keyboard configuration.";
|
||||||
|
};
|
||||||
|
|
||||||
|
home.sessionVariables = mkOption {
|
||||||
|
default = {};
|
||||||
|
type = types.attrs;
|
||||||
|
description = "Environment variables to always set at login.";
|
||||||
|
};
|
||||||
|
|
||||||
|
home.packages = mkOption {
|
||||||
|
type = types.listOf types.package;
|
||||||
|
default = [];
|
||||||
|
description = "The set of packages to appear in the user environment.";
|
||||||
|
};
|
||||||
|
|
||||||
|
home.path = mkOption {
|
||||||
|
internal = true;
|
||||||
|
description = "The derivation installing the user packages.";
|
||||||
|
};
|
||||||
|
|
||||||
|
home.activation = mkOption {
|
||||||
|
internal = true;
|
||||||
|
default = {};
|
||||||
|
type = types.attrs;
|
||||||
|
description = "Activation scripts for the home environment.";
|
||||||
|
};
|
||||||
|
|
||||||
|
home.activationPackage = mkOption {
|
||||||
|
internal = true;
|
||||||
|
type = types.package;
|
||||||
|
description = "The package containing the complete activation script.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = {
|
||||||
|
home.sessionVariables =
|
||||||
|
let
|
||||||
|
maybeSet = name: value:
|
||||||
|
listToAttrs (optional (value != null) { inherit name value; });
|
||||||
|
in
|
||||||
|
(maybeSet "LANG" cfg.language.base)
|
||||||
|
//
|
||||||
|
(maybeSet "LC_ADDRESS" cfg.language.address)
|
||||||
|
//
|
||||||
|
(maybeSet "LC_MONETARY" cfg.language.monetary)
|
||||||
|
//
|
||||||
|
(maybeSet "LC_PAPER" cfg.language.paper)
|
||||||
|
//
|
||||||
|
(maybeSet "LC_TIME" cfg.language.time);
|
||||||
|
|
||||||
|
home.activation.linkages =
|
||||||
|
let
|
||||||
|
pak = pkgs.stdenv.mkDerivation {
|
||||||
|
name = "home-environment";
|
||||||
|
|
||||||
|
phases = [ "installPhase" ];
|
||||||
|
|
||||||
|
installPhase =
|
||||||
|
concatStringsSep "\n" (
|
||||||
|
mapAttrsToList (name: value:
|
||||||
|
"install -v -D -m${value.mode} ${value.source} $out/${value.target}"
|
||||||
|
) cfg.file
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
link = pkgs.writeText "link" ''
|
||||||
|
for sourcePath in "$@" ; do
|
||||||
|
basePath="''${sourcePath#/nix/store/*-home-environment/}"
|
||||||
|
targetPath="$HOME/$basePath"
|
||||||
|
mkdir -vp "$(dirname "$targetPath")"
|
||||||
|
ln -vsf "$sourcePath" "$targetPath"
|
||||||
|
done
|
||||||
|
'';
|
||||||
|
|
||||||
|
cleanup = pkgs.writeText "cleanup" ''
|
||||||
|
for sourcePath in "$@" ; do
|
||||||
|
basePath="''${sourcePath#/nix/store/*-home-environment/}"
|
||||||
|
targetPath="$HOME/$basePath"
|
||||||
|
echo -n "Checking $targetPath"
|
||||||
|
if [[ -f "${pak}/$basePath" ]] ; then
|
||||||
|
echo " exists"
|
||||||
|
else
|
||||||
|
echo " gone (deleting)"
|
||||||
|
rm -v "$targetPath"
|
||||||
|
rmdir --ignore-fail-on-non-empty -v -p "$(dirname "$targetPath")"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
'';
|
||||||
|
in
|
||||||
|
''
|
||||||
|
function setupVars() {
|
||||||
|
local gcPath="/nix/var/nix/gcroots/per-user/$(whoami)"
|
||||||
|
local greatestGenNum=( \
|
||||||
|
$(find "$gcPath" -name 'home-*' \
|
||||||
|
| sed 's/^.*-\([0-9]*\)$/\1/' \
|
||||||
|
| sort -rn \
|
||||||
|
| head -1) \
|
||||||
|
)
|
||||||
|
if [[ -n "$greatestGenNum" ]] ; then
|
||||||
|
oldGenNum=$greatestGenNum
|
||||||
|
newGenNum=$(($oldGenNum + 1))
|
||||||
|
oldGenPath="$(readlink -e "$gcPath/home-$oldGenNum")"
|
||||||
|
else
|
||||||
|
newGenNum=1
|
||||||
|
fi
|
||||||
|
newGenPath="${pak}";
|
||||||
|
newGenGcPath="$gcPath/home-$newGenNum"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Set some vars, these can be used later on as well.
|
||||||
|
setupVars
|
||||||
|
|
||||||
|
if [[ "$oldGenPath" != "$newGenPath" ]] ; then
|
||||||
|
ln -sfv "$newGenPath" "$newGenGcPath"
|
||||||
|
find "$newGenPath" -type f -print0 | xargs -0 bash ${link}
|
||||||
|
if [[ -n "$oldGenPath" ]] ; then
|
||||||
|
echo "Cleaning up orphan links from $HOME"
|
||||||
|
find "$oldGenPath" -type f -print0 | xargs -0 bash ${cleanup}
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "Same home files as previous generation ... doing nothing"
|
||||||
|
fi
|
||||||
|
'';
|
||||||
|
|
||||||
|
home.activation.installPackages =
|
||||||
|
''
|
||||||
|
nix-env -i ${cfg.path}
|
||||||
|
'';
|
||||||
|
|
||||||
|
home.activationPackage =
|
||||||
|
let
|
||||||
|
addHeader = n: v:
|
||||||
|
v // {
|
||||||
|
text = ''
|
||||||
|
echo Activating ${n}
|
||||||
|
${v.text}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
toDepString = n: v: if isString v then noDepEntry v else v;
|
||||||
|
activationWithDeps =
|
||||||
|
mapAttrs addHeader (mapAttrs toDepString cfg.activation);
|
||||||
|
activationCmds =
|
||||||
|
textClosureMap id activationWithDeps (attrNames activationWithDeps);
|
||||||
|
|
||||||
|
sf = pkgs.writeText "activation-script" ''
|
||||||
|
#!${pkgs.stdenv.shell}
|
||||||
|
|
||||||
|
${activationCmds}
|
||||||
|
'';
|
||||||
|
in
|
||||||
|
pkgs.stdenv.mkDerivation {
|
||||||
|
name = "activate-home";
|
||||||
|
|
||||||
|
phases = [ "installPhase" ];
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
install -v -D -m755 ${sf} $out/libexec/home-activate
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
home.path = pkgs.buildEnv {
|
||||||
|
name = "home-manager-path";
|
||||||
|
|
||||||
|
paths = cfg.packages;
|
||||||
|
|
||||||
|
meta = {
|
||||||
|
description = "Environment of packages installed through home-manager";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
93
modules/lib/generators.nix
Normal file
93
modules/lib/generators.nix
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
/* Functions that generate widespread file
|
||||||
|
* formats from nix data structures.
|
||||||
|
*
|
||||||
|
* They all follow a similar interface:
|
||||||
|
* generator { config-attrs } data
|
||||||
|
*
|
||||||
|
* Tests can be found in ./tests.nix
|
||||||
|
* Documentation in the manual, #sec-generators
|
||||||
|
*/
|
||||||
|
with import <nixpkgs/lib/trivial.nix>;
|
||||||
|
let
|
||||||
|
libStr = import <nixpkgs/lib/strings.nix>;
|
||||||
|
libAttr = import <nixpkgs/lib/attrsets.nix>;
|
||||||
|
|
||||||
|
flipMapAttrs = flip libAttr.mapAttrs;
|
||||||
|
in
|
||||||
|
|
||||||
|
rec {
|
||||||
|
|
||||||
|
/* Generate a line of key k and value v, separated by
|
||||||
|
* character sep. If sep appears in k, it is escaped.
|
||||||
|
* Helper for synaxes with different separators.
|
||||||
|
*
|
||||||
|
* mkKeyValueDefault ":" "f:oo" "bar"
|
||||||
|
* > "f\:oo:bar"
|
||||||
|
*/
|
||||||
|
mkKeyValueDefault = sep: k: v:
|
||||||
|
"${libStr.escape [sep] k}${sep}${toString v}";
|
||||||
|
|
||||||
|
|
||||||
|
/* Generate a key-value-style config file from an attrset.
|
||||||
|
*
|
||||||
|
* mkKeyValue is the same as in toINI.
|
||||||
|
*/
|
||||||
|
toKeyValue = {
|
||||||
|
mkKeyValue ? mkKeyValueDefault "="
|
||||||
|
}: attrs:
|
||||||
|
let mkLine = k: v: mkKeyValue k v + "\n";
|
||||||
|
in libStr.concatStrings (libAttr.mapAttrsToList mkLine attrs);
|
||||||
|
|
||||||
|
|
||||||
|
/* Generate an INI-style config file from an
|
||||||
|
* attrset of sections to an attrset of key-value pairs.
|
||||||
|
*
|
||||||
|
* generators.toINI {} {
|
||||||
|
* foo = { hi = "${pkgs.hello}"; ciao = "bar"; };
|
||||||
|
* baz = { "also, integers" = 42; };
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
*> [baz]
|
||||||
|
*> also, integers=42
|
||||||
|
*>
|
||||||
|
*> [foo]
|
||||||
|
*> ciao=bar
|
||||||
|
*> hi=/nix/store/y93qql1p5ggfnaqjjqhxcw0vqw95rlz0-hello-2.10
|
||||||
|
*
|
||||||
|
* The mk* configuration attributes can generically change
|
||||||
|
* the way sections and key-value strings are generated.
|
||||||
|
*
|
||||||
|
* For more examples see the test cases in ./tests.nix.
|
||||||
|
*/
|
||||||
|
toINI = {
|
||||||
|
# apply transformations (e.g. escapes) to section names
|
||||||
|
mkSectionName ? (name: libStr.escape [ "[" "]" ] name),
|
||||||
|
# format a setting line from key and value
|
||||||
|
mkKeyValue ? mkKeyValueDefault "="
|
||||||
|
}: attrsOfAttrs:
|
||||||
|
let
|
||||||
|
# map function to string for each key val
|
||||||
|
mapAttrsToStringsSep = sep: mapFn: attrs:
|
||||||
|
libStr.concatStringsSep sep
|
||||||
|
(libAttr.mapAttrsToList mapFn attrs);
|
||||||
|
mkSection = sectName: sectValues: ''
|
||||||
|
[${mkSectionName sectName}]
|
||||||
|
'' + toKeyValue { inherit mkKeyValue; } sectValues;
|
||||||
|
in
|
||||||
|
# map input to ini sections
|
||||||
|
mapAttrsToStringsSep "\n" mkSection attrsOfAttrs;
|
||||||
|
|
||||||
|
|
||||||
|
/* Generates JSON from an arbitrary (non-function) value.
|
||||||
|
* For more information see the documentation of the builtin.
|
||||||
|
*/
|
||||||
|
toJSON = {}: builtins.toJSON;
|
||||||
|
|
||||||
|
|
||||||
|
/* YAML has been a strict superset of JSON since 1.2, so we
|
||||||
|
* use toJSON. Before it only had a few differences referring
|
||||||
|
* to implicit typing rules, so it should work with older
|
||||||
|
* parsers as well.
|
||||||
|
*/
|
||||||
|
toYAML = {}@args: toJSON args;
|
||||||
|
}
|
159
modules/programs/bash.nix
Normal file
159
modules/programs/bash.nix
Normal file
|
@ -0,0 +1,159 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
|
||||||
|
cfg = config.programs.bash;
|
||||||
|
|
||||||
|
in
|
||||||
|
|
||||||
|
{
|
||||||
|
options = {
|
||||||
|
programs.bash = {
|
||||||
|
enable = mkEnableOption "GNU Bourne-Again SHell";
|
||||||
|
|
||||||
|
historySize = mkOption {
|
||||||
|
type = types.int;
|
||||||
|
default = 10000;
|
||||||
|
description = "Number of history lines to keep in memory.";
|
||||||
|
};
|
||||||
|
|
||||||
|
historyFileSize = mkOption {
|
||||||
|
type = types.int;
|
||||||
|
default = 100000;
|
||||||
|
description = "Number of history lines to keep on file.";
|
||||||
|
};
|
||||||
|
|
||||||
|
historyControl = mkOption {
|
||||||
|
type = types.listOf (types.enum [
|
||||||
|
"erasedups"
|
||||||
|
"ignoredups"
|
||||||
|
"ignorespace"
|
||||||
|
]);
|
||||||
|
default = [];
|
||||||
|
description = "Controlling how commands are saved on the history list.";
|
||||||
|
};
|
||||||
|
|
||||||
|
historyIgnore = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [];
|
||||||
|
description = "List of commands that should not be saved to the history list.";
|
||||||
|
};
|
||||||
|
|
||||||
|
shellOptions = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [
|
||||||
|
# Append to history file rather than replacing it.
|
||||||
|
"histappend"
|
||||||
|
|
||||||
|
# check the window size after each command and, if
|
||||||
|
# necessary, update the values of LINES and COLUMNS.
|
||||||
|
"checkwinsize"
|
||||||
|
|
||||||
|
# Extended globbing.
|
||||||
|
"extglob"
|
||||||
|
"globstar"
|
||||||
|
|
||||||
|
# Warn if closing shell with running jobs.
|
||||||
|
"checkjobs"
|
||||||
|
];
|
||||||
|
description = "Shell options to set.";
|
||||||
|
};
|
||||||
|
|
||||||
|
shellAliases = mkOption {
|
||||||
|
default = {};
|
||||||
|
example = { ll = "ls -l"; ".." = "cd .."; };
|
||||||
|
description = ''
|
||||||
|
An attribute set that maps aliases (the top level attribute names in
|
||||||
|
this option) to command strings or directly to build outputs. The
|
||||||
|
aliases are added to all users' shells.
|
||||||
|
'';
|
||||||
|
type = types.attrs;
|
||||||
|
};
|
||||||
|
|
||||||
|
enableAutojump = mkOption {
|
||||||
|
default = false;
|
||||||
|
type = types.bool;
|
||||||
|
description = "Enable the autojump navigation tool.";
|
||||||
|
};
|
||||||
|
|
||||||
|
profileExtra = mkOption {
|
||||||
|
default = "";
|
||||||
|
type = types.lines;
|
||||||
|
description = "Extra commands that should be added to .profile.";
|
||||||
|
};
|
||||||
|
|
||||||
|
initExtra = mkOption {
|
||||||
|
default = "";
|
||||||
|
type = types.lines;
|
||||||
|
description = "Extra commands that should be added to .bashrc.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = (
|
||||||
|
let
|
||||||
|
aliasesStr = concatStringsSep "\n" (
|
||||||
|
mapAttrsToList (k: v: "alias ${k}='${v}'") cfg.shellAliases
|
||||||
|
);
|
||||||
|
|
||||||
|
shoptsStr = concatStringsSep "\n" (
|
||||||
|
map (v: "shopt -s ${v}") cfg.shellOptions
|
||||||
|
);
|
||||||
|
|
||||||
|
export = n: v: "export ${n}=\"${toString v}\"";
|
||||||
|
exportIfNonNull = n: v: optionalString (v != null) (export n v);
|
||||||
|
exportIfNonEmpty = n: v: optionalString (v != "") (export n v);
|
||||||
|
|
||||||
|
histControlStr = concatStringsSep ":" cfg.historyControl;
|
||||||
|
histIgnoreStr = concatStringsSep ":" cfg.historyIgnore;
|
||||||
|
|
||||||
|
envVarsStr = concatStringsSep "\n" (
|
||||||
|
mapAttrsToList export config.home.sessionVariables
|
||||||
|
);
|
||||||
|
in mkIf cfg.enable {
|
||||||
|
home.file.".bash_profile".text = ''
|
||||||
|
# -*- mode: sh -*-
|
||||||
|
|
||||||
|
# include .profile if it exists
|
||||||
|
[[ -f ~/.profile ]] && . ~/.profile
|
||||||
|
|
||||||
|
# include .bashrc if it exists
|
||||||
|
[[ -f ~/.bashrc ]] && . ~/.bashrc
|
||||||
|
'';
|
||||||
|
|
||||||
|
home.file.".profile".text = ''
|
||||||
|
# -*- mode: sh -*-
|
||||||
|
|
||||||
|
${envVarsStr}
|
||||||
|
|
||||||
|
${cfg.profileExtra}
|
||||||
|
'';
|
||||||
|
|
||||||
|
home.file.".bashrc".text = ''
|
||||||
|
# -*- mode: sh -*-
|
||||||
|
|
||||||
|
# Skip if not running interactively.
|
||||||
|
[ -z "$PS1" ] && return
|
||||||
|
|
||||||
|
${export "HISTSIZE" cfg.historySize}
|
||||||
|
${export "HISTFILESIZE" cfg.historyFileSize}
|
||||||
|
${exportIfNonEmpty "HISTCONTROL" histControlStr}
|
||||||
|
${exportIfNonEmpty "HISTIGNORE" histIgnoreStr}
|
||||||
|
|
||||||
|
${shoptsStr}
|
||||||
|
|
||||||
|
${aliasesStr}
|
||||||
|
|
||||||
|
${cfg.initExtra}
|
||||||
|
|
||||||
|
${optionalString cfg.enableAutojump
|
||||||
|
". ${pkgs.autojump}/share/autojump/autojump.bash"}
|
||||||
|
'';
|
||||||
|
|
||||||
|
home.packages =
|
||||||
|
optional (cfg.enableAutojump) pkgs.autojump;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
28
modules/programs/beets.nix
Normal file
28
modules/programs/beets.nix
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
|
||||||
|
cfg = config.programs.beets;
|
||||||
|
|
||||||
|
in
|
||||||
|
|
||||||
|
{
|
||||||
|
options = {
|
||||||
|
programs.beets = {
|
||||||
|
settings = mkOption {
|
||||||
|
type = types.attrs;
|
||||||
|
default = {};
|
||||||
|
description = "Configuration written to ~/.config/beets/config.yaml";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf (cfg.settings != {}) {
|
||||||
|
home.packages = [ pkgs.beets ];
|
||||||
|
|
||||||
|
home.file.".config/beets/config.yaml".text =
|
||||||
|
builtins.toJSON config.programs.beets.settings;
|
||||||
|
};
|
||||||
|
}
|
39
modules/programs/eclipse.nix
Normal file
39
modules/programs/eclipse.nix
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
|
||||||
|
cfg = config.programs.eclipse;
|
||||||
|
|
||||||
|
in
|
||||||
|
|
||||||
|
{
|
||||||
|
options = {
|
||||||
|
programs.eclipse = {
|
||||||
|
enable = mkEnableOption "Eclipse";
|
||||||
|
|
||||||
|
jvmArgs = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [];
|
||||||
|
description = "JVM arguments to use for the Eclipse process.";
|
||||||
|
};
|
||||||
|
|
||||||
|
plugins = mkOption {
|
||||||
|
type = types.listOf types.package;
|
||||||
|
default = [];
|
||||||
|
description = "Plugins that should be added to Eclipse.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
home.packages = [
|
||||||
|
(pkgs.eclipses.eclipseWithPlugins {
|
||||||
|
eclipse = pkgs.eclipses.eclipse-platform;
|
||||||
|
jvmArgs = cfg.jvmArgs;
|
||||||
|
plugins = cfg.plugins;
|
||||||
|
})
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
29
modules/programs/emacs.nix
Normal file
29
modules/programs/emacs.nix
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
|
||||||
|
cfg = config.programs.emacs;
|
||||||
|
|
||||||
|
in
|
||||||
|
|
||||||
|
{
|
||||||
|
options = {
|
||||||
|
programs.emacs = {
|
||||||
|
enable = mkEnableOption "Emacs";
|
||||||
|
|
||||||
|
extraPackages = mkOption {
|
||||||
|
default = self: [];
|
||||||
|
example = literalExample ''
|
||||||
|
epkgs: [ epkgs.emms epkgs.magit ]
|
||||||
|
'';
|
||||||
|
description = "Extra packages available to Emacs.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
home.packages = [ (pkgs.emacsWithPackages cfg.extraPackages) ];
|
||||||
|
};
|
||||||
|
}
|
102
modules/programs/git.nix
Normal file
102
modules/programs/git.nix
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
|
||||||
|
cfg = config.programs.git;
|
||||||
|
|
||||||
|
toINI = (import ../lib/generators.nix).toINI {};
|
||||||
|
|
||||||
|
signModule = types.submodule (
|
||||||
|
{ ... }: {
|
||||||
|
options = {
|
||||||
|
key = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = null;
|
||||||
|
description = "The default GPG signing key fingerprint.";
|
||||||
|
};
|
||||||
|
|
||||||
|
signByDefault = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
description = "Whether commits should be signed by default.";
|
||||||
|
};
|
||||||
|
|
||||||
|
gpgPath = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
default = "${pkgs.gnupg}/bin/gpg2";
|
||||||
|
defaultText = "''${pkgs.gnupg}/bin/gpg2";
|
||||||
|
description = "Path to GnuPG binary to use.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
in
|
||||||
|
|
||||||
|
{
|
||||||
|
options = {
|
||||||
|
programs.git = {
|
||||||
|
enable = mkEnableOption "Git";
|
||||||
|
|
||||||
|
package = mkOption {
|
||||||
|
type = types.package;
|
||||||
|
default = pkgs.git;
|
||||||
|
defaultText = "pkgs.git";
|
||||||
|
description = "Git package to install.";
|
||||||
|
};
|
||||||
|
|
||||||
|
userName = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
description = "Default user name to use.";
|
||||||
|
};
|
||||||
|
|
||||||
|
userEmail = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
description = "Default user email to use.";
|
||||||
|
};
|
||||||
|
|
||||||
|
aliases = mkOption {
|
||||||
|
type = types.attrs;
|
||||||
|
default = {};
|
||||||
|
description = "Git aliases to define.";
|
||||||
|
};
|
||||||
|
|
||||||
|
signing = mkOption {
|
||||||
|
type = types.nullOr signModule;
|
||||||
|
default = null;
|
||||||
|
description = "Options related to signing commits using GnuPG.";
|
||||||
|
};
|
||||||
|
|
||||||
|
extraConfig = mkOption {
|
||||||
|
type = types.lines;
|
||||||
|
default = null;
|
||||||
|
description = "Additional configuration to add.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable (
|
||||||
|
let
|
||||||
|
ini = {
|
||||||
|
user = {
|
||||||
|
name = cfg.userName;
|
||||||
|
email = cfg.userEmail;
|
||||||
|
} // optionalAttrs (cfg.signing != null) {
|
||||||
|
signingKey = cfg.signing.key;
|
||||||
|
};
|
||||||
|
} // optionalAttrs (cfg.signing != null) {
|
||||||
|
commit.gpgSign = cfg.signing.signByDefault;
|
||||||
|
gpg.program = cfg.signing.gpgPath;
|
||||||
|
} // optionalAttrs (cfg.aliases != {}) {
|
||||||
|
alias = cfg.aliases;
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
home.packages = [ cfg.package ];
|
||||||
|
|
||||||
|
home.file.".gitconfig".text = toINI ini + "\n" + cfg.extraConfig;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
186
modules/programs/gnome-terminal.nix
Normal file
186
modules/programs/gnome-terminal.nix
Normal file
|
@ -0,0 +1,186 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
|
||||||
|
cfg = config.programs.gnome-terminal;
|
||||||
|
|
||||||
|
profileColorsSubModule = types.submodule (
|
||||||
|
{ ... }: {
|
||||||
|
options = {
|
||||||
|
foregroundColor = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
description = "The foreground color.";
|
||||||
|
};
|
||||||
|
|
||||||
|
backgroundColor = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
description = "The background color.";
|
||||||
|
};
|
||||||
|
|
||||||
|
boldColor = mkOption {
|
||||||
|
default = null;
|
||||||
|
type = types.nullOr types.str;
|
||||||
|
description = "The bold color, null to use same as foreground.";
|
||||||
|
};
|
||||||
|
|
||||||
|
palette = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
description = "The terminal palette.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
profileSubModule = types.submodule (
|
||||||
|
{ name, config, ... }: {
|
||||||
|
options = {
|
||||||
|
default = mkOption {
|
||||||
|
default = false;
|
||||||
|
type = types.bool;
|
||||||
|
description = "Whether this should be the default profile.";
|
||||||
|
};
|
||||||
|
|
||||||
|
visibleName = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
description = "The profile name.";
|
||||||
|
};
|
||||||
|
|
||||||
|
colors = mkOption {
|
||||||
|
default = null;
|
||||||
|
type = types.nullOr profileColorsSubModule;
|
||||||
|
description = "The terminal colors, null to use system default.";
|
||||||
|
};
|
||||||
|
|
||||||
|
cursorShape = mkOption {
|
||||||
|
default = "block";
|
||||||
|
type = types.enum [ "block" "ibeam" "underline" ];
|
||||||
|
description = "The cursor shape.";
|
||||||
|
};
|
||||||
|
|
||||||
|
font = mkOption {
|
||||||
|
default = null;
|
||||||
|
type = types.nullOr types.str;
|
||||||
|
description = "The font name, null to use system default.";
|
||||||
|
};
|
||||||
|
|
||||||
|
scrollOnOutput = mkOption {
|
||||||
|
default = true;
|
||||||
|
type = types.bool;
|
||||||
|
description = "Whether to scroll when output is written.";
|
||||||
|
};
|
||||||
|
|
||||||
|
showScrollbar = mkOption {
|
||||||
|
default = true;
|
||||||
|
type = types.bool;
|
||||||
|
description = "Whether the scroll bar should be visible.";
|
||||||
|
};
|
||||||
|
|
||||||
|
scrollbackLines = mkOption {
|
||||||
|
default = 10000;
|
||||||
|
type = types.nullOr types.int;
|
||||||
|
description =
|
||||||
|
''
|
||||||
|
The number of scrollback lines to keep, null for infinite.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
toINI = (import ../lib/generators.nix).toINI { mkKeyValue = mkIniKeyValue; };
|
||||||
|
|
||||||
|
mkIniKeyValue = key: value:
|
||||||
|
let
|
||||||
|
tweakVal = v:
|
||||||
|
if isString v then "'${v}'"
|
||||||
|
else if isList v then "[" + concatStringsSep "," (map tweakVal v) + "]"
|
||||||
|
else if isBool v && v then "true"
|
||||||
|
else if isBool v && !v then "false"
|
||||||
|
else toString v;
|
||||||
|
in
|
||||||
|
"${key}=${tweakVal value}";
|
||||||
|
|
||||||
|
buildProfileSet = pcfg:
|
||||||
|
{
|
||||||
|
visible-name = pcfg.visibleName;
|
||||||
|
scrollbar-policy = if pcfg.showScrollbar then "always" else "never";
|
||||||
|
scrollback-lines = pcfg.scrollbackLines;
|
||||||
|
cursor-shape = pcfg.cursorShape;
|
||||||
|
}
|
||||||
|
// (
|
||||||
|
if (pcfg.font == null)
|
||||||
|
then { use-system-font = true; }
|
||||||
|
else { use-system-font = false; font = pcfg.font; }
|
||||||
|
) // (
|
||||||
|
if (pcfg.colors == null)
|
||||||
|
then { use-theme-colors = true; }
|
||||||
|
else (
|
||||||
|
{
|
||||||
|
use-theme-colors = false;
|
||||||
|
foreground-color = pcfg.colors.foregroundColor;
|
||||||
|
background-color = pcfg.colors.backgroundColor;
|
||||||
|
palette = pcfg.colors.palette;
|
||||||
|
}
|
||||||
|
// (
|
||||||
|
if (pcfg.colors.boldColor == null)
|
||||||
|
then { bold-color-same-as-fg = true; }
|
||||||
|
else {
|
||||||
|
bold-color-same-as-fg = false;
|
||||||
|
bold-color = pcfg.colors.boldColor;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
buildIniSet = cfg:
|
||||||
|
{
|
||||||
|
"/" = {
|
||||||
|
default-show-menubar = cfg.showMenubar;
|
||||||
|
schema-version = 3;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
//
|
||||||
|
{
|
||||||
|
"profiles:" = {
|
||||||
|
default = head (attrNames (filterAttrs (n: v: v.default) cfg.profile));
|
||||||
|
list = attrNames cfg.profile; #mapAttrsToList (n: v: n) cfg.profile;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
//
|
||||||
|
mapAttrs' (name: value:
|
||||||
|
nameValuePair ("profiles:/:${name}") (buildProfileSet value)
|
||||||
|
) cfg.profile;
|
||||||
|
|
||||||
|
in
|
||||||
|
|
||||||
|
{
|
||||||
|
options = {
|
||||||
|
programs.gnome-terminal = {
|
||||||
|
enable = mkEnableOption "Gnome Terminal";
|
||||||
|
|
||||||
|
showMenubar = mkOption {
|
||||||
|
default = true;
|
||||||
|
type = types.bool;
|
||||||
|
description = "Whether to show the menubar by default";
|
||||||
|
};
|
||||||
|
|
||||||
|
profile = mkOption {
|
||||||
|
default = {};
|
||||||
|
type = types.loaOf profileSubModule;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
home.activation.gnome-terminal =
|
||||||
|
let
|
||||||
|
sf = pkgs.writeText "gnome-terminal.ini" (toINI (buildIniSet cfg));
|
||||||
|
dconfPath = "/org/gnome/terminal/legacy/";
|
||||||
|
in
|
||||||
|
''
|
||||||
|
${pkgs.gnome3.dconf}/bin/dconf load ${dconfPath} < ${sf}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
}
|
17
modules/programs/lesspipe.nix
Normal file
17
modules/programs/lesspipe.nix
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
{
|
||||||
|
options = {
|
||||||
|
programs.lesspipe = {
|
||||||
|
enable = mkEnableOption "lesspipe preprocessor for less";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf config.programs.lesspipe.enable {
|
||||||
|
home.sessionVariables = {
|
||||||
|
LESSOPEN = "|${pkgs.lesspipe}/bin/lesspipe.sh %s";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
32
modules/programs/texlive.nix
Normal file
32
modules/programs/texlive.nix
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
|
||||||
|
cfg = config.programs.texlive;
|
||||||
|
|
||||||
|
in
|
||||||
|
|
||||||
|
{
|
||||||
|
options = {
|
||||||
|
programs.texlive = {
|
||||||
|
enable = mkEnableOption "Texlive";
|
||||||
|
|
||||||
|
extraPackages = mkOption {
|
||||||
|
default = self: {};
|
||||||
|
example = literalExample ''
|
||||||
|
tpkgs: { inherit (tpkgs) collection-fontsrecommended algorithms; }
|
||||||
|
'';
|
||||||
|
description = "Extra packages available to Texlive.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
home.packages = [
|
||||||
|
(pkgs.texlive.combine (cfg.extraPackages pkgs.texlive))
|
||||||
|
];
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
35
modules/services/dunst.nix
Normal file
35
modules/services/dunst.nix
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
{
|
||||||
|
options = {
|
||||||
|
services.dunst = {
|
||||||
|
enable = mkEnableOption "the dunst notification daemon";
|
||||||
|
|
||||||
|
settings = mkOption {
|
||||||
|
type = types.attrs;
|
||||||
|
default = {};
|
||||||
|
description = "Configuration written to ~/.config/dunstrc";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf config.services.dunst.enable {
|
||||||
|
systemd.user.services.dunst = {
|
||||||
|
Unit = {
|
||||||
|
Description = "Dunst notification daemon";
|
||||||
|
};
|
||||||
|
|
||||||
|
Install = {
|
||||||
|
WantedBy = [ "xorg.target" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
Service = {
|
||||||
|
# Type = "dbus";
|
||||||
|
# BusName = "org.freedesktop.Notifications";
|
||||||
|
ExecStart = "${pkgs.dunst}/bin/dunst";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
52
modules/services/gnome-keyring.nix
Normal file
52
modules/services/gnome-keyring.nix
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
|
||||||
|
cfg = config.services.gnome-keyring;
|
||||||
|
|
||||||
|
in
|
||||||
|
|
||||||
|
{
|
||||||
|
options = {
|
||||||
|
services.gnome-keyring = {
|
||||||
|
enable = mkEnableOption "GNOME Keyring";
|
||||||
|
|
||||||
|
components = mkOption {
|
||||||
|
type = types.listOf (types.enum ["pkcs11" "secrets" "ssh"]);
|
||||||
|
default = [];
|
||||||
|
description = ''
|
||||||
|
The GNOME keyring components to start. If empty then the
|
||||||
|
default set of components will be started.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
systemd.user.services.gnome-keyring = {
|
||||||
|
Unit = {
|
||||||
|
Description = "GNOME Keyring";
|
||||||
|
};
|
||||||
|
|
||||||
|
Service = {
|
||||||
|
ExecStart =
|
||||||
|
let
|
||||||
|
args = concatStringsSep " " (
|
||||||
|
[ "--start" "--foreground" ]
|
||||||
|
++ optional (cfg.components != []) (
|
||||||
|
"--components=" + concatStringsSep "," cfg.components
|
||||||
|
)
|
||||||
|
);
|
||||||
|
in
|
||||||
|
"${pkgs.gnome3.gnome_keyring}/bin/gnome-keyring-daemon ${args}";
|
||||||
|
Restart = "on-abort";
|
||||||
|
};
|
||||||
|
|
||||||
|
Install = {
|
||||||
|
WantedBy = [ "xorg.target" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
69
modules/services/gpg-agent.nix
Normal file
69
modules/services/gpg-agent.nix
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
|
||||||
|
cfg = config.services.gpg-agent;
|
||||||
|
|
||||||
|
in
|
||||||
|
|
||||||
|
{
|
||||||
|
options = {
|
||||||
|
services.gpg-agent = {
|
||||||
|
enable = mkEnableOption "GnuPG private key agent";
|
||||||
|
|
||||||
|
defaultCacheTtl = mkOption {
|
||||||
|
type = types.nullOr types.int;
|
||||||
|
default = null;
|
||||||
|
description = ''
|
||||||
|
Set the time a cache entry is valid to the given number of seconds.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
enableSshSupport = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = false;
|
||||||
|
description = "Whether to use the GnuPG key agent for SSH keys.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
home.file.".gnupg/gpg-agent.conf".text = concatStringsSep "\n" (
|
||||||
|
optional cfg.enableSshSupport
|
||||||
|
"enable-ssh-support"
|
||||||
|
++
|
||||||
|
optional (cfg.defaultCacheTtl != null)
|
||||||
|
"default-cache-ttl ${toString cfg.defaultCacheTtl}"
|
||||||
|
);
|
||||||
|
|
||||||
|
home.sessionVariables =
|
||||||
|
optionalAttrs cfg.enableSshSupport {
|
||||||
|
SSH_AUTH_SOCK = "\${XDG_RUNTIME_DIR}/gnupg/S.gpg-agent.ssh";
|
||||||
|
};
|
||||||
|
|
||||||
|
programs.bash.initExtra = ''
|
||||||
|
GPG_TTY="$(tty)"
|
||||||
|
export GPG_TTY
|
||||||
|
gpg-connect-agent updatestartuptty /bye > /dev/null
|
||||||
|
'';
|
||||||
|
|
||||||
|
systemd.user.services.gpg-agent = {
|
||||||
|
Unit = {
|
||||||
|
Description = "GnuPG private key agent";
|
||||||
|
IgnoreOnIsolate = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
Service = {
|
||||||
|
Type = "forking";
|
||||||
|
ExecStart = "${pkgs.gnupg}/bin/gpg-agent --daemon --use-standard-socket";
|
||||||
|
Restart = "on-abort";
|
||||||
|
};
|
||||||
|
|
||||||
|
Install = {
|
||||||
|
WantedBy = [ "default.target" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
27
modules/services/keepassx.nix
Normal file
27
modules/services/keepassx.nix
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
{
|
||||||
|
options = {
|
||||||
|
services.keepassx = {
|
||||||
|
enable = mkEnableOption "the KeePassX password manager";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf config.services.keepassx.enable {
|
||||||
|
systemd.user.services.keepassx = {
|
||||||
|
Unit = {
|
||||||
|
Description = "KeePassX password manager";
|
||||||
|
};
|
||||||
|
|
||||||
|
Install = {
|
||||||
|
WantedBy = [ "xorg.target" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
Service = {
|
||||||
|
ExecStart = "${pkgs.keepassx}/bin/keepassx -min -lock";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
27
modules/services/network-manager-applet.nix
Normal file
27
modules/services/network-manager-applet.nix
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
{
|
||||||
|
options = {
|
||||||
|
services.network-manager-applet = {
|
||||||
|
enable = mkEnableOption "the Network Manager applet";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf config.services.network-manager-applet.enable {
|
||||||
|
systemd.user.services.network-manager-applet = {
|
||||||
|
Unit = {
|
||||||
|
Description = "Network Manager applet";
|
||||||
|
};
|
||||||
|
|
||||||
|
Install = {
|
||||||
|
WantedBy = [ "xorg.target" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
Service = {
|
||||||
|
ExecStart = "${pkgs.networkmanagerapplet}/bin/nm-applet --sm-disable";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
74
modules/services/random-background.nix
Normal file
74
modules/services/random-background.nix
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
|
||||||
|
cfg = config.services.random-background;
|
||||||
|
|
||||||
|
in
|
||||||
|
|
||||||
|
{
|
||||||
|
options = {
|
||||||
|
services.random-background = {
|
||||||
|
enable = mkEnableOption "random desktop background";
|
||||||
|
|
||||||
|
imageDirectory = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
description =
|
||||||
|
''
|
||||||
|
The directory of images from which a background should be
|
||||||
|
chosen. Should be formatted in a way understood by
|
||||||
|
systemd, e.g., '%h' is the home directory.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
interval = mkOption {
|
||||||
|
default = null;
|
||||||
|
type = types.nullOr types.str;
|
||||||
|
description = ''
|
||||||
|
The duration between changing background image, set to null
|
||||||
|
to only set background when logging in.
|
||||||
|
|
||||||
|
Should be formatted as a duration understood by systemd.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable (
|
||||||
|
mkMerge ([
|
||||||
|
{
|
||||||
|
systemd.user.services.random-background = {
|
||||||
|
Unit = {
|
||||||
|
Description = "Set random desktop background using feh";
|
||||||
|
};
|
||||||
|
|
||||||
|
Service = {
|
||||||
|
Type = "oneshot";
|
||||||
|
ExecStart = "${pkgs.feh}/bin/feh --randomize --bg-fill %h/backgrounds/";
|
||||||
|
IOSchedulingClass = "idle";
|
||||||
|
};
|
||||||
|
|
||||||
|
Install = {
|
||||||
|
WantedBy = [ "xorg.target" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
(mkIf (cfg.interval != null) {
|
||||||
|
systemd.user.timers.random-background = {
|
||||||
|
Unit = {
|
||||||
|
Description = "Set random desktop background using feh";
|
||||||
|
};
|
||||||
|
|
||||||
|
Timer = {
|
||||||
|
OnUnitActiveSec = cfg.interval;
|
||||||
|
};
|
||||||
|
|
||||||
|
Install = {
|
||||||
|
WantedBy = [ "timers.target" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
})
|
||||||
|
]));
|
||||||
|
}
|
41
modules/services/taffybar.nix
Normal file
41
modules/services/taffybar.nix
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
|
||||||
|
cfg = config.services.taffybar;
|
||||||
|
|
||||||
|
in
|
||||||
|
|
||||||
|
{
|
||||||
|
options = {
|
||||||
|
services.taffybar = {
|
||||||
|
enable = mkEnableOption "Taffybar";
|
||||||
|
|
||||||
|
package = mkOption {
|
||||||
|
default = pkgs.taffybar;
|
||||||
|
defaultText = "pkgs.taffybar";
|
||||||
|
type = types.package;
|
||||||
|
example = literalExample "pkgs.taffybar";
|
||||||
|
description = "The package to use for the Taffybar binary.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf config.services.taffybar.enable {
|
||||||
|
systemd.user.services.taffybar = {
|
||||||
|
Unit = {
|
||||||
|
Description = "Taffybar desktop bar";
|
||||||
|
};
|
||||||
|
|
||||||
|
Service = {
|
||||||
|
ExecStart = "${cfg.package}/bin/taffybar";
|
||||||
|
};
|
||||||
|
|
||||||
|
Install = {
|
||||||
|
WantedBy = [ "xorg.target" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
23
modules/services/tahoe-lafs.nix
Normal file
23
modules/services/tahoe-lafs.nix
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
{
|
||||||
|
options = {
|
||||||
|
services.tahoe-lafs = {
|
||||||
|
enable = mkEnableOption "Tahoe-LAFS";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf config.services.tahoe-lafs.enable {
|
||||||
|
systemd.user.services.tahoe-lafs = {
|
||||||
|
Unit = {
|
||||||
|
Description = "Tahoe-LAFS";
|
||||||
|
};
|
||||||
|
|
||||||
|
Service = {
|
||||||
|
ExecStart = "${pkgs.tahoelafs}/bin/tahoe run -C %h/.tahoe";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
29
modules/services/udiskie.nix
Normal file
29
modules/services/udiskie.nix
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
{
|
||||||
|
options = {
|
||||||
|
services.udiskie = {
|
||||||
|
enable = mkEnableOption "Udiskie mount daemon";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf config.services.udiskie.enable {
|
||||||
|
systemd.user.services.udiskie = {
|
||||||
|
Unit = {
|
||||||
|
Description = "Udiskie mount daemon";
|
||||||
|
Requires = [ "taffybar.service" ];
|
||||||
|
After = [ "taffybar.service" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
Service = {
|
||||||
|
ExecStart = "${pkgs.pythonPackages.udiskie}/bin/udiskie -2 -A -n -s";
|
||||||
|
};
|
||||||
|
|
||||||
|
Install = {
|
||||||
|
WantedBy = [ "xorg.target" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
27
modules/services/xscreensaver.nix
Normal file
27
modules/services/xscreensaver.nix
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
{
|
||||||
|
options = {
|
||||||
|
services.xscreensaver = {
|
||||||
|
enable = mkEnableOption "XScreenSaver";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf config.services.xscreensaver.enable {
|
||||||
|
systemd.user.services.xscreensaver = {
|
||||||
|
Unit = {
|
||||||
|
Description = "XScreenSaver";
|
||||||
|
};
|
||||||
|
|
||||||
|
Service = {
|
||||||
|
ExecStart = "${pkgs.xscreensaver}/bin/xscreensaver -no-splash";
|
||||||
|
};
|
||||||
|
|
||||||
|
Install = {
|
||||||
|
WantedBy = [ "xorg.target" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
119
modules/systemd.nix
Normal file
119
modules/systemd.nix
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
|
||||||
|
toSystemdIni = (import lib/generators.nix).toINI {
|
||||||
|
mkKeyValue = key: value:
|
||||||
|
let
|
||||||
|
value' =
|
||||||
|
if isBool value then (if value then "true" else "false")
|
||||||
|
else toString value;
|
||||||
|
in
|
||||||
|
"${key}=${value'}";
|
||||||
|
};
|
||||||
|
|
||||||
|
buildService = style: name: serviceCfg:
|
||||||
|
let
|
||||||
|
source = pkgs.writeText "${name}.${style}" (toSystemdIni serviceCfg);
|
||||||
|
|
||||||
|
wantedBy = target:
|
||||||
|
{
|
||||||
|
name = ".config/systemd/user/${target}.wants/${name}.${style}";
|
||||||
|
value = { inherit source; };
|
||||||
|
};
|
||||||
|
in
|
||||||
|
singleton {
|
||||||
|
name = ".config/systemd/user/${name}.${style}";
|
||||||
|
value = { inherit source; };
|
||||||
|
}
|
||||||
|
++
|
||||||
|
map wantedBy (serviceCfg.Install.WantedBy or []);
|
||||||
|
|
||||||
|
buildServices = style: serviceCfgs:
|
||||||
|
concatLists (mapAttrsToList (buildService style) serviceCfgs);
|
||||||
|
|
||||||
|
in
|
||||||
|
|
||||||
|
{
|
||||||
|
options = {
|
||||||
|
systemd.user = {
|
||||||
|
services = mkOption {
|
||||||
|
default = {};
|
||||||
|
type = types.attrs;
|
||||||
|
description = "Definition of systemd per-user service units.";
|
||||||
|
};
|
||||||
|
|
||||||
|
timers = mkOption {
|
||||||
|
default = {};
|
||||||
|
type = types.attrs;
|
||||||
|
description = "Definition of systemd per-user timers";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = {
|
||||||
|
home.file =
|
||||||
|
listToAttrs (
|
||||||
|
(buildServices "service" config.systemd.user.services)
|
||||||
|
++
|
||||||
|
(buildServices "timer" config.systemd.user.timers)
|
||||||
|
);
|
||||||
|
|
||||||
|
home.activation.reloadSystemD = stringAfter ["linkages"] ''
|
||||||
|
function systemdPostReload() {
|
||||||
|
local servicesDiffFile="$(mktemp)"
|
||||||
|
|
||||||
|
diff \
|
||||||
|
--new-line-format='+%L' \
|
||||||
|
--old-line-format='-%L' \
|
||||||
|
--unchanged-line-format=' %L' \
|
||||||
|
<(basename -a $(echo "$oldGenPath/.config/systemd/user/*.service") | sort) \
|
||||||
|
<(basename -a $(echo "$newGenPath/.config/systemd/user/*.service") | sort) \
|
||||||
|
> $servicesDiffFile
|
||||||
|
|
||||||
|
local -a maybeRestart=( $(grep '^ ' $servicesDiffFile | cut -c2-) )
|
||||||
|
local -a toStop=( $(grep '^-' $servicesDiffFile | cut -c2-) )
|
||||||
|
local -a toStart=( $(grep '^+' $servicesDiffFile | cut -c2-) )
|
||||||
|
local -a toRestart=( )
|
||||||
|
|
||||||
|
for f in ''${maybeRestart[@]} ; do
|
||||||
|
if systemctl --quiet --user is-active "$f" \
|
||||||
|
&& ! cmp --quiet \
|
||||||
|
"$oldGenPath/.config/systemd/user/$f" \
|
||||||
|
"$newGenPath/.config/systemd/user/$f" ; then
|
||||||
|
echo "Adding '$f' to restart list";
|
||||||
|
toRestart+=("$f")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
rm $servicesDiffFile
|
||||||
|
|
||||||
|
sugg=""
|
||||||
|
|
||||||
|
if [[ -n "''${toRestart[@]}" ]] ; then
|
||||||
|
sugg="$sugg\nsystemctl --user restart ''${toRestart[@]}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n "''${toStop[@]}" ]] ; then
|
||||||
|
sugg="$sugg\nsystemctl --user stop ''${toStop[@]}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n "''${toStart[@]}" ]] ; then
|
||||||
|
sugg="$sugg\nsystemctl --user start ''${toStart[@]}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n "$sugg" ]] ; then
|
||||||
|
echo "Suggested commands:"
|
||||||
|
echo -e "$sugg"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ "$oldGenPath" != "$newGenPath" ]] ; then
|
||||||
|
systemctl --user daemon-reload
|
||||||
|
systemdPostReload
|
||||||
|
fi
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
}
|
77
modules/xsession.nix
Normal file
77
modules/xsession.nix
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
|
||||||
|
cfg = config.xsession;
|
||||||
|
|
||||||
|
in
|
||||||
|
|
||||||
|
{
|
||||||
|
options = {
|
||||||
|
xsession = {
|
||||||
|
enable = mkEnableOption "X Session";
|
||||||
|
|
||||||
|
windowManager = mkOption {
|
||||||
|
default = {};
|
||||||
|
type = types.str;
|
||||||
|
description = "Path to window manager to exec.";
|
||||||
|
};
|
||||||
|
|
||||||
|
initExtra = mkOption {
|
||||||
|
type = types.lines;
|
||||||
|
default = "";
|
||||||
|
description = "Extra shell commands to run during initialization.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
systemd.user.services.setxkbmap = {
|
||||||
|
Unit = {
|
||||||
|
Description = "Set up keyboard in X";
|
||||||
|
};
|
||||||
|
|
||||||
|
Install = {
|
||||||
|
WantedBy = [ "xorg.target" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
Service = {
|
||||||
|
Type = "oneshot";
|
||||||
|
ExecStart =
|
||||||
|
let
|
||||||
|
args = concatStringsSep " " (
|
||||||
|
[
|
||||||
|
"-layout '${config.home.keyboard.layout}'"
|
||||||
|
"-variant '${config.home.keyboard.variant}'"
|
||||||
|
] ++
|
||||||
|
(map (v: "-option '${v}'") config.home.keyboard.options)
|
||||||
|
);
|
||||||
|
in
|
||||||
|
"${pkgs.xorg.setxkbmap}/bin/setxkbmap ${args}";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
home.file.".xsession" = {
|
||||||
|
mode = "555";
|
||||||
|
text = ''
|
||||||
|
# Rely on Bash to set session variables.
|
||||||
|
. "$HOME/.profile"
|
||||||
|
|
||||||
|
systemctl --user import-environment DBUS_SESSION_BUS_ADDRESS
|
||||||
|
systemctl --user import-environment DISPLAY
|
||||||
|
systemctl --user import-environment SSH_AUTH_SOCK
|
||||||
|
systemctl --user import-environment XDG_DATA_DIRS
|
||||||
|
systemctl --user import-environment XDG_RUNTIME_DIR
|
||||||
|
systemctl --user start xorg.target
|
||||||
|
|
||||||
|
${cfg.initExtra}
|
||||||
|
|
||||||
|
${cfg.windowManager}
|
||||||
|
|
||||||
|
systemctl --user stop xorg.target
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
Loading…
Reference in a new issue