1{
2 config,
3 lib,
4 pkgs,
5 ...
6}:
7
8let
9
10 cfg = config.programs.zsh.ohMyZsh;
11
12 mkLinkFarmEntry =
13 name: dir:
14 let
15 env = pkgs.buildEnv {
16 name = "zsh-${name}-env";
17 paths = cfg.customPkgs;
18 pathsToLink = "/share/zsh/${dir}";
19 };
20 in
21 {
22 inherit name;
23 path = "${env}/share/zsh/${dir}";
24 };
25
26 mkLinkFarmEntry' = name: mkLinkFarmEntry name name;
27
28 custom =
29 if cfg.custom != null then
30 cfg.custom
31 else if builtins.length cfg.customPkgs == 0 then
32 null
33 else
34 pkgs.linkFarm "oh-my-zsh-custom" [
35 (mkLinkFarmEntry' "themes")
36 (mkLinkFarmEntry "completions" "site-functions")
37 (mkLinkFarmEntry' "plugins")
38 ];
39
40in
41{
42 imports = [
43 (lib.mkRenamedOptionModule
44 [ "programs" "zsh" "oh-my-zsh" "enable" ]
45 [ "programs" "zsh" "ohMyZsh" "enable" ]
46 )
47 (lib.mkRenamedOptionModule
48 [ "programs" "zsh" "oh-my-zsh" "theme" ]
49 [ "programs" "zsh" "ohMyZsh" "theme" ]
50 )
51 (lib.mkRenamedOptionModule
52 [ "programs" "zsh" "oh-my-zsh" "custom" ]
53 [ "programs" "zsh" "ohMyZsh" "custom" ]
54 )
55 (lib.mkRenamedOptionModule
56 [ "programs" "zsh" "oh-my-zsh" "plugins" ]
57 [ "programs" "zsh" "ohMyZsh" "plugins" ]
58 )
59 ];
60
61 options = {
62 programs.zsh.ohMyZsh = {
63 enable = lib.mkOption {
64 type = lib.types.bool;
65 default = false;
66 description = ''
67 Enable oh-my-zsh.
68 '';
69 };
70
71 package = lib.mkPackageOption pkgs "oh-my-zsh" { };
72
73 plugins = lib.mkOption {
74 default = [ ];
75 type = lib.types.listOf (lib.types.str);
76 description = ''
77 List of oh-my-zsh plugins
78 '';
79 };
80
81 custom = lib.mkOption {
82 default = null;
83 type = with lib.types; nullOr str;
84 description = ''
85 Path to a custom oh-my-zsh package to override config of oh-my-zsh.
86 (Can't be used along with `customPkgs`).
87 '';
88 };
89
90 customPkgs = lib.mkOption {
91 default = [ ];
92 type = lib.types.listOf lib.types.package;
93 description = ''
94 List of custom packages that should be loaded into `oh-my-zsh`.
95 '';
96 };
97
98 theme = lib.mkOption {
99 default = "";
100 type = lib.types.str;
101 description = ''
102 Name of the theme to be used by oh-my-zsh.
103 '';
104 };
105
106 cacheDir = lib.mkOption {
107 default = "$HOME/.cache/oh-my-zsh";
108 type = lib.types.str;
109 description = ''
110 Cache directory to be used by `oh-my-zsh`.
111 Without this option it would default to the read-only nix store.
112 '';
113 };
114
115 preLoaded = lib.mkOption {
116 type = lib.types.lines;
117 default = "";
118 description = ''
119 Shell commands executed before the `oh-my-zsh` is loaded.
120 For example, to disable async git prompt write `zstyle ':omz:alpha:lib:git' async-prompt no` (more information <https://github.com/ohmyzsh/ohmyzsh?tab=readme-ov-file#async-git-prompt>)
121 '';
122 };
123 };
124 };
125
126 config = lib.mkIf cfg.enable {
127
128 # Prevent zsh from overwriting oh-my-zsh's prompt
129 programs.zsh.promptInit = lib.mkDefault "";
130
131 environment.systemPackages = [ cfg.package ];
132
133 programs.zsh.interactiveShellInit = ''
134 # oh-my-zsh configuration generated by NixOS
135 export ZSH=${cfg.package}/share/oh-my-zsh
136
137 ${lib.optionalString (
138 builtins.length (cfg.plugins) > 0
139 ) "plugins=(${builtins.concatStringsSep " " cfg.plugins})"}
140
141 ${lib.optionalString (custom != null) "ZSH_CUSTOM=\"${custom}\""}
142
143 ${lib.optionalString (builtins.stringLength (cfg.theme) > 0) "ZSH_THEME=\"${cfg.theme}\""}
144
145 ${lib.optionalString (cfg.cacheDir != null) ''
146 if [[ ! -d "${cfg.cacheDir}" ]]; then
147 mkdir -p "${cfg.cacheDir}"
148 fi
149 ZSH_CACHE_DIR=${cfg.cacheDir}
150 ''}
151
152 ${cfg.preLoaded}
153 source $ZSH/oh-my-zsh.sh
154 '';
155
156 assertions = [
157 {
158 assertion = cfg.custom != null -> cfg.customPkgs == [ ];
159 message = "If `cfg.custom` is set for `ZSH_CUSTOM`, `customPkgs` can't be used!";
160 }
161 ];
162
163 };
164
165 meta.doc = ./oh-my-zsh.md;
166}