Friday, January 30, 2009

xmonad Stops Responding to Keyboard Input

I have been using xmonad on Ubuntu Hardy and extremely happy with its model. When compared to my previous window manager stumpwm, it is missing a few niceties but more than makes up for those with its flexible layout management. But I nearly gave up on xmonad when I started running into an issue which is a real deal breaker.

The problem is this: everything is fine and dandy and for no apparent reason, xmonad stops responding to keyboard. The current window, however, accepts the keyboard input. My only workaround was to restart my session. Completely unacceptable.

Googling for "xmonad stops responding" brought up this bug report http://code.google.com/p/xmonad/issues/detail?id=97. Comment number 26 clued me in to what might be happening. Some more googling and I chanced upon this http://markmail.org/message/4gmek2d5pxv76dlw#query:xmonad%20xmobar%20dynamiclog+page:1+mid:rnmlvyyft33gnjpm+state:results,  Andrea Rossato's last entry on that thread gives you the solution which is to run the StdinReader in xmobar's configuration.

Finally, I understand what is happening. xmonad is writing to stdout and xmobar to which the xmonad's output is being piped, must read it or xmonad will block when the pipe fills up. The problem is with xmobar configuration below.

Config { font = "-misc-fixed-*-*-*-*-10-*-*-*-*-*-*-*"
       , bgColor = "black"
       , fgColor = "grey"
       , position = Top
       , commands = [ Run Weather "KSQL" ["-t",": F/C","-L","18","-H","80","--normal","green","--high","red","--low","lightblue"] 36000
                    , Run Network "eth0" ["-L","0","-H","32","--normal","green","--high","red"] 10
                    , Run Network "eth1" ["-L","0","-H","32","--normal","green","--high","red"] 10
                    , Run Cpu ["-L","3","-H","50","--normal","green","--high","red"] 10
                    , Run Memory ["-t","Mem: %"] 10
                    , Run Swap [] 10
                    , Run Com "uname" ["-s","-r"] "" 36000
                , Run Date "%a %b %_d %Y %H:%M:%S" "date" 10
                , Run StdinReader
                    ]
       , sepChar = "%"
       , alignSep = "}{"
       , template = "%cpu% | %memory% * %swap% | %eth0% - %eth1% }{ %date%| %KSQL% %StdinReader%"
       }

The "Run StdinReader" line is the key to fixing this problem. I think it is optional to add %StdinReader% to the template.

Thursday, January 08, 2009

Haskell XML Processing Using HXT


There seem to be two ways to process XML in Haskell -- HaXmL and HXT. HXT seems to be the most capable and understands XML namespaces. Support for namespaces being key for my needs, I started with HXT. As it happens often, I ran into some issues and spent more than a few hours trying to understand them.

Here is a simple HXT program to parse an XML document  and write it to the terminal. The XML document is embedded in the code. It works as expected.

--{-# LANGUAGE Arrows, NoMonomorphismRestriction #-}
--{-# OPTIONS -fglasgow-exts -cpp #-}

import System.Environment
import System.IO

   
import Text.XML.HXT.Arrow

main :: IO ()
main = do
  runX ( readString [(a_validate, v_0)
                    , (a_encoding, isoLatin1)]
         "<a><b/><b/></a>"
         >>>
  writeDocument [] "/dev/tty"
       )             
  return ()

Okay, that works beautifully. I will now add filter to select only XML  elements from the document.

--{-# LANGUAGE Arrows, NoMonomorphismRestriction #-}
--{-# OPTIONS -fglasgow-exts -cpp #-}

import System.Environment
import System.IO

   
import Text.XML.HXT.Arrow

main :: IO ()
main = do
  runX ( readString [(a_validate, v_0)
                    , (a_encoding, isoLatin1)]
         "<a><b/><b/></a>"
         >>>
         deep isElem
         >>>
  writeDocument [] "/dev/tty"
       )             
  return ()

That produces the entire document. Say, I am interested in extracting all elements named b, and I will enhance my filter.


--{-# LANGUAGE Arrows, NoMonomorphismRestriction #-}
--{-# OPTIONS -fglasgow-exts -cpp #-}

import System.Environment
import System.IO

   
import Text.XML.HXT.Arrow

main :: IO ()
main = do
  runX ( readString [(a_validate, v_0)
                    , (a_encoding, isoLatin1)]
         "<a><b/><b/></a>"
         >>>
         deep (isElem >>> hasName "a")
         >>>
  writeDocument [] "/dev/tty"
       )             
  return () 
 
This is where my productivity came to a screeching halt. I started suspecting that somehow,  my filter wasn't specified right, HXT has a silly bug and so on. 
After significant frustration, I started reading HXT tutorial. Turns out that readDocument returns a Rose Tree and write document expects to receive a similar tree. Once I added
the hasName filter, the result of the arrow no longer returned something that was acceptable to writeDocument. These filter functions, silently ignore errors. Phew! The fix is,
adding root element to the result of filter.

--{-# LANGUAGE Arrows, NoMonomorphismRestriction #-}
--{-# OPTIONS -fglasgow-exts -cpp #-}

import System.Environment
import System.IO

   
import Text.XML.HXT.Arrow

main :: IO ()
main = do
  runX ( readString [(a_validate, v_0)
                    , (a_encoding, isoLatin1)]
         "<a><b/><b/></a>"
         >>>
         root [] [deep (isElem >>> hasName "b")]
         >>>
  writeDocument [] "/dev/tty"
       )             
  return () 
HXT tutorial shows a canonical way to write HXT code and I should probably switch to that style for serious work, 
Hope this serves as a reminder to rtfm next time around!