{-# LANGUAGE TupleSections, CPP #-}
module Jukebox.Utils where

import System.Process
import System.IO
import System.Exit
import Control.Concurrent
import qualified Data.Set as Set
#if __GLASGOW_HASKELL__ < 710
import Control.Applicative
#endif

usort :: Ord a => [a] -> [a]
--usort = map head . group . sort
usort :: [a] -> [a]
usort = Set a -> [a]
forall a. Set a -> [a]
Set.toAscList (Set a -> [a]) -> ([a] -> Set a) -> [a] -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> Set a
forall a. Ord a => [a] -> Set a
Set.fromList

merge :: Ord a => [a] -> [a] -> [a]
merge :: [a] -> [a] -> [a]
merge [] [a]
ys = [a]
ys
merge [a]
xs [] = [a]
xs
merge (a
x:[a]
xs) (a
y:[a]
ys) =
  case a
x a -> a -> Ordering
forall a. Ord a => a -> a -> Ordering
`compare` a
y of
    Ordering
LT -> a
xa -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a] -> [a] -> [a]
forall a. Ord a => [a] -> [a] -> [a]
merge [a]
xs (a
ya -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a]
ys)
    Ordering
EQ -> a
xa -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a] -> [a] -> [a]
forall a. Ord a => [a] -> [a] -> [a]
merge [a]
xs [a]
ys
    Ordering
GT -> a
ya -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a] -> [a] -> [a]
forall a. Ord a => [a] -> [a] -> [a]
merge (a
xa -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a]
xs) [a]
ys

popen :: FilePath -> [String] -> String -> IO (ExitCode, String)
popen :: FilePath -> [FilePath] -> FilePath -> IO (ExitCode, FilePath)
popen FilePath
prog [FilePath]
args FilePath
inp = do
  (Handle
stdin, Handle
stdout, Handle
stderr_, ProcessHandle
pid) <- FilePath
-> [FilePath]
-> Maybe FilePath
-> Maybe [(FilePath, FilePath)]
-> IO (Handle, Handle, Handle, ProcessHandle)
runInteractiveProcess FilePath
prog [FilePath]
args Maybe FilePath
forall a. Maybe a
Nothing Maybe [(FilePath, FilePath)]
forall a. Maybe a
Nothing
  IO () -> IO ThreadId
forkIO (IO () -> IO ThreadId) -> IO () -> IO ThreadId
forall a b. (a -> b) -> a -> b
$ Handle -> IO FilePath
hGetContents Handle
stderr_ IO FilePath -> (FilePath -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Handle -> FilePath -> IO ()
hPutStr Handle
stderr
  Handle -> FilePath -> IO ()
hPutStr Handle
stdin FilePath
inp
  Handle -> IO ()
hFlush Handle
stdin
  Handle -> IO ()
hClose Handle
stdin
  ExitCode
code <- ProcessHandle -> IO ExitCode
waitForProcess ProcessHandle
pid
  (FilePath -> (ExitCode, FilePath))
-> IO FilePath -> IO (ExitCode, FilePath)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (ExitCode
code,) (Handle -> IO FilePath
hGetContents Handle
stdout)