From 1922b43b7ed61c2e638cd8374b48d5e5cf8b6c5d Mon Sep 17 00:00:00 2001 From: Maximilian Bosch Date: Tue, 10 Jul 2018 15:17:32 +0200 Subject: [PATCH 1/4] nix-zsh-completions: install nix.plugin.zsh and init.zsh as well These files feature simple aliases and a nix-shell detector when using `nix-shell --run zsh`. The package itself contains the completion scripts in `$out/share/zsh/site-functions` (to keep it compatible with ZSH-only setups) and the plugins in `$out/share/zsh/plugins` for oh-my-zsh. --- pkgs/shells/zsh/nix-zsh-completions/default.nix | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/pkgs/shells/zsh/nix-zsh-completions/default.nix b/pkgs/shells/zsh/nix-zsh-completions/default.nix index 3c4c3fabfd1..4405902ec3e 100644 --- a/pkgs/shells/zsh/nix-zsh-completions/default.nix +++ b/pkgs/shells/zsh/nix-zsh-completions/default.nix @@ -15,15 +15,16 @@ stdenv.mkDerivation rec { }; installPhase = '' - mkdir -p $out/share/zsh/site-functions + mkdir -p $out/share/zsh/{site-functions,plugins/nix} cp _* $out/share/zsh/site-functions + cp *.zsh $out/share/zsh/plugins/nix ''; - meta = { + meta = with stdenv.lib; { homepage = https://github.com/spwhitt/nix-zsh-completions; description = "ZSH completions for Nix, NixOS, and NixOps"; - license = stdenv.lib.licenses.bsd3; - platforms = stdenv.lib.platforms.all; - maintainers = [ stdenv.lib.maintainers.spwhitt stdenv.lib.maintainers.olejorgenb stdenv.lib.maintainers.hedning ]; + license = licenses.bsd3; + platforms = platforms.all; + maintainers = with maintainers; [ spwhitt olejorgenb hedning ma27 ]; }; } From efc9511c1645b77227a9df140c9861c6e6b4faaf Mon Sep 17 00:00:00 2001 From: Maximilian Bosch Date: Tue, 10 Jul 2018 15:28:47 +0200 Subject: [PATCH 2/4] lambda-mod-zsh-theme: add hooks and patch shebangs This ensures that no impurity exists due to implicitly depending on`/usr/bin/env`. It stores the theme into `$out/share/zsh/themes` to make it possible to find theme using `buildEnv` and remain consistent with other ZSH extensions. --- pkgs/shells/zsh/lambda-mod-zsh-theme/default.nix | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/pkgs/shells/zsh/lambda-mod-zsh-theme/default.nix b/pkgs/shells/zsh/lambda-mod-zsh-theme/default.nix index 6dea51a487e..c4d63bd2771 100644 --- a/pkgs/shells/zsh/lambda-mod-zsh-theme/default.nix +++ b/pkgs/shells/zsh/lambda-mod-zsh-theme/default.nix @@ -1,4 +1,4 @@ -{ stdenv, fetchFromGitHub }: +{ stdenv, fetchFromGitHub, zsh }: stdenv.mkDerivation { name = "lambda-mod-zsh-theme-unstable-2017-10-08"; @@ -10,9 +10,13 @@ stdenv.mkDerivation { rev = "61c373c8aa5556d51522290b82ad44e7166bced1"; }; + buildInputs = [ zsh ]; + installPhase = '' - mkdir -p $out/share/themes - cp lambda-mod.zsh-theme $out/share/themes + chmod +x lambda-mod.zsh-theme # only executable scripts are found by `patchShebangs` + patchShebangs . + + install -Dm0644 lambda-mod.zsh-theme $out/share/zsh/themes/lambda-mod.zsh-theme ''; meta = with stdenv.lib; { From 39b85451de2daa7927629dbac7b641becffc839e Mon Sep 17 00:00:00 2001 From: Maximilian Bosch Date: Tue, 10 Jul 2018 15:52:30 +0200 Subject: [PATCH 3/4] nixos/oh-my-zsh: add `customPkgs` option to allow multiple derivations for `ZSH_CUSTOM` If multiple third-party modules shall be used for `oh-my-zsh` it has to be possible to create another env which composes all the packages. Now it can be done like this: ``` { pkgs, ... }: { programs.zsh.enable = true; programs.zsh.ohMyZsh = { enable = true; customPkgs = with pkgs; [ lambda-mod-zsh-theme nix-zsh-completions ]; theme = "lambda-mod"; plugins = [ "nix" ]; }; } ``` Please keep in mind that this is not compatible with `programs.zsh.ohMyZsh.custom`, only one of these options can be used ATM. Each package should store its outputs into `$out/share/zsh/`. Completions (and ZSH-only) extensions should live in the `fpath` (`$out/share/zsh/site-functions`), plugins in `.../plugins` and themes in `.../themes` (please refer to fdb6bf6ed68c2f089ae6c729dfeaa3eddea2ce6a and 406d64aad162b3a4881747be4e24705fb5182573). All scripts in `customPkgs` will be linked together using `linkFarm` to provide a single directory for all scripts from all derivations in `customPkgs` as suggested in https://github.com/NixOS/nixpkgs/pull/43282#issuecomment-410396365. --- nixos/modules/programs/zsh/oh-my-zsh.nix | 50 +++++++++++++++++++++--- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/nixos/modules/programs/zsh/oh-my-zsh.nix b/nixos/modules/programs/zsh/oh-my-zsh.nix index b995d390b27..8435e0eb9f0 100644 --- a/nixos/modules/programs/zsh/oh-my-zsh.nix +++ b/nixos/modules/programs/zsh/oh-my-zsh.nix @@ -3,7 +3,30 @@ with lib; let + cfg = config.programs.zsh.ohMyZsh; + + mkLinkFarmEntry = name: dir: + let + env = pkgs.buildEnv { + name = "zsh-${name}-env"; + paths = cfg.customPkgs; + pathsToLink = "/share/zsh/${dir}"; + }; + in + { inherit name; path = "${env}/share/zsh/${dir}"; }; + + mkLinkFarmEntry' = name: mkLinkFarmEntry name name; + + custom = + if cfg.custom != null then cfg.custom + else if length cfg.customPkgs == 0 then null + else pkgs.linkFarm "oh-my-zsh-custom" [ + (mkLinkFarmEntry' "themes") + (mkLinkFarmEntry "completions" "site-functions") + (mkLinkFarmEntry' "plugins") + ]; + in { options = { @@ -34,10 +57,19 @@ in }; custom = mkOption { - default = ""; - type = types.str; + default = null; + type = with types; nullOr str; description = '' Path to a custom oh-my-zsh package to override config of oh-my-zsh. + (Can't be used along with `customPkgs`). + ''; + }; + + customPkgs = mkOption { + default = []; + type = types.listOf types.package; + description = '' + List of custom packages that should be loaded into `oh-my-zsh`. ''; }; @@ -67,7 +99,7 @@ in environment.systemPackages = [ cfg.package ]; - programs.zsh.interactiveShellInit = with builtins; '' + programs.zsh.interactiveShellInit = '' # oh-my-zsh configuration generated by NixOS export ZSH=${cfg.package}/share/oh-my-zsh @@ -75,8 +107,8 @@ in "plugins=(${concatStringsSep " " cfg.plugins})" } - ${optionalString (stringLength(cfg.custom) > 0) - "ZSH_CUSTOM=\"${cfg.custom}\"" + ${optionalString (custom != null) + "ZSH_CUSTOM=\"${custom}\"" } ${optionalString (stringLength(cfg.theme) > 0) @@ -92,5 +124,13 @@ in source $ZSH/oh-my-zsh.sh ''; + + assertions = [ + { + assertion = cfg.custom != null -> cfg.customPkgs == []; + message = "If `cfg.custom` is set for `ZSH_CUSTOM`, `customPkgs` can't be used!"; + } + ]; + }; } From bd40c92c2c3c862bff59318ea29677dd66de9526 Mon Sep 17 00:00:00 2001 From: Maximilian Bosch Date: Tue, 7 Aug 2018 15:38:20 +0200 Subject: [PATCH 4/4] nixos/oh-my-zsh: add documentation In the last year `programs.oh-my-zsh` gained more complexity and since the introduction of features like `customPkgs` which builds a `ZSH_CUSTOM` path from a sequence of derivation a documentation may be fairly helpful to make the knowledge how to use the module and how to package new ZSH plugins visible. See https://github.com/NixOS/nixpkgs/pull/43282#issuecomment-410770432 --- nixos/modules/programs/zsh/oh-my-zsh.nix | 2 + nixos/modules/programs/zsh/oh-my-zsh.xml | 125 +++++++++++++++++++++++ 2 files changed, 127 insertions(+) create mode 100644 nixos/modules/programs/zsh/oh-my-zsh.xml diff --git a/nixos/modules/programs/zsh/oh-my-zsh.nix b/nixos/modules/programs/zsh/oh-my-zsh.nix index 8435e0eb9f0..f4df4e983e4 100644 --- a/nixos/modules/programs/zsh/oh-my-zsh.nix +++ b/nixos/modules/programs/zsh/oh-my-zsh.nix @@ -133,4 +133,6 @@ in ]; }; + + meta.doc = ./oh-my-zsh.xml; } diff --git a/nixos/modules/programs/zsh/oh-my-zsh.xml b/nixos/modules/programs/zsh/oh-my-zsh.xml new file mode 100644 index 00000000000..b74da8630ee --- /dev/null +++ b/nixos/modules/programs/zsh/oh-my-zsh.xml @@ -0,0 +1,125 @@ + + +Oh my ZSH + +oh-my-zsh is a framework +to manage your ZSH configuration +including completion scripts for several CLI tools or custom prompt themes. + +
Basic usage +The module uses the oh-my-zsh package with all available features. The +initial setup using Nix expressions is fairly similar to the configuration format +of oh-my-zsh. + + +{ + programs.ohMyZsh = { + enable = true; + plugins = [ "git" "python" "man" ]; + theme = "agnoster"; + }; +} + + +For a detailed explanation of these arguments please refer to the +oh-my-zsh docs. + +The expression generates the needed +configuration and writes it into your /etc/zshrc. +
+ +
Custom additions + +Sometimes third-party or custom scripts such as a modified theme may be needed. +oh-my-zsh provides the +ZSH_CUSTOM +environment variable for this which points to a directory with additional scripts. + +The module can do this as well: + + +{ + programs.ohMyZsh.custom = "~/path/to/custom/scripts"; +} + +
+ +
Custom environments + +There are several extensions for oh-my-zsh packaged in nixpkgs. +One of them is nix-zsh-completions +which bundles completion scripts and a plugin for oh-my-zsh. + +Rather than using a single mutable path for ZSH_CUSTOM, it's also possible to +generate this path from a list of Nix packages: + + +{ pkgs, ... }: +{ + programs.ohMyZsh.customPkgs = with pkgs; [ + pkgs.nix-zsh-completions + # and even more... + ]; +} + + +Internally a single store path will be created using buildEnv. +Please refer to the docs of +buildEnv +for further reference. + +Please keep in mind that this is not compatible with programs.ohMyZsh.custom +as it requires an immutable store path while custom shall remain mutable! An evaluation failure +will be thrown if both custom and customPkgs are set. +
+ +
Package your own customizations + +If third-party customizations (e.g. new themes) are supposed to be added to oh-my-zsh +there are several pitfalls to keep in mind: + + + + To comply with the default structure of ZSH the entire output needs to be written to + $out/share/zsh. + + + Completion scripts are supposed to be stored at $out/share/zsh/site-functions. This directory + is part of the fpath + and the package should be compatible with pure ZSH setups. The module will automatically link + the contents of site-functions to completions directory in the proper store path. + + + The plugins directory needs the structure pluginname/pluginname.plugin.zsh + as structured in the upstream repo. + + + + + +A derivation for oh-my-zsh may look like this: + +{ stdenv, fetchFromGitHub }: + +stdenv.mkDerivation rec { + name = "exemplary-zsh-customization-${version}"; + version = "1.0.0"; + src = fetchFromGitHub { + # path to the upstream repository + }; + + dontBuild = true; + installPhase = '' + mkdir -p $out/share/zsh/site-functions + cp {themes,plugins} $out/share/zsh + cp completions $out/share/zsh/site-functions + ''; +} + + +
+