{-| Module: IHP.IDE.ToolServer.Helper.Controller Description: Provides helpers for controllers of the ToolServer Copyright: (c) digitally induced GmbH, 2020 -} module IHP.IDE.ToolServer.Helper.Controller ( theAppPort , openEditor , findWebControllers , findControllers , findApplications , theToolServerApplication , clearDatabaseNeedsMigration , markDatabaseNeedsMigration ) where import IHP.Prelude import IHP.ControllerSupport import IHP.IDE.ToolServer.Types import qualified IHP.IDE.PortConfig as PortConfig import IHP.IDE.Types import qualified Network.Socket as Socket import qualified System.Process as Process import System.Info (os) import qualified IHP.EnvVar as EnvVar import IHP.Controller.Context import System.IO.Unsafe (unsafePerformIO) import qualified Data.Text as Text import System.Directory import qualified Data.Text.IO as IO -- | Returns the port used by the running app. Usually returns @8000@. theAppPort :: (?context :: ControllerContext) => IO Socket.PortNumber theAppPort = do toolServerApplication <- fromContext @ToolServerApplication pure toolServerApplication.appPort openEditor :: Text -> Int -> Int -> IO () openEditor path line col = do (supportsLineAndCol, editor) <- findEditor let command = editor <> " " <> path <> if supportsLineAndCol then ":" <> tshow line <> ":" <> tshow col else "" _ <- Process.system (cs command) unless supportsLineAndCol (putStrLn "Pro Tip: Set the env var IHP_EDITOR to your favorite editor. Then all your files will be opened at the right line and column where the error is reported.") pure () -- | Returns the editor command for the user and also whether the command supports line and col notation -- -- Line and col notation means that calling @editor myfile.hs:10:5@ works. Tools like @xdg-open@ or on macOS @open@ -- don't support this notation and thus need to be called like @xdg-open myfile.hs@ instead of @xdg-open myfile.hs:10:5@ -- -- Looks for a the env vars IHP_EDITOR or EDITOR. As fallback it uses @open@ or @xdg-open@ (depends on OS). -- findEditor :: IO (Bool, Text) findEditor = do ihpEditorEnv <- EnvVar.envOrNothing "IHP_EDITOR" editorEnv <- EnvVar.envOrNothing "EDITOR" pure case catMaybes [ihpEditorEnv, editorEnv] of (editor:_) -> (True, editor) [] -> case os of "linux" -> (False, "xdg-open") "darwin" -> (False, "open") findWebControllers :: IO [Text] findWebControllers = do directoryFiles <- listDirectory "Web/Controller" let controllerFiles :: [Text] = filter (\x -> not $ "Prelude" `isInfixOf` x || "Context" `isInfixOf` x) $ map cs directoryFiles pure $ map (Text.replace ".hs" "") controllerFiles findControllers :: Text -> IO [Text] findControllers application = do directoryFiles <- listDirectory $ cs $ application <> "/Controller" let controllerFiles :: [Text] = filter (\x -> not $ "Prelude" `isInfixOf` x || "Context" `isInfixOf` x) $ map cs directoryFiles pure $ map (Text.replace ".hs" "") controllerFiles findApplications :: IO ([Text]) findApplications = do mainhs <- IO.readFile "Main.hs" let imports = filter (\line -> "import " `isPrefixOf` line && ".FrontController" `isSuffixOf` line) (lines mainhs) pure (map removeImport imports) where removeImport line = Text.replace ".FrontController" "" (Text.replace "import " "" line) theToolServerApplication :: (?context :: ControllerContext) => IO ToolServerApplication theToolServerApplication = fromContext @ToolServerApplication clearDatabaseNeedsMigration :: (?context :: ControllerContext) => IO () clearDatabaseNeedsMigration = do toolServerApp <- theToolServerApplication writeIORef toolServerApp.databaseNeedsMigration False markDatabaseNeedsMigration :: (?context :: ControllerContext) => IO () markDatabaseNeedsMigration = do toolServerApp <- theToolServerApplication writeIORef toolServerApp.databaseNeedsMigration True