ghcup-0.2.1.0: lib-tui/GHCup/Brick/Widgets/Menus/AdvancedInstall.hs
{-# LANGUAGE CPP #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ViewPatterns #-}
{-# OPTIONS_GHC -Wno-unused-record-wildcards #-}
{-# OPTIONS_GHC -Wno-unused-matches #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE InstanceSigs #-}
{-# OPTIONS_GHC -Wno-incomplete-patterns #-}
module GHCup.Brick.Widgets.Menus.AdvancedInstall (
InstallOptions (..),
AdvancedInstallMenu,
create,
handler,
draw,
instBindistL,
instSetL,
instVersionL,
isolateDirL,
forceInstallL,
addConfArgsL,
installTargetsL,
) where
import GHCup.Types (TargetVersionReq(..))
import GHCup.Brick.Widgets.Menu (Menu, MenuKeyBindings)
import qualified GHCup.Brick.Widgets.Menu as Menu
import GHCup.Brick.Common(Name(..))
import Brick
( BrickEvent(..),
EventM,
Widget(..))
import Prelude hiding ( appendFile )
import Optics.TH (makeLensesFor)
import qualified GHCup.Brick.Common as Common
import URI.ByteString (URI)
import qualified Data.Text as T
import Data.Bifunctor (Bifunctor(..))
import Data.Function ((&))
import Optics ((.~))
import Data.Char (isSpace)
import qualified GHCup.Input.Parsers as Utils
data InstallOptions = InstallOptions
{ instBindist :: Maybe URI
, instSet :: Bool
, instVersion :: Maybe TargetVersionReq
-- ^ User specified version to override default
, isolateDir :: Maybe FilePath
, forceInstall :: Bool
, addConfArgs :: [T.Text]
, installTargets :: Maybe T.Text
} deriving (Eq, Show)
makeLensesFor [
("instBindist", "instBindistL")
, ("instSet", "instSetL")
, ("instVersion", "instVersionL")
, ("isolateDir", "isolateDirL")
, ("forceInstall", "forceInstallL")
, ("addConfArgs", "addConfArgsL")
, ("installTargets", "installTargetsL")
]
''InstallOptions
type AdvancedInstallMenu = Menu InstallOptions Name
create :: MenuKeyBindings -> AdvancedInstallMenu
create k = Menu.createMenu AdvancedInstallBox initialState "Advanced Install" validator k [ok] fields
where
initialState = InstallOptions Nothing False Nothing Nothing False [] Nothing
validator InstallOptions {..} = case (instSet, isolateDir) of
(True, Just _) -> Just "Cannot set active when doing an isolated install"
_ -> Nothing
-- Brick's internal editor representation is [mempty].
emptyEditor i = T.null i || (i == "\n")
whenEmpty :: a -> (T.Text -> Either Menu.ErrorMessage a) -> T.Text -> Either Menu.ErrorMessage a
whenEmpty emptyval f i = if not (emptyEditor i) then f i else Right emptyval
uriValidator :: T.Text -> Either Menu.ErrorMessage (Maybe URI)
uriValidator = whenEmpty Nothing (second Just . readUri)
where readUri = first T.pack . Utils.uriParser . T.unpack
filepathValidator :: T.Text -> Either Menu.ErrorMessage (Maybe FilePath)
filepathValidator = whenEmpty Nothing (bimap T.pack Just . Utils.absolutePathParser . T.unpack)
installTargetValidator :: T.Text -> Either Menu.ErrorMessage (Maybe T.Text)
installTargetValidator = whenEmpty Nothing (Right . Just)
toolVersionValidator :: T.Text -> Either Menu.ErrorMessage (Maybe TargetVersionReq)
toolVersionValidator = whenEmpty Nothing (bimap T.pack Just . Utils.ghcVersionEither' . T.unpack)
additionalValidator :: T.Text -> Either Menu.ErrorMessage [T.Text]
additionalValidator = Right . T.split isSpace
fields =
[ Menu.createEditableField (Common.MenuElement Common.UrlEditBox) uriValidator instBindistL
& Menu.fieldLabelL .~ "url"
& Menu.fieldHelpMsgL .~ "Install the specified version from this bindist"
, Menu.createCheckBoxField (Common.MenuElement Common.SetCheckBox) instSetL
& Menu.fieldLabelL .~ "set"
& Menu.fieldHelpMsgL .~ "Set as active version after install"
, Menu.createEditableField (Common.MenuElement Common.ToolVersionBox) toolVersionValidator instVersionL
& Menu.fieldLabelL .~ "version"
& Menu.fieldHelpMsgL .~ "Specify a custom version"
, Menu.createEditableField (Common.MenuElement Common.GHCInstallTargets) installTargetValidator installTargetsL
& Menu.fieldLabelL .~ "install-targets"
& Menu.fieldHelpMsgL .~ "Overwrite install targets (space separated list)"
, Menu.createEditableField (Common.MenuElement Common.IsolateEditBox) filepathValidator isolateDirL
& Menu.fieldLabelL .~ "isolated"
& Menu.fieldHelpMsgL .~ "install in an isolated absolute directory instead of the default one"
, Menu.createCheckBoxField (Common.MenuElement Common.ForceCheckBox) forceInstallL
& Menu.fieldLabelL .~ "force"
& Menu.fieldHelpMsgL .~ "Force install (THIS IS UNSAFE, only use it in Dockerfiles or CI)"
, Menu.createEditableField (Common.MenuElement Common.AdditionalEditBox) additionalValidator addConfArgsL
& Menu.fieldLabelL .~ "CONFIGURE_ARGS"
& Menu.fieldHelpMsgL .~ "Additional arguments to bindist configure"
]
ok = Menu.createButtonField (Common.MenuElement Common.OkButton)
& Menu.fieldLabelL .~ "Advanced Install"
& Menu.fieldHelpMsgL .~ "Install with options below"
handler :: BrickEvent Name e -> EventM Name AdvancedInstallMenu ()
handler = Menu.handlerMenu
draw :: AdvancedInstallMenu -> [Widget Name]
draw = Menu.drawMenu