{-# LANGUAGE CPP #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TemplateHaskell #-}
-- | Information and display strings for HIE's version
-- and the current project's version
module Ide.Version where
import Data.Maybe (listToMaybe)
import Data.Version
import GitHash (giCommitCount, tGitInfoCwdTry)
import Options.Applicative.Simple (simpleVersion)
import qualified Paths_haskell_language_server as Meta
import System.Directory
import System.Exit
import System.Info
import System.Process
import Text.ParserCombinators.ReadP
-- >>> hlsVersion
hlsVersion :: String
hlsVersion =
let gi = $$tGitInfoCwdTry
commitCount = case gi of
Right gi -> show $ giCommitCount gi
Left _ -> "UNKNOWN"
in concat $ concat
[ [$(simpleVersion Meta.version)]
-- Leave out number of commits for --depth=1 clone
-- See https://github.com/commercialhaskell/stack/issues/792
, [" (" ++ commitCount ++ " commits)" | commitCount /= ("1"::String) &&
commitCount /= ("UNKNOWN" :: String)]
, [" ", arch]
, [" ", hlsGhcDisplayVersion]
]
where
hlsGhcDisplayVersion = compilerName ++ "-" ++ VERSION_ghc
data ProgramsOfInterest = ProgramsOfInterest
{ cabalVersion :: Maybe Version
, stackVersion :: Maybe Version
, ghcVersion :: Maybe Version
}
showProgramVersionOfInterest :: ProgramsOfInterest -> String
showProgramVersionOfInterest ProgramsOfInterest {..} =
unlines
[ showProgramVersion "cabal" cabalVersion
, showProgramVersion "stack" stackVersion
, showProgramVersion "ghc" ghcVersion
]
showProgramVersion :: String -> Maybe Version -> String
showProgramVersion name version =
pad 16 (name ++ ":") ++ showVersionWithDefault version
where
showVersionWithDefault = maybe "Not found" showVersion
pad n s = s ++ replicate (n - length s) ' '
findProgramVersions :: IO ProgramsOfInterest
findProgramVersions = ProgramsOfInterest
<$> findVersionOf "cabal"
<*> findVersionOf "stack"
<*> findVersionOf "ghc"
-- | Find the version of the given program.
-- Assumes the program accepts the cli argument "--numeric-version".
-- If the invocation has a non-zero exit-code, we return 'Nothing'
findVersionOf :: FilePath -> IO (Maybe Version)
findVersionOf tool =
findExecutable tool >>= \case
Nothing -> pure Nothing
Just path ->
readProcessWithExitCode path ["--numeric-version"] "" >>= \case
(ExitSuccess, sout, _) -> pure $ mkVersion sout
_ -> pure Nothing
mkVersion :: String -> Maybe Version
mkVersion = consumeParser myVersionParser
where
myVersionParser = do
skipSpaces
version <- parseVersion
skipSpaces
pure version
consumeParser :: ReadP a -> String -> Maybe a
consumeParser p input =
listToMaybe $ map fst . filter (null . snd) $ readP_to_S p input