mirror of
https://github.com/nix-community/home-manager.git
synced 2025-11-08 11:36:05 +01:00
Compare commits
9 commits
95d65dddae
...
aa6936bb63
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aa6936bb63 | ||
|
|
65bf99c579 | ||
|
|
6feb368511 | ||
|
|
5cdf9ef995 | ||
|
|
1342b821db | ||
|
|
9ff9a94fd4 | ||
|
|
c740351870 | ||
|
|
083b20c1a0 | ||
|
|
1f34c2c855 |
32 changed files with 1272 additions and 42 deletions
25
modules/misc/news/2025/11/2025-11-03_11-18-15.nix
Normal file
25
modules/misc/news/2025/11/2025-11-03_11-18-15.nix
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
time = "2025-11-03T10:18:15+00:00";
|
||||
condition = true;
|
||||
message = ''
|
||||
A new module 'programs.mcp' is now available for managing Model
|
||||
Context Protocol (MCP) server configurations.
|
||||
|
||||
The 'programs.mcp.servers' option allows you to define MCP servers
|
||||
in a central location. These configurations can be automatically
|
||||
integrated into applications that support MCP.
|
||||
|
||||
Two modules now support MCP integration:
|
||||
|
||||
- 'programs.opencode.enableMcpIntegration': Integrates MCP servers
|
||||
into OpenCode's configuration.
|
||||
|
||||
- 'programs.vscode.profiles.<name>.enableMcpIntegration': Integrates
|
||||
MCP servers into VSCode profiles.
|
||||
|
||||
When integration is enabled, servers from 'programs.mcp.servers' are
|
||||
merged with application-specific MCP settings, with the latter taking
|
||||
precedence. This allows you to define MCP servers once and reuse them
|
||||
across multiple applications.
|
||||
'';
|
||||
}
|
||||
20
modules/misc/news/2025/11/2025-11-03_20-33-15.nix
Normal file
20
modules/misc/news/2025/11/2025-11-03_20-33-15.nix
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
{ pkgs, ... }:
|
||||
{
|
||||
time = "2025-11-04T02:33:15+00:00";
|
||||
condition = pkgs.stdenv.hostPlatform.isLinux;
|
||||
message = ''
|
||||
A new program is available: 'programs.vicinae'.
|
||||
|
||||
Vicinae is a modern application launcher daemon for Linux with support for
|
||||
extensions, custom themes, and layer shell integration.
|
||||
|
||||
The module provides:
|
||||
- Systemd service integration with automatic start support
|
||||
- Extension management with helpers for Vicinae and Raycast extensions
|
||||
- Theme configuration support
|
||||
- Declarative settings via 'programs.vicinae.settings'
|
||||
- Layer shell integration for Wayland compositors
|
||||
|
||||
See the module options for more details on configuration.
|
||||
'';
|
||||
}
|
||||
64
modules/programs/mcp.nix
Normal file
64
modules/programs/mcp.nix
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (lib)
|
||||
literalExpression
|
||||
mkEnableOption
|
||||
mkIf
|
||||
mkOption
|
||||
;
|
||||
|
||||
cfg = config.programs.mcp;
|
||||
|
||||
jsonFormat = pkgs.formats.json { };
|
||||
in
|
||||
{
|
||||
meta.maintainers = with lib.maintainers; [ delafthi ];
|
||||
|
||||
options.programs.mcp = {
|
||||
enable = mkEnableOption "mcp";
|
||||
|
||||
servers = mkOption {
|
||||
inherit (jsonFormat) type;
|
||||
default = { };
|
||||
example = literalExpression ''
|
||||
{
|
||||
everything = {
|
||||
command = "npx";
|
||||
args = [
|
||||
"-y"
|
||||
"@modelcontextprotocol/server-everything"
|
||||
];
|
||||
};
|
||||
context7 = {
|
||||
url = "https://mcp.context7.com/mcp";
|
||||
headers = {
|
||||
CONTEXT7_API_KEY = "{env:CONTEXT7_API_KEY}";
|
||||
};
|
||||
};
|
||||
}
|
||||
'';
|
||||
description = ''
|
||||
MCP server configurations written to
|
||||
{file}`XDG_CONFIG_HOME/.config/mcp/mcp.json`
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
xdg.configFile = mkIf (cfg.servers != { }) (
|
||||
let
|
||||
mcp-config = {
|
||||
mcpServers = cfg.servers;
|
||||
};
|
||||
in
|
||||
{
|
||||
"mcp/mcp.json".source = jsonFormat.generate "mcp.json" mcp-config;
|
||||
}
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
@ -16,6 +16,35 @@ let
|
|||
cfg = config.programs.opencode;
|
||||
|
||||
jsonFormat = pkgs.formats.json { };
|
||||
|
||||
transformMcpServer = name: server: {
|
||||
name = name;
|
||||
value = {
|
||||
enabled = !(server.disabled or false);
|
||||
}
|
||||
// (
|
||||
if server ? url then
|
||||
{
|
||||
type = "remote";
|
||||
url = server.url;
|
||||
}
|
||||
// (lib.optionalAttrs (server ? headers) { headers = server.headers; })
|
||||
else if server ? command then
|
||||
{
|
||||
type = "local";
|
||||
command = [ server.command ] ++ (server.args or [ ]);
|
||||
}
|
||||
// (lib.optionalAttrs (server ? env) { environment = server.env; })
|
||||
else
|
||||
{ }
|
||||
);
|
||||
};
|
||||
|
||||
transformedMcpServers =
|
||||
if cfg.enableMcpIntegration && config.programs.mcp.enable && config.programs.mcp.servers != { } then
|
||||
lib.listToAttrs (lib.mapAttrsToList transformMcpServer config.programs.mcp.servers)
|
||||
else
|
||||
{ };
|
||||
in
|
||||
{
|
||||
meta.maintainers = with lib.maintainers; [ delafthi ];
|
||||
|
|
@ -25,6 +54,20 @@ in
|
|||
|
||||
package = mkPackageOption pkgs "opencode" { nullable = true; };
|
||||
|
||||
enableMcpIntegration = mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to integrate the MCP servers config from
|
||||
{option}`programs.mcp.servers` into
|
||||
{option}`programs.opencode.settings.mcp`.
|
||||
|
||||
Note: Settings defined in {option}`programs.mcp.servers` are merged
|
||||
with {option}`programs.opencode.settings.mcp`, with OpenCode settings
|
||||
taking precedence.
|
||||
'';
|
||||
};
|
||||
|
||||
settings = mkOption {
|
||||
inherit (jsonFormat) type;
|
||||
default = { };
|
||||
|
|
@ -147,7 +190,7 @@ in
|
|||
Custom themes for opencode. The attribute name becomes the theme
|
||||
filename, and the value is either:
|
||||
- An attribute set, that is converted to a json
|
||||
- A path to a file conaining the content
|
||||
- A path to a file containing the content
|
||||
Themes are stored in {file}`$XDG_CONFIG_HOME/opencode/themes/` directory.
|
||||
Set `programs.opencode.settings.theme` to enable the custom theme.
|
||||
See <https://opencode.ai/docs/themes/> for the documentation.
|
||||
|
|
@ -159,12 +202,20 @@ in
|
|||
home.packages = mkIf (cfg.package != null) [ cfg.package ];
|
||||
|
||||
xdg.configFile = {
|
||||
"opencode/config.json" = mkIf (cfg.settings != { }) {
|
||||
source = jsonFormat.generate "config.json" (
|
||||
"opencode/config.json" = mkIf (cfg.settings != { } || transformedMcpServers != { }) {
|
||||
source =
|
||||
let
|
||||
# Merge MCP servers: transformed servers + user settings, with user settings taking precedence
|
||||
mergedMcpServers = transformedMcpServers // (cfg.settings.mcp or { });
|
||||
# Merge all settings
|
||||
mergedSettings =
|
||||
cfg.settings // (lib.optionalAttrs (mergedMcpServers != { }) { mcp = mergedMcpServers; });
|
||||
in
|
||||
jsonFormat.generate "config.json" (
|
||||
{
|
||||
"$schema" = "https://opencode.ai/config.json";
|
||||
}
|
||||
// cfg.settings
|
||||
// mergedSettings
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
|||
244
modules/programs/vicinae.nix
Normal file
244
modules/programs/vicinae.nix
Normal file
|
|
@ -0,0 +1,244 @@
|
|||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.programs.vicinae;
|
||||
|
||||
jsonFormat = pkgs.formats.json { };
|
||||
in
|
||||
{
|
||||
meta.maintainers = [ lib.maintainers.leiserfg ];
|
||||
|
||||
options.programs.vicinae = {
|
||||
enable = lib.mkEnableOption "vicinae launcher daemon";
|
||||
|
||||
package = lib.mkPackageOption pkgs "vicinae" { nullable = true; };
|
||||
|
||||
systemd = {
|
||||
enable = lib.mkEnableOption "vicinae systemd integration";
|
||||
|
||||
autoStart = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = "If the vicinae daemon should be started automatically";
|
||||
};
|
||||
|
||||
target = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "graphical-session.target";
|
||||
example = "sway-session.target";
|
||||
description = ''
|
||||
The systemd target that will automatically start the vicinae service.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
useLayerShell = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = "If vicinae should use the layer shell";
|
||||
};
|
||||
|
||||
extensions = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.package;
|
||||
default = [ ];
|
||||
description = ''
|
||||
List of Vicinae extensions to install.
|
||||
|
||||
You can use the `config.lib.vicinae.mkExtension` and `config.lib.vicinae.mkRayCastExtension` functions to create them, like:
|
||||
```nix
|
||||
[
|
||||
(config.lib.vicinae.mkExtension {
|
||||
name = "test-extension";
|
||||
src =
|
||||
pkgs.fetchFromGitHub {
|
||||
owner = "schromp";
|
||||
repo = "vicinae-extensions";
|
||||
rev = "f8be5c89393a336f773d679d22faf82d59631991";
|
||||
sha256 = "sha256-zk7WIJ19ITzRFnqGSMtX35SgPGq0Z+M+f7hJRbyQugw=";
|
||||
}
|
||||
+ "/test-extension";
|
||||
})
|
||||
(config.lib.vicinae.mkRayCastExtension {
|
||||
name = "gif-search";
|
||||
sha256 = "sha256-G7il8T1L+P/2mXWJsb68n4BCbVKcrrtK8GnBNxzt73Q=";
|
||||
rev = "4d417c2dfd86a5b2bea202d4a7b48d8eb3dbaeb1";
|
||||
})
|
||||
],
|
||||
```
|
||||
'';
|
||||
};
|
||||
|
||||
themes = lib.mkOption {
|
||||
inherit (jsonFormat) type;
|
||||
default = { };
|
||||
description = ''
|
||||
Theme settings to add to the themes folder in `~/.config/vicinae/themes`.
|
||||
|
||||
The attribute name of the theme will be the name of theme json file,
|
||||
e.g. `base16-default-dark` will be `base16-default-dark.json`.
|
||||
'';
|
||||
example =
|
||||
lib.literalExpression # nix
|
||||
''
|
||||
{
|
||||
base16-default-dark = {
|
||||
version = "1.0.0";
|
||||
appearance = "dark";
|
||||
icon = /path/to/icon.png;
|
||||
name = "base16 default dark";
|
||||
description = "base16 default dark by Chris Kempson";
|
||||
palette = {
|
||||
background = "#181818";
|
||||
foreground = "#d8d8d8";
|
||||
blue = "#7cafc2";
|
||||
green = "#a3be8c";
|
||||
magenta = "#ba8baf";
|
||||
orange = "#dc9656";
|
||||
purple = "#a16946";
|
||||
red = "#ab4642";
|
||||
yellow = "#f7ca88";
|
||||
cyan = "#86c1b9";
|
||||
};
|
||||
};
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
settings = lib.mkOption {
|
||||
inherit (jsonFormat) type;
|
||||
default = { };
|
||||
description = "Settings written as JSON to `~/.config/vicinae/vicinae.json.";
|
||||
example = lib.literalExpression ''
|
||||
{
|
||||
faviconService = "twenty";
|
||||
font = {
|
||||
size = 10;
|
||||
};
|
||||
popToRootOnClose = false;
|
||||
rootSearch = {
|
||||
searchFiles = false;
|
||||
};
|
||||
theme = {
|
||||
name = "vicinae-dark";
|
||||
};
|
||||
window = {
|
||||
csd = true;
|
||||
opacity = 0.95;
|
||||
rounding = 10;
|
||||
};
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
assertions = [
|
||||
(lib.hm.assertions.assertPlatform "programs.vicinae" pkgs lib.platforms.linux)
|
||||
{
|
||||
assertion = cfg.systemd.enable -> cfg.package != null;
|
||||
message = "{option}programs.vicinae.systemd.enable requires non null {option}programs.vicinae.package";
|
||||
}
|
||||
];
|
||||
lib.vicinae.mkExtension = (
|
||||
{
|
||||
name,
|
||||
src,
|
||||
}:
|
||||
(pkgs.buildNpmPackage {
|
||||
inherit name src;
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
|
||||
mkdir -p $out
|
||||
cp -r /build/.local/share/vicinae/extensions/${name}/* $out/
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
npmDeps = pkgs.importNpmLock { npmRoot = src; };
|
||||
npmConfigHook = pkgs.importNpmLock.npmConfigHook;
|
||||
})
|
||||
);
|
||||
|
||||
lib.vicinae.mkRayCastExtension = (
|
||||
{
|
||||
name,
|
||||
sha256,
|
||||
rev,
|
||||
}:
|
||||
let
|
||||
src =
|
||||
pkgs.fetchgit {
|
||||
inherit rev sha256;
|
||||
url = "https://github.com/raycast/extensions";
|
||||
sparseCheckout = [
|
||||
"/extensions/${name}"
|
||||
];
|
||||
}
|
||||
+ "/extensions/${name}";
|
||||
in
|
||||
(pkgs.buildNpmPackage {
|
||||
inherit name src;
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
|
||||
mkdir -p $out
|
||||
cp -r /build/.config/raycast/extensions/${name}/* $out/
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
npmDeps = pkgs.importNpmLock { npmRoot = src; };
|
||||
npmConfigHook = pkgs.importNpmLock.npmConfigHook;
|
||||
})
|
||||
);
|
||||
|
||||
home.packages = lib.mkIf (cfg.package != null) [ cfg.package ];
|
||||
|
||||
xdg = {
|
||||
configFile = {
|
||||
"vicinae/vicinae.json" = lib.mkIf (cfg.settings != { }) {
|
||||
source = jsonFormat.generate "vicinae-settings" cfg.settings;
|
||||
};
|
||||
}
|
||||
// lib.mapAttrs' (
|
||||
name: theme:
|
||||
lib.nameValuePair "vicinae/themes/${name}.json" {
|
||||
source = jsonFormat.generate "vicinae-${name}-theme" theme;
|
||||
}
|
||||
) cfg.themes;
|
||||
|
||||
dataFile = builtins.listToAttrs (
|
||||
builtins.map (item: {
|
||||
name = "vicinae/extensions/${item.name}";
|
||||
value.source = item;
|
||||
}) cfg.extensions
|
||||
);
|
||||
};
|
||||
|
||||
systemd.user.services.vicinae = lib.mkIf (cfg.systemd.enable && cfg.package != null) {
|
||||
Unit = {
|
||||
Description = "Vicinae server daemon";
|
||||
Documentation = [ "https://docs.vicinae.com" ];
|
||||
After = [ cfg.systemd.target ];
|
||||
PartOf = [ cfg.systemd.target ];
|
||||
BindsTo = [ cfg.systemd.target ];
|
||||
};
|
||||
Service = {
|
||||
EnvironmentFile = pkgs.writeText "vicinae-env" ''
|
||||
USE_LAYER_SHELL=${if cfg.useLayerShell then builtins.toString 1 else builtins.toString 0}
|
||||
'';
|
||||
Type = "simple";
|
||||
ExecStart = "${lib.getExe' cfg.package "vicinae"} server";
|
||||
Restart = "always";
|
||||
RestartSec = 5;
|
||||
KillMode = "process";
|
||||
};
|
||||
Install = lib.mkIf cfg.systemd.autoStart {
|
||||
WantedBy = [ cfg.systemd.target ];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
@ -114,6 +114,33 @@ let
|
|||
|
||||
isPath = p: builtins.isPath p || lib.isStorePath p;
|
||||
|
||||
transformMcpServerForVscode =
|
||||
name: server:
|
||||
let
|
||||
# Remove the disabled field from the server config
|
||||
cleanServer = lib.filterAttrs (n: v: n != "disabled") server;
|
||||
in
|
||||
{
|
||||
name = name;
|
||||
value = {
|
||||
enabled = !(server.disabled or false);
|
||||
}
|
||||
// (
|
||||
if server ? url then
|
||||
{
|
||||
type = "http";
|
||||
}
|
||||
// cleanServer
|
||||
else if server ? command then
|
||||
{
|
||||
type = "stdio";
|
||||
}
|
||||
// cleanServer
|
||||
else
|
||||
{ }
|
||||
);
|
||||
};
|
||||
|
||||
profileType = types.submodule {
|
||||
options = {
|
||||
userSettings = mkOption {
|
||||
|
|
@ -154,6 +181,20 @@ let
|
|||
'';
|
||||
};
|
||||
|
||||
enableMcpIntegration = mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to integrate the MCP servers config from
|
||||
{option}`programs.mcp.servers` into
|
||||
{option}`programs.vscode.profiles.<name>.userMcp`.
|
||||
|
||||
Note: Settings defined in {option}`programs.mcp.servers` are merged
|
||||
with {option}`programs.vscode.profiles.<name>.userMcp`, with VSCode
|
||||
settings taking precedence.
|
||||
'';
|
||||
};
|
||||
|
||||
userMcp = mkOption {
|
||||
type = types.either types.path jsonFormat.type;
|
||||
default = { };
|
||||
|
|
@ -459,10 +500,31 @@ in
|
|||
if isPath v.userTasks then v.userTasks else jsonFormat.generate "vscode-user-tasks" v.userTasks;
|
||||
})
|
||||
|
||||
(mkIf (v.userMcp != { }) {
|
||||
(mkIf
|
||||
(
|
||||
v.userMcp != { }
|
||||
|| (v.enableMcpIntegration && config.programs.mcp.enable && config.programs.mcp.servers != { })
|
||||
)
|
||||
{
|
||||
"${mcpFilePath n}".source =
|
||||
if isPath v.userMcp then v.userMcp else jsonFormat.generate "vscode-user-mcp" v.userMcp;
|
||||
})
|
||||
if isPath v.userMcp then
|
||||
v.userMcp
|
||||
else
|
||||
let
|
||||
transformedMcpServers =
|
||||
if v.enableMcpIntegration && config.programs.mcp.enable && config.programs.mcp.servers != { } then
|
||||
lib.listToAttrs (lib.mapAttrsToList transformMcpServerForVscode config.programs.mcp.servers)
|
||||
else
|
||||
{ };
|
||||
# Merge MCP servers: transformed servers + user servers, with user servers taking precedence
|
||||
mergedServers = transformedMcpServers // ((v.userMcp.servers or { }));
|
||||
# Merge all MCP config
|
||||
mergedMcpConfig =
|
||||
v.userMcp // (lib.optionalAttrs (mergedServers != { }) { servers = mergedServers; });
|
||||
in
|
||||
jsonFormat.generate "vscode-user-mcp" mergedMcpConfig;
|
||||
}
|
||||
)
|
||||
|
||||
(mkIf (v.keybindings != [ ]) {
|
||||
"${keybindingsFilePath n}".source =
|
||||
|
|
|
|||
|
|
@ -221,7 +221,7 @@ in
|
|||
function ${cfg.shellWrapperName}() {
|
||||
local tmp="$(mktemp -t "yazi-cwd.XXXXX")"
|
||||
yazi "$@" --cwd-file="$tmp"
|
||||
if cwd="$(cat -- "$tmp")" && [ -n "$cwd" ] && [ "$cwd" != "$PWD" ]; then
|
||||
if cwd="$(<"$tmp")" && [ -n "$cwd" ] && [ "$cwd" != "$PWD" ]; then
|
||||
builtin cd -- "$cwd"
|
||||
fi
|
||||
rm -f -- "$tmp"
|
||||
|
|
@ -231,7 +231,7 @@ in
|
|||
fishIntegration = ''
|
||||
set -l tmp (mktemp -t "yazi-cwd.XXXXX")
|
||||
command yazi $argv --cwd-file="$tmp"
|
||||
if set cwd (cat -- "$tmp"); and [ -n "$cwd" ]; and [ "$cwd" != "$PWD" ]
|
||||
if read cwd < "$tmp"; and [ -n "$cwd" ]; and [ "$cwd" != "$PWD" ]
|
||||
builtin cd -- "$cwd"
|
||||
end
|
||||
rm -f -- "$tmp"
|
||||
|
|
|
|||
|
|
@ -81,6 +81,15 @@ in
|
|||
'';
|
||||
};
|
||||
|
||||
mutableUserDebug = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
example = false;
|
||||
description = ''
|
||||
Whether user debug configurations (debug.json) can be updated by zed.
|
||||
'';
|
||||
};
|
||||
|
||||
userSettings = mkOption {
|
||||
type = jsonFormat.type;
|
||||
default = { };
|
||||
|
|
@ -140,6 +149,27 @@ in
|
|||
'';
|
||||
};
|
||||
|
||||
userDebug = mkOption {
|
||||
type = jsonFormat.type;
|
||||
default = [ ];
|
||||
example = literalExpression ''
|
||||
[
|
||||
{
|
||||
label = "Go (Delve)";
|
||||
adapter = "Delve";
|
||||
program = "$ZED_FILE";
|
||||
request = "launch";
|
||||
mode = "debug";
|
||||
}
|
||||
]
|
||||
'';
|
||||
description = ''
|
||||
Configuration written to Zed's {file}`debug.json`.
|
||||
|
||||
Global debug configurations for Zed's [Debugger](https://zed.dev/docs/debugger).
|
||||
'';
|
||||
};
|
||||
|
||||
extensions = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
|
|
@ -241,6 +271,14 @@ in
|
|||
(jsonFormat.generate "zed-user-tasks" cfg.userTasks)
|
||||
);
|
||||
})
|
||||
(mkIf (cfg.mutableUserDebug && cfg.userDebug != [ ]) {
|
||||
zedDebugActivation = lib.hm.dag.entryAfter [ "linkGeneration" ] (
|
||||
impureConfigMerger "[]"
|
||||
"$dynamic + $static | group_by(.label) | map(reduce .[] as $item ({}; . * $item))"
|
||||
"${config.xdg.configHome}/zed/debug.json"
|
||||
(jsonFormat.generate "zed-user-debug" cfg.userDebug)
|
||||
);
|
||||
})
|
||||
];
|
||||
|
||||
xdg.configFile = mkMerge [
|
||||
|
|
@ -265,6 +303,9 @@ in
|
|||
(mkIf (!cfg.mutableUserTasks && cfg.userTasks != [ ]) {
|
||||
"zed/tasks.json".source = jsonFormat.generate "zed-user-tasks" cfg.userTasks;
|
||||
})
|
||||
(mkIf (!cfg.mutableUserDebug && cfg.userDebug != [ ]) {
|
||||
"zed/debug.json".source = jsonFormat.generate "zed-user-debug" cfg.userDebug;
|
||||
})
|
||||
];
|
||||
|
||||
assertions = [
|
||||
|
|
|
|||
4
tests/modules/programs/mcp/default.nix
Normal file
4
tests/modules/programs/mcp/default.nix
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
mcp-servers = ./servers.nix;
|
||||
mcp-empty-servers = ./empty-servers.nix;
|
||||
}
|
||||
9
tests/modules/programs/mcp/empty-servers.nix
Normal file
9
tests/modules/programs/mcp/empty-servers.nix
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
programs.mcp = {
|
||||
enable = true;
|
||||
servers = { };
|
||||
};
|
||||
nmt.script = ''
|
||||
assertPathNotExists home-files/.config/mcp/mcp.json
|
||||
'';
|
||||
}
|
||||
17
tests/modules/programs/mcp/mcp.json
Normal file
17
tests/modules/programs/mcp/mcp.json
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"mcpServers": {
|
||||
"context7": {
|
||||
"headers": {
|
||||
"CONTEXT7_API_KEY": "{env:CONTEXT7_API_KEY}"
|
||||
},
|
||||
"serverUrl": "https://mcp.context7.com/mcp"
|
||||
},
|
||||
"everything": {
|
||||
"args": [
|
||||
"-y",
|
||||
"@modelcontextprotocol/server-everything"
|
||||
],
|
||||
"command": "npx"
|
||||
}
|
||||
}
|
||||
}
|
||||
25
tests/modules/programs/mcp/servers.nix
Normal file
25
tests/modules/programs/mcp/servers.nix
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
programs.mcp = {
|
||||
enable = true;
|
||||
servers = {
|
||||
everything = {
|
||||
command = "npx";
|
||||
args = [
|
||||
"-y"
|
||||
"@modelcontextprotocol/server-everything"
|
||||
];
|
||||
};
|
||||
context7 = {
|
||||
serverUrl = "https://mcp.context7.com/mcp";
|
||||
headers = {
|
||||
CONTEXT7_API_KEY = "{env:CONTEXT7_API_KEY}";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
nmt.script = ''
|
||||
assertFileExists home-files/.config/mcp/mcp.json
|
||||
assertFileContent home-files/.config/mcp/mcp.json \
|
||||
${./mcp.json}
|
||||
'';
|
||||
}
|
||||
|
|
@ -11,4 +11,6 @@
|
|||
opencode-mixed-content = ./mixed-content.nix;
|
||||
opencode-themes-inline = ./themes-inline.nix;
|
||||
opencode-themes-path = ./themes-path.nix;
|
||||
opencode-mcp-integration = ./mcp-integration.nix;
|
||||
opencode-mcp-integration-with-override = ./mcp-integration-with-override.nix;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"mcp": {
|
||||
"context7": {
|
||||
"enabled": true,
|
||||
"headers": {
|
||||
"CONTEXT7_API_KEY": "{env:CONTEXT7_API_KEY}"
|
||||
},
|
||||
"type": "remote",
|
||||
"url": "https://mcp.context7.com/mcp"
|
||||
},
|
||||
"custom-server": {
|
||||
"enabled": true,
|
||||
"type": "remote",
|
||||
"url": "https://example.com"
|
||||
},
|
||||
"everything": {
|
||||
"command": [
|
||||
"custom-command"
|
||||
],
|
||||
"enabled": false,
|
||||
"type": "local"
|
||||
}
|
||||
},
|
||||
"model": "anthropic/claude-sonnet-4-20250514",
|
||||
"theme": "opencode"
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
{
|
||||
programs.mcp = {
|
||||
enable = true;
|
||||
servers = {
|
||||
everything = {
|
||||
command = "npx";
|
||||
args = [
|
||||
"-y"
|
||||
"@modelcontextprotocol/server-everything"
|
||||
];
|
||||
};
|
||||
context7 = {
|
||||
url = "https://mcp.context7.com/mcp";
|
||||
headers = {
|
||||
CONTEXT7_API_KEY = "{env:CONTEXT7_API_KEY}";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
programs.opencode = {
|
||||
enable = true;
|
||||
enableMcpIntegration = true;
|
||||
settings = {
|
||||
theme = "opencode";
|
||||
model = "anthropic/claude-sonnet-4-20250514";
|
||||
# User's custom MCP settings should override generated ones
|
||||
mcp = {
|
||||
everything = {
|
||||
enabled = false; # Override to disable
|
||||
command = [ "custom-command" ];
|
||||
type = "local";
|
||||
};
|
||||
custom-server = {
|
||||
enabled = true;
|
||||
type = "remote";
|
||||
url = "https://example.com";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
nmt.script = ''
|
||||
assertFileExists home-files/.config/opencode/config.json
|
||||
assertFileContent home-files/.config/opencode/config.json \
|
||||
${./mcp-integration-with-override.json}
|
||||
'';
|
||||
}
|
||||
30
tests/modules/programs/opencode/mcp-integration.json
Normal file
30
tests/modules/programs/opencode/mcp-integration.json
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"mcp": {
|
||||
"context7": {
|
||||
"enabled": true,
|
||||
"headers": {
|
||||
"CONTEXT7_API_KEY": "{env:CONTEXT7_API_KEY}"
|
||||
},
|
||||
"type": "remote",
|
||||
"url": "https://mcp.context7.com/mcp"
|
||||
},
|
||||
"disabled-server": {
|
||||
"command": [
|
||||
"echo",
|
||||
"test"
|
||||
],
|
||||
"enabled": false,
|
||||
"type": "local"
|
||||
},
|
||||
"everything": {
|
||||
"command": [
|
||||
"npx",
|
||||
"-y",
|
||||
"@modelcontextprotocol/server-everything"
|
||||
],
|
||||
"enabled": true,
|
||||
"type": "local"
|
||||
}
|
||||
}
|
||||
}
|
||||
36
tests/modules/programs/opencode/mcp-integration.nix
Normal file
36
tests/modules/programs/opencode/mcp-integration.nix
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
programs.mcp = {
|
||||
enable = true;
|
||||
servers = {
|
||||
everything = {
|
||||
command = "npx";
|
||||
args = [
|
||||
"-y"
|
||||
"@modelcontextprotocol/server-everything"
|
||||
];
|
||||
};
|
||||
context7 = {
|
||||
url = "https://mcp.context7.com/mcp";
|
||||
headers = {
|
||||
CONTEXT7_API_KEY = "{env:CONTEXT7_API_KEY}";
|
||||
};
|
||||
};
|
||||
disabled-server = {
|
||||
command = "echo";
|
||||
args = [ "test" ];
|
||||
disabled = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
programs.opencode = {
|
||||
enable = true;
|
||||
enableMcpIntegration = true;
|
||||
};
|
||||
|
||||
nmt.script = ''
|
||||
assertFileExists home-files/.config/opencode/config.json
|
||||
assertFileContent home-files/.config/opencode/config.json \
|
||||
${./mcp-integration.json}
|
||||
'';
|
||||
}
|
||||
4
tests/modules/programs/vicinae/default.nix
Normal file
4
tests/modules/programs/vicinae/default.nix
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{ lib, pkgs, ... }:
|
||||
lib.optionalAttrs (pkgs.stdenv.hostPlatform.isLinux) {
|
||||
vicinae-example-settings = ./example-settings.nix;
|
||||
}
|
||||
77
tests/modules/programs/vicinae/example-settings.nix
Normal file
77
tests/modules/programs/vicinae/example-settings.nix
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
{
|
||||
pkgs,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
|
||||
{
|
||||
programs.vicinae = {
|
||||
enable = true;
|
||||
systemd.enable = true;
|
||||
|
||||
settings = {
|
||||
faviconService = "twenty";
|
||||
font = {
|
||||
size = 10;
|
||||
};
|
||||
popToRootOnClose = false;
|
||||
rootSearch = {
|
||||
searchFiles = false;
|
||||
};
|
||||
theme = {
|
||||
name = "vicinae-dark";
|
||||
};
|
||||
window = {
|
||||
csd = true;
|
||||
opacity = 0.95;
|
||||
rounding = 10;
|
||||
};
|
||||
};
|
||||
themes = {
|
||||
base16-default-dark = {
|
||||
version = "1.0.0";
|
||||
appearance = "dark";
|
||||
name = "base16 default dark";
|
||||
description = "base16 default dark by Chris Kempson";
|
||||
palette = {
|
||||
background = "#181818";
|
||||
foreground = "#d8d8d8";
|
||||
blue = "#7cafc2";
|
||||
green = "#a3be8c";
|
||||
magenta = "#ba8baf";
|
||||
orange = "#dc9656";
|
||||
purple = "#a16946";
|
||||
red = "#ab4642";
|
||||
yellow = "#f7ca88";
|
||||
cyan = "#86c1b9";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
extensions = [
|
||||
(config.lib.vicinae.mkRayCastExtension {
|
||||
name = "gif-search";
|
||||
sha256 = "sha256-G7il8T1L+P/2mXWJsb68n4BCbVKcrrtK8GnBNxzt73Q=";
|
||||
rev = "4d417c2dfd86a5b2bea202d4a7b48d8eb3dbaeb1";
|
||||
})
|
||||
(config.lib.vicinae.mkExtension {
|
||||
name = "test-extension";
|
||||
src =
|
||||
pkgs.fetchFromGitHub {
|
||||
owner = "schromp";
|
||||
repo = "vicinae-extensions";
|
||||
rev = "f8be5c89393a336f773d679d22faf82d59631991";
|
||||
sha256 = "sha256-zk7WIJ19ITzRFnqGSMtX35SgPGq0Z+M+f7hJRbyQugw=";
|
||||
}
|
||||
+ "/test-extension";
|
||||
})
|
||||
];
|
||||
};
|
||||
|
||||
nmt.script = ''
|
||||
assertFileExists "home-files/.config/vicinae/vicinae.json"
|
||||
assertFileExists "home-files/.config/systemd/user/vicinae.service"
|
||||
assertFileExists "home-files/.local/share/vicinae/extensions/gif-search/package.json"
|
||||
assertFileExists "home-files/.local/share/vicinae/extensions/test-extension/package.json"
|
||||
'';
|
||||
}
|
||||
|
|
@ -24,6 +24,8 @@ let
|
|||
keybindings = import ./keybindings.nix;
|
||||
tasks = import ./tasks.nix;
|
||||
mcp = import ./mcp.nix;
|
||||
mcp-integration = import ./mcp-integration.nix;
|
||||
mcp-integration-with-override = import ./mcp-integration-with-override.nix;
|
||||
update-checks = import ./update-checks.nix;
|
||||
snippets = import ./snippets.nix;
|
||||
};
|
||||
|
|
|
|||
26
tests/modules/programs/vscode/mcp-integration-default.json
Normal file
26
tests/modules/programs/vscode/mcp-integration-default.json
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"servers": {
|
||||
"context7": {
|
||||
"enabled": true,
|
||||
"headers": {
|
||||
"CONTEXT7_API_KEY": "{env:CONTEXT7_API_KEY}"
|
||||
},
|
||||
"type": "http",
|
||||
"url": "https://mcp.context7.com/mcp"
|
||||
},
|
||||
"disabled-server": {
|
||||
"command": "echo",
|
||||
"enabled": false,
|
||||
"type": "stdio"
|
||||
},
|
||||
"everything": {
|
||||
"args": [
|
||||
"-y",
|
||||
"@modelcontextprotocol/server-everything"
|
||||
],
|
||||
"command": "npx",
|
||||
"enabled": true,
|
||||
"type": "stdio"
|
||||
}
|
||||
}
|
||||
}
|
||||
7
tests/modules/programs/vscode/mcp-integration-test.json
Normal file
7
tests/modules/programs/vscode/mcp-integration-test.json
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"servers": {
|
||||
"Github": {
|
||||
"url": "https://api.githubcopilot.com/mcp/"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"servers": {
|
||||
"CustomServer": {
|
||||
"type": "http",
|
||||
"url": "https://example.com/mcp"
|
||||
},
|
||||
"context7": {
|
||||
"enabled": true,
|
||||
"headers": {
|
||||
"CONTEXT7_API_KEY": "{env:CONTEXT7_API_KEY}"
|
||||
},
|
||||
"type": "http",
|
||||
"url": "https://mcp.context7.com/mcp"
|
||||
},
|
||||
"everything": {
|
||||
"args": [
|
||||
"-y",
|
||||
"@modelcontextprotocol/server-everything"
|
||||
],
|
||||
"command": "custom-npx",
|
||||
"enabled": false,
|
||||
"type": "stdio"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
package:
|
||||
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
cfg = config.programs.vscode;
|
||||
willUseIfd = package.pname != "vscode";
|
||||
|
||||
mcpFilePath =
|
||||
name:
|
||||
if pkgs.stdenv.hostPlatform.isDarwin then
|
||||
"Library/Application Support/${cfg.nameShort}/User/${
|
||||
lib.optionalString (name != "default") "profiles/${name}/"
|
||||
}mcp.json"
|
||||
else
|
||||
".config/${cfg.nameShort}/User/${
|
||||
lib.optionalString (name != "default") "profiles/${name}/"
|
||||
}mcp.json";
|
||||
|
||||
in
|
||||
|
||||
lib.mkIf (willUseIfd -> config.test.enableLegacyIfd) {
|
||||
programs.mcp = {
|
||||
enable = true;
|
||||
servers = {
|
||||
everything = {
|
||||
command = "npx";
|
||||
args = [
|
||||
"-y"
|
||||
"@modelcontextprotocol/server-everything"
|
||||
];
|
||||
};
|
||||
context7 = {
|
||||
url = "https://mcp.context7.com/mcp";
|
||||
headers = {
|
||||
CONTEXT7_API_KEY = "{env:CONTEXT7_API_KEY}";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
programs.vscode = {
|
||||
enable = true;
|
||||
inherit package;
|
||||
profiles = {
|
||||
default = {
|
||||
enableMcpIntegration = true;
|
||||
# User MCP settings should override generated ones
|
||||
userMcp = {
|
||||
servers = {
|
||||
everything = {
|
||||
command = "custom-npx";
|
||||
args = [
|
||||
"-y"
|
||||
"@modelcontextprotocol/server-everything"
|
||||
];
|
||||
enabled = false;
|
||||
type = "stdio";
|
||||
};
|
||||
CustomServer = {
|
||||
type = "http";
|
||||
url = "https://example.com/mcp";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
nmt.script = ''
|
||||
assertFileExists "home-files/${mcpFilePath "default"}"
|
||||
assertFileContent "home-files/${mcpFilePath "default"}" ${./mcp-integration-with-override.json}
|
||||
'';
|
||||
}
|
||||
73
tests/modules/programs/vscode/mcp-integration.nix
Normal file
73
tests/modules/programs/vscode/mcp-integration.nix
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
package:
|
||||
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
|
||||
let
|
||||
cfg = config.programs.vscode;
|
||||
willUseIfd = package.pname != "vscode";
|
||||
|
||||
mcpFilePath =
|
||||
name:
|
||||
if pkgs.stdenv.hostPlatform.isDarwin then
|
||||
"Library/Application Support/${cfg.nameShort}/User/${
|
||||
lib.optionalString (name != "default") "profiles/${name}/"
|
||||
}mcp.json"
|
||||
else
|
||||
".config/${cfg.nameShort}/User/${
|
||||
lib.optionalString (name != "default") "profiles/${name}/"
|
||||
}mcp.json";
|
||||
|
||||
in
|
||||
|
||||
lib.mkIf (willUseIfd -> config.test.enableLegacyIfd) {
|
||||
programs.mcp = {
|
||||
enable = true;
|
||||
servers = {
|
||||
everything = {
|
||||
command = "npx";
|
||||
args = [
|
||||
"-y"
|
||||
"@modelcontextprotocol/server-everything"
|
||||
];
|
||||
};
|
||||
context7 = {
|
||||
url = "https://mcp.context7.com/mcp";
|
||||
headers = {
|
||||
CONTEXT7_API_KEY = "{env:CONTEXT7_API_KEY}";
|
||||
};
|
||||
};
|
||||
disabled-server = {
|
||||
command = "echo";
|
||||
disabled = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
programs.vscode = {
|
||||
enable = true;
|
||||
inherit package;
|
||||
profiles = {
|
||||
default.enableMcpIntegration = true;
|
||||
test.userMcp = {
|
||||
servers = {
|
||||
Github = {
|
||||
url = "https://api.githubcopilot.com/mcp/";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
nmt.script = ''
|
||||
assertFileExists "home-files/${mcpFilePath "default"}"
|
||||
assertFileContent "home-files/${mcpFilePath "default"}" ${./mcp-integration-default.json}
|
||||
|
||||
assertFileExists "home-files/${mcpFilePath "test"}"
|
||||
assertFileContent "home-files/${mcpFilePath "test"}" ${./mcp-integration-test.json}
|
||||
'';
|
||||
}
|
||||
|
|
@ -1,15 +1,3 @@
|
|||
let
|
||||
shellIntegration = ''
|
||||
function yy() {
|
||||
local tmp="$(mktemp -t "yazi-cwd.XXXXX")"
|
||||
yazi "$@" --cwd-file="$tmp"
|
||||
if cwd="$(cat -- "$tmp")" && [ -n "$cwd" ] && [ "$cwd" != "$PWD" ]; then
|
||||
builtin cd -- "$cwd"
|
||||
fi
|
||||
rm -f -- "$tmp"
|
||||
}
|
||||
'';
|
||||
in
|
||||
{
|
||||
programs.bash.enable = true;
|
||||
|
||||
|
|
@ -19,6 +7,12 @@ in
|
|||
};
|
||||
|
||||
nmt.script = ''
|
||||
assertFileContains home-files/.bashrc '${shellIntegration}'
|
||||
assertFileExists home-files/.bashrc
|
||||
assertFileContains home-files/.bashrc 'function yy() {'
|
||||
assertFileContains home-files/.bashrc 'local tmp="$(mktemp -t "yazi-cwd.XXXXX")"'
|
||||
assertFileContains home-files/.bashrc 'yazi "$@" --cwd-file="$tmp"'
|
||||
assertFileContains home-files/.bashrc 'if cwd="$(<"$tmp")" && [ -n "$cwd" ] && [ "$cwd" != "$PWD" ]; then'
|
||||
assertFileContains home-files/.bashrc 'builtin cd -- "$cwd"'
|
||||
assertFileContains home-files/.bashrc 'rm -f -- "$tmp"'
|
||||
'';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
function yy
|
||||
set -l tmp (mktemp -t "yazi-cwd.XXXXX")
|
||||
command yazi $argv --cwd-file="$tmp"
|
||||
if set cwd (cat -- "$tmp"); and [ -n "$cwd" ]; and [ "$cwd" != "$PWD" ]
|
||||
if read cwd <"$tmp"; and [ -n "$cwd" ]; and [ "$cwd" != "$PWD" ]
|
||||
builtin cd -- "$cwd"
|
||||
end
|
||||
rm -f -- "$tmp"
|
||||
|
|
|
|||
|
|
@ -1,24 +1,18 @@
|
|||
let
|
||||
shellIntegration = ''
|
||||
function yy() {
|
||||
local tmp="$(mktemp -t "yazi-cwd.XXXXX")"
|
||||
yazi "$@" --cwd-file="$tmp"
|
||||
if cwd="$(cat -- "$tmp")" && [ -n "$cwd" ] && [ "$cwd" != "$PWD" ]; then
|
||||
builtin cd -- "$cwd"
|
||||
fi
|
||||
rm -f -- "$tmp"
|
||||
}
|
||||
'';
|
||||
in
|
||||
{
|
||||
programs.zsh.enable = true;
|
||||
|
||||
programs.yazi = {
|
||||
enable = true;
|
||||
enableBashIntegration = true;
|
||||
enableZshIntegration = true;
|
||||
};
|
||||
|
||||
nmt.script = ''
|
||||
assertFileContains home-files/.zshrc '${shellIntegration}'
|
||||
assertFileExists home-files/.zshrc
|
||||
assertFileContains home-files/.zshrc 'function yy() {'
|
||||
assertFileContains home-files/.zshrc 'local tmp="$(mktemp -t "yazi-cwd.XXXXX")"'
|
||||
assertFileContains home-files/.zshrc 'yazi "$@" --cwd-file="$tmp"'
|
||||
assertFileContains home-files/.zshrc 'if cwd="$(<"$tmp")" && [ -n "$cwd" ] && [ "$cwd" != "$PWD" ]; then'
|
||||
assertFileContains home-files/.zshrc 'builtin cd -- "$cwd"'
|
||||
assertFileContains home-files/.zshrc 'rm -f -- "$tmp"'
|
||||
'';
|
||||
}
|
||||
|
|
|
|||
83
tests/modules/programs/zed-editor/debug-empty.nix
Normal file
83
tests/modules/programs/zed-editor/debug-empty.nix
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
{
|
||||
programs.zed-editor = {
|
||||
enable = true;
|
||||
package = config.lib.test.mkStubPackage { };
|
||||
userDebug = [
|
||||
{
|
||||
label = "PHP: Listen to Xdebug";
|
||||
adapter = "Xdebug";
|
||||
request = "launch";
|
||||
port = 9003;
|
||||
}
|
||||
{
|
||||
label = "PHP: Debug this test";
|
||||
adapter = "Xdebug";
|
||||
request = "launch";
|
||||
program = "vendor/bin/phpunit";
|
||||
args = [
|
||||
"--filter"
|
||||
"$ZED_SYMBOL"
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
home.homeDirectory = lib.mkForce "/@TMPDIR@/hm-user";
|
||||
|
||||
nmt.script =
|
||||
let
|
||||
preexistingDebug = builtins.toFile "preexisting.json" "";
|
||||
|
||||
expectedContent = builtins.toFile "expected.json" ''
|
||||
[
|
||||
{
|
||||
"adapter": "Xdebug",
|
||||
"args": [
|
||||
"--filter",
|
||||
"$ZED_SYMBOL"
|
||||
],
|
||||
"label": "PHP: Debug this test",
|
||||
"program": "vendor/bin/phpunit",
|
||||
"request": "launch"
|
||||
},
|
||||
{
|
||||
"adapter": "Xdebug",
|
||||
"label": "PHP: Listen to Xdebug",
|
||||
"port": 9003,
|
||||
"request": "launch"
|
||||
}
|
||||
]
|
||||
'';
|
||||
|
||||
debugPath = ".config/zed/debug.json";
|
||||
activationScript = pkgs.writeScript "activation" config.home.activation.zedDebugActivation.data;
|
||||
in
|
||||
''
|
||||
export HOME=$TMPDIR/hm-user
|
||||
|
||||
# Simulate preexisting debug
|
||||
mkdir -p $HOME/.config/zed
|
||||
cat ${preexistingDebug} > $HOME/${debugPath}
|
||||
|
||||
# Run the activation script
|
||||
substitute ${activationScript} $TMPDIR/activate --subst-var TMPDIR
|
||||
chmod +x $TMPDIR/activate
|
||||
$TMPDIR/activate
|
||||
|
||||
# Validate the merged debug
|
||||
assertFileExists "$HOME/${debugPath}"
|
||||
assertFileContent "$HOME/${debugPath}" "${expectedContent}"
|
||||
|
||||
# Test idempotency
|
||||
$TMPDIR/activate
|
||||
assertFileExists "$HOME/${debugPath}"
|
||||
assertFileContent "$HOME/${debugPath}" "${expectedContent}"
|
||||
'';
|
||||
}
|
||||
58
tests/modules/programs/zed-editor/debug-immutable.nix
Normal file
58
tests/modules/programs/zed-editor/debug-immutable.nix
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
# Test custom keymap functionality
|
||||
{ config, ... }:
|
||||
|
||||
{
|
||||
programs.zed-editor = {
|
||||
enable = true;
|
||||
package = config.lib.test.mkStubPackage { };
|
||||
mutableUserDebug = false;
|
||||
userDebug = [
|
||||
{
|
||||
label = "PHP: Listen to Xdebug";
|
||||
adapter = "Xdebug";
|
||||
request = "launch";
|
||||
port = 9003;
|
||||
}
|
||||
{
|
||||
label = "PHP: Debug this test";
|
||||
adapter = "Xdebug";
|
||||
request = "launch";
|
||||
program = "vendor/bin/phpunit";
|
||||
args = [
|
||||
"--filter"
|
||||
"$ZED_SYMBOL"
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
nmt.script =
|
||||
let
|
||||
expectedContent = builtins.toFile "expected.json" ''
|
||||
[
|
||||
{
|
||||
"adapter": "Xdebug",
|
||||
"label": "PHP: Listen to Xdebug",
|
||||
"port": 9003,
|
||||
"request": "launch"
|
||||
},
|
||||
{
|
||||
"adapter": "Xdebug",
|
||||
"args": [
|
||||
"--filter",
|
||||
"$ZED_SYMBOL"
|
||||
],
|
||||
"label": "PHP: Debug this test",
|
||||
"program": "vendor/bin/phpunit",
|
||||
"request": "launch"
|
||||
}
|
||||
]
|
||||
'';
|
||||
|
||||
settingsPath = ".config/zed/debug.json";
|
||||
in
|
||||
''
|
||||
assertFileExists "home-files/${settingsPath}"
|
||||
assertFileContent "home-files/${settingsPath}" "${expectedContent}"
|
||||
'';
|
||||
}
|
||||
100
tests/modules/programs/zed-editor/debug.nix
Normal file
100
tests/modules/programs/zed-editor/debug.nix
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
|
||||
{
|
||||
programs.zed-editor = {
|
||||
enable = true;
|
||||
package = config.lib.test.mkStubPackage { };
|
||||
userDebug = [
|
||||
{
|
||||
label = "PHP: Listen to Xdebug";
|
||||
adapter = "Xdebug";
|
||||
request = "launch";
|
||||
port = 9003;
|
||||
}
|
||||
{
|
||||
label = "PHP: Debug this test";
|
||||
adapter = "Xdebug";
|
||||
request = "launch";
|
||||
program = "vendor/bin/phpunit";
|
||||
args = [
|
||||
"--filter"
|
||||
"$ZED_SYMBOL"
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
home.homeDirectory = lib.mkForce "/@TMPDIR@/hm-user";
|
||||
|
||||
nmt.script =
|
||||
let
|
||||
preexistingDebug = builtins.toFile "preexisting.json" ''
|
||||
[
|
||||
{
|
||||
"label": "Debug active Python file",
|
||||
"adapter": "Debugpy",
|
||||
"program": "$ZED_FILE",
|
||||
"request": "launch",
|
||||
"cwd": "$ZED_WORKTREE_ROOT"
|
||||
}
|
||||
]
|
||||
'';
|
||||
|
||||
expectedContent = builtins.toFile "expected.json" ''
|
||||
[
|
||||
{
|
||||
"label": "Debug active Python file",
|
||||
"adapter": "Debugpy",
|
||||
"program": "$ZED_FILE",
|
||||
"request": "launch",
|
||||
"cwd": "$ZED_WORKTREE_ROOT"
|
||||
},
|
||||
{
|
||||
"adapter": "Xdebug",
|
||||
"args": [
|
||||
"--filter",
|
||||
"$ZED_SYMBOL"
|
||||
],
|
||||
"label": "PHP: Debug this test",
|
||||
"program": "vendor/bin/phpunit",
|
||||
"request": "launch"
|
||||
},
|
||||
{
|
||||
"adapter": "Xdebug",
|
||||
"label": "PHP: Listen to Xdebug",
|
||||
"port": 9003,
|
||||
"request": "launch"
|
||||
}
|
||||
]
|
||||
'';
|
||||
|
||||
debugPath = ".config/zed/debug.json";
|
||||
activationScript = pkgs.writeScript "activation" config.home.activation.zedDebugActivation.data;
|
||||
in
|
||||
''
|
||||
export HOME=$TMPDIR/hm-user
|
||||
|
||||
# Simulate preexisting debug
|
||||
mkdir -p $HOME/.config/zed
|
||||
cat ${preexistingDebug} > $HOME/${debugPath}
|
||||
|
||||
# Run the activation script
|
||||
substitute ${activationScript} $TMPDIR/activate --subst-var TMPDIR
|
||||
chmod +x $TMPDIR/activate
|
||||
$TMPDIR/activate
|
||||
|
||||
# Validate the merged debug
|
||||
assertFileExists "$HOME/${debugPath}"
|
||||
assertFileContent "$HOME/${debugPath}" "${expectedContent}"
|
||||
|
||||
# Test idempotency
|
||||
$TMPDIR/activate
|
||||
assertFileExists "$HOME/${debugPath}"
|
||||
assertFileContent "$HOME/${debugPath}" "${expectedContent}"
|
||||
'';
|
||||
}
|
||||
|
|
@ -11,5 +11,8 @@
|
|||
zed-tasks = ./tasks.nix;
|
||||
zed-tasks-immutable = ./tasks-immutable.nix;
|
||||
zed-tasks-empty = ./tasks-empty.nix;
|
||||
zed-debug = ./debug.nix;
|
||||
zed-debug-immutable = ./debug-immutable.nix;
|
||||
zed-debug-empty = ./debug-empty.nix;
|
||||
zed-themes = ./themes;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue