blob: d5393b05a2ab4532302c29cb8822cb438d9917d6 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
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}"'';
};
};
}
|