xmonad的logHook可以按设定的时间间隔运行而不是(仅仅)响应布局事件吗?

ben*_*n w 5 haskell xmonad statusbar

我使用的是dynamicLogWithPPXMonad.Hooks.DynamicLog与dzen2作为下xmonad状态栏在一起.我希望在栏中显示的其中一项内容是当前播放曲目的大胆时间(如果有的话).获取此信息很简单:

audStatus :: Player -> X (Maybe String)
audStatus p = do
  info <- liftIO $ tryS $ withPlayer p $ do
                ispaused <- paused
                md <- getMetadataString
                timeleftmillis <- (-) <$> (getCurrentTrack >>= songFrames) <*> time
                let artist = md ! "artist"
                    title = md ! "title"
                    timeleft = timeleftmillis `quot` 1000
                    (minutes, seconds) = timeleft `quotRem` 60
                    disp = artist ++ " - " ++ title ++ " (-"++(show minutes)++":"++(show seconds)++")" -- will be wrong if seconds < 10
                    audcolor False = dzenColor base0  base03
                    audcolor True = dzenColor base1 base02 
                return $ wrap "^ca(1, pms p)" "^ca()" (audcolor ispaused disp)
  return $ either (const Nothing) Just info
Run Code Online (Sandbox Code Playgroud)

所以我可以坚持下去ppExtras并且它运行良好 - 除了它只在运行时logHook运行,并且只有当一个合适的事件从长矛下来时才会发生.因此显示器可能长时间静态,直到我(例如)切换工作空间.

似乎有些人只运行了两个数据库,其中一个从shell脚本输出管道输出.这是定期更新的唯一方法吗?或者这可以在xmonad中完成(不会太疯狂/ hacky)?

ETA:我试过这个,好像它应该比它更好地工作:

  1. 从XMonad创建一个TChan用于更新,另一个用于从函数轮询Audacious创建更新;
  2. 设置结构中的ppOutput字段PPDynamicLog写入第一个TChan;
  3. 分叉大胆轮询功能并将其写入第二个TChan;
  4. fork一个函数从两个TChans中读取(首先检查它们是否为空),然后组合输出.

从频道中读取XMonad的更新并及时处理,但Audacious的更新几乎没有注册 - 最多每五秒钟就会注册一次.但是,似乎某些方法应该起作用.

Dar*_*nec 6

我知道这是一个老问题,但我几天前来到这里寻找答案,我想我会分享我解决它的方式.你实际上可以完全从xmonad完成.这有点像hacky,但我认为它比我遇到的任何替代方案都要好得多.

基本上,我使用了XMonad.Util.Timer库,它将在指定的时间段(在这种情况下,一秒钟)后发送一个X事件.然后我只为它编写了一个事件挂钩,它再次启动计时器,然后手动运行日志挂钩.

我还必须使用XMonad.Util.ExtensibleState库,因为Timer使用id变量来确保它响应正确的事件,所以我必须在事件之间存储该变量.

这是我的代码:

{-# LANGUAGE DeriveDataTypeable #-}

import qualified XMonad.Util.ExtensibleState as XS
import XMonad.Util.Timer

...

-- wrapper for the Timer id, so it can be stored as custom mutable state
data TidState = TID TimerId deriving Typeable

instance ExtensionClass TidState where
  initialValue = TID 0

...

-- put this in your startupHook
-- start the initial timer, store its id
clockStartupHook = startTimer 1 >>= XS.put . TID

-- put this in your handleEventHook
clockEventHook e = do               -- e is the event we've hooked
  (TID t) <- XS.get                 -- get the recent Timer id
  handleTimer t e $ do              -- run the following if e matches the id
    startTimer 1 >>= XS.put . TID   -- restart the timer, store the new id
    ask >>= logHook.config          -- get the loghook and run it
    return Nothing                  -- return required type
  return $ All True                 -- return required type
Run Code Online (Sandbox Code Playgroud)

非常直截了当.我希望这对某人有帮助.