如何在flake.nix中执行外部命令并转换为Nix值?
在Flake.nix中执行外部命令解析文件为Nix列表值
需求背景
你已有一段Perl脚本,可从init.el中提取不带:nodep标记的use-package包名,输出每行一个包名。现在需要在flake.nix的programs.emacs.extraPackages中调用该脚本,将输出转为Nix列表,自动生成Emacs额外包配置。
实现方案
Nix提供builtins.readCommand函数,用于在求值阶段执行外部命令并捕获输出。结合字符串分割与过滤,可将命令输出转为可用的Nix列表,再映射为Emacs ELPA包。
完整配置示例
programs.emacs = { enable = true; extraConfig = builtins.readFile ./init.el; extraPackages = elpa: let # 调用Perl脚本提取包名,处理输出为非空列表 packageNames = builtins.filter (s: s != "") (builtins.split "\n" ( builtins.readCommand "perl" [ "-007" "-nE" 'say for m{[(]use-package \s* ([a-z-0-9]+) \s* (?!:nodep)}xsgm' ./init.el ] )); in # 将每个包名映射为ELPA仓库中的对应包 map (name: elpa.${name}) packageNames; };
优化说明(可选)
若要避免依赖系统环境中的Perl,改用Nixpkgs提供的Perl包,可调整为以下代码:
programs.emacs = { enable = true; extraConfig = builtins.readFile ./init.el; extraPackages = elpa: let pkgs = import <nixpkgs> { system = builtins.currentSystem; }; # 使用Nixpkgs中的Perl路径 perlPath = pkgs.perl + "/bin/perl"; packageNames = builtins.filter (s: s != "") (builtins.split "\n" ( builtins.readCommand perlPath [ "-007" "-nE" 'say for m{[(]use-package \s* ([a-z-0-9]+) \s* (?!:nodep)}xsgm' ./init.el ] )); in map (name: elpa.${name}) packageNames; };
关键细节
builtins.readCommand <命令路径> <参数数组>:执行外部命令并返回输出字符串builtins.split "\n":将输出按换行分割为列表builtins.filter (s: s != ""):过滤列表中的空字符串(避免命令末尾空行导致的无效元素)map (name: elpa.${name}):将包名字符串转为ELPA包的引用,符合extraPackages的函数要求
内容的提问来源于stack exchange,提问作者andreoss
相关产品推荐
相关产品推荐

