summaryrefslogtreecommitdiff
path: root/pkgs/shells/fish/wrapper.nix
blob: 29a7a1ce9bdfb30317473b06f43d2b7ece9a0aba (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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
{
  lib,
  writeShellApplication,
  fish,
  writeTextFile,
}:

lib.makeOverridable (
  /**
    Creates a wrapped fish shell binary with some plugins, completions,
    configuration snippets and functions sourced from the function
    arguments.

    This can for example be used as a convenient way to test fish plugins
    and scripts without having to alter the environment.

    # Type

    ```pseudocode
    wrapFish :: {
      completionDirs :: [Path] ?,
      functionDirs :: [Path] ?,
      confDirs :: [Path] ?,
      pluginPkgs :: [Derivation] ?,
      localConfig :: String ?,
      shellAliases :: {
        [ N :: T ] :: String
      } ?,
      runtimeInputs :: [Derivation] ?,
    } -> Derivation
    ```

    # Example

    ::: {.example}
    ```nix
    wrapFish {
      pluginPkgs = with fishPlugins; [
        pure
        foreign-env
      ];
      completionDirs = [ ];
      functionDirs = [ ];
      confDirs = [ "/path/to/some/fish/init/dir/" ];
      shellAliases = {
        hello = "echo 'Hello World!'";
        bye = "echo 'Bye World!'; exit";
      };
      runtimeInputs = with pkgs; [
        curl
        w3m
      ];
    }
    ```
    :::

    # Arguments

    All arguments are optional.

    ## `completionDirs` (list of paths)

    Directories containing fish completions which will be prepended to
    {env}`fish_complete_paths` in the environment of the resulting wrapped
    fish binary.

    ## `functionDirs` (list of paths)

    Directories containing fish functions which will be prepended to
    {env}`fish_function_path` in the environment of the resulting wrapped
    fish binary.

    ## `confDirs` (list of paths)

    Directories containing fish code which will be sourced by the resulting
    wrapped fish binary.

    ## `pluginPkgs` (list of derivations)

    Derivations, usually from the package set `fishPlugins`, that will be
    added to the resulting wrapped fish binary.

    ## `localConfig` (string)

    String containing a fish script which will be sourced by the resulting
    wrapped fish binary.

    ## `shellAliases` (attribute set of strings)

    Shell aliases that will be made available in the resulting wrapped fish
    binary.

    ## `runtimeInputs` (list of derivations)

    A list of Derivations that will be added to the {env}`PATH` of the
    resulting wrapped fish binary.
  */
  {
    completionDirs ? [ ],
    functionDirs ? [ ],
    confDirs ? [ ],
    pluginPkgs ? [ ],
    localConfig ? "",
    shellAliases ? { },
    runtimeInputs ? [ ],
  }:

  let
    aliasesStr = builtins.concatStringsSep "\n" (
      lib.mapAttrsToList (k: v: "alias ${k} ${lib.escapeShellArg v}") shellAliases
    );

    shellAliasesFishConfig = writeTextFile {
      name = "wrapfish.aliases.fish";
      destination = "/share/fish/vendor_conf.d/aliases.fish";
      text = ''
        status is-interactive; and begin
          # Aliases
          ${aliasesStr}
        end
      '';
    };

    localFishConfig = writeTextFile {
      name = "wrapfish.local.fish";
      destination = "/share/fish/vendor_conf.d/config.local.fish";
      text = localConfig;
    };

    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)
      ++ (map (vendorDir "conf") [
        localFishConfig
        shellAliasesFishConfig
      ]);

  in
  writeShellApplication {
    inherit runtimeInputs;
    name = "fish";
    text = ''
      ${fish}/bin/fish --init-command "
        set --prepend fish_complete_path ${lib.escapeShellArgs complPath}
        set --prepend fish_function_path ${lib.escapeShellArgs funcPath}
        set --local fish_conf_source_path ${lib.escapeShellArgs confPath}
        for c in \$fish_conf_source_path/*; source \$c; end
      " "$@"
    '';
  }
)