zellij: add support for plugins

This commit is contained in:
Perchun Pak 2026-04-20 20:57:50 +02:00 committed by Austin Horstman
parent ec56189b4f
commit 301871cd96
5 changed files with 156 additions and 6 deletions

View file

@ -0,0 +1,8 @@
{ config, ... }:
{
time = "2026-06-04T17:10:21+00:00";
condition = config.programs.zellij.enable;
message = ''
Added support for Zellij plugins using `programs.zellij.plugins`.
'';
}

View file

@ -31,6 +31,15 @@ in
package = lib.mkPackageOption pkgs "zellij" { };
finalPackage = mkOption {
type = types.package;
visible = false;
readOnly = true;
description = ''
The zellij package with all plugin dependencies.
'';
};
layouts = lib.mkOption {
type = types.attrsOf (
types.oneOf [
@ -139,6 +148,15 @@ in
'';
};
plugins = mkOption {
type = types.listOf types.package;
default = [ ];
example = lib.literalExpression ''
with pkgs.zellijPlugins; [ jbz vim-plugins-navigator zjstatus ]
'';
description = "List of Zellij plugins";
};
settings = lib.mkOption {
inherit (yamlFormat) type;
default = { };
@ -263,9 +281,23 @@ in
shellIntegrationEnabled = (
cfg.enableBashIntegration || cfg.enableZshIntegration || cfg.enableFishIntegration
);
pluginsWithNames = lib.map (plugin: {
inherit plugin;
name = lib.removePrefix "zellij-" plugin.pname;
}) cfg.plugins;
pluginRuntimeDeps = lib.concatLists (
lib.map ({ plugin, ... }: plugin.runtimeDeps or [ ]) pluginsWithNames
);
in
mkIf cfg.enable {
home.packages = [ cfg.package ];
home.packages = [ cfg.finalPackage ];
programs.zellij.finalPackage =
if pluginRuntimeDeps != [ ] then
cfg.package.override {
extraPackages = pluginRuntimeDeps;
}
else
cfg.package;
# Zellij switched from yaml to KDL in version 0.32.0:
# https://github.com/zellij-org/zellij/releases/tag/v0.32.0
@ -273,14 +305,15 @@ in
{
"zellij/config.yaml" =
mkIf ((lib.versionOlder cfg.package.version "0.32.0") && cfg.settings != { })
mkIf ((lib.versionOlder cfg.finalPackage.version "0.32.0") && cfg.settings != { })
{
source = yamlFormat.generate "zellij.yaml" cfg.settings;
};
"zellij/config.kdl" =
mkIf
(
(lib.versionAtLeast cfg.package.version "0.32.0") && (cfg.settings != { } || cfg.extraConfig != "")
(lib.versionAtLeast cfg.finalPackage.version "0.32.0")
&& (cfg.settings != { } || cfg.extraConfig != "")
)
{
text =
@ -321,20 +354,57 @@ in
);
}
) cfg.themes)
# on every plugin update, zellij asks for permissions again, because
# the plugin path has changed (=/nix/store path has changed)
# to avoid that, we symlink all plugins to `.config/zellij/plugins` and
# use those paths
(lib.listToAttrs (
lib.map (
{ plugin, name }:
{
name = "zellij/plugins/${name}.wasm";
value.source = plugin;
}
) pluginsWithNames
))
];
programs.zellij.settings = {
# define plugin aliases
plugins = mkIf (pluginsWithNames != [ ]) (
lib.listToAttrs (
lib.map (
{ name, ... }:
{
inherit name;
value._props.location = "file:${config.xdg.configHome}/zellij/plugins/${name}.wasm";
}
) pluginsWithNames
)
);
# auto-load plugins on start
load_plugins = mkIf (pluginsWithNames != [ ]) {
_children = lib.map (
{ name, ... }:
{
${name} = [ ];
}
) pluginsWithNames;
};
};
programs.bash.initExtra = mkIf cfg.enableBashIntegration ''
eval "$(${lib.getExe cfg.package} setup --generate-auto-start bash)"
eval "$(${lib.getExe cfg.finalPackage} setup --generate-auto-start bash)"
'';
programs.zsh.initContent = mkIf cfg.enableZshIntegration (
lib.mkOrder 200 ''
eval "$(${lib.getExe cfg.package} setup --generate-auto-start zsh)"
eval "$(${lib.getExe cfg.finalPackage} setup --generate-auto-start zsh)"
''
);
programs.fish.interactiveShellInit = mkIf cfg.enableFishIntegration ''
eval (${lib.getExe cfg.package} setup --generate-auto-start fish | string collect)
eval (${lib.getExe cfg.finalPackage} setup --generate-auto-start fish | string collect)
'';
home.sessionVariables = mkIf shellIntegrationEnabled {

View file

@ -4,5 +4,6 @@
zellij-config-extra_config = ./config-extra_config.nix;
zellij-enable-shells = ./enable-shells.nix;
zellij-layout = ./layout.nix;
zellij-plugins = ./plugins.nix;
zellij-theme = ./theme.nix;
}

View file

@ -0,0 +1,12 @@
load_plugins {
foo
bar
baz
}
plugins {
bar location="file:/home/hm-user/.config/zellij/plugins/bar.wasm" {
foo 123
}
baz location="file:/home/hm-user/.config/zellij/plugins/baz.wasm"
foo location="file:/home/hm-user/.config/zellij/plugins/foo.wasm"
}

View file

@ -0,0 +1,59 @@
{ config, ... }:
let
zellijPackage = config.lib.test.mkStubPackage {
name = "zellij";
version = "0.44.3";
extraAttrs.override =
args:
zellijPackage
// {
extraPackages = args.extraPackages or [ ];
};
};
runtimeDep = config.lib.test.mkStubPackage {
name = "just";
};
mkPlugin =
name: deps:
config.lib.test.mkStubPackage {
name = "zellij-${name}";
outPath = null;
buildScript = ''
echo wasm > "$out"
'';
extraAttrs = {
pname = "zellij-${name}";
runtimeDeps = deps;
};
};
in
{
programs.zellij = {
enable = true;
package = zellijPackage;
plugins = [
(mkPlugin "foo" [ ])
(mkPlugin "bar" [ ])
(mkPlugin "baz" [ runtimeDep ])
];
settings = {
plugins.bar.foo = 123;
};
};
nmt.script =
assert builtins.elem runtimeDep config.programs.zellij.finalPackage.extraPackages;
# sh
''
assertFileExists home-files/.config/zellij/plugins/foo.wasm
assertFileExists home-files/.config/zellij/plugins/bar.wasm
assertFileExists home-files/.config/zellij/plugins/baz.wasm
assertFileContent \
home-files/.config/zellij/config.kdl \
${./plugins-config.kdl}
'';
}