{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE CPP #-}
-----------------------------------------------------------------------------
-- |
-- Module      : System.Taffybar.Util
-- Copyright   : (c) Ivan A. Malison
-- License     : BSD3-style (see LICENSE)
--
-- Maintainer  : Ivan A. Malison
-- Stability   : unstable
-- Portability : unportable
-----------------------------------------------------------------------------

module System.Taffybar.Util where

import           Conduit
import           Control.Applicative
import           Control.Arrow ((&&&))
import           Control.Concurrent
import           Control.Exception.Base
import           Control.Monad
import           Control.Monad.Trans.Maybe
import           Control.Monad.Trans.Reader
import           Data.Either.Combinators
import           Data.GI.Base.GError
import           Control.Exception.Enclosed (catchAny)
import qualified Data.GI.Gtk.Threading as Gtk
import           Data.Maybe
import qualified Data.Text as T
import           Data.Tuple.Sequence
import qualified GI.GdkPixbuf.Objects.Pixbuf as Gdk
import           Network.HTTP.Simple
import           System.Directory
import           System.Environment.XDG.BaseDir
import           System.Exit (ExitCode (..))
import           System.FilePath.Posix
import           System.Log.Logger
import qualified System.Process as P
import           Text.Printf


taffyStateDir :: IO FilePath
taffyStateDir :: IO FilePath
taffyStateDir = FilePath -> IO FilePath
getUserDataDir FilePath
"taffybar"

liftReader ::
  Monad m => (m1 a -> m b) -> ReaderT r m1 a -> ReaderT r m b
liftReader :: forall (m :: * -> *) (m1 :: * -> *) a b r.
Monad m =>
(m1 a -> m b) -> ReaderT r m1 a -> ReaderT r m b
liftReader m1 a -> m b
modifier ReaderT r m1 a
action =
  ReaderT r m r
forall (m :: * -> *) r. Monad m => ReaderT r m r
ask ReaderT r m r -> (r -> ReaderT r m b) -> ReaderT r m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= m b -> ReaderT r m b
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m b -> ReaderT r m b) -> (r -> m b) -> r -> ReaderT r m b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. m1 a -> m b
modifier (m1 a -> m b) -> (r -> m1 a) -> r -> m b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ReaderT r m1 a -> r -> m1 a
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT ReaderT r m1 a
action

logPrintF
  :: (MonadIO m, Show t)
  => String -> Priority -> String -> t -> m ()
logPrintF :: forall (m :: * -> *) t.
(MonadIO m, Show t) =>
FilePath -> Priority -> FilePath -> t -> m ()
logPrintF FilePath
logPath Priority
priority FilePath
format t
toPrint =
  IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ FilePath -> Priority -> FilePath -> IO ()
logM FilePath
logPath Priority
priority (FilePath -> IO ()) -> FilePath -> IO ()
forall a b. (a -> b) -> a -> b
$ FilePath -> FilePath -> FilePath
forall r. PrintfType r => FilePath -> r
printf FilePath
format (FilePath -> FilePath) -> FilePath -> FilePath
forall a b. (a -> b) -> a -> b
$ t -> FilePath
forall a. Show a => a -> FilePath
show t
toPrint

logPrintFDebug :: (MonadIO m, Show t) => String -> String -> t -> m ()
logPrintFDebug :: forall (m :: * -> *) t.
(MonadIO m, Show t) =>
FilePath -> FilePath -> t -> m ()
logPrintFDebug FilePath
path = FilePath -> Priority -> FilePath -> t -> m ()
forall (m :: * -> *) t.
(MonadIO m, Show t) =>
FilePath -> Priority -> FilePath -> t -> m ()
logPrintF FilePath
path Priority
DEBUG

infixl 4 ??
(??) :: Functor f => f (a -> b) -> a -> f b
f (a -> b)
fab ?? :: forall (f :: * -> *) a b. Functor f => f (a -> b) -> a -> f b
?? a
a = ((a -> b) -> b) -> f (a -> b) -> f b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((a -> b) -> a -> b
forall a b. (a -> b) -> a -> b
$ a
a) f (a -> b)
fab
{-# INLINE (??) #-}

ifM :: Monad m => m Bool -> m a -> m a -> m a
ifM :: forall (m :: * -> *) a. Monad m => m Bool -> m a -> m a -> m a
ifM m Bool
cond m a
whenTrue m a
whenFalse =
  m Bool
cond m Bool -> (Bool -> m a) -> m a
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (\Bool
bool -> if Bool
bool then m a
whenTrue else m a
whenFalse)

forkM :: Monad m => (c -> m a) -> (c -> m b) -> c -> m (a, b)
forkM :: forall (m :: * -> *) c a b.
Monad m =>
(c -> m a) -> (c -> m b) -> c -> m (a, b)
forkM c -> m a
a c -> m b
b = (m a, m b) -> m (a, b)
forall a b. SequenceT a b => a -> b
sequenceT ((m a, m b) -> m (a, b)) -> (c -> (m a, m b)) -> c -> m (a, b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (c -> m a
a (c -> m a) -> (c -> m b) -> c -> (m a, m b)
forall (a :: * -> * -> *) b c c'.
Arrow a =>
a b c -> a b c' -> a b (c, c')
&&& c -> m b
b)

maybeToEither :: b -> Maybe a -> Either b a
maybeToEither :: forall b a. b -> Maybe a -> Either b a
maybeToEither = (Either b a -> (a -> Either b a) -> Maybe a -> Either b a)
-> (a -> Either b a) -> Either b a -> Maybe a -> Either b a
forall a b c. (a -> b -> c) -> b -> a -> c
flip Either b a -> (a -> Either b a) -> Maybe a -> Either b a
forall b a. b -> (a -> b) -> Maybe a -> b
maybe a -> Either b a
forall a b. b -> Either a b
Right (Either b a -> Maybe a -> Either b a)
-> (b -> Either b a) -> b -> Maybe a -> Either b a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. b -> Either b a
forall a b. a -> Either a b
Left

truncateString :: Int -> String -> String
truncateString :: Int -> FilePath -> FilePath
truncateString Int
n FilePath
incoming
  | FilePath -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length FilePath
incoming Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
n = FilePath
incoming
  | Bool
otherwise = Int -> FilePath -> FilePath
forall a. Int -> [a] -> [a]
take Int
n FilePath
incoming FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"…"

truncateText :: Int -> T.Text -> T.Text
truncateText :: Int -> Text -> Text
truncateText Int
n Text
incoming
  | Text -> Int
T.length Text
incoming Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
n = Text
incoming
  | Bool
otherwise = Text -> Text -> Text
T.append (Int -> Text -> Text
T.take Int
n Text
incoming) Text
"…"

runCommandFromPath :: MonadIO m => [String] -> m (Either String String)
runCommandFromPath :: forall (m :: * -> *).
MonadIO m =>
[FilePath] -> m (Either FilePath FilePath)
runCommandFromPath = FilePath -> [FilePath] -> m (Either FilePath FilePath)
forall (m :: * -> *).
MonadIO m =>
FilePath -> [FilePath] -> m (Either FilePath FilePath)
runCommand FilePath
"/usr/bin/env"

-- | Run the provided command with the provided arguments.
runCommand :: MonadIO m => FilePath -> [String] -> m (Either String String)
runCommand :: forall (m :: * -> *).
MonadIO m =>
FilePath -> [FilePath] -> m (Either FilePath FilePath)
runCommand FilePath
cmd [FilePath]
args = IO (Either FilePath FilePath) -> m (Either FilePath FilePath)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Either FilePath FilePath) -> m (Either FilePath FilePath))
-> IO (Either FilePath FilePath) -> m (Either FilePath FilePath)
forall a b. (a -> b) -> a -> b
$ do
  (ExitCode
ecode, FilePath
stdout, FilePath
stderr) <- FilePath
-> [FilePath] -> FilePath -> IO (ExitCode, FilePath, FilePath)
P.readProcessWithExitCode FilePath
cmd [FilePath]
args FilePath
""
  FilePath -> Priority -> FilePath -> IO ()
logM FilePath
"System.Taffybar.Util" Priority
INFO (FilePath -> IO ()) -> FilePath -> IO ()
forall a b. (a -> b) -> a -> b
$
       FilePath -> FilePath -> FilePath -> FilePath
forall r. PrintfType r => FilePath -> r
printf FilePath
"Running command %s with args %s" (FilePath -> FilePath
forall a. Show a => a -> FilePath
show FilePath
cmd) ([FilePath] -> FilePath
forall a. Show a => a -> FilePath
show [FilePath]
args)
  Either FilePath FilePath -> IO (Either FilePath FilePath)
forall (m :: * -> *) a. Monad m => a -> m a
return (Either FilePath FilePath -> IO (Either FilePath FilePath))
-> Either FilePath FilePath -> IO (Either FilePath FilePath)
forall a b. (a -> b) -> a -> b
$ case ExitCode
ecode of
    ExitCode
ExitSuccess -> FilePath -> Either FilePath FilePath
forall a b. b -> Either a b
Right FilePath
stdout
    ExitFailure Int
exitCode -> FilePath -> Either FilePath FilePath
forall a b. a -> Either a b
Left (FilePath -> Either FilePath FilePath)
-> FilePath -> Either FilePath FilePath
forall a b. (a -> b) -> a -> b
$ FilePath -> FilePath -> FilePath -> FilePath
forall r. PrintfType r => FilePath -> r
printf FilePath
"Exit code %s: %s " (Int -> FilePath
forall a. Show a => a -> FilePath
show Int
exitCode) FilePath
stderr

-- | Execute the provided IO action at the provided interval.
foreverWithDelay :: (MonadIO m, RealFrac d) => d -> IO () -> m ThreadId
foreverWithDelay :: forall (m :: * -> *) d.
(MonadIO m, RealFrac d) =>
d -> IO () -> m ThreadId
foreverWithDelay d
delay IO ()
action =
  IO d -> m ThreadId
forall (m :: * -> *) d.
(MonadIO m, RealFrac d) =>
IO d -> m ThreadId
foreverWithVariableDelay (IO d -> m ThreadId) -> IO d -> m ThreadId
forall a b. (a -> b) -> a -> b
$ IO ()
safeAction IO () -> IO d -> IO d
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> d -> IO d
forall (m :: * -> *) a. Monad m => a -> m a
return d
delay
  where safeAction :: IO ()
safeAction =
          IO () -> (SomeException -> IO ()) -> IO ()
forall (m :: * -> *) a.
MonadBaseControl IO m =>
m a -> (SomeException -> m a) -> m a
catchAny IO ()
action ((SomeException -> IO ()) -> IO ())
-> (SomeException -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \SomeException
e ->
            FilePath -> Priority -> FilePath -> SomeException -> IO ()
forall (m :: * -> *) t.
(MonadIO m, Show t) =>
FilePath -> Priority -> FilePath -> t -> m ()
logPrintF FilePath
"System.Taffybar.Util" Priority
WARNING FilePath
"Error in foreverWithDelay %s" SomeException
e

-- | Execute the provided IO action, and use the value it returns to decide how
-- long to wait until executing it again. The value returned by the action is
-- interpreted as a number of seconds.
foreverWithVariableDelay :: (MonadIO m, RealFrac d) => IO d -> m ThreadId
foreverWithVariableDelay :: forall (m :: * -> *) d.
(MonadIO m, RealFrac d) =>
IO d -> m ThreadId
foreverWithVariableDelay IO d
action = IO ThreadId -> m ThreadId
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO ThreadId -> m ThreadId) -> IO ThreadId -> m ThreadId
forall a b. (a -> b) -> a -> b
$ IO () -> IO ThreadId
forkIO (IO () -> IO ThreadId) -> IO () -> IO ThreadId
forall a b. (a -> b) -> a -> b
$ IO d
action IO d -> (d -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= d -> IO ()
delayThenAction
  where delayThenAction :: d -> IO ()
delayThenAction d
delay =
          Int -> IO ()
threadDelay (d -> Int
forall a b. (RealFrac a, Integral b) => a -> b
floor (d -> Int) -> d -> Int
forall a b. (a -> b) -> a -> b
$ d
delay d -> d -> d
forall a. Num a => a -> a -> a
* d
1000000) IO () -> IO d -> IO d
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> IO d
action IO d -> (d -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= d -> IO ()
delayThenAction

liftActionTaker
  :: (Monad m)
  => ((a -> m a) -> m b) -> (a -> ReaderT c m a) -> ReaderT c m b
liftActionTaker :: forall (m :: * -> *) a b c.
Monad m =>
((a -> m a) -> m b) -> (a -> ReaderT c m a) -> ReaderT c m b
liftActionTaker (a -> m a) -> m b
actionTaker a -> ReaderT c m a
action = do
  c
ctx <- ReaderT c m c
forall (m :: * -> *) r. Monad m => ReaderT r m r
ask
  m b -> ReaderT c m b
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m b -> ReaderT c m b) -> m b -> ReaderT c m b
forall a b. (a -> b) -> a -> b
$ (a -> m a) -> m b
actionTaker ((a -> m a) -> m b) -> (a -> m a) -> m b
forall a b. (a -> b) -> a -> b
$ (ReaderT c m a -> c -> m a) -> c -> ReaderT c m a -> m a
forall a b c. (a -> b -> c) -> b -> a -> c
flip ReaderT c m a -> c -> m a
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT c
ctx (ReaderT c m a -> m a) -> (a -> ReaderT c m a) -> a -> m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> ReaderT c m a
action

maybeTCombine
  :: Monad m
  => m (Maybe a) -> m (Maybe a) -> m (Maybe a)
maybeTCombine :: forall (m :: * -> *) a.
Monad m =>
m (Maybe a) -> m (Maybe a) -> m (Maybe a)
maybeTCombine m (Maybe a)
a m (Maybe a)
b = MaybeT m a -> m (Maybe a)
forall (m :: * -> *) a. MaybeT m a -> m (Maybe a)
runMaybeT (MaybeT m a -> m (Maybe a)) -> MaybeT m a -> m (Maybe a)
forall a b. (a -> b) -> a -> b
$ m (Maybe a) -> MaybeT m a
forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
MaybeT m (Maybe a)
a MaybeT m a -> MaybeT m a -> MaybeT m a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> m (Maybe a) -> MaybeT m a
forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
MaybeT m (Maybe a)
b

infixl 3 <||>
(<||>) ::
  Monad m =>
  (t -> m (Maybe a)) -> (t -> m (Maybe a)) -> t -> m (Maybe a)
t -> m (Maybe a)
a <||> :: forall (m :: * -> *) t a.
Monad m =>
(t -> m (Maybe a)) -> (t -> m (Maybe a)) -> t -> m (Maybe a)
<||> t -> m (Maybe a)
b = t -> m (Maybe a)
combineOptions
  where combineOptions :: t -> m (Maybe a)
combineOptions t
v = m (Maybe a) -> m (Maybe a) -> m (Maybe a)
forall (m :: * -> *) a.
Monad m =>
m (Maybe a) -> m (Maybe a) -> m (Maybe a)
maybeTCombine (t -> m (Maybe a)
a t
v) (t -> m (Maybe a)
b t
v)

infixl 3 <|||>
(<|||>)
  :: Monad m
  => (t -> t1 -> m (Maybe a))
  -> (t -> t1 -> m (Maybe a))
  -> t
  -> t1
  -> m (Maybe a)
t -> t1 -> m (Maybe a)
a <|||> :: forall (m :: * -> *) t t1 a.
Monad m =>
(t -> t1 -> m (Maybe a))
-> (t -> t1 -> m (Maybe a)) -> t -> t1 -> m (Maybe a)
<|||> t -> t1 -> m (Maybe a)
b = t -> t1 -> m (Maybe a)
combineOptions
  where combineOptions :: t -> t1 -> m (Maybe a)
combineOptions t
v t1
v1 = m (Maybe a) -> m (Maybe a) -> m (Maybe a)
forall (m :: * -> *) a.
Monad m =>
m (Maybe a) -> m (Maybe a) -> m (Maybe a)
maybeTCombine (t -> t1 -> m (Maybe a)
a t
v t1
v1) (t -> t1 -> m (Maybe a)
b t
v t1
v1)

catchGErrorsAsLeft :: IO a -> IO (Either GError a)
catchGErrorsAsLeft :: forall a. IO a -> IO (Either GError a)
catchGErrorsAsLeft IO a
action = IO (Either GError a)
-> (GError -> IO (Either GError a)) -> IO (Either GError a)
forall e a. Exception e => IO a -> (e -> IO a) -> IO a
catch (a -> Either GError a
forall a b. b -> Either a b
Right (a -> Either GError a) -> IO a -> IO (Either GError a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO a
action) (Either GError a -> IO (Either GError a)
forall (m :: * -> *) a. Monad m => a -> m a
return (Either GError a -> IO (Either GError a))
-> (GError -> Either GError a) -> GError -> IO (Either GError a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. GError -> Either GError a
forall a b. a -> Either a b
Left)

catchGErrorsAsNothing :: IO a -> IO (Maybe a)
catchGErrorsAsNothing :: forall a. IO a -> IO (Maybe a)
catchGErrorsAsNothing = (Either GError a -> Maybe a)
-> IO (Either GError a) -> IO (Maybe a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Either GError a -> Maybe a
forall a b. Either a b -> Maybe b
rightToMaybe (IO (Either GError a) -> IO (Maybe a))
-> (IO a -> IO (Either GError a)) -> IO a -> IO (Maybe a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO a -> IO (Either GError a)
forall a. IO a -> IO (Either GError a)
catchGErrorsAsLeft

safePixbufNewFromFile :: FilePath -> IO (Maybe Gdk.Pixbuf)
safePixbufNewFromFile :: FilePath -> IO (Maybe Pixbuf)
safePixbufNewFromFile =
  IO (Maybe (Maybe Pixbuf)) -> IO (Maybe Pixbuf)
forall {a}. IO (Maybe (Maybe a)) -> IO (Maybe a)
handleResult (IO (Maybe (Maybe Pixbuf)) -> IO (Maybe Pixbuf))
-> (FilePath -> IO (Maybe (Maybe Pixbuf)))
-> FilePath
-> IO (Maybe Pixbuf)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IO (Maybe Pixbuf) -> IO (Maybe (Maybe Pixbuf))
forall a. IO a -> IO (Maybe a)
catchGErrorsAsNothing (IO (Maybe Pixbuf) -> IO (Maybe (Maybe Pixbuf)))
-> (FilePath -> IO (Maybe Pixbuf))
-> FilePath
-> IO (Maybe (Maybe Pixbuf))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> IO (Maybe Pixbuf)
forall (m :: * -> *).
(HasCallStack, MonadIO m) =>
FilePath -> m (Maybe Pixbuf)
Gdk.pixbufNewFromFile
  where
#if MIN_VERSION_gi_gdkpixbuf(2,0,26)
    handleResult :: IO (Maybe (Maybe a)) -> IO (Maybe a)
handleResult = (Maybe (Maybe a) -> Maybe a)
-> IO (Maybe (Maybe a)) -> IO (Maybe a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Maybe (Maybe a) -> Maybe a
forall (m :: * -> *) a. Monad m => m (m a) -> m a
join
#else
    handleResult = id
#endif

getPixbufFromFilePath :: FilePath -> IO (Maybe Gdk.Pixbuf)
getPixbufFromFilePath :: FilePath -> IO (Maybe Pixbuf)
getPixbufFromFilePath FilePath
filepath = do
  Maybe Pixbuf
result <- FilePath -> IO (Maybe Pixbuf)
safePixbufNewFromFile FilePath
filepath
  Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Maybe Pixbuf -> Bool
forall a. Maybe a -> Bool
isNothing Maybe Pixbuf
result) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
       FilePath -> Priority -> FilePath -> IO ()
logM FilePath
"System.Taffybar.WindowIcon" Priority
WARNING (FilePath -> IO ()) -> FilePath -> IO ()
forall a b. (a -> b) -> a -> b
$
            FilePath -> FilePath -> FilePath
forall r. PrintfType r => FilePath -> r
printf FilePath
"Failed to load icon from filepath %s" FilePath
filepath
  Maybe Pixbuf -> IO (Maybe Pixbuf)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe Pixbuf
result

downloadURIToPath :: Request -> FilePath -> IO ()
downloadURIToPath :: Request -> FilePath -> IO ()
downloadURIToPath Request
uri FilePath
filepath =
  Bool -> FilePath -> IO ()
createDirectoryIfMissing Bool
True FilePath
directory IO () -> IO () -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>>
  ConduitT () Void (ResourceT IO) () -> IO ()
forall (m :: * -> *) r.
MonadUnliftIO m =>
ConduitT () Void (ResourceT m) r -> m r
runConduitRes (Request
-> (Response (ConduitM () ByteString (ResourceT IO) ())
    -> ConduitM () ByteString (ResourceT IO) ())
-> ConduitM () ByteString (ResourceT IO) ()
forall (m :: * -> *) (n :: * -> *) i o r.
(MonadResource m, MonadIO n) =>
Request
-> (Response (ConduitM i ByteString n ()) -> ConduitM i o m r)
-> ConduitM i o m r
httpSource Request
uri Response (ConduitM () ByteString (ResourceT IO) ())
-> ConduitM () ByteString (ResourceT IO) ()
forall a. Response a -> a
getResponseBody ConduitM () ByteString (ResourceT IO) ()
-> ConduitM ByteString Void (ResourceT IO) ()
-> ConduitT () Void (ResourceT IO) ()
forall (m :: * -> *) a b c r.
Monad m =>
ConduitM a b m () -> ConduitM b c m r -> ConduitM a c m r
.| FilePath -> ConduitM ByteString Void (ResourceT IO) ()
forall (m :: * -> *) o.
MonadResource m =>
FilePath -> ConduitT ByteString o m ()
sinkFile FilePath
filepath)
  where (FilePath
directory, FilePath
_) = FilePath -> (FilePath, FilePath)
splitFileName FilePath
filepath

postGUIASync :: IO () -> IO ()
postGUIASync :: IO () -> IO ()
postGUIASync = IO () -> IO ()
Gtk.postGUIASync

postGUISync :: IO () -> IO ()
postGUISync :: IO () -> IO ()
postGUISync = IO () -> IO ()
forall a. IO a -> IO a
Gtk.postGUISync

anyM :: (Monad m) => (a -> m Bool) -> [a] -> m Bool
anyM :: forall (m :: * -> *) a. Monad m => (a -> m Bool) -> [a] -> m Bool
anyM a -> m Bool
_ [] = Bool -> m Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
anyM a -> m Bool
p (a
x:[a]
xs) = do
  Bool
q <- a -> m Bool
p a
x
  if Bool
q
  then Bool -> m Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
  else (a -> m Bool) -> [a] -> m Bool
forall (m :: * -> *) a. Monad m => (a -> m Bool) -> [a] -> m Bool
anyM a -> m Bool
p [a]
xs