diff options
| author | Quentin Aristote <quentin@aristote.fr> | 2021-12-03 11:48:19 +0100 |
|---|---|---|
| committer | Quentin Aristote <quentin@aristote.fr> | 2021-12-03 11:48:19 +0100 |
| commit | 6bb027dbeb3dedb6c65cb27274465105bccdfb18 (patch) | |
| tree | 7613a6397d866617c5c71cb3c906d86f03baba75 | |
initial commit
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | default.nix | 14 | ||||
| -rw-r--r-- | modules/coq.nix | 35 | ||||
| -rw-r--r-- | modules/default.nix | 149 | ||||
| -rw-r--r-- | modules/golang.nix | 22 | ||||
| -rw-r--r-- | modules/latex.nix | 95 | ||||
| -rw-r--r-- | modules/nix.nix | 16 | ||||
| -rw-r--r-- | modules/ocaml.nix | 92 | ||||
| -rw-r--r-- | modules/python.nix | 52 |
9 files changed, 476 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..30fa1ce --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +config
\ No newline at end of file diff --git a/default.nix b/default.nix new file mode 100644 index 0000000..9da8a93 --- /dev/null +++ b/default.nix @@ -0,0 +1,14 @@ +{ pkgs, settings }: + +let + lib = pkgs.lib; + defaultSettings = lib.optional (lib.pathExists ./config/default.nix) ./config; + module = lib.evalModules { + modules = [ settings ./modules ] ++ defaultSettings; + specialArgs.pkgs = pkgs; + }; +in +pkgs.mkShell ({ + inherit (module.config) + inputsFrom buildInputs nativeBuildInputs shellHook exitHook; +}) diff --git a/modules/coq.nix b/modules/coq.nix new file mode 100644 index 0000000..3a1dfef --- /dev/null +++ b/modules/coq.nix @@ -0,0 +1,35 @@ +{ config, lib, pkgs, ... }: + +with lib; +let + cfg = config.coq; + coqBuildInputs = (with cfg.coqPackages; [ coq ]) + ++ (cfg.packages cfg.coqPackages); +in { + options.coq = { + enable = mkEnableOption { name = "coq"; }; + coqPackages = mkOption { + type = types.lazyAttrsOf types.package; + default = pkgs.coqPackages; + defaultText = literalExample "pkgs.coqPackages"; + description = '' + The set of Coq packages from which to get Coq and its packages. + Use this option to set the version of Coq. + ''; + }; + packages = mkOption { + type = with types; functionTo (listOf package); + default = _: [ ]; + defaultText = literalExample "_: [ ]"; + description = '' + Coq packages that will be made available to the environment. + ''; + example = literalExample '' + coqPackages: with coqPackages; [ autosubst ]; + ''; + }; + }; + config = mkIf cfg.enable { + buildInputs = coqBuildInputs; + }; +} diff --git a/modules/default.nix b/modules/default.nix new file mode 100644 index 0000000..fbe500d --- /dev/null +++ b/modules/default.nix @@ -0,0 +1,149 @@ +{ config, lib, pkgs, ... }: + +with lib; +let cfg = config; +in { + imports = + [ ./coq.nix ./golang.nix ./latex.nix ./nix.nix ./python.nix ./ocaml.nix ]; + + options = { + # Inputs + inputsFrom = mkOption { + type = types.listOf types.package; + default = [ ]; + description = '' + The list of derivations whose inputs will be made available to the environment. + ''; + example = literalExample '' + [ pkgs.python3 ] + ''; + }; + buildInputs = mkOption { + type = types.listOf types.package; + default = [ ]; + description = '' + The list of derivations which will be made available to the environment. + ''; + example = literalExample '' + [ pkgs.ocamlPackages.owl ] + ''; + }; + nativeBuildInputs = mkOption { + type = types.listOf types.package; + default = [ ]; + description = '' + The list of derivations which will be made available to the environment at run-time. + ''; + example = literalExample '' + [ pkgs.python3 ]; + ''; + }; + + # EnvVars + envVars = mkOption { + type = types.attrsOf (types.submodule { + options = { + reset = mkOption { + type = types.bool; + default = false; + description = '' + If `true`, reset the value of the variable before changing it. + If `false`, the new value is thus set as $VAR=$VAR:`config.envVars.VAR.value`. + ''; + }; + value = mkOption { + type = types.envVar; + default = ""; + description = '' + The new value to give to the environment variable. + ''; + }; + }; + }); + default = { }; + description = '' + Environment variables that will be made available to the environment. + ''; + example = { + PATH = { + reset = true; + value = "~/.local/bin"; + }; + }; + }; + aliases = mkOption { + type = types.attrsOf types.str; + default = { }; + description = '' + Aliases. + If direnv is enabled, they are installed as executables in + .direnv/aliases. They may then take arguments. This also means that + "recursive" aliases (e.g. ssh="export A=something ssh") will fail ; the + executable in the definition should be called by its full path (e.g. + $\{pkgs.openssh\}/bin/ssh). + ''; + example = literalExample '' + { zz = "ls -la"; }; + ''; + }; + + # Misc + ## Whether the shell is to be loaded by direnv + direnv.enable = mkEnableOption "direnv"; + + # Hooks + shellHook = mkOption { + type = types.lines; + default = ""; + description = '' + Commands to run after initializing the environment. + ''; + example = '' + alias ll="ls -l" + git status + ''; + }; + exitHook = mkOption { + type = types.lines; + default = ""; + description = '' + Commands to run when exiting the shell. + ''; + example = '' + git clean + ''; + }; + }; + + config.shellHook = concatStringsSep "\n" ( + # Environment variables are declared in a shell hook because simply adding the + # top-level arguments of pkgs.mkShell ovewrites the old values of the + # variables, which may be a problem, for example for PATH. + (let + dollar = "$"; + makeEnvVarCommand = name: + { reset, value }: + '' + export "${name}"=${ + optionalString (!reset) (''"${dollar}${name}":'') + }"${value}"''; + in (attrValues (mapAttrs makeEnvVarCommand cfg.envVars))) + ++ (if cfg.direnv.enable then + (let + aliasDir = ''"$PWD"/.direnv/aliases''; + makeAliasCommand = name: value: + let target = ''${aliasDir}/${name}''; + in '' + echo '#!${pkgs.bash}/bin/bash -e' > "${target}" + echo "${value}" >> "${target}" + chmod +x "${target}" + ''; + in (['' + mkdir -p "${aliasDir}" + rm -f "${aliasDir}"/* + PATH="${aliasDir}":"$PATH" # $PATH has to come last for the alias to take effect + ''] ++ (attrValues (mapAttrs makeAliasCommand cfg.aliases)))) + else + (let makeAliasCommand = name: value: ''alias "${name}"="${value}"''; + in (attrValues (mapAttrs makeAliasCommand cfg.aliases))))); +} diff --git a/modules/golang.nix b/modules/golang.nix new file mode 100644 index 0000000..e6e0821 --- /dev/null +++ b/modules/golang.nix @@ -0,0 +1,22 @@ +{ config, lib, pkgs, ... }: + +with lib; +let cfg = config.golang; +in { + options.golang = { + enable = mkEnableOption { name = "golang"; }; + package = mkOption { + type = types.package; + default = pkgs.go; + defaultText = literalExample "pkgs.go"; + description = '' + The package for Go. This sets the version of Go.. + ''; + example = literalExample "pkgs.go_1_15"; + }; + }; + + config = mkIf cfg.enable { + buildInputs = [ cfg.package ] ++ (with pkgs; [ gofumpt golint ]); + }; +} diff --git a/modules/latex.nix b/modules/latex.nix new file mode 100644 index 0000000..0c06ec7 --- /dev/null +++ b/modules/latex.nix @@ -0,0 +1,95 @@ +{ config, lib, pkgs, ... }: + +with lib; +let + cfg = config.latex; + latexmkFlags = concatStringsSep " " ([ + (if cfg.latexmk.output.dvi.enable then "-dvi" else "-dvi-") + (if cfg.latexmk.output.ps.enable then "-ps" else "-ps-") + (if cfg.latexmk.output.pdf.enable then + ("-pdf" + cfg.latexmk.output.pdf.method) + else + "-pdf-") + (optionalString cfg.minted.enable "-shell-escape") + ] ++ (map (filename: ''-r "${filename}"'') cfg.latexmk.rc) + ++ cfg.latexmk.extraFlags); + latexBuildInput = cfg.texlive.combine ((cfg.packages cfg.texlive) + // (optionalAttrs cfg.latexmk.enable { inherit (cfg.texlive) latexmk; }) + // (optionalAttrs cfg.minted.enable { inherit (cfg.texlive) minted; })); +in { + options.latex = { + enable = mkEnableOption { name = "LaTex"; }; + + texlive = mkOption { + type = types.attrs; + default = pkgs.texlive; + defaultText = literalExample "pkgs.texlive"; + description = '' + The package providing LaTex. + Use this option to set the version of LaTex. + ''; + }; + + packages = mkOption { + type = with types; functionTo attrs; + default = tl: { inherit (tl) scheme-full; }; + defaultText = literalExample "tl: { inherit (tl) scheme-full; }"; + description = '' + Collection of packages that will be made available to the environment. + ''; + example = literalExample '' + tl: { + inherit (tl) scheme-full calligra; + my-package = { pkgs = [ (pkgs.callPackage ./my-package.nix {}) ]; }; + } + ''; + }; + + latexmk = { + enable = mkEnableOption "latexmk"; + output = { + dvi.enable = mkEnableOption "dvi output"; + pdf = { + enable = mkEnableOption "pdf output"; + method = mkOption { + type = types.enum [ "" "dvi" "lua" "ps" "xe" ]; + default = "lua"; + description = '' + Method by which to generate the pdf. + ''; + }; + }; + ps.enable = mkEnableOption "ps output"; + }; + rc = mkOption { + type = types.listOf types.path; + default = [ ]; + description = '' + List of LaTeXmk rc files to load. + ''; + example = literalExample "[ ~/.config/latexmkrc ]"; + }; + extraFlags = mkOption { + # TODO vulnerable to shell injection + type = types.listOf types.str; + default = [ ]; + description = '' + Flags to pass to latexmk. + ''; + example = [ "-shell-escape" "-M" ]; + }; + }; + + minted.enable = mkEnableOption "minted"; + }; + + config = mkIf cfg.enable { + buildInputs = [ latexBuildInput ] ++ (optional cfg.latexmk.enable pkgs.ps); + aliases.latexmk = mkIf cfg.latexmk.enable + "${latexBuildInput}/bin/latexmk ${latexmkFlags} \\$@"; + python = mkIf cfg.minted.enable { + enable = true; + packages = ps: with ps; [ pygments ]; + }; + }; +} diff --git a/modules/nix.nix b/modules/nix.nix new file mode 100644 index 0000000..a960e28 --- /dev/null +++ b/modules/nix.nix @@ -0,0 +1,16 @@ +{ config, lib, pkgs, ... }: + +with lib; +let cfg = config.nix; +in { + options.nix = { enable = mkEnableOption "nix"; }; + + config = mkIf cfg.enable { + buildInputs = with pkgs; [ + nixfmt + nixos-option + nix-prefetch-scripts + nix-prefetch-github + ]; + }; +} diff --git a/modules/ocaml.nix b/modules/ocaml.nix new file mode 100644 index 0000000..d5393b0 --- /dev/null +++ b/modules/ocaml.nix @@ -0,0 +1,92 @@ +{ config, lib, pkgs, ... }: + +with lib; +with builtins; +let + cfg = config.ocaml; + ocamlVersion = (parseDrvName cfg.ocamlPackages.ocaml.name).version; + + tuaregPackages = optionals cfg.tuareg.enable (with pkgs; [ ocamlformat opam ]) + ++ (with cfg.ocamlPackages; [ merlin ocp-indent utop ]); + userPackages = cfg.packages cfg.ocamlPackages; + ocamlBuildInputs = (with cfg.ocamlPackages; [ ocaml findlib ]) ++ (with pkgs; + if versionAtLeast ocamlVersion "4.12" then + [ dune_2 ] + else + (optional (versionAtLeast ocamlVersion "4.02") dune_1)) ++ tuaregPackages + ++ userPackages; + + ocamlInit = pkgs.writeText "ocamlinit" ('' + let () = + try Topdirs.dir_directory "${cfg.ocamlPackages.findlib}/lib/ocaml/${ocamlVersion}/site-lib" + with Not_found -> () + ;; + #use "topfind";; + '' + (optionalString cfg.toplevel.list "#list;;") + + (optionalString cfg.toplevel.thread "#thread;;") + (concatStringsSep "\n" + (map (pkg: ''#require "${pkg.pname}";;'') userPackages)) + + cfg.toplevel.extraInit); +in { + options.ocaml = { + enable = mkEnableOption { name = "ocaml"; }; + ocamlPackages = mkOption { + type = types.lazyAttrsOf types.package; + default = pkgs.ocamlPackages; + defaultText = literalExample "pkgs.ocamlPackages"; + description = '' + The set of OCaml packages from which to get OCaml and its packages. + Use this option to set the version of OCaml. + ''; + example = literalExample "pkgs.ocaml-ng.ocamlPackages_4_11"; + }; + packages = mkOption { + type = with types; functionTo (listOf package); + default = _: [ ]; + defaultText = literalExample "_ : []"; + description = '' + OCaml packages that will be made available to the environment. + ''; + example = literalExample '' + ocamlPackages: with ocamlPackages; [ owl lwt ]; + ''; + }; + toplevel = { + require = mkOption { + type = types.listOf types.str; + default = builtins.map (pkg: pkg.pname) cfg.packages; + defaultText = "builtins.map (pkg: pkg.pname) config.ocaml.packages"; + description = '' + The list of names of packages to load when launching a top-level. + ''; + example = [ "owl" "lwt" ]; + }; + # Whether to list loaded packages when launching a top-level. + list = mkEnableOption "#require list;;"; + # Whether to enable threading when running a top-level. + thread = mkEnableOption "#require thread;;"; + extraInit = mkOption { + type = types.lines; + default = ""; + description = '' + Additional commands to run when running a top-level. + ''; + example = "Topfind.reset();;"; + }; + }; + # Whether to load packages required by Tuareg (Emacs' OCaml mode). + tuareg.enable = mkEnableOption "tuareg"; + }; + + config = mkIf cfg.enable { + buildInputs = ocamlBuildInputs; + aliases = { + utop = let + utops = builtins.filter + (p: match "(.*-utop)" (parseDrvName p.name).name != null) + ocamlBuildInputs; + utop = head utops; + in mkIf (utops != [ ]) ''${utop}/bin/utop -init "${ocamlInit}"''; + ocaml = ''${cfg.ocamlPackages.ocaml}/bin/ocaml -init "${ocamlInit}"''; + }; + }; +} diff --git a/modules/python.nix b/modules/python.nix new file mode 100644 index 0000000..ce1154c --- /dev/null +++ b/modules/python.nix @@ -0,0 +1,52 @@ +{ config, lib, pkgs, ... }: + +with lib; +let + cfg = config.python; + pythonWithPackages = (cfg.python.withPackages cfg.packages).override { + ignoreCollisions = cfg.ignoreCollisions; + }; +in { + options.python = { + enable = mkEnableOption { name = "python"; }; + + python = mkOption { + type = types.package; + default = pkgs.python3; + defaultText = literalExample "pkgs.python3Minimal"; + description = '' + The package providing python. + Use this option to set the version of Python. + ''; + example = literalExample "pkgs.python310"; + }; + + packages = mkOption { + type = with types; functionTo (listOf package); + default = _: [ ]; + defaultText = literalExample "_: []"; + description = '' + Python packages that will be made available to the environment. + ''; + example = literalExample '' + pythonPackages: with pythonPackages; [ + requests (callPackage ./my-package.nix {}) + ]; + ''; + }; + + ignoreCollisions = mkEnableOption "ignoring collisions when building the Python environnement"; + }; + + config = mkIf cfg.enable { + buildInputs = [ pythonWithPackages ]; + # shellHook = '' + # # Tells pip to put packages into $PIP_PREFIX instead of the usual locations. + # # See https://pip.pypa.io/en/stable/user_guide/#environment-variables. + # export PIP_PREFIX=$(pwd)/_build/pip_packages + # export PYTHONPATH="$PIP_PREFIX/${cfg.python.sitePackages}:$PYTHONPATH" + # export PATH="$PIP_PREFIX/bin:$PATH" + # unset SOURCE_DATE_EPOCH + # ''; + }; +} |
