You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 15:50:31