numtide / devshell

Per project developer environments
https://numtide.github.io/devshell/
MIT License
1.27k stars 89 forks source link

Document how to build a devshell using nix or a mix of nix and toml #136

Open nova-nowiz opened 3 years ago

nova-nowiz commented 3 years ago

Is your feature request related to a problem? Please describe. The problem I'm facing is that I cannot add a custom package with the toml file. I would like to add more precisely a python with packages.

Another thing is that in the documentation, it is mentionned that 80% can be achieved with the toml but there is no mention (or did I miss it?) of a way to get that 20% in case it is necessary.

Describe the solution you'd like I would like to know how the mkShell works and what options it has so that I am able to use nix as a backup solution when the toml file is not enough.

Describe alternatives you've considered An alternative would be to use a bare nix devShell so not using this repository.

yusdacra commented 3 years ago

Perhaps what I do over here, at the bottom of the file, would be helpful?

nova-nowiz commented 3 years ago

woops, I left this issue hanging. Actually, it is totally possible to use it like this:

{
  description = "virtual environments";

  inputs.devshell.url = "github:numtide/devshell";
  inputs.flake-utils.url = "github:numtide/flake-utils";

  outputs = { self, flake-utils, devshell, nixpkgs }:
    flake-utils.lib.eachDefaultSystem (system: {
      devShell =
        let pkgs = import nixpkgs {
          inherit system;

          overlays = [ devshell.overlay ];
        };
        in
        pkgs.devshell.mkShell {
          imports = [ (pkgs.devshell.importTOML ./devshell.toml) ];
          devshell.packages = with pkgs; [
            (python39Full.withPackages(p: with p; [ pygments ]))
            elmPackages.elm
            elmPackages.elm-test
            elmPackages.elm-language-server
            elmPackages.elm-format
            elmPackages.elm-analyse
            elmPackages.elm-coverage
            elmPackages.elm-json
            elmPackages.elm-review
          ];
        };
    });
}

I got devshell.packages from the documentation here: https://numtide.github.io/devshell/modules_schema.html on a toml, you would do this iirc:

[[devshell]]
packages = [
python39Full
]

using devshell.packages in nix is the strict equivalent.

nova-nowiz commented 3 years ago

this should be however still be documented on the website.

nova-nowiz commented 3 years ago

@zimbatm how can you import the extra modules from nix?

blaggacao commented 3 years ago

That's what the extraModulesPath is for: https://www.github.com/numtide/devshell/tree/master/modules%2Fdefault.nix

nova-nowiz commented 3 years ago

ok I followed the trail once more. In our personal flake.nix that we create, we add devshell.overlay to the overlays of pkgs. So we should know what this overlay is. If we look at the flake.nix of this repo, we find the following: https://github.com/numtide/devshell/blob/4b5ac7cf7d9a1cc60b965bb51b59922f2210cbc7/flake.nix#L35-L43 the overlay is thus this file: https://github.com/numtide/devshell/blob/4b5ac7cf7d9a1cc60b965bb51b59922f2210cbc7/overlay.nix#L1-L5 these lines mean that we add devshell to whatever we apply the overlay to, meaning that we have in our personal flake.nix pkgs.devshell. in this pkgs.devshell attribute, we have everything that is in default.nix of this repository and so we have the following: https://github.com/numtide/devshell/blob/4b5ac7cf7d9a1cc60b965bb51b59922f2210cbc7/default.nix#L24-L27

here is the flake.nix I have as a result:

{
  description = "Developement environment for Nix users";

  inputs.devshell.url = "github:numtide/devshell";
  inputs.flake-utils.url = "github:numtide/flake-utils";

  outputs = { self, flake-utils, devshell, nixpkgs }:
    flake-utils.lib.eachDefaultSystem (system: {
      devShell =
        let pkgs = import nixpkgs {
          inherit system;

          overlays = [ devshell.overlay ];
        };
        in
        pkgs.devshell.mkShell {
          imports = [ "${pkgs.devshell.extraModulesDir}/language/c.nix" ];
          commands = [
            {
              package = pkgs.devshell.cli;
              help = "Per project developer environments";
            }
            {
              package = pkgs.gitflow;
            }
            {
              package = pkgs.elmPackages.elm;
            }
            {
              package = pkgs.nodejs;
            }
            {
              package = pkgs.nim;
              name = "nim";
            }
          ];
          devshell.packages = with pkgs; [
            (python39Full.withPackages(p: with p; [ pygments ]))
            elmPackages.elm-test
            elmPackages.elm-language-server
            elmPackages.elm-format
            elmPackages.elm-analyse
            elmPackages.elm-coverage
            elmPackages.elm-json
            elmPackages.elm-review
            nimlsp
          ];
          language.c.libraries = with pkgs; [
            libzip
          ];
        };
    });
}

This flake.nix could be of use in the documentation of the project so that everyone has an idea of how to achieve everything in pure nix ;) I hope that this comment will be of use to anyone having the same issue and wanting to know how this flake works internally. I tried my best to teach how to navigate the codebase and understanding it rather than just giving out the solution I found.

give a man a fish and he’ll eat for a day, teach him how to fish and he’ll eat forever

also thank you @blaggacao for your comment! I solved my issue and began the writing of this comment before you posted but thank you anyway for the help!

zimbatm commented 3 years ago

Nixpkgs modules can be passed either an attrset or a function. In which case the extraModulesDir becomes an available parameter. Something like that should also work:

pkgs.devshell.mkShell { extraModulesDir, ... }: {
  imports = [ "${extraModulesDir}/language/c.nix" ];
  //...
nova-nowiz commented 3 years ago

oh! I didn't know that, that's quite cool and a really good piece of information to keep in mind, thanks! I however don't understand why extraModulesDir is an available parameter in this case, is it because we are calling the pkgs.devshell.mkShell module which is directly under pkgs.devshell? Sorry for the newbie question in advance x) I've been on NixOS for a while but the language is still a tough nut to crack for me :joy: Where have you been able to learn these tricks? Is there a specification somewhere that I could read or is nix pills the way to gain such knowlegde?