<div dir="ltr"><div>Sounds cool.  I don't think I would personally use it, but I think you 
should submit it to xmonad-contrib regardless of whether anyone says 
they would use it.  If it's there, then perhaps someone will find it.<br><br></div>-Brent<br><div><br><div class="gmail_quote"><div dir="ltr">On Sun, Dec 13, 2015 at 11:50 AM Matt Walker <<a href="mailto:matt.g.d.walker@gmail.com">matt.g.d.walker@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><div><div><div><div><div><div>Hello everyone,<br><br></div>I've been using xmonad for a couple of months now, and there is something that has always bothered me, so I'm writing a package to fix it.<br><br></div>[Problem Statement]<br><br></div>Many people who use dzen2 do so with the help of Conky or other external programs.  While nice, if would be better to be able to control it with XMonad in a nice way without them.  This would require two things: more control over how information is outputted to dzen2 from xmonad than that afforded by DynamicLog, and ways of retrieving system information for xmonad to use.  Specifically, we would want a flexible, extensible, and elegant solution, and one that works for more than just Dzen.  I argue no such solution currently exists, and why this is a problem.<br><br></div>[Evidence of Problem]<br><br></div>People with advanced XMonad/Dzen2 setups often resort to using two different Dzen2 bars -- one for XMonad stuff that XMonad controls, and one that is piped output from something like Conky.  Here are just a few examples I've found around the web:<br><br><a href="https://wiki.haskell.org/Xmonad/Config_archive/And1's_xmonad.hs" target="_blank">https://wiki.haskell.org/Xmonad/Config_archive/And1's_xmonad.hs</a> (note the hacky (but effective) use of the DynamicLog PP facilities)<br><a href="https://wiki.haskell.org/Xmonad/Config_archive/Regalia's_xmonad.hs" target="_blank">https://wiki.haskell.org/Xmonad/Config_archive/Regalia's_xmonad.hs</a><br><a href="https://wiki.haskell.org/Xmonad/Config_archive/Thayer_Williams'_xmonad.hs" target="_blank">https://wiki.haskell.org/Xmonad/Config_archive/Thayer_Williams'_xmonad.hs</a><br><a href="https://wiki.haskell.org/Xmonad/Config_archive/avendael's_xmonad.hs" target="_blank">https://wiki.haskell.org/Xmonad/Config_archive/avendael's_xmonad.hs</a><br><a href="http://thinkingeek.com/2011/11/21/simple-guide-configure-xmonad-dzen2-conky/" target="_blank">http://thinkingeek.com/2011/11/21/simple-guide-configure-xmonad-dzen2-conky/</a><br><a href="https://github.com/davidbeckingsale/xmonad-config/blob/master/xmonad.hs" target="_blank">https://github.com/davidbeckingsale/xmonad-config/blob/master/xmonad.hs</a><br><br></div><div>In each of these cases, the status bar has two parts: one part controlled by XMonad that deals with the WM state, and another part controlled by Conky that contains the system state.  The premise of my argument is basically that this is undesirable, and all information should be available from, and outputted from, xmonad.  We have a Haskell environment, and we are completely by-passing it!<br></div><div><br></div>[Probable Cause of Problem]<br><br></div><div>DynamicLog's PP facility is extremely useful if you want to quickly get a statusbar up quickly and with minimal customization.  But it quickly becomes too weak to do anything fancy with, without getting very hacky.<br><br>For example, say I wanted my current layout and window-name information printed in the middle of the bar, and my list of workspaces printed on the left side of the bar.  This is difficult to achieve with the current tools -- one must be aware of the formatting characters when performing the translation if one wants the text to be correctly justified/centred.  One must be quite familiar with which parts of the PP get outputted when and how they are put together (since we want two fields to be output to the same region, but centring them both would make them overlap.)  This makes for a brittle and non-general solution to the problem.<br><br>The problem is that DynamicLog's PP facility is not extensible in any elegant way.  You have to know how the whole thing works to be able to extend it, even in minor ways.  Modifications to it are neither composable, nor factorable -- I can't just add or remove customizations without it probably breaking.<br><br></div><div>[Proposed Solution]<br><br></div><div>I propose a new solution.  The code for this solution is located here: <a href="https://github.com/Fizzixnerd/xmonad-config/tree/master/site-haskell/src/XMonad/Hooks/DynamicLog/Status" target="_blank">https://github.com/Fizzixnerd/xmonad-config/tree/master/site-haskell/src/XMonad/Hooks/DynamicLog/Status</a> .  I haven't yet spun off the code in that subdirectory into its own repo.  Right now, the whole repo is an unholy Frankenstein's monster of personal configuration, failed attempts, and worthwhile work.  Most of the good stuff is in XMonad.Hooks.DynamicLog.Status though.<br><br></div><div>The main idea is that we defined a new type, StatusText which has three bits: a prefix, a suffix, and some content.  The actual stuff you want to display goes in the content section, while the prefix and suffix hold the markup information.<br><br></div><div>Here is a brief summary of the type:<br><br></div><div>type Status b a = Writer (b, Dual b) a<br>type StatusText = Status [T.Text] T.Text<br><br></div><div>where Dual is defined in Data.Monoid.  And that's it!  We get a Functor and Writer Monad for free out of this definition, clearly.  The Dual is there so that if you have something like <bold><italics>hello there!</italics></bold>, then the wrapping happens in the correct order.  That is, you don't end up with <bold><italics>hello there!</bold></italics>.<br><br></div><div>We define the `length' of a StatusText to be the length of the content.  This allows us to calculate offsets within the status bar without having to strip away all the markup.<br><br></div><div>I have a library included in Status.DZen2 (name change is coming to get rid of the capital Z).  It contains combinators and so on for marking up StatusText using all the dzen2 commands, all from within XMonad.  Exciting!  I plan to make a universal interface and a fancy interface: the universal interface will contain all commands common to dzen2, xmobar, and possibly taffybar.  In this way, it will be possible to swap out your statusbar without everything breaking.  Maybe I'll abandon this part, but let me know if it sounds cool to you.<br><br></div><div>There are also facilities similar to those found in XMonad.Util.Logger for making StatusTexts from shell commands.  These are found in Status.StatusText.Dynamic.  The point of this is so that the formatting of the information can be cleanly separated from the retrieval of the information.  This makes things more composable, and doesn't have use relying on brittle solutions.  However, you can still just plug in your conky stuff and pipe it through xmonad if you want to just get it up and running to see what it's like.  I will be adding a few `standard' StatusTexts in Status.System.<br><br></div><div>I have replicated the facilities found in XMonad.Hooks.DynamicLog's PP's by factoring out the different parts of the PP and then wrapping those in StatusTexts in Status.X.  Big ups to the creator of DynamicLog's PPs.  They are a fantastic idea within the domain of their applicability, and I used a lot of the code from them.<br><br></div><div>I will be spending the coming days cleaning up the codebase and getting it ready to be submitted for possible inclusion in xmonad-contrib.  I don't think it even compiles right now, but past versions of it have worked so I'm not super worried about there being a fundamental flaw in it or whatever.  There are some examples using battery in Status.System of composing a StatusText to format content using the monadic interface in Status.DZen2.Fancy.<br><br></div><div>Finally, you take your StatusTexts, stick them in a list (one for the left, middle, and right side of the bar respectively), and then render them to a string.  This is the part that isn't quite done yet, but it's also probably the most straightforward.  More on that later.<br></div><div><br></div><div>Obviously, this package is best used with XMonad.Util.Timer, since you probably want your uptime and stuff to actually update properly with time, and not just on X events.<br><br></div><div>[License]<br><br></div><div>Its currently GPLv3, but I have no qualms about changing it once its ready.<br></div><div><br></div><div>[Conclusion]<br><br></div><div>I'd love to hear some feedback on this.  Does anyone even care?  Maybe this is better left as just a personal package for myself.  I have no idea.  I just felt it solved a rather general problem, and so could possibly be of use to other people.  If it helps reduce the (in my opinion) ugly hacky use of Conky and 2+ dzen bars, then I think that's pretty good.  Let me know!<br><br></div><div>Sincerely,<br></div><div>Matt<br></div></div>
_______________________________________________<br>
xmonad mailing list<br>
<a href="mailto:xmonad@haskell.org" target="_blank">xmonad@haskell.org</a><br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/xmonad" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/xmonad</a><br>
</blockquote></div></div></div>