aboutsummaryrefslogtreecommitdiff
path: root/home-manager/modules/programs/ncmpcpp.nix
blob: a39baab6ca5a1f504cb15caf920f87f4e2691570 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
{ 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 = if option then "yes" else "no";
      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 = with maintainers; [ olmokramer ];

  options.programs.ncmpcpp = {
    enable =
      mkEnableOption "ncmpcpp - an ncurses Music Player Daemon (MPD) client";

    package = mkOption {
      type = types.package;
      default = pkgs.ncmpcpp;
      defaultText = literalExample "pkgs.ncmpcpp";
      description = ''
        Package providing the <code>ncmpcpp</code> command.
      '';
      example =
        literalExample "pkgs.ncmpcpp.override { visualizerSupport = true; }";
    };

    mpdMusicDir = mkOption {
      type = types.nullOr types.path;
      default = let mpdCfg = config.services.mpd;
      in if pkgs.stdenv.hostPlatform.isLinux && mpdCfg.enable then
        mpdCfg.musicDirectory
      else
        null;
      defaultText = literalExample ''
        if pkgs.stdenv.hostPlatform.isLinux && config.services.mpd.enable then
          config.services.mpd.musicDirectory
        else
          null
      '';
      description = ''
        Value of the <code>mpd_music_dir</code> setting. On Linux platforms the
        value of <varname>services.mpd.musicDirectory</varname> is used as the
        default if <varname>services.mpd.enable</varname> is
        <literal>true</literal>.
      '';
      example = "~/music";
    };

    settings = mkOption {
      type = types.attrsOf valueType;
      default = { };
      description = ''
        Attribute set from name of a setting to its value. For available options
        see
        <citerefentry>
          <refentrytitle>ncmpcpp</refentrytitle>
          <manvolnum>1</manvolnum>
        </citerefentry>.
      '';
      example = { ncmpcpp_directory = "~/.local/share/ncmpcpp"; };
    };

    bindings = mkOption {
      type = types.listOf bindingType;
      default = [ ];
      description = "List of keybindings.";
      example = literalExample ''
        [
          { 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 = toString cfg.mpdMusicDir;
        };
      in mkIf (settings != { }) { text = renderSettings settings + "\n"; };

      "ncmpcpp/bindings" = mkIf (cfg.bindings != [ ]) {
        text = renderBindings cfg.bindings + "\n";
      };
    };
  };
}