1{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE FlexibleContexts #-}
3module Obelisk.Command.Run where
5import qualified Control.Exception as E
9import Control.Monad.Reader (ask)
11import Control.Monad.IO.Class (liftIO)
13import qualified Data.Text as T
14import Data.List.NonEmpty as NE
15import Distribution.Utils.Generic (withUTF8FileContents)
16import Distribution.PackageDescription.Parse (parseGenericPackageDescription, ParseResult(..))
17import Distribution.Types.BuildInfo
18import Distribution.Types.CondTree
19import Distribution.Types.Library
20import Distribution.Types.GenericPackageDescription
22import System.Directory
24import System.IO.Temp (withSystemTempDirectory)
25import System.Process (callCommand)
27import Obelisk.App (MonadObelisk, ObeliskT, runObelisk)
28import Obelisk.CLI (putLog, failWith, Severity(..))
30-- NOTE: `run` is not polymorphic like the rest because we use StaticPtr to invoke it.
33 freePort <- liftIO getFreePort
34 pkgs <- liftIO getLocalPkgs
35 (pkgDirErrs, hsSrcDirs) <- fmap partitionEithers $ forM pkgs $ \pkg -> do
36 let cabalFp = pkg </> pkg <.> "cabal"
37 xs <- parseHsSrcDir cabalFp
40 Just hsSrcDirs -> Right $ toList $ fmap (pkg </>) hsSrcDirs
41 when (null hsSrcDirs) $
42 failWith $ T.pack $ "No valid pkgs found in " <> intercalate ", " pkgs
43 when (not (null pkgDirErrs)) $
44 putLog Warning $ T.pack $ "Failed to find pkgs in " <> intercalate ", " pkgDirErrs
46 [ ":set -i" <> intercalate ":" (mconcat hsSrcDirs)
47 , ":add Backend Frontend"
48 , ":module + Obelisk.Run Frontend Backend"
50 testCmd = unwords ["Obelisk.Run.run", show freePort , "backend", "frontend"]
51 withSystemTempDirectory "ob-ghci" $ \fp -> do
52 let dotGhciPath = fp </> ".ghci"
54 writeFile dotGhciPath dotGhci
55 runDev dotGhciPath $ Just testCmd
57-- | Relative paths to local packages of an obelisk project
58-- TODO a way to query this
59getLocalPkgs :: IO [FilePath]
60getLocalPkgs = return ["backend", "common", "frontend"]
64 => FilePath -- ^ package cabal file path
65 -> m (Maybe (NE.NonEmpty FilePath)) -- ^ List of hs src dirs of the library component
66parseHsSrcDir cabalFp = do
67 exists <- liftIO $ doesFileExist cabalFp
71 liftIO $ withUTF8FileContents cabalFp $ \cabal -> runObelisk c $ do
72 case parseGenericPackageDescription cabal of
73 ParseOk warnings gpkg -> do
74 mapM_ (putLog Warning) $ fmap (T.pack . show) warnings
76 (_, lib) <- simplifyCondTree (const $ pure True) <$> condLibrary gpkg
77 pure $ fromMaybe (pure ".") $ NE.nonEmpty $ hsSourceDirs $ libBuildInfo lib
79 putLog Error $ T.pack $ "Failed to parse cabal file: " <> show e
84runDev :: FilePath -> Maybe String -> IO ()
85runDev dotGhci mcmd = callCommand $ unwords $ "ghcid" : ghcidOpts
89 , "--command='ghci -ghci-script " <> dotGhci <> "' "
91 , "--outputfile=ghcid-output.txt"
92 ] <> maybeToList (flip fmap mcmd $ \cmd -> "--test='" <> cmd <> "'")
94getFreePort :: IO PortNumber
95getFreePort = withSocketsDo $ do
96 addr:_ <- getAddrInfo (Just defaultHints) (Just "127.0.0.1") (Just "0")
97 E.bracket (open addr) close socketPort
100 sock <- socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr)
101 bind sock (addrAddress addr)
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list