module System.ReadEditor ( -- * Main exports readEditor , openEditor , openEditorWithPrompt -- * Utility , prompt , withSystemTempFile ) where import Control.Exception (finally) import System.Directory (getTemporaryDirectory, removeFile) import System.Environment (getEnv) import System.IO (Handle, hClose, hFlush, openTempFile, stdout) import System.IO.Error (catchIOError) import System.Process (system) -- | Opens a file in the sytem's editor and returns it's contents after it's saved. readEditor :: IO String readEditor = withSystemTempFile "read-editor" $ \fp _ -> do openEditor fp readFile fp -- | Opens a file in the sytem's editor, waits until it's closed. openEditor :: FilePath -> IO () openEditor = openEditorWithPrompt "What editor should I use? " -- | A version of 'openEditor' which takes the fallback prompt question. openEditorWithPrompt :: String -> FilePath -> IO () openEditorWithPrompt p fp = do editorCmd <- catchIOError (getEnv "EDITOR") (const promptForEditor) _ <- system $ editorCmd ++ " " ++ fp return () where promptForEditor = prompt p -- | Prompts for a line and returns it prompt :: String -> IO String prompt str = do putStr str hFlush stdout getLine -- | Executes a function with an open temporary file Handle. withSystemTempFile :: String -> (FilePath -> Handle -> IO a) -> IO a withSystemTempFile templ fn = do tempdir <- catchIOError getTemporaryDirectory (\_ -> return ".") (tempfile, temph) <- openTempFile tempdir templ finally (fn tempfile temph) (hClose temph >> removeFile tempfile)