-- GHCi customization file

-- vim: syntax=haskell expandtab

-- some sections are comented out with comments starting with -- &,
-- so you can uncomment them by removing this prefix to enamble them
-- note: block comments do not work here, the same holds for layout rule


-- Save to ~/.ghc/ghci.conf
-- Most of the code was taken from the official Haskell wiki.
-- https://wiki.haskell.org/GHC/GHCi

-- set coloured prompt with loaded modules on separate line
-- <https://coderwall.com/p/13h9bw/colored-ghci-prompt-with-and-modules-on-separate-lines>
-- :set prompt "\ESC[1;34m%s\n\ESC[0;34m\x03BB> \ESC[m"
--             -bold-blue-    -blue---- -lambda -black-

-- Set all warning on by default
-- but disable type defaults warning
:set -Wall
:set -Wno-type-defaults

-- The following definitions were taken from "getting more out of ghci", the mini-tutorial
-- <https://mail.haskell.org/pipermail/haskell-cafe/2007-September/032260.html>

-- make commands helpful
:{
let { cmdHelp _   msg "--help" = return $ "putStrLn " ++ show msg
    ; cmdHelp cmd _   other    = cmd other }
:}

-- :pwd, :ls
let pwd _ = return "System.Directory.getCurrentDirectory >>= putStrLn"
:def pwd cmdHelp pwd ":pwd\t\t\t-- print working directory"
:{
let ls p  = return $ "mapM_ putStrLn =<< System.Directory.getDirectoryContents "++show path
            where {path = if (null p) then "." else p}
:}
:def ls cmdHelp ls ":ls [<path>]\t\t-- list directory (\".\" by default)"

-- :redir
:{
let redir varcmd =
     case break Data.Char.isSpace varcmd of
     { (var,_:cmd) -> return $ unlines
        [":set -fno-print-bind-result"
        ,"tmp <- System.Directory.getTemporaryDirectory"
        ,"(f,h) <- System.IO.openTempFile tmp \"ghci\""
        ,"sto <- GHC.IO.Handle.hDuplicate System.IO.stdout"
        ,"GHC.IO.Handle.hDuplicateTo h System.IO.stdout"
        ,"System.IO.hClose h"
        ,cmd
        ,"GHC.IO.Handle.hDuplicateTo sto System.IO.stdout"
        ,"let readFileNow f = readFile f >>= \\t->length t `seq` return t"
        ,var++" <- readFileNow f"
        ,"System.Directory.removeFile f"]
      ; _ -> return "putStrLn \"usage: :redir <var> <cmd>\"" }
:}
:def redir cmdHelp redir ":redir <var> <cmd>\t-- execute <cmd>, redirecting stdout to <var>"

-- :hlint
-- requires hlint executable in PATH
-- tries to load ~/.ghc/HLint.hs with additional hints
:{
:def hlint \extra -> return $ unlines
        [":unset +t +s"
        ,":set -w"
        ,":redir hlintvar1 :show modules"
        ,":cmd return $ \":! hlint --color --hint ~/.ghc/HLint.hs \" ++ unwords (map (takeWhile (/=',') . drop 2 . dropWhile (/= '(')) $ lines hlintvar1) ++ \" \" ++ " ++ show extra
        ]
:}