Xmobar Plugin Development

I wrote a xmobar plugin to display the time as inexact text: http://www.wabdo.com/fred/FuzzyClock.hs It uses Data.Time, not the more widespread System.Time. It's not parameter-ised because it would be a huge pain to make a xmobar plugin take a function as an argument (seems like I'd have to take it as a string and eval it), and you're going to have to modify/recompile xmobar's source to add it anyway. I was surprised at just how un-idiomatic I found xmobar's configuration to be: * Uses format strings instead of functions * Uses property lists for the arguments to monitors instead of [(a,b)] or a data constructor * Commands aren't simple functions * 'Plugins' cannot be seperated from xmobar's source (and resulting binary) Currently the only way to extend xmobar's functionality without modifying/recompiling it is to use external processes. I think that having to hack/rebuild xmobar is a huge barrier to experimentation -- I could only find one other person who had published out-of-tree plugins (http://www.haskell.org/pipermail/xmonad/2008-April/005465.html). I think it should be possible to implement things like FuzzyClock in my configuration file without modifying xmobar at all! I should be able to use functions in my configuration file to do anything a Plugin can do now -- the output text should be composed of functions producing 'IO String'. Basically I think xmobar should be more like xmonad :) Here's what a simple xmobar configuration file would look like in my ideal world (though getting rid of the separate commands list may be unrealistic because of threading+STM setup): import Xmobar import Xmobar.Monitors as Mon main = do xmobar $ Config { font = "-misc-fixed-*-*-*-*-10-*-*-*-*-*-*-*" , bgColor = "black" , fgColor = "grey" , position = Top , format = Format { , left = myCpu ++ " | " ++ myMemory where myCpu = "Cpu: " ++ (run 10 $ Mon.cpu [(3,"green"),(50,"red")]) ++ "%" myMemory = "Mem: " ++ (run 10 Mon.memUsedRatio) ++ "%" , middle = color "#aaa" stdinReader , right = color "aquamarine" $ run 10 myHaskellFunction } } -- Fred Blasdel

First I'd like to point out the author of xmobar, Andrea Rossato, probably doesn't follow this list anymore. If you'd like to see action on these issues, you should probably forward this message to him. On Mon, Jul 14, 2008 at 10:08:45AM -0700, Fred Blasdel wrote:
I wrote a xmobar plugin to display the time as inexact text: http://www.wabdo.com/fred/FuzzyClock.hs
It uses Data.Time, not the more widespread System.Time. It's not parameter-ised because it would be a huge pain to make a xmobar plugin take a function as an argument (seems like I'd have to take it as a string and eval it), and you're going to have to modify/recompile xmobar's source to add it anyway.
I was surprised at just how un-idiomatic I found xmobar's configuration to be: * Uses format strings instead of functions * Uses property lists for the arguments to monitors instead of [(a,b)] or a data constructor
Yes, both of these are rather ugly -- it seems to have a shell script flavor to it, rather than a strongly typed combinator approach usually used in Haskell.
* Commands aren't simple functions * 'Plugins' cannot be seperated from xmobar's source (and resulting binary)
Andrea has chosen to use Read/Show serialization for xmobar rather than Haskell source ala xmonad. The things you mention are the negative aspects of this choice, but there are positive aspects -- not requiring GHC as a runtime dependency is a major one.
Currently the only way to extend xmobar's functionality without modifying/recompiling it is to use external processes. I think that having to hack/rebuild xmobar is a huge barrier to experimentation -- I could only find one other person who had published out-of-tree plugins (http://www.haskell.org/pipermail/xmonad/2008-April/005465.html).
In fact, I've written xmobar plugins but have not distributed them because there isn't really a convenient way to do it.
I think it should be possible to implement things like FuzzyClock in my configuration file without modifying xmobar at all! I should be able to use functions in my configuration file to do anything a Plugin can do now -- the output text should be composed of functions producing 'IO String'. Basically I think xmobar should be more like xmonad :)
Here's what a simple xmobar configuration file would look like in my ideal world (though getting rid of the separate commands list may be unrealistic because of threading+STM setup):
I think this is possible via some clever Applicative tricks, though I'm still pondering that.
import Xmobar import Xmobar.Monitors as Mon main = do xmobar $ Config { font = "-misc-fixed-*-*-*-*-10-*-*-*-*-*-*-*" , bgColor = "black" , fgColor = "grey" , position = Top , format = Format { , left = myCpu ++ " | " ++ myMemory where myCpu = "Cpu: " ++ (run 10 $ Mon.cpu [(3,"green"),(50,"red")]) ++ "%" myMemory = "Mem: " ++ (run 10 Mon.memUsedRatio) ++ "%" , middle = color "#aaa" stdinReader , right = color "aquamarine" $ run 10 myHaskellFunction } }
-- Fred Blasdel
Cheers, Spencer Janssen

On Mon, Jul 14, 2008 at 1:11 PM, Spencer Janssen
First I'd like to point out the author of xmobar, Andrea Rossato, probably doesn't follow this list anymore. If you'd like to see action on these issues, you should probably forward this message to him.
I did, and we've already replied to each other a few times :) I've pointed him here in my last reply.
Andrea has chosen to use Read/Show serialization for xmobar rather than Haskell source ala xmonad. The things you mention are the negative aspects of this choice, but there are positive aspects -- not requiring GHC as a runtime dependency is a major one.
Isn't nearly every xmobar user a xmonad user? I thought that was the impetus for xmobar's existence. It's true that ghc takes up 300mb on disk plus dependencies, but I and most all other users already have it there for xmonad (if not just for haskell development). I find ghc's compilation of my xmonad.hs pretty snappy on my OLPC XO-1, I'll have to test it out on a 70mhz Sparcstation 5 (the slowest hardware I've used that can usefully run Xorg) the next time I'm back at my alma mater (though I may have to wait a few days for ghc to compile!). Interestingly, there's a module in the xmonad-contrib darcs that allows you to avoid the runtime ghc dependency (though you still need ghc to build the initial xmonad.hs, a debian packager could do that and make it global): http://code.haskell.org/XMonadContrib/XMonad/Config/PlainConfig.hs Unfortunately you can't import anything from xmonad-contrib without using ghc to rebuild the xmonad.hs (a debian packager could make the default import all nonconflicting modules when contrib is installed). You also can't currently use any layouts from contrib, but more worrying for xmobar you also can't use a logHook :(
In fact, I've written xmobar plugins but have not distributed them because there isn't really a convenient way to do it.
Please do, publishing is rarely a bad thing :) -- Fred

Fred Blasdel wrote:
Interestingly, there's a module in the xmonad-contrib darcs that allows you to avoid the runtime ghc dependency (though you still need ghc to build the initial xmonad.hs, a debian packager could do that and make it global): http://code.haskell.org/XMonadContrib/XMonad/Config/PlainConfig.hs
Unfortunately you can't import anything from xmonad-contrib without using ghc to rebuild the xmonad.hs (a debian packager could make the default import all nonconflicting modules when contrib is installed). You also can't currently use any layouts from contrib, but more worrying for xmobar you also can't use a logHook :(
PlainConfig is my creation. I originally built it after seeing online and meeting in fellow undergraduates resistance to installing such a massive dependency as GHC in order to experiment with xmonad. So I wrote PlainConfig as a proof-of-concept for a text-only config parser. It is capable, in principle, of creating the equivalent of any xmonad.hs file. However, you can't use arbitrary contrib modules, they would have to be added to the PlainConfig module's compiler first. That said, it would be a fairly easy endeavour to write parsers for the more popular contrib layouts and other miscellaneous modules (EwmhDesktops, Prompt and CopyWindow come to mind) that people tend to use. In the end, though, text and a simple compiler is no match for Haskell and GHC as far as expressive power. PlainConfig was intended to be a decent replacement for simple xmonad.hs files, allowing someone to experiment and get a taste of xmonad without having to install GHC first, and also without being at the mercy of the default config. It would allow them to change their mod key, add workspaces and adjust their keybindings, the standard things newcomers to xmonad want to do. Though I imagine sooner or later most users would want some module or other feature PlainConfig doesn't support and would switch to using xmonad.hs files. To lower that barrier (having to install GHC makes it high enough already!) I intend to create another back end for PlainConfig so that instead of building an XConfig it outputs an xmonad.hs equivalent to the text configuration file, for seamless migration. If we intend to release this month and PlainConfig is a part of the release plans, I should have a chance from Wednesday onward this week to work on it.
-- Fred
Braden Shepherdson shepheb

On Mon, Jul 14, 2008 at 10:06 PM, Braden Shepherdson
PlainConfig is my creation. I originally built it after seeing online and meeting in fellow undergraduates resistance to installing such a massive dependency as GHC in order to experiment with xmonad.
So I wrote PlainConfig as a proof-of-concept for a text-only config parser. It is capable, in principle, of creating the equivalent of any xmonad.hs file. However, you can't use arbitrary contrib modules, they would have to be added to the PlainConfig module's compiler first.
That said, it would be a fairly easy endeavour to write parsers for the more popular contrib layouts and other miscellaneous modules (EwmhDesktops, Prompt and CopyWindow come to mind) that people tend to use.
I see now that all the functions available for binding are enumerated in key_actions.
In the end, though, text and a simple compiler is no match for Haskell and GHC as far as expressive power. PlainConfig was intended to be a decent replacement for simple xmonad.hs files, allowing someone to experiment and get a taste of xmonad without having to install GHC first, and also without being at the mercy of the default config. It would allow them to change their mod key, add workspaces and adjust their keybindings, the standard things newcomers to xmonad want to do.
Though I imagine sooner or later most users would want some module or other feature PlainConfig doesn't support and would switch to using xmonad.hs files. To lower that barrier (having to install GHC makes it high enough already!) I intend to create another back end for PlainConfig so that instead of building an XConfig it outputs an xmonad.hs equivalent to the text configuration file, for seamless migration.
If we intend to release this month and PlainConfig is a part of the release plans, I should have a chance from Wednesday onward this week to work on it.
I think that having a binary packaged version of PlainConfig-only xmonad could be really awesome. Perhaps it could be called "xmonad-simple" or "xmonad-plain". At runtime it should write a prebuilt xmonad-${arch} binary (and xmonad.conf if it doesn't exist) into ~/.xmonad/. It'd be a good idea to add a special target for it in the Cabal build. It'd be good to get debian and ubuntu packages made for it, but it'd be terrific if there could be i386 and x86_64 binaries hosted on xmonad.org -- "download this and run it from your home directory" -- convinent for students using lab computers. -- Fred
participants (3)
-
Braden Shepherdson
-
Fred Blasdel
-
Spencer Janssen