2022-02-10 20:34:41 +00:00
|
|
|
|
{ lib
|
|
|
|
|
, stdenv
|
|
|
|
|
, haskellPackages
|
|
|
|
|
, haskell
|
2023-11-16 04:20:00 +00:00
|
|
|
|
|
|
|
|
|
# Which GHC versions this hls can support.
|
|
|
|
|
# These are looked up in nixpkgs as `pkgs.haskell.packages."ghc${version}`.
|
|
|
|
|
# Run
|
|
|
|
|
# $ nix-instantiate --eval -E 'with import <nixpkgs> {}; builtins.attrNames pkgs.haskell.packages'
|
|
|
|
|
# to list for your nixpkgs version.
|
2024-04-21 15:54:59 +00:00
|
|
|
|
, supportedGhcVersions ? [ "96" ]
|
2023-11-16 04:20:00 +00:00
|
|
|
|
|
|
|
|
|
# Whether to build hls with the dynamic run-time system.
|
|
|
|
|
# See https://haskell-language-server.readthedocs.io/en/latest/troubleshooting.html#static-binaries for more information.
|
|
|
|
|
, dynamic ? true
|
|
|
|
|
|
|
|
|
|
# Which formatters are supported. Pass `[]` to remove all formatters.
|
|
|
|
|
#
|
|
|
|
|
# Maintainers: if a new formatter is added, add it here and down in knownFormatters
|
|
|
|
|
, supportedFormatters ? [ "ormolu" "fourmolu" "floskell" "stylish-haskell" ]
|
2022-02-10 20:34:41 +00:00
|
|
|
|
}:
|
2023-11-16 04:20:00 +00:00
|
|
|
|
|
|
|
|
|
# make sure the user only sets GHC versions that actually exist
|
|
|
|
|
assert supportedGhcVersions != [];
|
|
|
|
|
assert
|
|
|
|
|
lib.asserts.assertEachOneOf
|
|
|
|
|
"supportedGhcVersions"
|
|
|
|
|
supportedGhcVersions
|
|
|
|
|
(lib.pipe haskell.packages [
|
|
|
|
|
lib.attrNames
|
|
|
|
|
(lib.filter (lib.hasPrefix "ghc"))
|
|
|
|
|
(map (lib.removePrefix "ghc"))
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
let
|
|
|
|
|
# A mapping from formatter name to
|
|
|
|
|
# - cabal flag to disable
|
|
|
|
|
# - formatter-specific packages that can be stripped from the build of hls if it is disabled
|
|
|
|
|
knownFormatters = {
|
|
|
|
|
ormolu = {
|
|
|
|
|
cabalFlag = "ormolu";
|
|
|
|
|
packages = [
|
|
|
|
|
"hls-ormolu-plugin"
|
|
|
|
|
];
|
|
|
|
|
};
|
|
|
|
|
fourmolu = {
|
|
|
|
|
cabalFlag = "fourmolu";
|
|
|
|
|
packages = [
|
|
|
|
|
"hls-fourmolu-plugin"
|
|
|
|
|
];
|
|
|
|
|
};
|
|
|
|
|
floskell = {
|
|
|
|
|
cabalFlag = "floskell";
|
|
|
|
|
packages = [
|
|
|
|
|
"hls-floskell-plugin"
|
|
|
|
|
];
|
|
|
|
|
};
|
|
|
|
|
stylish-haskell = {
|
|
|
|
|
cabalFlag = "stylishhaskell";
|
|
|
|
|
packages = [
|
|
|
|
|
"hls-stylish-haskell-plugin"
|
|
|
|
|
];
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
in
|
|
|
|
|
|
|
|
|
|
# make sure any formatter that is set is actually supported by us
|
|
|
|
|
assert
|
|
|
|
|
lib.asserts.assertEachOneOf
|
|
|
|
|
"supportedFormatters"
|
|
|
|
|
supportedFormatters
|
|
|
|
|
(lib.attrNames knownFormatters);
|
|
|
|
|
|
2020-10-16 20:44:37 +00:00
|
|
|
|
#
|
|
|
|
|
# The recommended way to override this package is
|
|
|
|
|
#
|
2022-09-22 12:36:57 +00:00
|
|
|
|
# pkgs.haskell-language-server.override { supportedGhcVersions = [ "90" "92"]; }
|
2020-10-16 20:44:37 +00:00
|
|
|
|
#
|
|
|
|
|
# for example. Read more about this in the haskell-language-server section of the nixpkgs manual.
|
|
|
|
|
#
|
|
|
|
|
let
|
2023-11-16 04:20:00 +00:00
|
|
|
|
inherit (haskell.lib.compose)
|
|
|
|
|
justStaticExecutables
|
|
|
|
|
overrideCabal
|
|
|
|
|
enableCabalFlag
|
|
|
|
|
disableCabalFlag
|
|
|
|
|
;
|
|
|
|
|
|
2020-10-16 20:44:37 +00:00
|
|
|
|
getPackages = version: haskell.packages."ghc${version}";
|
2023-11-16 04:20:00 +00:00
|
|
|
|
|
|
|
|
|
# Given the list of `supportedFormatters`, remove every formatter that we know of (knownFormatters)
|
|
|
|
|
# by disabling the cabal flag and also removing the formatter libraries.
|
|
|
|
|
removeUnnecessaryFormatters =
|
|
|
|
|
let
|
|
|
|
|
# only formatters that were not requested
|
|
|
|
|
unwanted = lib.pipe knownFormatters [
|
|
|
|
|
(lib.filterAttrs (fmt: _: ! (lib.elem fmt supportedFormatters)))
|
|
|
|
|
lib.attrsToList
|
|
|
|
|
];
|
|
|
|
|
# all flags to disable
|
|
|
|
|
flags = map (fmt: fmt.value.cabalFlag) unwanted;
|
|
|
|
|
# all dependencies to remove from hls
|
|
|
|
|
deps = lib.concatMap (fmt: fmt.value.packages) unwanted;
|
|
|
|
|
|
|
|
|
|
# remove nulls from a list
|
|
|
|
|
stripNulls = lib.filter (x: x != null);
|
|
|
|
|
|
|
|
|
|
# remove all unwanted dependencies of formatters we don’t want
|
|
|
|
|
stripDeps = overrideCabal (drv: {
|
|
|
|
|
libraryHaskellDepends = lib.pipe (drv.libraryHaskellDepends or []) [
|
|
|
|
|
# the existing list may contain nulls, so let’s strip them first
|
|
|
|
|
stripNulls
|
|
|
|
|
(lib.filter (dep: ! (lib.elem dep.pname deps)))
|
|
|
|
|
];
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
in drv: lib.pipe drv ([stripDeps] ++ map disableCabalFlag flags);
|
|
|
|
|
|
2020-10-16 20:44:37 +00:00
|
|
|
|
tunedHls = hsPkgs:
|
2022-02-20 05:27:41 +00:00
|
|
|
|
lib.pipe hsPkgs.haskell-language-server ([
|
|
|
|
|
(haskell.lib.compose.overrideCabal (old: {
|
|
|
|
|
enableSharedExecutables = dynamic;
|
|
|
|
|
${if !dynamic then "postInstall" else null} = ''
|
|
|
|
|
${old.postInstall or ""}
|
|
|
|
|
|
|
|
|
|
remove-references-to -t ${hsPkgs.ghc} $out/bin/haskell-language-server
|
|
|
|
|
'';
|
|
|
|
|
}))
|
|
|
|
|
((if dynamic then enableCabalFlag else disableCabalFlag) "dynamic")
|
2023-11-16 04:20:00 +00:00
|
|
|
|
removeUnnecessaryFormatters
|
|
|
|
|
]
|
|
|
|
|
++ lib.optionals (!dynamic) [
|
2022-02-20 05:27:41 +00:00
|
|
|
|
justStaticExecutables
|
|
|
|
|
]);
|
2023-11-16 04:20:00 +00:00
|
|
|
|
|
2020-10-16 20:44:37 +00:00
|
|
|
|
targets = version:
|
|
|
|
|
let packages = getPackages version;
|
2023-11-16 04:20:00 +00:00
|
|
|
|
in [ "haskell-language-server-${packages.ghc.version}" ];
|
|
|
|
|
|
2020-10-16 20:44:37 +00:00
|
|
|
|
makeSymlinks = version:
|
2023-11-16 04:20:00 +00:00
|
|
|
|
lib.concatMapStringsSep "\n"
|
|
|
|
|
(x:
|
|
|
|
|
"ln -s ${
|
|
|
|
|
tunedHls (getPackages version)
|
|
|
|
|
}/bin/haskell-language-server $out/bin/${x}")
|
|
|
|
|
(targets version);
|
|
|
|
|
|
|
|
|
|
in stdenv.mkDerivation {
|
2020-10-16 20:44:37 +00:00
|
|
|
|
pname = "haskell-language-server";
|
|
|
|
|
version = haskellPackages.haskell-language-server.version;
|
2023-11-16 04:20:00 +00:00
|
|
|
|
|
2020-10-16 20:44:37 +00:00
|
|
|
|
buildCommand = ''
|
|
|
|
|
mkdir -p $out/bin
|
2022-12-28 21:21:41 +00:00
|
|
|
|
ln -s ${tunedHls (getPackages (builtins.head supportedGhcVersions))}/bin/haskell-language-server-wrapper $out/bin/haskell-language-server-wrapper
|
2023-11-16 04:20:00 +00:00
|
|
|
|
${lib.concatMapStringsSep "\n" makeSymlinks supportedGhcVersions}
|
2020-10-16 20:44:37 +00:00
|
|
|
|
'';
|
2023-11-16 04:20:00 +00:00
|
|
|
|
|
2020-10-16 20:44:37 +00:00
|
|
|
|
meta = haskellPackages.haskell-language-server.meta // {
|
|
|
|
|
maintainers = [ lib.maintainers.maralorn ];
|
|
|
|
|
longDescription = ''
|
2022-12-28 21:21:41 +00:00
|
|
|
|
This package provides the executables ${
|
2023-11-16 04:20:00 +00:00
|
|
|
|
lib.concatMapStringsSep ", " (x: lib.concatStringsSep ", " (targets x))
|
2020-10-16 20:44:37 +00:00
|
|
|
|
supportedGhcVersions
|
2022-12-28 21:21:41 +00:00
|
|
|
|
} and haskell-language-server-wrapper.
|
2022-09-22 12:36:57 +00:00
|
|
|
|
You can choose for which ghc versions to install hls with pkgs.haskell-language-server.override { supportedGhcVersions = [ "90" "92" ]; }.
|
2020-10-16 20:44:37 +00:00
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
}
|