Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Help Configuring NixVim Config Files Path #2477

Open
RicSanOP opened this issue Nov 2, 2024 · 9 comments
Open

Help Configuring NixVim Config Files Path #2477

RicSanOP opened this issue Nov 2, 2024 · 9 comments

Comments

@RicSanOP
Copy link

RicSanOP commented Nov 2, 2024

I want to run multiple styles of neovim configuration simultaneously on my systems. With NixVim, all config files are by default simlinked into the ~/.config/nvim directory (as a side note I am using the home-manager nixvim module). I want to be able to redefine where the nixvim generated config files are placed. After some digging into the nixvim codebase I see 2 potential places where the config filepath could be configured:

  1. this one is probably wrong but worth mentioning. nixvim has a path top-level option which I can't seem to exactly understand is used how.

  2. looking at https://github.com/nix-community/nixvim/blob/main/wrappers/_shared.nix which is imported into each nixvim module wrapper (home-manager, nixos, darwin and standalone), I see a filesPrefix argument which is never really set but seems to solve the issue (it is set to nvim/ by default). However I don't see how I can set this variable myself.

Assuming the second option is the correct path to configuring where nixvim, could anyone suggest how I can easily set the variable? If the task requires building another complex wrapper or some internal mods to this codebase, I would be happy to work on a pull request if given a bit of guidance (I would say my nix level is intermediate as I have some experience now reading through nix codebases). This could also lead to further improvements of nixvim whereby one could create multiple configs that could be switched using the recent NVIM_APPNAME env variable. This could eventually lead to something like https://lazyman.dev (or an integration with it) which could help people explore neovim through multiple configs and distros.

Any help on this matter is very much appreciated.

@MattSturgeon
Copy link
Member

We could (and probably should) add an option to allow configuring the files prefix, however you'll only be able to create one nixvim configuration if you're using a wrapper module to configure nixvim.

Maybe we should consider having a way to have multiple nixvim's configured per module eval... Perhaps we could setup something similar to our files option and have an attrset of name -> nixvimConfiguration.

All that said, this exact scenario is really what the "standalone" nixvim is intended to solve; although even that has some limitations.

The standalone build will not install the config files anywhere (other than the nix store, of course), and will instead tell the nvim wrapper script to use the -u flag with the init file when running neovim.

The main limitation for standalone builds is that we don't currently offer a sensible way to configure the nvim exe's name, meaning if you install multiple standalone nixvim they will conflict.

It would be possible to do something like this though, but we should probably consider better ways to solve all of these scenarios with new nixvim options.

.overrideAttrs {
  postInstall = ''
    mv $out/bin/nvim $out/bin/custom-nvim
  '';
}

@GaetanLepage
Copy link
Member

Also, we have the wrapRc option that prevents the config file to end up in ~/.config. Not sure if this will work for your use case.

@RicSanOP
Copy link
Author

RicSanOP commented Nov 2, 2024

@MattSturgeon @GaetanLepage thank you for your responses. Yes, overall I think it would be great for nixvim itself to have the ability to define multiple profiles and perhaps even manage multiple nvim installs.

In the most basic case, I just want to move the configs to another directory. Would it be possible to use an overrideAttr on the home manager module to move the config files from config/nvim to config/othername (similar to @MattSturgeon postInstall example)? If so, please advise where would a good place (in the flake or in home.nix) to define the override.

In the meantime I'm interested in helping define the option that would set the filePrefix wrapping on the wrapper scripts. Would appreciate if anyone can give some guidance on where to define the option appropriately and how to correctly pass it through the nix modules into the wrapper directory.

As for the bigger idea on letting nixvim create entire profiles, I would be interested in exploring further but it is not my personal priority as the other configs I want to run would be defined more standard neovim style, whilst leveraging nixvim extrapackages option.

@RicSanOP
Copy link
Author

RicSanOP commented Nov 2, 2024

As for the wrapRc option, it technically solves the problem but introduces a new one which is getting access to the unwrapped nvim executable in order to run other configs. I wonder if the -u option has priority over NVIM_APPNAME. Will test when back on my computer.

@RicSanOP
Copy link
Author

RicSanOP commented Nov 4, 2024

@MattSturgeon @GaetanLepage, I have worked on a home-manager module that allows for multiple concurrent profiles. I think I have done just about everything right on my end with regards to creating a multi profile option set for the module, which would reside at programs.nixvims. The only problem I seem to be having is that, for some odd reason, the .overrideAttrs invoking that overrides the postInstall derivation attribute does not seem to apply. Everytime I build a profile's nixvim derivation (which at the moment is a wrapped standalone), the nvim executable remains unchanged and is not renamed as I'd indicated in .overrideAttrs.postInstall. Here is the code of the module and an example of me testing it. It should be quite straightforward. @MattSturgeon @GaetanLepage please help me find the correct way to change the executable's filename because after that I could even build a pull request here or at home-manager. Go easy on me though, its my first time writing my own nix modules.

The module that is added to the home-manager modules list in the flake

{ self, inputs, config, pkgs, lib, nixvimFactory, ... }: # assume nixvimFactory alroady handles profile renaming and integration
let
  inherit (lib)
    mkEnableOption
    mkOption
    mkDefault
    mkIf
    types
    lists;
  cfg = config.programs.nixvims;
  mkNixvimProfile = profile: ((nixvimFactory {
      inherit pkgs;
      module = profile.module // { wrapRc = true; };
      extraSpecialArgs = profile.extraSpecialArgs;
    }).overrideAttrs {
      postInstall = ''
        mv $out/bin/nvim $out/bin/nvim${profile.exeName}
      ''; # in the future wrapRc can be toggled to move config files within ~/.config/nvim subdirectories
    });
  genNixvimDrvs = profiles: (lists.forEach profiles (p:
      mkNixvimProfile p
    ));
in
{
  options.programs.nixvims = {
    enable = mkEnableOption "enables nixvims";
    profiles = mkOption {
      type = types.listOf (types.submodule {
        options = {
          profileName = mkOption {
            type = types.str;
            default = "Default";
            description = "the profile's config path name if exported";
          };
          exeName = mkOption {
            type = types.str;
            default = "default";
            description = "the profile's executable name append nvim$exeName";
          };
          module = mkOption {
            type = types.attrs;
            default = { colorschemes.tokyonight.enable = true; };
            description = "the modules as they would be passed to the makeNixvimWithModule function";
          };
          extraSpecialArgs = mkOption {
            type = types.attrs;
            default = { };
            description = "the extraSpecialArgs as they would be passed to the makeNixvimWithModule function";
          };
        };
      });
    };
    default = [ ];
    description = "a list of profile attribute sets";
  };

  config = mkIf cfg.enable {
    home.packages = [
      #output of nixvimFactory should go here (start with one then do a map on profiles
      pkgs.hello #placeholder
    ] ++ (genNixvimDrvs cfg.profiles);
  };
}

An example home config using the new nixvims module

{ self, inputs, config, pkgs, lib, nixvimFactory, ... }:

{
  programs.nixvims = {
    enable = true;
    profiles = [
      {
        profileName = "Test";
        exeName = "test";
        module = { };
      }
      {
        profileName = "Tokyo";
        exeName = "tokyo";
        module = { colorschemes.tokyonight.enable = true; };
      }
      {
        profileName = "Gruv";
        exeName = "gruv";
        module = { colorschemes.gruvbox.enable = true; };
      }
    ];
  };
...

@RicSanOP
Copy link
Author

RicSanOP commented Nov 8, 2024

After some more digging, I believe the derivation that nixvim produces does not run the postInstall hook which is why I cannot rename the output executable. @GaetanLepage @MattSturgeon please feel free to evaluate my above module and also give guidance on how we can modify the above or nixvim itself to make this a possibility. As I mentioned before, I am willing to contribute but would appreciate some initial guidance.

@GaetanLepage
Copy link
Member

Hello,
Sorry for taking so long to reply to your message. Last few weeks were quite busy...
To me, this design looks quite good. Now, it is very important to get an estimation of the complexity this would imply in terms of implementation.
Do you have some draft/PoC ?

Also, pinging @nix-community/nixvim to see if someone has a strong opinion.

@khaneliman
Copy link
Contributor

I love the idea and the usage looks pretty good imo. I used to have multiple neovim configurations separated by NVIM_APPNAME so I could have different setups to compare.

@MattSturgeon
Copy link
Member

I believe the derivation that nixvim produces does not run the postInstall hook which is why I cannot rename the output executable.

If you're talking about nixvim's "standalone" build, then that's a symlinkJoin derivation. Which would make sense.

If you would rather make changes to the underlying wrapped nvim package, exposed as config.build.package, then I think we would need to add an overrides or some kinda functionTo package transformer option, similar to the per-plugin packageDecorator option.


We've also been brainstorming some fairly fundamental changes to how nixvim should be installed, so it might make sense to consider the use cases you are talking about in that upcoming redesign.

In particular, I'm proposing we rely more transparently on evalNixvim (itself a thin wrapper around lib.evalModules). We could offer:

  • mkNixvimPackage - similar to our current standalone mode
  • mkNixvimWrapperModule - a more general way to make wrapper modules for hm,nixos,etc

Maybe mkNixvimWrapperModule or a variant of it could also support creating per-profile nixvim modules? Do you have a design/api in mind?


Getting a bit more into the weeds, your example looks interesting. In practice I think it may benefit from taking advantage of evalNixvm and the extendModules and type attrs available on the resulting configuration.

extendModules allows you to add additional modules to an existing configuration.

type allows using a configuration as a submodule option-type. For example, the programs.nixvim option's type is essentially (evalNixvim {}).type:

options.programs.nixvim = lib.mkOption {
inherit (nixvimConfiguration) type;
default = { };
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants