Output path interpolation in file sources?

I’m finally getting around to instituting home-manager on my system, and it’s pretty great so far.

I am now looking at using it to manage my dotfiles. The home.file.<filename> option is intriguing: I can either use text to supply the content of each dotfile inline, or I can use source to point to a file on disk that I want to use. I prefer to use source so that I am able to edit files in their natural habitat (rather than inside quotation marks within a .nix file). However, if I do that, I am not able to embed derivations within the text. That is:

home.file."foobar".text = ''
  ${pkgs.hello}
'';

will place a file foobar in my home directory with the Nix store path of the hello package, while

home.file."foobar".source = ./dotfiles/foobar;

with the file dotfiles/foobar having the content of the text attribute above will place a file in my home directory with the literal contents of that file (i.e., no “expansion” to the Nix store path).

This makes sense, but is there some way to get the best of both worlds–use the source attribute, while also getting output path expansion therein?

roni

One way to do it might be to use the function substituteAll from nixpkgs:

home.file."foobar".source = pkgs.substituteAll {
  name = "config.ini";
  src = ./config.ini;
  hello = "${pkgs.hello}"
};

And then use the syntax "@hello@" in ./config.ini and it will get replaced.

(totally untested)

4 Likes

@rmcgibbo, I’m sorry I never got back to you, but thank you for the idea. I think this would work (though it’s not ideal).

I am bumping this thread after so long because I wanted to see if there have been any developments since I asked my question. Any new ways to do string interpolation for string data read in from a file?

It may help to know what kinds of files they are, but the short answer is that substitution without modifying the variables in the file will take some kind of tool that can parse the file format and understand what to even replace.

If they are shell scripts, GitHub - abathur/resholve: a shell resolver? :) (find and resolve shell script dependencies) is the closest thing to what you are asking for. You can read a little about different approaches to handling shell with Nix in no-look, no-leap Shell script dependencies.

If it’s something other than shell, you can use the other substitute functions mentioned in the nixpkgs manual (or sed, or awk), or may need a tool like resholve for that given format.

1 Like

Not sure if it matches your style, but I have been working to get language syntax injections in Helix into a nice state. Technically this is not a feature unique to Helix, but any editor that supports tree-sitter should be able to do this.

However, Helix doesn’t used upstream queries but defines it’s own in repo, so other editors might not have quite as nice an experience. Here is a screen of what I’m talking about:

It isn’t perfect, for example, it would be nice if I could start a seperate LSP for the injected language. There is a PR to start work toward that though. It isn’t perfect but it sure makes reading the code inside these strings a lot easier.

Some of the features in this screenshot are not yet merged ¹ ²

But I have a fork with some useful PRs and all this stuff merged into it, if that helps.

1 Like

This is really neat! I am very old school and use vim, where this kind of thing is probably possible, but beyond my reach. (Well, I’m not old school enough, I suppose, because really I use neovim. Perhaps I should become post-old school and try Helix!)

I tried this out and I think it’s the best available solution. I can still edit the “source” with full syntax highlighting support, etc., and I can fill in the variables exactly as you’ve shown here. Thanks!