`Status' Package [xmonad-contrib]

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

`Status' Package [xmonad-contrib]

Matt Walker
Hello everyone,

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.

[Problem Statement]

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.

[Evidence of Problem]

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:

https://wiki.haskell.org/Xmonad/Config_archive/And1's_xmonad.hs (note the hacky (but effective) use of the DynamicLog PP facilities)
https://wiki.haskell.org/Xmonad/Config_archive/Regalia's_xmonad.hs
https://wiki.haskell.org/Xmonad/Config_archive/Thayer_Williams'_xmonad.hs
https://wiki.haskell.org/Xmonad/Config_archive/avendael's_xmonad.hs
http://thinkingeek.com/2011/11/21/simple-guide-configure-xmonad-dzen2-conky/
https://github.com/davidbeckingsale/xmonad-config/blob/master/xmonad.hs

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!

[Probable Cause of Problem]

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.

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.

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.

[Proposed Solution]

I propose a new solution.  The code for this solution is located here: https://github.com/Fizzixnerd/xmonad-config/tree/master/site-haskell/src/XMonad/Hooks/DynamicLog/Status .  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.

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.

Here is a brief summary of the type:

type Status b a = Writer (b, Dual b) a
type StatusText = Status [T.Text] T.Text

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>.

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.

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.

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.

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.

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.

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.

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.

[License]

Its currently GPLv3, but I have no qualms about changing it once its ready.

[Conclusion]

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!

Sincerely,
Matt

_______________________________________________
xmonad mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/xmonad
vrs
Reply | Threaded
Open this post in threaded view
|

Re: `Status' Package [xmonad-contrib]

vrs
Quoting Matt Walker (2015-12-13 18:49:59)

> [Evidence of Problem]
>
> 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:
>
> https://wiki.haskell.org/Xmonad/Config_archive/And1's_xmonad.hs (note the
> hacky (but effective) use of the DynamicLog PP facilities)
> https://wiki.haskell.org/Xmonad/Config_archive/Regalia's_xmonad.hs
> https://wiki.haskell.org/Xmonad/Config_archive/Thayer_Williams'_xmonad.hs
> https://wiki.haskell.org/Xmonad/Config_archive/avendael's_xmonad.hs
> http://thinkingeek.com/2011/11/21/simple-guide-configure-xmonad-dzen2-conky/
> https://github.com/davidbeckingsale/xmonad-config/blob/master/xmonad.hs
>
> 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!
I have something similar (unpublished) with two xmobars, but I do this
because I essentially ran out of space to display all the info I want to
display. One top xmobar per screen that displays workspace info, current
directory (heavily integrated with topicspaces) and window titles (that
took some hacking), and a bottom one on the main screen for system info.

> 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.
To add to this: xmobar doesn't interpret separators in the output piped
to it at all.

> 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.
Hm works for me? You just need to be able to use ppExtras, the rest can
be entirely custom. I do agree that the code is quite specific to your
status bar though.

> 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.
That is neat but it takes only an application of shorten in the right
place, namely before adding all the markup.

> 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.
Well to be honest I would expect such a migration to involve a certain
amount of work regardless of the way my xmonad output is formatted - for
example I'd need to migrate all my system information scripts and maybe
write some new ones. The formatting would be a minor problem.

> [Conclusion]
>
> 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!
I'm interested, but so far I see nothing that would make me migrate. The
most difficult part for me as a relative haskell noob was to get getName
to behave and generally get all the desired info out of xmonad in the
first place. Formatting was verbose to do but not particularly difficult.
Personally, the first place I'd improve would be the xmobar config
parser (not applicable to your usecase).

Cheers,
vrs

PS: since you're familiar with dzen and its syntax, you may want to look
at this commit and check whether dzenstrip has a similar issue:
<https://github.com/xmonad/xmonad-contrib/commit/0a7ae19f90ceeac609f71eccd47cd3e07c4e5f25>
_______________________________________________
xmonad mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/xmonad
Reply | Threaded
Open this post in threaded view
|

Re: `Status' Package [xmonad-contrib]

Brent Yorgey
In reply to this post by Matt Walker
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.

-Brent

On Sun, Dec 13, 2015 at 11:50 AM Matt Walker <[hidden email]> wrote:
Hello everyone,

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.

[Problem Statement]

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.

[Evidence of Problem]

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:

https://wiki.haskell.org/Xmonad/Config_archive/And1's_xmonad.hs (note the hacky (but effective) use of the DynamicLog PP facilities)
https://wiki.haskell.org/Xmonad/Config_archive/Regalia's_xmonad.hs
https://wiki.haskell.org/Xmonad/Config_archive/Thayer_Williams'_xmonad.hs
https://wiki.haskell.org/Xmonad/Config_archive/avendael's_xmonad.hs
http://thinkingeek.com/2011/11/21/simple-guide-configure-xmonad-dzen2-conky/
https://github.com/davidbeckingsale/xmonad-config/blob/master/xmonad.hs

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!

[Probable Cause of Problem]

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.

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.

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.

[Proposed Solution]

I propose a new solution.  The code for this solution is located here: https://github.com/Fizzixnerd/xmonad-config/tree/master/site-haskell/src/XMonad/Hooks/DynamicLog/Status .  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.

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.

Here is a brief summary of the type:

type Status b a = Writer (b, Dual b) a
type StatusText = Status [T.Text] T.Text

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>.

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.

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.

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.

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.

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.

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.

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.

[License]

Its currently GPLv3, but I have no qualms about changing it once its ready.

[Conclusion]

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!

Sincerely,
Matt
_______________________________________________
xmonad mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/xmonad

_______________________________________________
xmonad mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/xmonad