Compare commits

..

3 Commits
tui-1 ... tui

Author SHA1 Message Date
3824f6417a Update libarchive 2020-07-10 22:44:16 +02:00
Ben Gamari
2be1aa2707 Simplify upgrade copying logic 2020-07-10 22:03:04 +02:00
da94fa5f92 Create brick tui wrt #24 2020-07-10 21:55:12 +02:00
6 changed files with 86 additions and 59 deletions

View File

@@ -17,7 +17,6 @@ ecabal update
if [ "${OS}" = "LINUX" ] ; then if [ "${OS}" = "LINUX" ] ; then
if [ "${BIT}" = "32" ] ; then if [ "${BIT}" = "32" ] ; then
rm -r 3rdparty/libarchive
ecabal build -w ghc-${GHC_VERSION} --ghc-options='-split-sections -optl-static' ecabal build -w ghc-${GHC_VERSION} --ghc-options='-split-sections -optl-static'
else else
ecabal build -w ghc-${GHC_VERSION} --ghc-options='-split-sections -optl-static' -ftui ecabal build -w ghc-${GHC_VERSION} --ghc-options='-split-sections -optl-static' -ftui

View File

@@ -606,7 +606,7 @@
/* #undef HAVE_LCHFLAGS */ /* #undef HAVE_LCHFLAGS */
/* Define to 1 if you have the `lchmod' function. */ /* Define to 1 if you have the `lchmod' function. */
#define HAVE_LCHMOD 1 /* #undef HAVE_LCHMOD 1 */
/* Define to 1 if you have the `lchown' function. */ /* Define to 1 if you have the `lchown' function. */
#define HAVE_LCHOWN 1 #define HAVE_LCHOWN 1
@@ -1028,10 +1028,10 @@
/* #undef HAVE_STRUCT_STAT_ST_UMTIME */ /* #undef HAVE_STRUCT_STAT_ST_UMTIME */
/* Define to 1 if `tm_gmtoff' is a member of `struct tm'. */ /* Define to 1 if `tm_gmtoff' is a member of `struct tm'. */
#define HAVE_STRUCT_TM_TM_GMTOFF 1 /* #undef HAVE_STRUCT_TM_TM_GMTOFF 1 */
/* Define to 1 if `__tm_gmtoff' is a member of `struct tm'. */ /* Define to 1 if `__tm_gmtoff' is a member of `struct tm'. */
#define HAVE_STRUCT_TM___TM_GMTOFF 1 /* #undef HAVE_STRUCT_TM___TM_GMTOFF 1 */
/* Define to 1 if the system has the type `struct vfsconf'. */ /* Define to 1 if the system has the type `struct vfsconf'. */
/* #undef HAVE_STRUCT_VFSCONF */ /* #undef HAVE_STRUCT_VFSCONF */

View File

@@ -27,6 +27,7 @@ import Control.Monad.Trans.Resource
import Data.Bool import Data.Bool
import Data.Functor import Data.Functor
import Data.List import Data.List
import Data.Maybe
import Data.Char import Data.Char
import Data.IORef import Data.IORef
import Data.String.Interpolate import Data.String.Interpolate
@@ -51,6 +52,16 @@ data AppState = AppState {
type LR = GenericList String Vector ListResult type LR = GenericList String Vector ListResult
keyHandlers :: [(Char, String, AppState -> EventM n (Next AppState))]
keyHandlers =
[ ('q', "Quit" , halt)
, ('i', "Install" , withIOAction install')
, ('u', "Uninstall", withIOAction del')
, ('s', "Set" , withIOAction set')
, ('c', "ChangeLog", withIOAction changelog')
]
ui :: AppState -> Widget String ui :: AppState -> Widget String
ui AppState {..} = ui AppState {..} =
( padBottom Max ( padBottom Max
@@ -59,15 +70,13 @@ ui AppState {..} =
$ (center $ renderList renderItem True lr) $ (center $ renderList renderItem True lr)
) )
) )
<=> foldr1 <=> ( withAttr "help"
(\x y -> x <+> str " " <+> y) . txtWrap
[ (str "q:Quit") . T.pack
, (str "i:Install") . foldr1 (\x y -> x <> " " <> y)
, (str "s:Set") . (++ ["↑↓:Navigation"])
, (str "u:Uninstall") $ (fmap (\(c, s, _) -> (c : ':' : s)) keyHandlers)
, (str "c:ChangeLog") )
, (str "↑↓:Navigation")
]
where where
renderItem b ListResult {..} = renderItem b ListResult {..} =
@@ -83,11 +92,11 @@ ui AppState {..} =
$ minHSize 20 $ minHSize 20
$ (withAttr $ (withAttr
(bool "inactive" "active" b) (bool "inactive" "active" b)
(str (fmap toLower . show $ lTool) <+> str " " <+> str ver) (str $ (fmap toLower . show $ lTool) <> " " <> ver)
) )
) )
<+> (padLeft (Pad 1) $ if null lTag <+> (padLeft (Pad 1) $ if null lTag
then str "" then emptyWidget
else else
foldr1 (\x y -> x <+> str "," <+> y) foldr1 (\x y -> x <+> str "," <+> y)
$ (fmap printTag $ sort lTag) $ (fmap printTag $ sort lTag)
@@ -101,7 +110,7 @@ ui AppState {..} =
minHSize :: Int -> Widget n -> Widget n minHSize :: Int -> Widget n -> Widget n
minHSize s' = hLimit s' . vLimit 1 . (<+> str (replicate s' ' ')) minHSize s' = hLimit s' . vLimit 1 . (<+> fill ' ')
app :: App AppState e String app :: App AppState e String
@@ -120,6 +129,7 @@ app = App { appDraw = \st -> [ui st]
, ("installed" , fg Vty.green) , ("installed" , fg Vty.green)
, ("recommended" , fg Vty.green) , ("recommended" , fg Vty.green)
, ("latest" , fg Vty.yellow) , ("latest" , fg Vty.yellow)
, ("help" , Vty.defAttr `Vty.withStyle` Vty.italic)
] ]
@@ -131,16 +141,22 @@ eventHandler AppState {..} (VtyEvent (Vty.EvKey (Vty.KUp) _)) =
continue (AppState (listMoveUp lr) dls) continue (AppState (listMoveUp lr) dls)
eventHandler AppState {..} (VtyEvent (Vty.EvKey (Vty.KDown) _)) = eventHandler AppState {..} (VtyEvent (Vty.EvKey (Vty.KDown) _)) =
continue (AppState (listMoveDown lr) dls) continue (AppState (listMoveDown lr) dls)
eventHandler AppState { dls = dls', lr = lr' } (VtyEvent (Vty.EvKey (Vty.KChar c) _)) eventHandler as (VtyEvent (Vty.EvKey (Vty.KChar c) _)) =
| (Just (ix, e)) <- listSelectedElement lr' case find (\(c', _, _) -> c' == c) keyHandlers of
, c `elem` ['i', 's', 'u', 'c'] Nothing -> continue as
= suspendAndResume $ do Just (_, _, handler) -> handler as
r <- case c of eventHandler st _ = continue st
'i' -> install' e dls'
's' -> set' e
'u' -> del' e -- | Suspend the current UI and run an IO action in terminal. If the
'c' -> changelog' e dls' -- IO action returns a Left value, then it's thrown as userError.
_ -> error "" withIOAction :: (AppState -> (Int, ListResult) -> IO (Either String a))
-> AppState
-> EventM n (Next AppState)
withIOAction action as = case listSelectedElement (lr as) of
Nothing -> continue as
Just (ix, e) -> suspendAndResume $ do
r <- action as (ix, e)
case r of case r of
Left err -> throwIO $ userError err Left err -> throwIO $ userError err
Right _ -> do Right _ -> do
@@ -148,17 +164,17 @@ eventHandler AppState { dls = dls', lr = lr' } (VtyEvent (Vty.EvKey (Vty.KChar c
(\AppState {..} -> AppState { lr = listMoveTo ix lr, .. }) (\AppState {..} -> AppState { lr = listMoveTo ix lr, .. })
getAppState getAppState
case apps of case apps of
Right as -> do Right nas -> do
putStrLn "Press enter to continue" putStrLn "Press enter to continue"
_ <- getLine _ <- getLine
pure as pure nas
Left err -> throwIO $ userError err Left err -> throwIO $ userError err
eventHandler st _ = continue st
install' :: ListResult -> GHCupDownloads -> IO (Either String ()) install' :: AppState -> (Int, ListResult) -> IO (Either String ())
install' ListResult {..} dls = do install' AppState {..} (_, ListResult {..}) = do
l <- readIORef logger' settings <- readIORef settings'
l <- readIORef logger'
let runLogger = myLoggerT l let runLogger = myLoggerT l
let let
@@ -187,9 +203,10 @@ install' ListResult {..} dls = do
Also check the logs in ~/.ghcup/logs|] Also check the logs in ~/.ghcup/logs|]
set' :: ListResult -> IO (Either String ()) set' :: AppState -> (Int, ListResult) -> IO (Either String ())
set' ListResult {..} = do set' _ (_, ListResult {..}) = do
l <- readIORef logger' settings <- readIORef settings'
l <- readIORef logger'
let runLogger = myLoggerT l let runLogger = myLoggerT l
let run = let run =
@@ -208,9 +225,10 @@ set' ListResult {..} = do
VLeft e -> pure $ Left [i|#{e}|] VLeft e -> pure $ Left [i|#{e}|]
del' :: ListResult -> IO (Either String ()) del' :: AppState -> (Int, ListResult) -> IO (Either String ())
del' ListResult {..} = do del' _ (_, ListResult {..}) = do
l <- readIORef logger' settings <- readIORef settings'
l <- readIORef logger'
let runLogger = myLoggerT l let runLogger = myLoggerT l
let run = runLogger . flip runReaderT settings . runE @'[NotInstalled] let run = runLogger . flip runReaderT settings . runE @'[NotInstalled]
@@ -226,8 +244,8 @@ del' ListResult {..} = do
VLeft e -> pure $ Left [i|#{e}|] VLeft e -> pure $ Left [i|#{e}|]
changelog' :: ListResult -> GHCupDownloads -> IO (Either String ()) changelog' :: AppState -> (Int, ListResult) -> IO (Either String ())
changelog' ListResult {..} dls = do changelog' AppState {..} (_, ListResult {..}) = do
case getChangeLog dls lTool (Left lVer) of case getChangeLog dls lTool (Left lVer) of
Nothing -> pure $ Left Nothing -> pure $ Left
[i|Could not find ChangeLog for #{lTool}, version #{prettyVer lVer}|] [i|Could not find ChangeLog for #{lTool}, version #{prettyVer lVer}|]
@@ -237,12 +255,15 @@ changelog' ListResult {..} dls = do
Left e -> pure $ Left [i|#{e}|] Left e -> pure $ Left [i|#{e}|]
settings :: Settings settings' :: IORef Settings
settings = Settings { cache = True {-# NOINLINE settings' #-}
, noVerify = False settings' = unsafePerformIO
, keepDirs = Never (newIORef Settings { cache = True
, downloader = Curl , noVerify = False
} , keepDirs = Never
, downloader = Curl
}
)
logger' :: IORef LoggerConfig logger' :: IORef LoggerConfig
@@ -255,23 +276,32 @@ logger' = unsafePerformIO
) )
brickMain :: LoggerConfig -> IO () brickMain :: Settings -> LoggerConfig -> IO ()
brickMain l = do brickMain s l = do
writeIORef settings' s
-- logger interpreter -- logger interpreter
writeIORef logger' l writeIORef logger' l
let runLogger = myLoggerT l let runLogger = myLoggerT l
eApps <- getAppState eApps <- getAppState
case eApps of case eApps of
Right as -> defaultMain app as $> () Right as -> defaultMain app (selectLatest as) $> ()
Left _ -> do Left e -> do
runLogger ($(logError) [i|Error building app state|]) runLogger ($(logError) [i|Error building app state: #{show e}|])
exitWith $ ExitFailure 2 exitWith $ ExitFailure 2
where
selectLatest :: AppState -> AppState
selectLatest AppState {..} =
(\ix -> AppState { lr = listMoveTo ix lr, .. })
. fromJust
. V.findIndex (\ListResult {..} -> lTool == GHC && Latest `elem` lTag)
$ (listElements lr)
getAppState :: IO (Either String AppState) getAppState :: IO (Either String AppState)
getAppState = do getAppState = do
l <- readIORef logger' settings <- readIORef settings'
l <- readIORef logger'
let runLogger = myLoggerT l let runLogger = myLoggerT l
r <- r <-
@@ -282,10 +312,9 @@ getAppState = do
$ do $ do
(GHCupInfo _ dls) <- liftE $ getDownloadsF GHCupURL (GHCupInfo _ dls) <- liftE $ getDownloadsF GHCupURL
lV <- liftE $ listVersions dls Nothing Nothing lV <- liftE $ listVersions dls Nothing Nothing
pure $ (AppState (list "Tool versions" (V.fromList lV) 1) dls) pure $ (AppState (list "Tool versions" (V.fromList lV) 1) dls)
case r of case r of
VRight a -> pure $ Right a VRight a -> pure $ Right a
VLeft e -> pure $ Left [i|#{e}|] VLeft e -> pure $ Left [i|#{e}|]

View File

@@ -1150,7 +1150,7 @@ Report bugs at <https://gitlab.haskell.org/haskell/ghcup-hs/issues>|]
res <- case optCommand of res <- case optCommand of
#if defined(BRICK) #if defined(BRICK)
Interactive -> liftIO $ brickMain loggerConfig >> pure ExitSuccess Interactive -> liftIO $ brickMain settings loggerConfig >> pure ExitSuccess
#endif #endif
Install (Right iopts) -> do Install (Right iopts) -> do
runLogger ($(logWarn) [i|This is an old-style command for installing GHC. Use 'ghcup install ghc' instead.|]) runLogger ($(logWarn) [i|This is an old-style command for installing GHC. Use 'ghcup install ghc' instead.|])

View File

@@ -22,7 +22,7 @@ source-repository head
location: https://gitlab.haskell.org/haskell/ghcup-hs.git location: https://gitlab.haskell.org/haskell/ghcup-hs.git
flag tui flag tui
description: Build the brick powered tui (ghcup \-\-interactive) description: Build the brick powered tui (ghcup tui)
default: False default: False
manual: True manual: True

View File

@@ -928,7 +928,6 @@ upgradeGHCup dls mtarget force = do
`unionFileModes` groupExecuteMode `unionFileModes` groupExecuteMode
`unionFileModes` otherExecuteMode `unionFileModes` otherExecuteMode
binDir <- liftIO $ ghcupBinDir binDir <- liftIO $ ghcupBinDir
liftIO $ createDirIfMissing newDirPerms binDir
let fullDest = fromMaybe (binDir </> fn) mtarget let fullDest = fromMaybe (binDir </> fn) mtarget
liftIO $ hideError NoSuchThing $ deleteFile fullDest liftIO $ hideError NoSuchThing $ deleteFile fullDest
handleIO (throwE . CopyError . show) $ liftIO $ copyFile p handleIO (throwE . CopyError . show) $ liftIO $ copyFile p