From ae5c6621825f73fb32a734b4bf2127655369f97a Mon Sep 17 00:00:00 2001 From: pacien Date: Tue, 5 Jan 2021 17:20:39 +0100 Subject: [PATCH 1/4] wrapFish: add fish shell wrapper package This adds a wrapper for fish which allows creating shells pre-initialised with some completions, functions, and configuration scripts from given paths or from fish plugin packages (`pkgs.fishPlugins.*`). This is especially handy when one wants to try a plugin in an ephemeral shell. GitHub: see https://github.com/NixOS/nixpkgs/pull/107834#discussion_r550612519 --- pkgs/shells/fish/wrapper.nix | 25 +++++++++++++++++++++++++ pkgs/top-level/all-packages.nix | 2 ++ 2 files changed, 27 insertions(+) create mode 100644 pkgs/shells/fish/wrapper.nix diff --git a/pkgs/shells/fish/wrapper.nix b/pkgs/shells/fish/wrapper.nix new file mode 100644 index 00000000000..053568bc6b9 --- /dev/null +++ b/pkgs/shells/fish/wrapper.nix @@ -0,0 +1,25 @@ +{ lib, writeShellScriptBin, fish }: + +with lib; + +makeOverridable ({ + completionDirs ? [], + functionDirs ? [], + confDirs ? [], + pluginPkgs ? [] +}: + +let + vendorDir = kind: plugin: "${plugin}/share/fish/vendor_${kind}.d"; + complPath = completionDirs ++ map (vendorDir "completions") pluginPkgs; + funcPath = functionDirs ++ map (vendorDir "functions") pluginPkgs; + confPath = confDirs ++ map (vendorDir "conf") pluginPkgs; + safeConfPath = map escapeShellArg confPath; + +in writeShellScriptBin "fish" '' + ${fish}/bin/fish --init-command " + set --prepend fish_complete_path ${escapeShellArgs complPath} + set --prepend fish_function_path ${escapeShellArgs funcPath} + for c in {${concatStringsSep "," safeConfPath}}/*; source $c; end + " "$@" +'') diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index d4ca2d6f741..2e6911c6939 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -8843,6 +8843,8 @@ in fish = callPackage ../shells/fish { }; + wrapFish = callPackage ../shells/fish/wrapper.nix { }; + fishPlugins = recurseIntoAttrs (callPackage ../shells/fish/plugins { }); ion = callPackage ../shells/ion { From 648a3db9343755a3d380c3247bc0bb2f3b4c5b30 Mon Sep 17 00:00:00 2001 From: pacien Date: Tue, 5 Jan 2021 17:30:52 +0100 Subject: [PATCH 2/4] fishPlugins.buildFishPlugin: use wrapFish --- .../shells/fish/plugins/build-fish-plugin.nix | 34 +++++++------------ pkgs/shells/fish/plugins/pure.nix | 2 +- 2 files changed, 13 insertions(+), 23 deletions(-) diff --git a/pkgs/shells/fish/plugins/build-fish-plugin.nix b/pkgs/shells/fish/plugins/build-fish-plugin.nix index e2ec342e544..98e0912a33c 100644 --- a/pkgs/shells/fish/plugins/build-fish-plugin.nix +++ b/pkgs/shells/fish/plugins/build-fish-plugin.nix @@ -1,23 +1,6 @@ -{ stdenv, lib, writeShellScriptBin, writeScript, fish }: +{ stdenv, lib, writeScript, wrapFish }: -let - rtpPath = "share/fish"; - - mapToFuncPath = v: - if lib.isString v - then v - else "${v}/${rtpPath}/vendor_functions.d"; - - fishWithFunctionPath = plugins: let - funcPaths = map mapToFuncPath plugins; - in writeShellScriptBin "fish" '' - ${fish}/bin/fish \ - --init-command \ - "set --prepend fish_function_path ${lib.escapeShellArgs funcPaths}" \ - "$@" - ''; - -in attrs@{ +attrs@{ pname, version, src, @@ -32,7 +15,9 @@ in attrs@{ installPath ? lib.getName pname, checkInputs ? [], - # plugins or paths to add to the function path of the test fish shell + # plugin packages to add to the vendor paths of the test fish shell + checkPlugins ? [], + # vendor directories to add to the function path of the test fish shell checkFunctionPath ? [], # test script to be executed in a fish shell checkPhase ? "", @@ -52,7 +37,7 @@ stdenv.mkDerivation (attrs // { ( install_vendor_files() { source="$1" - target="$out/${rtpPath}/vendor_$2.d" + target="$out/share/fish/vendor_$2.d" [ -d $source ] || return 0 mkdir -p $target @@ -69,7 +54,12 @@ stdenv.mkDerivation (attrs // { ''; inherit doCheck; - checkInputs = [ (fishWithFunctionPath checkFunctionPath) ] ++ checkInputs; + + checkInputs = [ (wrapFish { + pluginPkgs = checkPlugins; + functionDirs = checkFunctionPath; + }) ] ++ checkInputs; + checkPhase = '' export HOME=$(mktemp -d) # fish wants a writable home fish "${writeScript "${name}-test" checkPhase}" diff --git a/pkgs/shells/fish/plugins/pure.nix b/pkgs/shells/fish/plugins/pure.nix index 54af2e0663e..3221f6b97ca 100644 --- a/pkgs/shells/fish/plugins/pure.nix +++ b/pkgs/shells/fish/plugins/pure.nix @@ -12,7 +12,7 @@ buildFishPlugin rec { }; checkInputs = [ git ]; - checkFunctionPath = [ fishtape ]; + checkPlugins = [ fishtape ]; checkPhase = '' # https://github.com/rafaelrinaldi/pure/issues/264 rm tests/_pure_string_width.test.fish From 165937d01ec18c80c6171fa44df054207efebe93 Mon Sep 17 00:00:00 2001 From: pacien Date: Mon, 11 Jan 2021 01:28:22 +0100 Subject: [PATCH 3/4] doc/fish: document fish plugins packaging --- doc/builders/packages/fish.section.md | 50 +++++++++++++++++++++++++++ doc/builders/packages/index.xml | 1 + 2 files changed, 51 insertions(+) create mode 100644 doc/builders/packages/fish.section.md diff --git a/doc/builders/packages/fish.section.md b/doc/builders/packages/fish.section.md new file mode 100644 index 00000000000..43956fc531b --- /dev/null +++ b/doc/builders/packages/fish.section.md @@ -0,0 +1,50 @@ +# Fish {#sec-fish} + +Fish is a "smart and user-friendly command line shell" with support for plugins. + + +## Vendor Fish scripts {#sec-fish-vendor} + +Any package may ship its own Fish completions, configuration snippets, and +functions. Those should be installed to +`$out/share/fish/vendor_{completions,conf,functions}.d` respectively. + +When the `programs.fish.enable` and +`programs.fish.vendor.{completions,config,functions}.enable` options from the +NixOS Fish module are set to true, those paths are symlinked in the current +system environment and automatically loaded by Fish. + + +## Packaging Fish plugins {#sec-fish-plugins-pkg} + +While packages providing standalone executables belong to the top level, +packages which have the sole purpose of extending Fish belong to the +`fishPlugins` scope and should be registered in +`pkgs/shells/fish/plugins/default.nix`. + +The `buildFishPlugin` utility function can be used to automatically copy Fish +scripts from `$src/{completions,conf,conf.d,functions}` to the standard vendor +installation paths. It also sets up the test environment so that the optional +`checkPhase` is executed in a Fish shell with other already packaged plugins +and package-local Fish functions specified in `checkPlugins` and +`checkFunctionPath` respectively. + +See `pkgs/shells/fish/plugins/pure.nix` for an example of Fish plugin package +using `buildFishPlugin` and running unit tests with the `fishtape` test runner. + + +## Fish wrapper {#sec-fish-wrapper} + +The `wrapFish` package is a wrapper around Fish which can be used to create +Fish shells initialised with some plugins as well as completions, configuration +snippets and functions sourced from the given paths. This provides a convenient +way to test Fish plugins and scripts without having to alter the environment. + +```nix +wrapFish { + pluginPkgs = with fishPlugins; [ pure foreign-env ]; + completionDirs = []; + functionDirs = []; + confDirs = [ "/path/to/some/fish/init/dir/" ]; +} +``` diff --git a/doc/builders/packages/index.xml b/doc/builders/packages/index.xml index 732560ec199..ab335e24ff9 100644 --- a/doc/builders/packages/index.xml +++ b/doc/builders/packages/index.xml @@ -11,6 +11,7 @@ + From 108fd69a8c40d4488c96fd275430b6638fed19df Mon Sep 17 00:00:00 2001 From: pacien Date: Mon, 11 Jan 2021 03:39:57 +0100 Subject: [PATCH 4/4] fishPlugins.buildFishPlugin: rename checkFunctionPath parameter --- doc/builders/packages/fish.section.md | 2 +- pkgs/shells/fish/plugins/build-fish-plugin.nix | 4 ++-- pkgs/shells/fish/plugins/fishtape.nix | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/builders/packages/fish.section.md b/doc/builders/packages/fish.section.md index 43956fc531b..3086bd68348 100644 --- a/doc/builders/packages/fish.section.md +++ b/doc/builders/packages/fish.section.md @@ -27,7 +27,7 @@ scripts from `$src/{completions,conf,conf.d,functions}` to the standard vendor installation paths. It also sets up the test environment so that the optional `checkPhase` is executed in a Fish shell with other already packaged plugins and package-local Fish functions specified in `checkPlugins` and -`checkFunctionPath` respectively. +`checkFunctionDirs` respectively. See `pkgs/shells/fish/plugins/pure.nix` for an example of Fish plugin package using `buildFishPlugin` and running unit tests with the `fishtape` test runner. diff --git a/pkgs/shells/fish/plugins/build-fish-plugin.nix b/pkgs/shells/fish/plugins/build-fish-plugin.nix index 98e0912a33c..a52c5746492 100644 --- a/pkgs/shells/fish/plugins/build-fish-plugin.nix +++ b/pkgs/shells/fish/plugins/build-fish-plugin.nix @@ -18,7 +18,7 @@ attrs@{ # plugin packages to add to the vendor paths of the test fish shell checkPlugins ? [], # vendor directories to add to the function path of the test fish shell - checkFunctionPath ? [], + checkFunctionDirs ? [], # test script to be executed in a fish shell checkPhase ? "", doCheck ? checkPhase != "", @@ -57,7 +57,7 @@ stdenv.mkDerivation (attrs // { checkInputs = [ (wrapFish { pluginPkgs = checkPlugins; - functionDirs = checkFunctionPath; + functionDirs = checkFunctionDirs; }) ] ++ checkInputs; checkPhase = '' diff --git a/pkgs/shells/fish/plugins/fishtape.nix b/pkgs/shells/fish/plugins/fishtape.nix index 326ff61c417..82f2375d5e3 100644 --- a/pkgs/shells/fish/plugins/fishtape.nix +++ b/pkgs/shells/fish/plugins/fishtape.nix @@ -11,7 +11,7 @@ buildFishPlugin rec { sha256 = "0dxcyhs2shhgy5xnwcimqja8vqsyk841x486lgq13i3y1h0kp2kd"; }; - checkFunctionPath = [ "./" ]; # fishtape is introspective + checkFunctionDirs = [ "./" ]; # fishtape is introspective checkPhase = '' rm test/tty.fish # test expects a tty fishtape test/*.fish