2021-11-24 00:43:58 -05:00
|
|
|
module Xmobar.Plugins.Common
|
2021-11-27 17:33:02 -05:00
|
|
|
( colorText
|
2021-11-24 01:14:23 -05:00
|
|
|
, startListener
|
2021-11-26 23:35:03 -05:00
|
|
|
, procSignalMatch
|
2021-11-25 00:12:00 -05:00
|
|
|
, na
|
2021-11-26 23:35:03 -05:00
|
|
|
, fromSingletonVariant
|
2023-10-15 21:50:46 -04:00
|
|
|
, withNestedDBusClientConnection
|
2021-11-26 23:35:03 -05:00
|
|
|
, withDBusClientConnection
|
|
|
|
, Callback
|
2022-12-30 14:58:23 -05:00
|
|
|
, Colors (..)
|
2021-11-27 13:24:13 -05:00
|
|
|
, displayMaybe
|
2022-12-30 10:56:09 -05:00
|
|
|
, displayMaybe'
|
2021-11-27 17:33:02 -05:00
|
|
|
, xmobarFGColor
|
2023-10-01 00:24:33 -04:00
|
|
|
, PluginEnv (..)
|
|
|
|
, PluginIO
|
2023-10-01 01:02:06 -04:00
|
|
|
, pluginDisplay
|
2021-11-24 01:14:23 -05:00
|
|
|
)
|
2022-12-30 14:58:23 -05:00
|
|
|
where
|
2022-12-26 14:45:49 -05:00
|
|
|
|
2022-12-30 14:58:23 -05:00
|
|
|
import DBus
|
|
|
|
import DBus.Client
|
|
|
|
import Data.Internal.DBus
|
2023-01-03 23:33:08 -05:00
|
|
|
import Data.Internal.XIO
|
2022-12-30 16:44:00 -05:00
|
|
|
import RIO
|
2022-12-30 14:58:23 -05:00
|
|
|
import qualified RIO.Text as T
|
|
|
|
import XMonad.Hooks.DynamicLog (xmobarColor)
|
2021-11-24 01:14:23 -05:00
|
|
|
|
2023-10-01 00:24:33 -04:00
|
|
|
data PluginEnv s c = PluginEnv
|
|
|
|
{ plugClient :: !c
|
|
|
|
, plugState :: !(MVar s)
|
2023-10-01 01:02:06 -04:00
|
|
|
, plugDisplay :: !(Callback -> PluginIO s c ())
|
|
|
|
, plugCallback :: !Callback
|
2023-10-01 00:24:33 -04:00
|
|
|
, plugEnv :: !SimpleApp
|
|
|
|
}
|
|
|
|
|
2023-10-01 01:02:06 -04:00
|
|
|
pluginDisplay :: PluginIO s c ()
|
|
|
|
pluginDisplay = do
|
|
|
|
cb <- asks plugCallback
|
|
|
|
dpy <- asks plugDisplay
|
|
|
|
dpy cb
|
|
|
|
|
2023-10-01 00:24:33 -04:00
|
|
|
type PluginIO s c = RIO (PluginEnv s c)
|
|
|
|
|
|
|
|
instance HasClient (PluginEnv s) where
|
|
|
|
clientL = lens plugClient (\x y -> x {plugClient = y})
|
|
|
|
|
|
|
|
instance HasLogFunc (PluginEnv s c) where
|
|
|
|
logFuncL = lens plugEnv (\x y -> x {plugEnv = y}) . logFuncL
|
|
|
|
|
2022-12-26 14:45:49 -05:00
|
|
|
-- use string here since all the callbacks in xmobar use strings :(
|
2021-11-26 23:35:03 -05:00
|
|
|
type Callback = String -> IO ()
|
|
|
|
|
2021-11-27 17:33:02 -05:00
|
|
|
data Colors = Colors
|
2022-12-30 14:58:23 -05:00
|
|
|
{ colorsOn :: T.Text
|
2022-12-26 14:45:49 -05:00
|
|
|
, colorsOff :: T.Text
|
2021-11-27 17:33:02 -05:00
|
|
|
}
|
|
|
|
deriving (Eq, Show, Read)
|
|
|
|
|
2022-12-30 14:58:23 -05:00
|
|
|
startListener
|
2023-02-12 23:08:05 -05:00
|
|
|
:: ( HasClient env
|
2023-01-03 22:18:55 -05:00
|
|
|
, MonadReader (env c) m
|
|
|
|
, MonadUnliftIO m
|
|
|
|
, SafeClient c
|
|
|
|
, IsVariant a
|
|
|
|
)
|
2022-12-30 14:58:23 -05:00
|
|
|
=> MatchRule
|
2023-01-03 22:18:55 -05:00
|
|
|
-> m [Variant]
|
2022-12-30 14:58:23 -05:00
|
|
|
-> ([Variant] -> SignalMatch a)
|
2022-12-30 16:44:00 -05:00
|
|
|
-> (a -> m T.Text)
|
2022-12-30 14:58:23 -05:00
|
|
|
-> Callback
|
2022-12-30 16:44:00 -05:00
|
|
|
-> m ()
|
2023-01-03 22:18:55 -05:00
|
|
|
startListener rule getProp fromSignal toColor cb = do
|
|
|
|
reply <- getProp
|
2022-12-30 10:56:09 -05:00
|
|
|
displayMaybe cb toColor $ fromSingletonVariant reply
|
2023-01-03 22:18:55 -05:00
|
|
|
void $ addMatchCallback rule (procMatch . fromSignal)
|
2021-11-24 01:14:23 -05:00
|
|
|
where
|
2021-11-26 23:35:03 -05:00
|
|
|
procMatch = procSignalMatch cb toColor
|
|
|
|
|
2022-12-30 16:44:00 -05:00
|
|
|
procSignalMatch
|
|
|
|
:: MonadUnliftIO m => Callback -> (a -> m T.Text) -> SignalMatch a -> m ()
|
2021-11-27 13:24:13 -05:00
|
|
|
procSignalMatch cb f = withSignalMatch (displayMaybe cb f)
|
2021-11-24 00:43:58 -05:00
|
|
|
|
2022-12-26 14:45:49 -05:00
|
|
|
colorText :: Colors -> Bool -> T.Text -> T.Text
|
2022-12-30 14:58:23 -05:00
|
|
|
colorText Colors {colorsOn = c} True = xmobarFGColor c
|
|
|
|
colorText Colors {colorsOff = c} False = xmobarFGColor c
|
2021-11-27 17:33:02 -05:00
|
|
|
|
2022-12-26 14:45:49 -05:00
|
|
|
xmobarFGColor :: T.Text -> T.Text -> T.Text
|
|
|
|
xmobarFGColor c = T.pack . xmobarColor (T.unpack c) "" . T.unpack
|
2021-11-25 00:12:00 -05:00
|
|
|
|
2022-12-26 14:45:49 -05:00
|
|
|
na :: T.Text
|
2021-11-25 00:12:00 -05:00
|
|
|
na = "N/A"
|
2021-11-26 23:35:03 -05:00
|
|
|
|
2022-12-30 16:44:00 -05:00
|
|
|
displayMaybe :: MonadUnliftIO m => Callback -> (a -> m T.Text) -> Maybe a -> m ()
|
|
|
|
displayMaybe cb f = (liftIO . cb . T.unpack) <=< maybe (return na) f
|
2021-11-27 13:24:13 -05:00
|
|
|
|
2022-12-30 16:44:00 -05:00
|
|
|
displayMaybe' :: MonadUnliftIO m => Callback -> (a -> m ()) -> Maybe a -> m ()
|
|
|
|
displayMaybe' cb = maybe (liftIO $ cb $ T.unpack na)
|
2021-11-26 23:35:03 -05:00
|
|
|
|
2022-12-30 16:44:00 -05:00
|
|
|
withDBusClientConnection
|
|
|
|
:: (MonadUnliftIO m, SafeClient c)
|
|
|
|
=> Callback
|
2023-01-03 23:33:08 -05:00
|
|
|
-> Maybe FilePath
|
2022-12-31 22:22:36 -05:00
|
|
|
-> (c -> RIO SimpleApp ())
|
2022-12-30 16:44:00 -05:00
|
|
|
-> m ()
|
2023-01-03 23:33:08 -05:00
|
|
|
withDBusClientConnection cb logfile f =
|
|
|
|
maybe (run stderr) (`withLogFile` run) logfile
|
2023-01-01 22:29:29 -05:00
|
|
|
where
|
2023-01-03 23:33:08 -05:00
|
|
|
run h = do
|
|
|
|
logOpts <- setLogVerboseFormat True . setLogUseTime True <$> logOptionsHandle h False
|
|
|
|
withLogFunc logOpts $ \lf -> do
|
|
|
|
env <- mkSimpleApp lf Nothing
|
|
|
|
runRIO env $ displayMaybe' cb f =<< getDBusClient
|
2023-10-15 21:50:46 -04:00
|
|
|
|
|
|
|
-- | Run a plugin action with a new DBus client and logfile path.
|
|
|
|
-- This is necessary for DBus callbacks which run in separate threads, which
|
|
|
|
-- will usually fire when the parent thread already exited and killed off its
|
|
|
|
-- DBus connection and closed its logfile.
|
|
|
|
withNestedDBusClientConnection
|
|
|
|
:: (MonadUnliftIO m, SafeClient c, MonadReader (PluginEnv s c) m)
|
|
|
|
=> Maybe FilePath
|
|
|
|
-> PluginIO s c ()
|
|
|
|
-> m ()
|
|
|
|
withNestedDBusClientConnection logfile f = do
|
|
|
|
dpy <- asks plugDisplay
|
|
|
|
s <- asks plugState
|
|
|
|
cb <- asks plugCallback
|
|
|
|
withDBusClientConnection cb logfile $ \c -> mapRIO (PluginEnv c s dpy cb) f
|