{- | You'll likely want to import this if you're
 using Procex for your shell, though you'll
 likely want to customize your 'promptFunction'
 some time.
-}
module Procex.Shell (promptFunction, initInteractive, cd) where

import System.IO
import System.Posix.Directory
import System.Posix.Env

{- | For some ungodly reason, cd-ing inside ghci won't change the cwd of ghci itself,
 so completion, etc. will always happen from the directory you started ghci in.
 This is a quick hack to work around this by also running changeWorkingDirectory
 "above" the shell.

 Do `:set prompt-function promptFunction` in GHCi
-}
promptFunction :: [String] -> Int -> IO String
promptFunction :: [String] -> Int -> IO String
promptFunction [String]
_modules Int
_line = do
  String
d <- String -> String -> IO String
getEnvDefault String
"PWD" String
""
  String -> IO ()
changeWorkingDirectory String
d
  forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ String
d forall a. Semigroup a => a -> a -> a
<> String
": "

-- | You need to run this if you want stdin to work properly inside ghci.
initInteractive :: IO ()
initInteractive :: IO ()
initInteractive = Handle -> BufferMode -> IO ()
hSetBuffering Handle
stdin BufferMode
LineBuffering

{- | This goes hand-in-hand with 'promptFunction'. It is a standard
 'System.Posix.Directory.changeWorkingDirectory', but it sets "PWD" in the environment too.
-}
cd :: String -> IO ()
cd :: String -> IO ()
cd String
x = String -> IO ()
changeWorkingDirectory String
x forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> IO String
getWorkingDirectory forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \String
d -> String -> String -> Bool -> IO ()
setEnv String
"PWD" String
d Bool
True