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 :: String
srcLocModule :: String
srcLocFile :: String
srcLocStartLine :: Int
srcLocStartCol :: Int
srcLocEndLine :: Int
srcLocEndCol :: Int
srcLocPackage :: SrcLoc -> String
srcLocModule :: SrcLoc -> String
srcLocFile :: SrcLoc -> String
srcLocStartLine :: SrcLoc -> Int
srcLocStartCol :: SrcLoc -> Int
srcLocEndLine :: SrcLoc -> Int
srcLocEndCol :: SrcLoc -> Int
..}) = 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 a. Maybe a -> Maybe a -> Maybe a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Maybe String
terminalUIDefaultEditor

  case Maybe String
maybeEditor of
    Maybe String
Nothing -> () -> IO ()
forall a. a -> IO a
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
& HasCallStack => Text -> Text -> Text -> Text
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
& HasCallStack => Text -> Text -> Text -> Text
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 = True })
      ProcessHandle -> IO ExitCode
waitForProcess ProcessHandle
p IO ExitCode -> (ExitCode -> IO ()) -> IO ()
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
        ExitCode
ExitSuccess -> () -> IO ()
forall a. a -> IO a
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 = HasCallStack => Text -> Text -> Text -> Text
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
"'"

-- elisp = [i|(progn
--              (x-focus-frame (selected-frame))
--              (raise-frame)
--              (recenter)
--              )|]