-
Notifications
You must be signed in to change notification settings - Fork 258
Expand file tree
/
Copy pathshell-plugins.nix
More file actions
128 lines (125 loc) · 4.59 KB
/
shell-plugins.nix
File metadata and controls
128 lines (125 loc) · 4.59 KB
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
{ pkgs, lib, config, is-home-manager, ... }:
with lib;
let
cfg = config.programs._1password-shell-plugins;
supported_plugins = splitString "\n" (
lib.readFile "${
# get the list of supported plugin executable names
pkgs.runCommand "op-plugin-list" { }
# 1Password CLI tries to create the config directory automatically, so set a temp XDG_CONFIG_HOME
# since we don't actually need it for this
"mkdir $out && XDG_CONFIG_HOME=$out ${
if cfg.package != null then cfg.package else pkgs._1password-cli
}/bin/op plugin list | cut -d ' ' -f1 | tail -n +2 > $out/plugins.txt"
}/plugins.txt"
);
getExeName =
package:
# NOTE: SAFETY: This is okay because the `packages` list is also referred
# to below as `home.packages = packages;` or `environment.systemPackages = packages;`
# depending on if it's using `home-manager` or not; this means that Nix can still
# compute the dependency tree, even though we're discarding string context here,
# since the packages are still referred to below without discarding string context.
strings.unsafeDiscardStringContext (baseNameOf (getExe package));
in
{
options = {
programs._1password-shell-plugins = {
enable = mkEnableOption "1Password Shell Plugins";
package = mkPackageOption pkgs "_1password-cli" { nullable = true; };
plugins = mkOption {
type = types.listOf types.package;
default = [ ];
example = literalExpression ''
with pkgs; [
gh
awscli2
cachix
]
'';
description = "CLI Packages to enable 1Password Shell Plugins for; ensure that a Shell Plugin exists by checking the docs: https://developer.1password.com/docs/cli/shell-plugins/";
# this is a bit of a hack to do option validation;
# ensure that the list of packages include only packages
# for which the executable has a supported 1Password Shell Plugin
apply =
package_list:
map
(
package:
if (elem (getExeName package) supported_plugins) then
package
else
abort "${getExeName package} is not a valid 1Password Shell Plugin. A list of supported plugins can be found by running `op plugin list` or at: https://developer.1password.com/docs/cli/shell-plugins/"
)
package_list;
};
};
};
config =
let
# executable names as strings, e.g. `pkgs.gh` => `"gh"`, `pkgs.awscli2` => `"aws"`
pkg-exe-names = map getExeName cfg.plugins;
# Explanation:
# Map over `cfg.plugins` (the value of the `plugins` option provided by the user)
# and for each package specified, get the executable name, then create a shell function
# of the form:
#
# For Bash and Zsh:
# ```
# {pkg}() {
# op plugin run -- {pkg};
# }
# ```
#
# And for Fish:
# ```
# function {pkg} --wraps {pkg}
# op plugin run -- {pkg}
# end
# ```
# where `{pkg}` is the executable name of the package
posixFunctions = map
(package: ''
${package}() {
op plugin run -- ${package} "$@";
}
'')
pkg-exe-names;
fishFunctions = map
(package: ''
function ${package} --wraps "${package}" --description "1Password Shell Plugin for ${package}"
op plugin run -- ${package} $argv
end
'')
pkg-exe-names;
packages = lib.optional (cfg.package != null) cfg.package ++ cfg.plugins;
in
mkIf cfg.enable (mkMerge [
{
programs.fish.interactiveShellInit = strings.concatStringsSep "\n" fishFunctions;
}
(optionalAttrs is-home-manager {
programs = {
# for the Bash and Zsh home-manager modules,
# the initExtra option is equivalent to Fish's interactiveShellInit
bash.initExtra = strings.concatStringsSep "\n" posixFunctions;
zsh.initExtra = strings.concatStringsSep "\n" posixFunctions;
};
home = {
inherit packages;
sessionVariables = { OP_PLUGIN_ALIASES_SOURCED = "1"; };
};
})
(optionalAttrs (!is-home-manager) {
programs = {
bash.interactiveShellInit =
strings.concatStringsSep "\n" posixFunctions;
zsh.interactiveShellInit = strings.concatStringsSep "\n" posixFunctions;
};
environment = {
systemPackages = packages;
variables = { OP_PLUGIN_ALIASES_SOURCED = "1"; };
};
})
]);
}