From 2eca6dd48cc2b4cb879fcecc5fc06fc0cd38c26a Mon Sep 17 00:00:00 2001 From: blindfs Date: Wed, 26 Nov 2025 11:13:16 +0800 Subject: [PATCH 1/4] fix(nix): persist config files against nix-collect-garbage --- package.nix | 117 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 71 insertions(+), 46 deletions(-) diff --git a/package.nix b/package.nix index b1ca258..780ac72 100644 --- a/package.nix +++ b/package.nix @@ -1,6 +1,7 @@ { stdenv, lib, + pkgs, writeShellApplication, tree-sitter-nu ? fetchGit "https://github.com/nushell/tree-sitter-nu", topiary, @@ -8,52 +9,76 @@ writeText, callPackage, }: -writeShellApplication (let - libtree-sitter-nu = callPackage ({ - lib, - stdenv, - }: - stdenv.mkDerivation (finalAttrs: { - pname = "tree-sitter-nu"; - version = tree-sitter-nu.rev; - - src = tree-sitter-nu; - - makeFlags = [ - # The PREFIX var isn't picking up from stdenv. - "PREFIX=$(out)" - ]; - - meta = with lib; { - description = "A tree-sitter grammar for nu-lang, the language of nushell"; - homepage = "https://github.com/nushell/tree-sitter-nu"; - license = licenses.mit; - }; - })) {}; -in { - name = "topiary-nushell"; - runtimeInputs = [nushell topiary]; - runtimeEnv = let - extension = with stdenv; - if isLinux - then ".so" - else if isDarwin - then ".dylib" - else throw "Unsupported system: ${system}"; - in { - TOPIARY_CONFIG_FILE = writeText "languages.ncl" '' +writeShellApplication ( + let + libtree-sitter-nu = callPackage ( { - languages = { - nu = { - extensions = ["nu"], - grammar.source.path = "${libtree-sitter-nu}/lib/libtree-sitter-nu${extension}", + lib, + stdenv, + }: + stdenv.mkDerivation (finalAttrs: { + pname = "tree-sitter-nu"; + version = tree-sitter-nu.rev; + + src = tree-sitter-nu; + + makeFlags = [ + # The PREFIX var isn't picking up from stdenv. + "PREFIX=$(out)" + ]; + + meta = with lib; { + description = "A tree-sitter grammar for nu-lang, the language of nushell"; + homepage = "https://github.com/nushell/tree-sitter-nu"; + license = licenses.mit; + }; + }) + ) { }; + + extension = + with stdenv; + if isLinux then + ".so" + else if isDarwin then + ".dylib" + else + throw "Unsupported system: ${system}"; + + # Create a directory holding ALL runtime config files + # This makes a single path for GC root. + topiaryConfigDir = pkgs.runCommand "topiary-nushell-config" { } '' + local_config_dir="$out" + + mkdir -p $local_config_dir/languages + + # 1. Copy the nu.scm language directory + cp -r ${./languages/nu.scm} $local_config_dir/languages/nu.scm + + # 2. Write the languages.ncl file, referencing the compiled grammar + cat ${writeText "languages.ncl" '' + { + languages = { + nu = { + extensions = ["nu"], + grammar.source.path = "${libtree-sitter-nu}/lib/libtree-sitter-nu${extension}", + }, }, - }, - } + } + ''} > $local_config_dir/languages.ncl + ''; + in + { + name = "topiary-nushell"; + runtimeInputs = [ + nushell + topiary + ]; + runtimeEnv = { + TOPIARY_CONFIG_FILE = "${topiaryConfigDir}/languages.ncl"; + TOPIARY_LANGUAGE_DIR = "${topiaryConfigDir}/languages"; + }; + text = '' + ${lib.getExe topiary} "$@" ''; - TOPIARY_LANGUAGE_DIR = ./languages; - }; - text = '' - ${lib.getExe topiary} "$@" - ''; -}) + } +) From efe9d54770eff355ce5a4968cbce35f74f90c394 Mon Sep 17 00:00:00 2001 From: blindfs Date: Wed, 26 Nov 2025 11:27:20 +0800 Subject: [PATCH 2/4] cleanup --- package.nix | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/package.nix b/package.nix index 780ac72..ed2441a 100644 --- a/package.nix +++ b/package.nix @@ -49,22 +49,20 @@ writeShellApplication ( topiaryConfigDir = pkgs.runCommand "topiary-nushell-config" { } '' local_config_dir="$out" - mkdir -p $local_config_dir/languages - # 1. Copy the nu.scm language directory - cp -r ${./languages/nu.scm} $local_config_dir/languages/nu.scm + mkdir -p $local_config_dir/languages + cp ${./languages/nu.scm} $local_config_dir/languages/nu.scm - # 2. Write the languages.ncl file, referencing the compiled grammar - cat ${writeText "languages.ncl" '' - { - languages = { - nu = { - extensions = ["nu"], - grammar.source.path = "${libtree-sitter-nu}/lib/libtree-sitter-nu${extension}", - }, + cat > $local_config_dir/languages.ncl < $local_config_dir/languages.ncl + }, + } + EOF ''; in { From 3e18c8ef7ab9fec92630cfeef3474b88db849409 Mon Sep 17 00:00:00 2001 From: blindfs Date: Wed, 26 Nov 2025 11:38:21 +0800 Subject: [PATCH 3/4] arg --- package.nix | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/package.nix b/package.nix index ed2441a..a88719e 100644 --- a/package.nix +++ b/package.nix @@ -1,12 +1,11 @@ { stdenv, lib, - pkgs, + runCommand, writeShellApplication, tree-sitter-nu ? fetchGit "https://github.com/nushell/tree-sitter-nu", topiary, nushell, - writeText, callPackage, }: writeShellApplication ( @@ -46,7 +45,7 @@ writeShellApplication ( # Create a directory holding ALL runtime config files # This makes a single path for GC root. - topiaryConfigDir = pkgs.runCommand "topiary-nushell-config" { } '' + topiaryConfigDir = runCommand "topiary-nushell-config" { } '' local_config_dir="$out" # 1. Copy the nu.scm language directory From 75e819fec6a62e58a08c1c2681324d4c88edafe6 Mon Sep 17 00:00:00 2001 From: blindfs Date: Wed, 26 Nov 2025 12:02:04 +0800 Subject: [PATCH 4/4] refactor: use symlinkJoin instead of runCommand ----------------- Co-authored-by: Notarin <424c414e4b@gmail.com> --- package.nix | 133 ++++++++++++++++++++++++++-------------------------- 1 file changed, 67 insertions(+), 66 deletions(-) diff --git a/package.nix b/package.nix index a88719e..9fa9cfa 100644 --- a/package.nix +++ b/package.nix @@ -1,81 +1,82 @@ { stdenv, lib, - runCommand, writeShellApplication, tree-sitter-nu ? fetchGit "https://github.com/nushell/tree-sitter-nu", topiary, nushell, + writeText, callPackage, + symlinkJoin, }: -writeShellApplication ( - let - libtree-sitter-nu = callPackage ( - { - lib, - stdenv, - }: - stdenv.mkDerivation (finalAttrs: { - pname = "tree-sitter-nu"; - version = tree-sitter-nu.rev; - - src = tree-sitter-nu; - - makeFlags = [ - # The PREFIX var isn't picking up from stdenv. - "PREFIX=$(out)" - ]; +symlinkJoin { + name = "topiary-nushell"; + paths = [ + (writeShellApplication ( + let + libtree-sitter-nu = callPackage ( + { + lib, + stdenv, + }: + stdenv.mkDerivation (finalAttrs: { + pname = "tree-sitter-nu"; + version = tree-sitter-nu.rev; - meta = with lib; { - description = "A tree-sitter grammar for nu-lang, the language of nushell"; - homepage = "https://github.com/nushell/tree-sitter-nu"; - license = licenses.mit; - }; - }) - ) { }; - - extension = - with stdenv; - if isLinux then - ".so" - else if isDarwin then - ".dylib" - else - throw "Unsupported system: ${system}"; + src = tree-sitter-nu; - # Create a directory holding ALL runtime config files - # This makes a single path for GC root. - topiaryConfigDir = runCommand "topiary-nushell-config" { } '' - local_config_dir="$out" + makeFlags = [ + # The PREFIX var isn't picking up from stdenv. + "PREFIX=$(out)" + ]; - # 1. Copy the nu.scm language directory - mkdir -p $local_config_dir/languages - cp ${./languages/nu.scm} $local_config_dir/languages/nu.scm + meta = with lib; { + description = "A tree-sitter grammar for nu-lang, the language of nushell"; + homepage = "https://github.com/nushell/tree-sitter-nu"; + license = licenses.mit; + }; + }) + ) { }; - cat > $local_config_dir/languages.ncl <