-- | 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
  String -> IO String
forall (f :: * -> *) a. Applicative f => a -> f a
pure (String -> IO String) -> String -> IO String
forall a b. (a -> b) -> a -> b
$ String
d String -> String -> String
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 IO () -> IO String -> IO String
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> IO String
getWorkingDirectory IO String -> (String -> IO ()) -> IO ()
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