feat(wrapperModules.noctalia-shell): init#337
feat(wrapperModules.noctalia-shell): init#337rachitvrma wants to merge 1 commit intoBirdeeHub:mainfrom
Conversation
Add wrapper module for noctalia-shell.
|
Edited: deleted this example so that the comment chain is not as crazy long to scroll through, the example at the end does all the things it did and then some |
|
Using NOCTALIA_CONFIG_DIR and XDG_CONFIG_HOME have the same issue. It tries to write back into that location for some things. Let me know how that module feels? It is like what you had, but I did all the files, and made placeholders work in them. If doing the whole dir feels too bad due to behavior when it cannot write to it, we should just set NOCTALIA_SETTINGS_FILE, and add a config dump script thing, and call it a day. Edit: the example at the end does this if only settings were provided and outOfStoreConfig is not set. {
config,
lib,
wlib,
pkgs,
...
}:
{
imports = [ wlib.modules.default ];
options = {
settings = lib.mkOption {
type = lib.types.json;
default = { };
example = lib.literalExpression ''
{
bar = {
position = "bottom";
floating = true;
backgroundOpacity = 0.95;
};
general = {
animationSpeed = 1.5;
radiusRatio = 1.2;
};
colorSchemes = {
darkMode = true;
useWallpaperColors = true;
};
}
'';
description = ''
Noctalia shell configuration settings as an attribute set, string
or filepath, to be written to ~/.config/noctalia/settings.json.
'';
};
};
config.package = pkgs.noctalia-shell;
config.env.NOCTALIA_SETTINGS_FILE = lib.mkIf (
config.settings != { }
) config.constructFiles.settingsJSON.path;
config.constructFiles = {
settingsJSON = lib.mkIf (config.settings != { }) {
relPath = "${config.binName}-settings.json";
content = builtins.toJSON config.settings;
};
dumpNoctaliaShell = {
relPath = "bin/dump-noctalia-shell";
builder = ''mkdir -p "$(dirname "$2")" && cp "$1" "$2" && chmod +x "$2"'';
content = ''
#!${pkgs.bash}/bin/bash
${config.wrapperPaths.placeholder} ipc call state all > /tmp/noctalia.json && \
${lib.getExe pkgs.nix} eval --impure --expr 'builtins.fromJSON (builtins.readFile /tmp/noctalia.json)'
'';
};
};
} |
|
The first one is a full reproduction of that module, but in the store instead of linking to xdg paths. It uses NOCTALIA_CONFIG_DIR to do it, which is processed in the same way as the XDG_CONFIG_HOME is, but with less chance of affecting unrelated files. However, noctalia tries to write to the directory. Their module somewhat works because, when it creates a NEW file, that isnt in the store. However if you point NOCTALIA_CONFIG_DIR into the store, now that new file is not able to be created. setting XDG_CONFIG_HOME has the same effect. You use the program, let me know how annoying that is. If it is really annoying, then lets do it the second way, where we just wrap the 1 file If it is not that annoying, then lets do it the first way, so we can specify more from the wrapper module. Alternatively, we could use basically the first module except: We could So, those are our 3 options it seems. we could actually combine them too, and ONLY set the other var if you set something other than settings? Or combine all 3, and only set the other var if you set something other than settings, AND copy it when you do? The downside of copying is, if you want nix to reprovision, you would have to delete the dir and restart noctalia The upside of copying is, it can edit the thing. Maybe I can make this do a combo of all 3, and let you choose between copy out of store and allow edits, or leave it in the store but no edits. So I guess that answers the question, is, do all 3. Which should be the default, I don't know still. I edited the first of the 2 modules I put in the discussion section, such that if you only set settings, it does the thing the second one does, otherwise it does the thing the first one did. To do the copy thing, you would do that here config.env.NOCTALIA_SETTINGS_FILE = lib.mkIf (config.settings != { } && ! hasOtherFiles) config.constructFiles.settingsJSON.path;
# some kind of option that changes where this points based on if you want to copy or not
# and then some kind of runShell that copies the generated dir if you want to copy
# probably connected to the option telling it where to copy it to, like, if not null, copy it out of the store to there.
config.env.NOCTALIA_CONFIG_DIR = lib.mkIf hasOtherFiles "${placeholder config.configDrvOutput}/${config.generatedConfigDirname}/"; |
{
config,
lib,
wlib,
pkgs,
...
}:
let
hasOtherFiles =
config.colors != { }
|| config.plugins != { }
|| config.user-templates != { }
|| config.pluginSettings != { };
in
{
config.meta.description = ''
`noctalia-shell` has a gui settings interface that edits the config files, rather than implementing a merging mechanism for runtime settings.
When provisioning from the nix store, this causes a few challenges.
To solve this, there are 3 ways to use this wrapper module.
If you only supply `settings`, and do not choose somewhere for `outOfStoreConfig` then it will only generate and set `NOCTALIA_SETTINGS_FILE`
If you leave `outOfStoreConfig == null` as it is by default, and you supply more then just `settings`, it will set `NOCTALIA_CONFIG_DIR` to the generated location
If you do `outOfStoreConfig = "/some/path/somewhere";` and `/some/path/somewhere` does not yet exist, it will copy it there at runtime when you start `noctalia-shell` and set `NOCTALIA_CONFIG_DIR` to that location instead.
This wrapper module also provides by default an extra executable in the bin directory called `dump-noctalia-shell`
It will return the current settings and state of noctalia in nix code format.
It also exports the path to the generated configuration directory from the package via passthru.
`wrapped-noctalia-shell.generatedConfig`
And likewise for the dump script (if it was enabled)
`wrapped-noctalia-shell.dump-noctalia-shell`
'';
config.meta.platforms = lib.platforms.linux;
config.meta.maintainers = [
wlib.maintainers.rachitvrma
wlib.maintainers.birdee
];
imports = [ wlib.modules.default ];
options = {
generatedConfigDirname = lib.mkOption {
type = lib.types.str;
default = "${config.binName}-config";
description = "Name of the directory which is created as the NOCTALIA_CONFIG_DIR in the wrapper output";
apply = x: lib.removePrefix "/" (lib.removeSuffix "/" x);
};
configDrvOutput = lib.mkOption {
type = lib.types.str;
default = config.outputName;
description = "Name of the derivation output where the generated NOCTALIA_CONFIG_DIR is output to.";
};
outOfStoreConfig = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
description = ''
If provided, the wrapper script will copy the generated configuration to this location, and use it for `NOCTALIA_CONFIG_DIR`.
Any files existing in that location will NOT be overridden.
Delete the desired file, and restart `noctalia-shell` to re-provision from nix.
'';
};
enableDumpScript = lib.mkOption {
type = lib.types.bool;
default = true;
description = ''
Whether to generate a script to `bin/dump-noctalia-shell` in the wrapper output which will dump the current configuration and state of noctalia to stdout as nix code.
'';
};
settings = lib.mkOption {
type =
with lib.types;
oneOf [
json
str
path
];
default = { };
example = lib.literalExpression ''
{
bar = {
position = "bottom";
floating = true;
backgroundOpacity = 0.95;
};
general = {
animationSpeed = 1.5;
radiusRatio = 1.2;
};
colorSchemes = {
darkMode = true;
useWallpaperColors = true;
};
}
'';
description = ''
Noctalia shell configuration settings as an attribute set, string
or filepath, to be written to ~/.config/noctalia/settings.json.
'';
};
colors = lib.mkOption {
type =
with lib.types;
oneOf [
json
str
path
];
default = { };
example = lib.literalExpression ''
{
mError = "#dddddd";
mOnError = "#111111";
mOnPrimary = "#111111";
mOnSecondary = "#111111";
mOnSurface = "#828282";
mOnSurfaceVariant = "#5d5d5d";
mOnTertiary = "#111111";
mOutline = "#3c3c3c";
mPrimary = "#aaaaaa";
mSecondary = "#a7a7a7";
mShadow = "#000000";
mSurface = "#111111";
mSurfaceVariant = "#191919";
mTertiary = "#cccccc";
}
'';
description = ''
Noctalia shell color configuration as an attribute set, string
or filepath, to be written to ~/.config/noctalia/colors.json.
'';
};
user-templates = lib.mkOption {
default = { };
type =
with lib.types;
oneOf [
(pkgs.formats.toml { }).type
str
path
];
example = lib.literalExpression ''
{
templates = {
neovim = {
input_path = "~/.config/noctalia/templates/template.lua";
output_path = "~/.config/nvim/generated.lua";
post_hook = "pkill -SIGUSR1 nvim";
};
};
}
'';
description = ''
Template definitions for Noctalia, to be written to ~/.config/noctalia/user-templates.toml.
This option accepts:
- a Nix attrset (converted to TOML automatically)
- a string containing raw TOML
- a path to an existing TOML file
'';
};
plugins = lib.mkOption {
type =
with lib.types;
oneOf [
json
str
path
];
default = { };
example = lib.literalExpression ''
{
sources = [
{
enabled = true;
name = "Noctalia Plugins";
url = "https://github.com/noctalia-dev/noctalia-plugins";
}
];
states = {
catwalk = {
enabled = true;
sourceUrl = "https://github.com/noctalia-dev/noctalia-plugins";
};
};
version = 2;
}
'';
description = ''
Noctalia shell plugin configuration as an attribute set, string
or filepath, to be written to ~/.config/noctalia/plugins.json.
'';
};
pluginSettings = lib.mkOption {
type =
with lib.types;
attrsOf (oneOf [
json
str
path
]);
default = { };
example = lib.literalExpression ''
{
catwalk = {
minimumThreshold = 25;
hideBackground = true;
};
}
'';
description = ''
Each plugin’s settings as an attribute set, string
or filepath, to be written to ~/.config/noctalia/plugins/plugin-name/settings.json.
'';
};
};
config.runShell = lib.mkIf (config.outOfStoreConfig != null) [
{
name = "COPY_GENERATED_CONFIG";
data = ''
mkdir -p ${config.outOfStoreConfig}
cp -rn ${placeholder config.configDrvOutput}/${config.generatedConfigDirname}/. ${config.outOfStoreConfig}
find ${config.outOfStoreConfig} ! -perm -u+w -exec chmod u+w {} +
'';
}
];
config.passthru = {
${if config.enableDumpScript then "dump-noctalia-shell" else null} =
config.constructFiles.dump-noctalia-shell.outPath;
generatedConfig = "${config.wrapper.${config.configDrvOutput}}/${config.generatedConfigDirname}";
};
config.package = lib.mkDefault pkgs.noctalia-shell;
config.env.NOCTALIA_SETTINGS_FILE = lib.mkIf (
config.outOfStoreConfig == null && config.settings != { } && !hasOtherFiles
) config.constructFiles.settings.path;
config.env.NOCTALIA_CONFIG_DIR = lib.mkIf (hasOtherFiles || config.outOfStoreConfig != null) (
if config.outOfStoreConfig != null then
# they have some kind of bug where we NEEED the final /
if lib.hasSuffix "/" config.outOfStoreConfig then
config.outOfStoreConfig
else
"${config.outOfStoreConfig}/"
else
"${placeholder config.configDrvOutput}/${config.generatedConfigDirname}/"
);
config.buildCommand.makeDirAnywayToSilenceWarning = ''
mkdir -p "${placeholder config.configDrvOutput}/${config.generatedConfigDirname}/plugins"
'';
config.constructFiles =
let
constructToml = constructAttrs true;
constructJson = constructAttrs false;
constructAttrs =
toml: val:
if builtins.isString val then
{
content = val;
}
else if builtins.isPath val || lib.isStorePath val then
{
builder = ''mkdir -p "$(dirname "$2")" && cp ${val} "$2"'';
}
else
{
content = builtins.toJSON val;
}
// lib.optionalAttrs toml {
builder = ''mkdir -p "$(dirname "$2")" && ${pkgs.remarshal}/bin/json2toml "$1" "$2"'';
};
in
{
dump-noctalia-shell = lib.mkIf config.enableDumpScript {
key = "dumpNoctaliaShell";
relPath = "bin/dump-noctalia-shell";
builder = ''mkdir -p "$(dirname "$2")" && cp "$1" "$2" && chmod +x "$2"'';
content = ''
#!${pkgs.bash}/bin/bash
${config.wrapperPaths.placeholder} ipc call state all > /tmp/noctalia.json && \
${lib.getExe pkgs.nix} eval --impure --expr 'builtins.fromJSON (builtins.readFile /tmp/noctalia.json)'
'';
};
settings = lib.mkIf (config.settings != { }) (
{
# mkOverride 0 to make sure the files are always grouped in the generated dir correctly
relPath = lib.mkOverride 0 "${config.generatedConfigDirname}/settings.json";
output = lib.mkOverride 0 config.configDrvOutput;
}
// constructJson config.settings
);
colors = lib.mkIf (config.colors != { }) (
{
relPath = lib.mkOverride 0 "${config.generatedConfigDirname}/colors.json";
output = lib.mkOverride 0 config.configDrvOutput;
}
// constructJson config.colors
);
plugins = lib.mkIf (config.plugins != { }) (
{
relPath = lib.mkOverride 0 "${config.generatedConfigDirname}/plugins.json";
output = lib.mkOverride 0 config.configDrvOutput;
}
// constructJson config.plugins
);
user-templates = lib.mkIf (config.user-templates != { }) (
{
key = "userTemplates";
relPath = lib.mkOverride 0 "${config.generatedConfigDirname}/user-templates.toml";
output = lib.mkOverride 0 config.configDrvOutput;
}
// constructToml config.user-templates
);
}
// lib.pipe config.pluginSettings [
(lib.mapAttrsToList (
name: value:
lib.nameValuePair name {
relPath = lib.mkOverride 0 "${config.generatedConfigDirname}/plugins/${name}/settings.json";
output = lib.mkOverride 0 config.configDrvOutput;
}
// constructJson value
))
(lib.imap0 (
i: v:
v
// {
value = v.value // {
key = "plugin_${i}";
};
}
))
builtins.listToAttrs
];
} |
|
Problem It installs plugins into the config dir also..... we need some way to actually install plugins for the wrapped version of the config..... We can link them into place in nix, but I am not sure if more needs to happen to them afterwards or not. Also we should avoid repeating the source a bunch of times, we should make it a separate option that accepts the plugins from nix and then maps into the results from the plugins and pluginSettings options already in the above attempt at the module to go into the respective files. |
|
maybe {
config,
lib,
wlib,
pkgs,
...
}:
let
hasOtherFiles =
config.colors != { }
|| config.plugins != { }
|| config.user-templates != { }
|| config.pluginSettings != { }
|| config.preInstalledPlugins != { };
in
{
config.meta.description = ''
`noctalia-shell` has a gui settings interface that edits the config files, rather than implementing a merging mechanism for runtime settings.
When provisioning from the nix store, this causes a few challenges.
To solve this, there are 3 ways to use this wrapper module.
If you only supply `settings`, and do not choose somewhere for `outOfStoreConfig` then it will only generate and set `NOCTALIA_SETTINGS_FILE`
If you leave `outOfStoreConfig == null` as it is by default, and you supply more then just `settings`, it will set `NOCTALIA_CONFIG_DIR` to the generated location
If you do `outOfStoreConfig = "/some/path/somewhere";` and `/some/path/somewhere` does not yet exist, it will copy it there at runtime when you start `noctalia-shell` and set `NOCTALIA_CONFIG_DIR` to that location instead.
This wrapper module also provides by default an extra executable in the bin directory called `dump-noctalia-shell`
It will return the current settings and state of noctalia in nix code format.
It also exports the path to the generated configuration directory from the package via passthru.
`wrapped-noctalia-shell.generatedConfig`
And likewise for the dump script (if it was enabled)
`wrapped-noctalia-shell.dump-noctalia-shell`
'';
config.meta.platforms = lib.platforms.linux;
config.meta.maintainers = [
wlib.maintainers.rachitvrma
wlib.maintainers.birdee
];
imports = [ wlib.modules.default ];
options = {
generatedConfigDirname = lib.mkOption {
type = lib.types.str;
default = "${config.binName}-config";
description = "Name of the directory which is created as the NOCTALIA_CONFIG_DIR in the wrapper output";
apply = x: lib.removePrefix "/" (lib.removeSuffix "/" x);
};
configDrvOutput = lib.mkOption {
type = lib.types.str;
default = config.outputName;
description = "Name of the derivation output where the generated NOCTALIA_CONFIG_DIR is output to.";
};
configPlaceholder = lib.mkOption {
type = lib.types.str;
default = "${placeholder config.configDrvOutput}/${config.generatedConfigDirname}";
readOnly = true;
};
outOfStoreConfig = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
description = ''
If provided, the wrapper script will copy the generated configuration to this location, and use it for `NOCTALIA_CONFIG_DIR`.
Any files existing in that location will NOT be overridden.
Delete the desired file, and restart `noctalia-shell` to re-provision from nix.
'';
};
enableDumpScript = lib.mkOption {
type = lib.types.bool;
default = true;
description = ''
Whether to generate a script to `bin/dump-noctalia-shell` in the wrapper output which will dump the current configuration and state of noctalia to stdout as nix code.
'';
};
settings = lib.mkOption {
type = lib.types.json;
default = { };
example = lib.literalExpression ''
{
bar = {
position = "bottom";
floating = true;
backgroundOpacity = 0.95;
};
general = {
animationSpeed = 1.5;
radiusRatio = 1.2;
};
colorSchemes = {
darkMode = true;
useWallpaperColors = true;
};
}
'';
description = ''
Noctalia shell configuration settings as an attribute set, string
or filepath, to be written to ~/.config/noctalia/settings.json.
'';
};
colors = lib.mkOption {
type = lib.types.json;
default = { };
example = lib.literalExpression ''
{
mError = "#dddddd";
mOnError = "#111111";
mOnPrimary = "#111111";
mOnSecondary = "#111111";
mOnSurface = "#828282";
mOnSurfaceVariant = "#5d5d5d";
mOnTertiary = "#111111";
mOutline = "#3c3c3c";
mPrimary = "#aaaaaa";
mSecondary = "#a7a7a7";
mShadow = "#000000";
mSurface = "#111111";
mSurfaceVariant = "#191919";
mTertiary = "#cccccc";
}
'';
description = ''
Noctalia shell color configuration as an attribute set, string
or filepath, to be written to ~/.config/noctalia/colors.json.
'';
};
user-templates = lib.mkOption {
default = { };
type = (pkgs.formats.toml { }).type;
example = lib.literalExpression ''
{
templates = {
neovim = {
input_path = "~/.config/noctalia/templates/template.lua";
output_path = "~/.config/nvim/generated.lua";
post_hook = "pkill -SIGUSR1 nvim";
};
};
}
'';
description = ''
Template definitions for Noctalia, to be written to ~/.config/noctalia/user-templates.toml.
This option accepts:
- a Nix attrset (converted to TOML automatically)
- a string containing raw TOML
- a path to an existing TOML file
'';
};
plugins = lib.mkOption {
type = lib.types.json;
default = { };
example = lib.literalExpression ''
{
sources = [
{
enabled = true;
name = "Noctalia Plugins";
url = "https://github.com/noctalia-dev/noctalia-plugins";
}
];
states = {
catwalk = {
enabled = true;
sourceUrl = "https://github.com/noctalia-dev/noctalia-plugins";
};
};
version = 2;
}
'';
description = ''
Noctalia shell plugin configuration as an attribute set, string
or filepath, to be written to ~/.config/noctalia/plugins.json.
'';
};
pluginSettings = lib.mkOption {
type = with lib.types; attrsOf json;
default = { };
example = lib.literalExpression ''
{
catwalk = {
minimumThreshold = 25;
hideBackground = true;
};
}
'';
description = ''
Each plugin’s settings as an attribute set, string
or filepath, to be written to ~/.config/noctalia/plugins/plugin-name/settings.json.
'';
};
preInstalledPlugins = lib.mkOption {
type = lib.types.attrsOf (
lib.types.submodule {
options = {
enabled = lib.mkOption {
type = lib.types.bool;
default = true;
description = "";
};
sourceUrl = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
description = "";
};
src = lib.mkOption {
type = wlib.types.stringable;
description = "";
};
settings = lib.mkOption {
type = lib.types.json;
default = { };
description = "";
};
};
}
);
default = { };
};
};
config.runShell = lib.mkIf (config.outOfStoreConfig != null) [
{
name = "COPY_GENERATED_CONFIG";
data = ''
mkdir -p ${config.outOfStoreConfig}
cp -rn ${config.configPlaceholder}/. ${config.outOfStoreConfig}
find ${config.outOfStoreConfig} ! -perm -u+w -exec chmod u+w {} +
'';
}
];
config.passthru = {
${if config.enableDumpScript then "dump-noctalia-shell" else null} =
config.constructFiles.dump-noctalia-shell.outPath;
generatedConfig = "${config.wrapper.${config.configDrvOutput}}/${config.generatedConfigDirname}";
};
config.package = lib.mkDefault pkgs.noctalia-shell;
config.env.NOCTALIA_SETTINGS_FILE = lib.mkIf (
config.outOfStoreConfig == null && config.settings != { } && !hasOtherFiles
) config.constructFiles.settings.path;
config.env.NOCTALIA_CONFIG_DIR = lib.mkIf (hasOtherFiles || config.outOfStoreConfig != null) (
if config.outOfStoreConfig != null then
# they have some kind of bug where we NEEED the final /
if lib.hasSuffix "/" config.outOfStoreConfig then
config.outOfStoreConfig
else
"${config.outOfStoreConfig}/"
else
"${config.configPlaceholder}/"
);
config.buildCommand.symlinkPlugins = lib.pipe config.preInstalledPlugins [
(lib.filterAttrs (_: plugin: plugin.enabled))
(lib.mapAttrsToList (
name: plugin: ''
mkdir -p ${lib.escapeShellArg "${config.configPlaceholder}/plugins/${name}"}
${pkgs.lndir}/bin/lndir -silent ${plugin.src} ${lib.escapeShellArg "${config.configPlaceholder}/plugins/${name}"}
''
))
(v: [ "mkdir -p ${lib.escapeShellArg "${config.configPlaceholder}/plugins"}" ] ++ v)
(lib.concatStringsSep "\n")
];
config.constructFiles = {
dump-noctalia-shell = lib.mkIf config.enableDumpScript {
key = "dumpNoctaliaShell";
relPath = "bin/dump-noctalia-shell";
builder = ''mkdir -p "$(dirname "$2")" && cp "$1" "$2" && chmod +x "$2"'';
content = ''
#!${pkgs.bash}/bin/bash
${config.wrapperPaths.placeholder} ipc call state all > /tmp/noctalia.json && \
${lib.getExe pkgs.nix} eval --impure --expr 'builtins.fromJSON (builtins.readFile /tmp/noctalia.json)'
'';
};
settings = lib.mkIf (config.settings != { }) {
# mkOverride 0 to make sure the files are always grouped in the generated dir correctly
relPath = lib.mkOverride 0 "${config.generatedConfigDirname}/settings.json";
output = lib.mkOverride 0 config.configDrvOutput;
content = builtins.toJSON config.settings;
};
colors = lib.mkIf (config.colors != { }) {
relPath = lib.mkOverride 0 "${config.generatedConfigDirname}/colors.json";
output = lib.mkOverride 0 config.configDrvOutput;
content = builtins.toJSON config.colors;
};
plugins = lib.mkIf (config.plugins != { } || config.preInstalledPlugins != { }) {
relPath = lib.mkOverride 0 "${config.generatedConfigDirname}/plugins.json";
output = lib.mkOverride 0 config.configDrvOutput;
content = builtins.toJSON (
config.plugins
// {
states =
config.plugins.states or { }
// lib.pipe config.preInstalledPlugins [
(lib.filterAttrs (_: plugin: plugin.enabled))
(builtins.mapAttrs (_: v: { inherit (v) enabled sourceUrl; }))
];
}
);
};
user-templates = lib.mkIf (config.user-templates != { }) {
key = "userTemplates";
relPath = lib.mkOverride 0 "${config.generatedConfigDirname}/user-templates.toml";
output = lib.mkOverride 0 config.configDrvOutput;
content = builtins.toJSON config.user-templates;
builder = ''mkdir -p "$(dirname "$2")" && ${pkgs.remarshal}/bin/json2toml "$1" "$2"'';
};
}
// lib.pipe config.preInstalledPlugins [
(lib.filterAttrs (_: plugin: plugin.enabled))
(lib.mapAttrs (_: plugin: plugin.settings))
(v: lib.recursiveUpdate v config.pluginSettings)
(lib.mapAttrsToList (
name: value:
lib.nameValuePair name {
relPath = lib.mkOverride 0 "${config.generatedConfigDirname}/plugins/${name}/settings.json";
output = lib.mkOverride 0 config.configDrvOutput;
content = builtins.toJSON value;
}
))
(lib.imap0 (
i: v:
v
// {
value = v.value // {
key = "plugin_${i}";
};
}
))
builtins.listToAttrs
];
}Havent tested this one yet, its just an idea for "solving" the plugins problem |
#337 Picking up and continuing on this PR ^ for reasons
#337 Picking up and continuing on this PR ^ for reasons
#337 Picking up and continuing on this PR ^ for reasons
#337 Picking up and continuing on this PR ^ for reasons
#337 Picking up and continuing on this PR ^ for reasons
#337 Picking up and continuing on this PR ^ for reasons
#337 Picking up and continuing on this PR ^ for reasons
#337 Picking up and continuing on this PR ^ for reasons
#337 Picking up and continuing on this PR ^ for reasons
Add wrapper module for noctalia-shell.
Inspired by @BirdeeHub 's helix wrapper module.
It's still a WIP
Todo:
noctalia-merged-config/noctalia/plugins