{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
module Test.Sandwich.Formatters.TerminalUI.OpenInEditor where
import Control.Applicative
import Data.Function
import qualified Data.Text as T
import GHC.Stack
import System.Environment
import System.Exit
import System.Process
autoOpenInEditor :: Maybe String -> (T.Text -> IO ()) -> SrcLoc -> IO ()
autoOpenInEditor :: Maybe String -> (Text -> IO ()) -> SrcLoc -> IO ()
autoOpenInEditor Maybe String
terminalUIDefaultEditor Text -> IO ()
debugFn (SrcLoc {Int
String
srcLocPackage :: SrcLoc -> String
srcLocModule :: SrcLoc -> String
srcLocFile :: SrcLoc -> String
srcLocStartLine :: SrcLoc -> Int
srcLocStartCol :: SrcLoc -> Int
srcLocEndLine :: SrcLoc -> Int
srcLocEndCol :: SrcLoc -> Int
srcLocEndCol :: Int
srcLocEndLine :: Int
srcLocStartCol :: Int
srcLocStartLine :: Int
srcLocFile :: String
srcLocModule :: String
srcLocPackage :: String
..}) = do
Maybe String
maybeEditor' <- String -> IO (Maybe String)
lookupEnv String
"EDITOR"
let maybeEditor :: Maybe String
maybeEditor = Maybe String
maybeEditor' Maybe String -> Maybe String -> Maybe String
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Maybe String
terminalUIDefaultEditor
case Maybe String
maybeEditor of
Maybe String
Nothing -> () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
Just String
editorString -> do
let editor :: String
editor = String
editorString
String -> (String -> Text) -> Text
forall a b. a -> (a -> b) -> b
& String -> Text
T.pack
Text -> (Text -> Text) -> Text
forall a b. a -> (a -> b) -> b
& Text -> Text -> Text -> Text
T.replace Text
"LINE" (String -> Text
T.pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ Int -> String
forall a. Show a => a -> String
show Int
srcLocStartLine)
Text -> (Text -> Text) -> Text
forall a b. a -> (a -> b) -> b
& Text -> Text -> Text -> Text
T.replace Text
"COLUMN" (String -> Text
T.pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ Int -> String
forall a. Show a => a -> String
show Int
srcLocStartCol)
Text -> (Text -> Text) -> Text
forall a b. a -> (a -> b) -> b
& Text -> Text
fillInFile
Text -> (Text -> String) -> String
forall a b. a -> (a -> b) -> b
& Text -> String
T.unpack
Text -> IO ()
debugFn (Text
"Opening editor with command: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack String
editor)
(Maybe Handle
_, Maybe Handle
_, Maybe Handle
_, ProcessHandle
p) <- CreateProcess
-> IO (Maybe Handle, Maybe Handle, Maybe Handle, ProcessHandle)
createProcess ((String -> CreateProcess
shell String
editor) { delegate_ctlc :: Bool
delegate_ctlc = Bool
True })
ProcessHandle -> IO ExitCode
waitForProcess ProcessHandle
p IO ExitCode -> (ExitCode -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
ExitCode
ExitSuccess -> () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
ExitFailure Int
n -> Text -> IO ()
debugFn (Text
"Editor failed with exit code " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (Int -> String
forall a. Show a => a -> String
show Int
n))
where
fillInFile :: Text -> Text
fillInFile Text
cmd
| Text
"FILE" Text -> Text -> Bool
`T.isInfixOf` Text
cmd = Text -> Text -> Text -> Text
T.replace Text
"FILE" (String -> Text
T.pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ String -> String
forall a. Show a => a -> String
show String
srcLocFile) Text
cmd
| Bool
otherwise = Text
cmd Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" '" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack String
srcLocFile Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"'"