{-# LANGUAGE CPP #-}
module Xmobar.System.Utils
( expandHome
, changeLoop
, onSomeException
, safeIndex
) where
import Control.Monad
import Control.Concurrent.STM
import qualified Data.List.NonEmpty as NE
import Data.Maybe (fromMaybe)
import System.Environment
import System.FilePath
import Control.Exception
expandHome :: FilePath -> IO FilePath
expandHome :: FilePath -> IO FilePath
expandHome ('~':'/':path :: FilePath
path) = (FilePath -> FilePath) -> IO FilePath -> IO FilePath
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (FilePath -> FilePath -> FilePath
</> FilePath
path) (FilePath -> IO FilePath
getEnv "HOME")
expandHome p :: FilePath
p = FilePath -> IO FilePath
forall (m :: * -> *) a. Monad m => a -> m a
return FilePath
p
changeLoop :: Eq a => STM a -> (a -> IO ()) -> IO ()
changeLoop :: STM a -> (a -> IO ()) -> IO ()
changeLoop s :: STM a
s f :: a -> IO ()
f = STM a -> IO a
forall a. STM a -> IO a
atomically STM a
s IO a -> (a -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= a -> IO ()
forall b. a -> IO b
go
where
go :: a -> IO b
go old :: a
old = do
a -> IO ()
f a
old
a -> IO b
go (a -> IO b) -> IO a -> IO b
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< STM a -> IO a
forall a. STM a -> IO a
atomically (do
a
new <- STM a
s
Bool -> STM ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (a
new a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/= a
old)
a -> STM a
forall (m :: * -> *) a. Monad m => a -> m a
return a
new)
onSomeException :: IO a -> (SomeException -> IO b) -> IO a
onSomeException :: IO a -> (SomeException -> IO b) -> IO a
onSomeException io :: IO a
io what :: SomeException -> IO b
what = IO a
io IO a -> (SomeException -> IO a) -> IO a
forall e a. Exception e => IO a -> (e -> IO a) -> IO a
`catch` \e :: SomeException
e -> do b
_ <- SomeException -> IO b
what SomeException
e
SomeException -> IO a
forall e a. Exception e => e -> IO a
throwIO (SomeException
e :: SomeException)
(!!?) :: [a] -> Int -> Maybe a
!!? :: [a] -> Int -> Maybe a
(!!?) xs :: [a]
xs i :: Int
i
| Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< 0 = Maybe a
forall a. Maybe a
Nothing
| Bool
otherwise = Int -> [a] -> Maybe a
forall a. Int -> [a] -> Maybe a
go Int
i [a]
xs
where
go :: Int -> [a] -> Maybe a
go :: Int -> [a] -> Maybe a
go 0 (x :: a
x:_) = a -> Maybe a
forall a. a -> Maybe a
Just a
x
go j :: Int
j (_:ys :: [a]
ys) = Int -> [a] -> Maybe a
forall a. Int -> [a] -> Maybe a
go (Int
j Int -> Int -> Int
forall a. Num a => a -> a -> a
- 1) [a]
ys
go _ [] = Maybe a
forall a. Maybe a
Nothing
{-# INLINE (!!?) #-}
safeIndex :: NE.NonEmpty a -> Int -> a
safeIndex :: NonEmpty a -> Int -> a
safeIndex xs :: NonEmpty a
xs index :: Int
index = a -> Maybe a -> a
forall a. a -> Maybe a -> a
fromMaybe (NonEmpty a -> a
forall a. NonEmpty a -> a
NE.head NonEmpty a
xs) (NonEmpty a -> [a]
forall a. NonEmpty a -> [a]
NE.toList NonEmpty a
xs [a] -> Int -> Maybe a
forall a. [a] -> Int -> Maybe a
!!? Int
index)