on master help sign in
Move run to it's own module
commitc4a5fa989bc8dff13cf3d14d45c8c7a762df7965 authorLuigy Leon <luigy@outlook.com> dateMon 7 May 2018, 11:15 (8 years ago) parentf64b6f5
4 files changed+94−77
lib/command/obelisk-command.cabal+1 lib/command/src/Obelisk/Command.hs+1−52 lib/command/src/Obelisk/Command/Repl.hs−25 lib/command/src/Obelisk/Command/Run.hs+92
lib/command/obelisk-command.cabal+1
@@ -36,6 +36,7 @@ library
3636 Obelisk.Command.Nix
3737 Obelisk.Command.Project
3838 Obelisk.Command.Repl
39+ Obelisk.Command.Run
3940 Obelisk.Command.Thunk
4041 -- -fobject-code is so that the StaticPointers extension can work in ghci
4142 ghc-options: -Wall -fobject-code
lib/command/src/Obelisk/Command.hs+1−52
@@ -36,58 +36,7 @@ import System.Posix.Process
3636import Obelisk.Command.Project
3737import Obelisk.Command.Thunk
3838import Obelisk.Command.Repl
39−
40−run :: IO ()
41−run = do
42− freePort <- getFreePort
43− pkgs <- getLocalPkgs
44− (pkgDirErrs, hsSrcDirs) <- fmap partitionEithers $ forM pkgs $ \pkg -> do
45− let cabalFp = pkg </> pkg <.> "cabal"
46− xs <- parseHsSrcDir cabalFp
47− return $ case xs of
48− Nothing -> Left pkg
49− Just hsSrcDirs -> Right $ toList $ fmap (pkg </>) hsSrcDirs
50− when (null hsSrcDirs) $
51− fail $ "No valid pkgs found in " <> intercalate ", " pkgs
52− when (not (null pkgDirErrs)) $
53− putStrLn $ "Failed to find pkgs in " <> intercalate ", " pkgDirErrs
54− let dotGhci = unlines
55− [ ":set args --quiet --port " <> show freePort
56− , ":set -i" <> intercalate ":" (mconcat hsSrcDirs)
57− , ":add Backend Frontend"
58− , ":module + Control.Concurrent Obelisk.Widget.Run Frontend Backend"
59− ]
60− testCmd = unlines
61− [ "backendId <- forkIO backend"
62− , "let conf = defRunConfig { _runConfig_redirectPort = " <> show freePort <> "}"
63− , "runWidget conf frontend"
64− , "killThread backendId"
65− ]
66− withSystemTempDirectory "ob-ghci" $ \fp -> do
67− let dotGhciPath = fp </> ".ghci"
68− writeFile dotGhciPath dotGhci
69− runDev dotGhciPath $ Just testCmd
70−
71−-- | Relative paths to local packages of an obelisk project
72−-- TODO a way to query this
73−getLocalPkgs :: IO [FilePath]
74−getLocalPkgs = return ["backend", "common", "frontend"]
75−
76−parseHsSrcDir :: FilePath -- ^ package cabal file path
77− -> IO (Maybe (NE.NonEmpty FilePath)) -- ^ List of hs src dirs of the library component
78−parseHsSrcDir cabalFp = do
79− exists <- doesFileExist cabalFp
80− if exists
81− then do
82− withUTF8FileContents cabalFp $ \cabal -> do
83− case parseGenericPackageDescription cabal of
84− ParseOk warnings gpkg -> do
85− mapM_ print warnings
86− return $ do
87− (_, lib) <- simplifyCondTree (const $ pure True) <$> condLibrary gpkg
88− pure $ fromMaybe (pure ".") $ NE.nonEmpty $ hsSourceDirs $ libBuildInfo lib
89− ParseFailed _ -> return Nothing
90− else return Nothing
39+import Obelisk.Command.Run
9140
9241data Args = Args
9342 { _args_noHandOffPassed :: Bool
lib/command/src/Obelisk/Command/Repl.hs−25
@@ -1,16 +1,10 @@
11{-# LANGUAGE OverloadedStrings #-}
22module Obelisk.Command.Repl
33 ( runRepl
4− , runDev
54 , watch
6− , getFreePort
75 ) where
86
9−import qualified Control.Exception as E
10−import Data.Maybe
117import Data.Monoid ((<>))
12−import Network.Socket
13−import System.Process (callCommand)
148
159import Obelisk.Command.Project
1610
@@ -22,22 +16,3 @@ runRepl dir = inProjectShell "ghc" $ "cd " <> dir <> "; cabal new-repl"
2216watch :: FilePath -> IO ()
2317watch dir = inProjectShell "ghc" $ "cd " <> dir <> "; ghcid -W --command='cabal new-repl'"
2418
25−-- | Dev
26−runDev :: FilePath -> Maybe String -> IO ()
27−runDev dotGhci mcmd = callCommand $ unwords $ "ghcid" : ghcidOpts
28− where
29− ghcidOpts =
30− [ "-W"
31− , "--command='ghci -ghci-script " <> dotGhci <> "' "
32− ] <> maybeToList (flip fmap mcmd $ \cmd -> " --test=$'" <> cmd <> "'")
33−
34−getFreePort :: IO PortNumber
35−getFreePort = withSocketsDo $ do
36− addr:_ <- getAddrInfo (Just defaultHints) (Just "127.0.0.1") (Just "0")
37− E.bracket (open addr) close socketPort
38− where
39− open addr = do
40− sock <- socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr)
41− bind sock (addrAddress addr)
42− return sock
43−
lib/command/src/Obelisk/Command/Run.hsnew file+92
@@ -0,0 +1,92 @@
1+{-# LANGUAGE OverloadedStrings #-}
2+module Obelisk.Command.Run where
3+
4+import qualified Control.Exception as E
5+import Control.Monad
6+import Data.Either
7+import Data.List
8+import Data.Maybe
9+import Data.Monoid
10+import Data.List.NonEmpty as NE
11+import Distribution.Utils.Generic (withUTF8FileContents)
12+import Distribution.PackageDescription.Parse (parseGenericPackageDescription, ParseResult(..))
13+import Distribution.Types.BuildInfo
14+import Distribution.Types.CondTree
15+import Distribution.Types.Library
16+import Distribution.Types.GenericPackageDescription
17+import Network.Socket
18+import System.Directory
19+import System.FilePath
20+import System.IO.Temp (withSystemTempDirectory)
21+import System.Process (callCommand)
22+
23+run :: IO ()
24+run = do
25+ freePort <- getFreePort
26+ pkgs <- getLocalPkgs
27+ (pkgDirErrs, hsSrcDirs) <- fmap partitionEithers $ forM pkgs $ \pkg -> do
28+ let cabalFp = pkg </> pkg <.> "cabal"
29+ xs <- parseHsSrcDir cabalFp
30+ return $ case xs of
31+ Nothing -> Left pkg
32+ Just hsSrcDirs -> Right $ toList $ fmap (pkg </>) hsSrcDirs
33+ when (null hsSrcDirs) $
34+ fail $ "No valid pkgs found in " <> intercalate ", " pkgs
35+ when (not (null pkgDirErrs)) $
36+ putStrLn $ "Failed to find pkgs in " <> intercalate ", " pkgDirErrs
37+ let dotGhci = unlines
38+ [ ":set args --quiet --port " <> show freePort
39+ , ":set -i" <> intercalate ":" (mconcat hsSrcDirs)
40+ , ":add Backend Frontend"
41+ , ":module + Control.Concurrent Obelisk.Widget.Run Frontend Backend"
42+ ]
43+ testCmd = unlines
44+ [ "backendId <- forkIO backend"
45+ , "let conf = defRunConfig { _runConfig_redirectPort = " <> show freePort <> "}"
46+ , "runWidget conf frontend"
47+ , "killThread backendId"
48+ ]
49+ withSystemTempDirectory "ob-ghci" $ \fp -> do
50+ let dotGhciPath = fp </> ".ghci"
51+ writeFile dotGhciPath dotGhci
52+ runDev dotGhciPath $ Just testCmd
53+
54+-- | Relative paths to local packages of an obelisk project
55+-- TODO a way to query this
56+getLocalPkgs :: IO [FilePath]
57+getLocalPkgs = return ["backend", "common", "frontend"]
58+
59+parseHsSrcDir :: FilePath -- ^ package cabal file path
60+ -> IO (Maybe (NE.NonEmpty FilePath)) -- ^ List of hs src dirs of the library component
61+parseHsSrcDir cabalFp = do
62+ exists <- doesFileExist cabalFp
63+ if exists
64+ then do
65+ withUTF8FileContents cabalFp $ \cabal -> do
66+ case parseGenericPackageDescription cabal of
67+ ParseOk warnings gpkg -> do
68+ mapM_ print warnings
69+ return $ do
70+ (_, lib) <- simplifyCondTree (const $ pure True) <$> condLibrary gpkg
71+ pure $ fromMaybe (pure ".") $ NE.nonEmpty $ hsSourceDirs $ libBuildInfo lib
72+ ParseFailed _ -> return Nothing
73+ else return Nothing
74+
75+-- | Dev
76+runDev :: FilePath -> Maybe String -> IO ()
77+runDev dotGhci mcmd = callCommand $ unwords $ "ghcid" : ghcidOpts
78+ where
79+ ghcidOpts =
80+ [ "-W"
81+ , "--command='ghci -ghci-script " <> dotGhci <> "' "
82+ ] <> maybeToList (flip fmap mcmd $ \cmd -> " --test=$'" <> cmd <> "'")
83+
84+getFreePort :: IO PortNumber
85+getFreePort = withSocketsDo $ do
86+ addr:_ <- getAddrInfo (Just defaultHints) (Just "127.0.0.1") (Just "0")
87+ E.bracket (open addr) close socketPort
88+ where
89+ open addr = do
90+ sock <- socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr)
91+ bind sock (addrAddress addr)
92+ return sock