From 0a5a165aca45dd9c9a8a87b123f1790681f6a3cb Mon Sep 17 00:00:00 2001 From: Ryan Horiguchi Date: Fri, 12 Sep 2025 14:39:03 +0200 Subject: [PATCH 1/3] superfile: add pinnded folder and first use option --- modules/programs/superfile.nix | 100 +++++++++++++++--- .../superfile/example-pinned-folders.json | 6 ++ .../programs/superfile/example-settings.nix | 16 +++ 3 files changed, 110 insertions(+), 12 deletions(-) create mode 100644 tests/modules/programs/superfile/example-pinned-folders.json diff --git a/modules/programs/superfile.nix b/modules/programs/superfile.nix index 4e7765c68..3eb21cfb3 100644 --- a/modules/programs/superfile.nix +++ b/modules/programs/superfile.nix @@ -7,7 +7,10 @@ let cfg = config.programs.superfile; + tomlFormat = pkgs.formats.toml { }; + jsonFormat = pkgs.formats.json { }; + inherit (pkgs.stdenv.hostPlatform) isDarwin; inherit (lib) literalExpression @@ -23,6 +26,29 @@ let types hm ; + + pinnedFolderModule = types.submodule { + freeformType = jsonFormat.type; + + options = { + name = mkOption { + type = types.nullOr types.str; + default = null; + example = "Nix Store"; + description = '' + Name that will be shown. + ''; + }; + + location = mkOption { + type = types.path; + example = "/nix/store"; + description = '' + Location of the pinned entry. + ''; + }; + }; + }; in { meta.maintainers = [ hm.maintainers.LucasWagler ]; @@ -106,11 +132,38 @@ in }; ''; }; + + firstUseCheck = mkOption { + type = types.bool; + default = true; + description = '' + Enables the first time use popup. + ''; + }; + + pinnedFolders = mkOption { + type = types.listOf pinnedFolderModule; + default = [ ]; + example = literalExpression '' + [ + { + name = "Nix Store"; + location = "/nix/store"; + } + ]; + ''; + description = '' + Entries that get added to the pinned panel. + ''; + }; }; config = let enableXdgConfig = !isDarwin || config.xdg.enable; + baseConfigPath = if enableXdgConfig then "superfile" else "Library/Application Support/superfile"; + baseDataPath = if enableXdgConfig then "superfile" else "Library/Application Support/superfile"; + themeSetting = if (!(cfg.settings ? theme) && cfg.themes != { }) then { @@ -118,7 +171,6 @@ in } else { }; - baseConfigPath = if enableXdgConfig then "superfile" else "Library/Application Support/superfile"; configFile = mkIf (cfg.settings != { }) { "${baseConfigPath}/config.toml".source = tomlFormat.generate "superfile-config.toml" ( recursiveUpdate themeSetting cfg.settings @@ -139,24 +191,48 @@ in (tomlFormat.generate "superfile-theme-${name}.toml" value); } ) cfg.themes; + + firstUseCheckFile = mkIf (!cfg.firstUseCheck) { "${baseDataPath}/firstUseCheck".text = ""; }; + pinnedFile = mkIf (cfg.pinnedFolders != [ ]) { + "${baseDataPath}/pinned.json".source = jsonFormat.generate "pinned.json" cfg.pinnedFolders; + }; + + files = mkMerge [ + configFile + hotkeysFile + themeFiles + + firstUseCheckFile + pinnedFile + ]; configFiles = mkMerge [ configFile hotkeysFile themeFiles ]; + dataFiles = mkMerge [ + firstUseCheckFile + pinnedFile + ]; in mkIf cfg.enable { - home.packages = mkIf (cfg.package != null) ( - [ cfg.package ] - ++ optional ( - cfg.metadataPackage != null && cfg.settings ? metadata && cfg.settings.metadata - ) cfg.metadataPackage - ++ optional ( - cfg.zoxidePackage != null && cfg.settings ? zoxide_support && cfg.settings.zoxide_support - ) cfg.zoxidePackage - ); + home = { + packages = mkIf (cfg.package != null) ( + [ cfg.package ] + ++ optional ( + cfg.metadataPackage != null && cfg.settings ? metadata && cfg.settings.metadata + ) cfg.metadataPackage + ++ optional ( + cfg.zoxidePackage != null && cfg.settings ? zoxide_support && cfg.settings.zoxide_support + ) cfg.zoxidePackage + ); - xdg.configFile = mkIf enableXdgConfig configFiles; - home.file = mkIf (!enableXdgConfig) configFiles; + file = mkIf (!enableXdgConfig) files; + }; + + xdg = { + configFile = mkIf enableXdgConfig configFiles; + dataFile = mkIf enableXdgConfig dataFiles; + }; }; } diff --git a/tests/modules/programs/superfile/example-pinned-folders.json b/tests/modules/programs/superfile/example-pinned-folders.json new file mode 100644 index 000000000..e7ec94643 --- /dev/null +++ b/tests/modules/programs/superfile/example-pinned-folders.json @@ -0,0 +1,6 @@ +[ + { + "location": "/nix/store", + "name": "Nix Store" + } +] diff --git a/tests/modules/programs/superfile/example-settings.nix b/tests/modules/programs/superfile/example-settings.nix index 8f682b4d2..5b2c96831 100644 --- a/tests/modules/programs/superfile/example-settings.nix +++ b/tests/modules/programs/superfile/example-settings.nix @@ -53,6 +53,13 @@ ]; }; }; + firstUseCheck = false; + pinnedFolders = [ + { + name = "Nix Store"; + location = "/nix/store"; + } + ]; }; nmt.script = @@ -60,6 +67,10 @@ configSubPath = if !pkgs.stdenv.isDarwin then ".config/superfile" else "Library/Application Support/superfile"; configBasePath = "home-files/" + configSubPath; + + dataSubPath = + if !pkgs.stdenv.isDarwin then ".local/share/superfile" else "Library/Application Support/superfile"; + dataBasePath = "home-files/" + dataSubPath; in '' assertFileExists "${configBasePath}/config.toml" @@ -82,5 +93,10 @@ assertFileContent \ "${configBasePath}/theme/test2.toml" \ ${./example-theme2-expected.toml} + assertFileExists "${dataBasePath}/firstUseCheck" + assertFileExists "${dataBasePath}/pinned.json" + assertFileContent \ + "${dataBasePath}/pinned.json" \ + ${./example-pinned-folders.json} ''; } From 1c75dd70229171f47ff10f4ed184101af7c7a392 Mon Sep 17 00:00:00 2001 From: heyzec <61238538+heyzec@users.noreply.github.com> Date: Tue, 4 Nov 2025 23:52:10 +0800 Subject: [PATCH 2/3] vscode: don't break when profile name has spaces --- modules/programs/vscode/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/programs/vscode/default.nix b/modules/programs/vscode/default.nix index 5c89da6e5..fb3064beb 100644 --- a/modules/programs/vscode/default.nix +++ b/modules/programs/vscode/default.nix @@ -459,7 +459,7 @@ in existing_profiles=$(jq '.userDataProfiles // [] | map({ (.name): .location }) | add // {}' "$file") for profile in "''${profiles[@]}"; do - if [[ "$(echo $existing_profiles | jq --arg profile $profile 'has ($profile)')" != "true" ]] || [[ "$(echo $existing_profiles | jq --arg profile $profile 'has ($profile)')" == "true" && "$(echo $existing_profiles | jq --arg profile $profile '.[$profile]')" != "\"$profile\"" ]]; then + if [[ "$(echo $existing_profiles | jq --arg profile "$profile" 'has ($profile)')" != "true" ]] || [[ "$(echo $existing_profiles | jq --arg profile "$profile" 'has ($profile)')" == "true" && "$(echo $existing_profiles | jq --arg profile "$profile" '.[$profile]')" != "\"$profile\"" ]]; then file_write="$file_write$([ "$file_write" != "" ] && echo "...")$profile" fi done From 34fe48801d2a5301b814eaa1efb496499d06cebc Mon Sep 17 00:00:00 2001 From: Martijn Boers Date: Mon, 3 Nov 2025 21:33:55 +0100 Subject: [PATCH 3/3] ghostty: Add systemd integration The systemd unit already exists on the system, this gives the option to enable it. --- .../misc/news/2025/11/2025-11-03_22-56-50.nix | 14 ++++++++ modules/programs/ghostty.nix | 34 +++++++++++++++++++ .../programs/ghostty/empty-settings.nix | 6 +++- .../programs/ghostty/example-settings.nix | 2 +- .../programs/ghostty/example-theme.nix | 2 ++ 5 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 modules/misc/news/2025/11/2025-11-03_22-56-50.nix diff --git a/modules/misc/news/2025/11/2025-11-03_22-56-50.nix b/modules/misc/news/2025/11/2025-11-03_22-56-50.nix new file mode 100644 index 000000000..d78de2292 --- /dev/null +++ b/modules/misc/news/2025/11/2025-11-03_22-56-50.nix @@ -0,0 +1,14 @@ +{ config, pkgs, ... }: +{ + time = "2025-11-03T21:56:50+00:00"; + condition = config.programs.ghostty.enable && pkgs.stdenv.hostPlatform.isLinux; + message = '' + Ghostty: now enables the user systemd service by default. + + Running Ghostty via these systemd units is the recommended way to run + Ghostty. The two most important benefits provided by Ghostty's systemd + integrations are: instantaneous launching and centralized logging. + + See https://ghostty.org/docs/linux/systemd for all details + ''; +} diff --git a/modules/programs/ghostty.nix b/modules/programs/ghostty.nix index 43f3d99fe..38cfadf1a 100644 --- a/modules/programs/ghostty.nix +++ b/modules/programs/ghostty.nix @@ -114,6 +114,24 @@ in defaultText = lib.literalMD "`true` if programs.ghostty.package is not null"; }; + systemd = lib.mkOption { + type = lib.types.submodule { + options = { + enable = lib.mkEnableOption "the Ghostty systemd user service" // { + default = pkgs.stdenv.hostPlatform.isLinux; + defaultText = lib.literalMD "`true` on Linux, `false` otherwise"; + }; + }; + }; + default = { }; + description = '' + Configuration for Ghostty's systemd integration. + This enables additional speed and features. + + See for more information. + ''; + }; + enableBashIntegration = mkShellIntegrationOption ( lib.hm.shell.mkBashIntegrationOption { inherit config; } ); @@ -195,6 +213,22 @@ in }; }) + (lib.mkIf cfg.systemd.enable { + assertions = [ + { + assertion = cfg.systemd.enable -> cfg.package != null; + message = "programs.ghostty.systemd.enable cannot be true when programs.ghostty.package is null"; + } + { + assertion = cfg.systemd.enable -> pkgs.stdenv.hostPlatform.isLinux; + message = "Ghostty systemd integration cannot be enabled for non-linux platforms"; + } + ]; + xdg.configFile."systemd/user/app-com.mitchellh.ghostty.service".source = + "${cfg.package}/share/systemd/user/app-com.mitchellh.ghostty.service"; + dbus.packages = [ cfg.package ]; + }) + (lib.mkIf cfg.enableBashIntegration { # Make order 101 to be placed exactly after bash completions, as Ghostty # documentation suggests sourcing the script as soon as possible diff --git a/tests/modules/programs/ghostty/empty-settings.nix b/tests/modules/programs/ghostty/empty-settings.nix index 1ea025eb5..d74972a4a 100644 --- a/tests/modules/programs/ghostty/empty-settings.nix +++ b/tests/modules/programs/ghostty/empty-settings.nix @@ -1,5 +1,9 @@ +{ config, ... }: { - programs.ghostty.enable = true; + programs.ghostty = { + enable = true; + package = config.lib.test.mkStubPackage { outPath = null; }; + }; nmt.script = '' assertPathNotExists home-files/.config/ghostty/config diff --git a/tests/modules/programs/ghostty/example-settings.nix b/tests/modules/programs/ghostty/example-settings.nix index 18b64b4fe..b45094d2f 100644 --- a/tests/modules/programs/ghostty/example-settings.nix +++ b/tests/modules/programs/ghostty/example-settings.nix @@ -2,7 +2,7 @@ { programs.ghostty = { enable = true; - package = config.lib.test.mkStubPackage { }; + package = config.lib.test.mkStubPackage { outPath = null; }; settings = { theme = "catppuccin-mocha"; diff --git a/tests/modules/programs/ghostty/example-theme.nix b/tests/modules/programs/ghostty/example-theme.nix index 29f40a897..320b073a1 100644 --- a/tests/modules/programs/ghostty/example-theme.nix +++ b/tests/modules/programs/ghostty/example-theme.nix @@ -1,6 +1,8 @@ +{ config, ... }: { programs.ghostty = { enable = true; + package = config.lib.test.mkStubPackage { outPath = null; }; themes = { catppuccin-mocha = {