xmonad-config/lib/XMonad/Internal/Shell.hs

137 lines
3.7 KiB
Haskell
Raw Normal View History

2020-04-01 22:06:00 -04:00
--------------------------------------------------------------------------------
-- | Functions for formatting and spawning shell commands
2020-04-01 20:17:47 -04:00
module XMonad.Internal.Shell
2021-06-19 00:17:47 -04:00
( MaybeExe(..)
, Dependency(..)
2021-06-19 00:17:47 -04:00
, MaybeX
, IOMaybeX
, runIfInstalled
2021-06-19 15:32:43 -04:00
, warnMissing
2021-06-19 00:17:47 -04:00
, whenInstalled
, spawnIfInstalled
, spawnCmdIfInstalled
, noCheck
, fmtCmd
2020-04-01 20:17:47 -04:00
, spawnCmd
2020-05-31 20:56:57 -04:00
, spawnSound
2021-06-19 00:17:47 -04:00
, playSound
2021-06-17 01:17:59 -04:00
, doubleQuote
, singleQuote
2021-06-19 00:17:47 -04:00
, skip
2020-04-01 20:17:47 -04:00
, (#!&&)
, (#!||)
, (#!>>)
) where
2020-03-18 12:17:39 -04:00
2021-06-19 00:17:47 -04:00
import Control.Monad (filterM)
import Control.Monad.IO.Class
import Data.Maybe (isJust)
2021-06-19 00:17:47 -04:00
import System.Directory (findExecutable)
import System.FilePath.Posix
2020-05-31 20:56:57 -04:00
import XMonad.Core (X, getXMonadDir)
import XMonad.Internal.Process
2020-03-28 18:38:38 -04:00
2021-06-19 00:17:47 -04:00
--------------------------------------------------------------------------------
-- | Gracefully handling missing binaries
data Dependency = Required String | Optional String deriving (Eq, Show)
data MaybeExe m = Installed (m ()) [String] | Missing [Dependency] | Ignore
2021-06-19 00:17:47 -04:00
type MaybeX = MaybeExe X
type IOMaybeX = IO MaybeX
2021-06-19 16:16:00 -04:00
warnMissing :: Dependency -> String
2021-06-19 15:32:43 -04:00
warnMissing d = case d of
Required d' -> warn "required" d'
Optional d' -> warn "optional" d'
where
2021-06-19 16:16:00 -04:00
warn t n = "WARNING: " ++ t ++ " executable not found: " ++ n
2021-06-19 15:32:43 -04:00
exeInstalled :: String -> IO Bool
exeInstalled x = isJust <$> findExecutable x
depInstalled :: Dependency -> IO Bool
depInstalled (Required d) = exeInstalled d
depInstalled (Optional d) = exeInstalled d
filterMissing :: [Dependency] -> IO [Dependency]
filterMissing = filterM (fmap not . depInstalled)
runIfInstalled :: MonadIO m => [Dependency] -> m () -> IO (MaybeExe m)
runIfInstalled ds x = do
missing <- filterMissing ds
return $ if null [m | Required m <- missing]
then Installed x [m | Optional m <- missing]
else Missing missing
2021-06-19 00:17:47 -04:00
spawnIfInstalled :: MonadIO m => String -> IO (MaybeExe m)
spawnIfInstalled exe = runIfInstalled [Required exe] $ spawn exe
2021-06-19 00:17:47 -04:00
spawnCmdIfInstalled :: MonadIO m => String -> [String] -> IO (MaybeExe m)
spawnCmdIfInstalled exe args = runIfInstalled [Required exe] $ spawnCmd exe args
2021-06-19 00:17:47 -04:00
whenInstalled :: Monad m => MaybeExe m -> m ()
whenInstalled (Installed x _) = x
whenInstalled _ = return ()
2021-06-19 00:17:47 -04:00
skip :: Monad m => m ()
skip = return ()
noCheck :: Monad m => a () -> m (MaybeExe a)
noCheck = return . flip Installed []
2021-06-19 00:17:47 -04:00
2020-04-01 22:06:00 -04:00
--------------------------------------------------------------------------------
-- | Opening subshell
2020-03-18 12:17:39 -04:00
spawnCmd :: MonadIO m => String -> [String] -> m ()
2020-03-18 12:17:39 -04:00
spawnCmd cmd args = spawn $ fmtCmd cmd args
2020-05-31 20:56:57 -04:00
--------------------------------------------------------------------------------
-- | Playing sound
soundDir :: FilePath
soundDir = "sound"
2021-06-19 00:17:47 -04:00
spawnSound :: MonadIO m => FilePath -> m () -> m () -> IO (MaybeExe m)
spawnSound file pre post = runIfInstalled [Required "paplay"]
2021-06-19 00:17:47 -04:00
$ pre >> playSound file >> post
playSound :: MonadIO m => FilePath -> m ()
playSound file = do
2020-05-31 20:56:57 -04:00
path <- (</> soundDir </> file) <$> getXMonadDir
2020-05-31 23:58:30 -04:00
-- paplay seems to have less latency than aplay
spawnCmd "paplay" [path]
2020-05-31 20:56:57 -04:00
2020-04-01 22:06:00 -04:00
--------------------------------------------------------------------------------
-- | Formatting commands
fmtCmd :: String -> [String] -> String
fmtCmd cmd args = unwords $ cmd : args
2020-03-18 12:17:39 -04:00
(#!&&) :: String -> String -> String
cmdA #!&& cmdB = cmdA ++ " && " ++ cmdB
infixr 0 #!&&
(#!||) :: String -> String -> String
cmdA #!|| cmdB = cmdA ++ " || " ++ cmdB
infixr 0 #!||
(#!>>) :: String -> String -> String
cmdA #!>> cmdB = cmdA ++ "; " ++ cmdB
infixr 0 #!>>
2021-06-17 01:17:59 -04:00
doubleQuote :: String -> String
doubleQuote s = "\"" ++ s ++ "\""
singleQuote :: String -> String
singleQuote s = "'" ++ s ++ "'"