{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.programs.ncmpcpp;
renderSettings = settings:
concatStringsSep "\n" (mapAttrsToList renderSetting settings);
renderSetting = name: value: "${name}=${renderValue value}";
renderValue = option:
{
int = toString option;
bool = lib.hm.booleans.yesNo option;
string = option;
}.${builtins.typeOf option};
renderBindings = bindings: concatStringsSep "\n" (map renderBinding bindings);
renderBinding = { key, command }:
concatStringsSep "\n " ([ ''def_key "${key}"'' ] ++ maybeWrapList command);
maybeWrapList = xs: if isList xs then xs else [ xs ];
valueType = with types; oneOf [ bool int str ];
bindingType = types.submodule ({ name, config, ... }: {
options = {
key = mkOption {
type = types.str;
description = "Key to bind.";
example = "j";
};
command = mkOption {
type = with types; either str (listOf str);
description = "Command or sequence of commands to be executed.";
example = "scroll_down";
};
};
});
in {
meta.maintainers = [ hm.maintainers.olmokramer ];
options.programs.ncmpcpp = {
enable =
mkEnableOption "ncmpcpp - an ncurses Music Player Daemon (MPD) client";
package = mkOption {
type = types.package;
default = pkgs.ncmpcpp;
defaultText = literalExpression "pkgs.ncmpcpp";
description = ''
Package providing the ncmpcpp
command.
'';
example =
literalExpression "pkgs.ncmpcpp.override { visualizerSupport = true; }";
};
mpdMusicDir = mkOption {
type = with types; nullOr (coercedTo path toString str);
default = let mpdCfg = config.services.mpd;
in if pkgs.stdenv.hostPlatform.isLinux && mpdCfg.enable then
mpdCfg.musicDirectory
else
null;
defaultText = literalExpression ''
if pkgs.stdenv.hostPlatform.isLinux && config.services.mpd.enable then
config.services.mpd.musicDirectory
else
null
'';
description = ''
Value of the mpd_music_dir
setting. On Linux platforms the
value of services.mpd.musicDirectory is used as the
default if services.mpd.enable is
true.
'';
example = "~/music";
};
settings = mkOption {
type = types.attrsOf valueType;
default = { };
description = ''
Attribute set from name of a setting to its value. For available options
see
ncmpcpp
1
.
'';
example = { ncmpcpp_directory = "~/.local/share/ncmpcpp"; };
};
bindings = mkOption {
type = types.listOf bindingType;
default = [ ];
description = "List of keybindings.";
example = literalExpression ''
[
{ key = "j"; command = "scroll_down"; }
{ key = "k"; command = "scroll_up"; }
{ key = "J"; command = [ "select_item" "scroll_down" ]; }
{ key = "K"; command = [ "select_item" "scroll_up" ]; }
]
'';
};
};
config = mkIf cfg.enable {
warnings = mkIf (cfg.settings ? mpd_music_dir && cfg.mpdMusicDir != null) [
("programs.ncmpcpp.settings.mpd_music_dir will be overridden by"
+ " programs.ncmpcpp.mpdMusicDir.")
];
home.packages = [ cfg.package ];
xdg.configFile = {
"ncmpcpp/config" = let
settings = cfg.settings // optionalAttrs (cfg.mpdMusicDir != null) {
mpd_music_dir = cfg.mpdMusicDir;
};
in mkIf (settings != { }) { text = renderSettings settings + "\n"; };
"ncmpcpp/bindings" = mkIf (cfg.bindings != [ ]) {
text = renderBindings cfg.bindings + "\n";
};
};
};
}