Skip to Content »

Tech Life of Recht » archive for 'dzen2'

 xmonad 0.5

  • December 16th, 2007
  • 12:57 am

xmonad 0.5 is out, and I haven't upgraded my installation in a while. It's pretty nice that configuration is now done in /.xmonad/xmonad.hs, then there's no need to recompile xmonad all the time. The configuration change did require a reorganisation of my old Config.hs, so I took a look at some of the samples to see what other people did.
I ended up with something which looks like this:

xmonad

This is my xmonad.hs:

CODE:
  1. -- XMonad Core
  2. import XMonad
  3. import XMonad.Layout
  4. import XMonad.Operations
  5. import qualified XMonad.StackSet as W
  6.  
  7. -- GHC hierarchical libraries
  8. import Data.Bits ((.|.))
  9. import qualified Data.Map as M
  10. import Graphics.X11
  11. import Graphics.X11.Xlib
  12. import Graphics.X11.Xlib.Extras
  13. import System.IO
  14.  
  15. -- Contribs
  16. import XMonad.Actions.CycleWS
  17. import XMonad.Actions.SwapWorkspaces
  18. import XMonad.Actions.Submap
  19. import XMonad.Actions.WindowBringer
  20. import XMonad.Actions.FloatKeys
  21.  
  22. import XMonad.Hooks.UrgencyHook
  23. import XMonad.Layout.NoBorders
  24. import XMonad.Layout.Tabbed
  25. import XMonad.Layout.WindowNavigation
  26. import XMonad.Layout.Grid
  27. import XMonad.Layout.LayoutHints
  28. import XMonad.Layout.Dishes
  29. import XMonad.Util.EZConfig
  30. import XMonad.Util.Run
  31.  
  32. import XMonad.Prompt.Shell
  33. import XMonad.Prompt
  34.  
  35. import XMonad.Hooks.DynamicLog   ( PP(..), dynamicLogWithPP, dzenColor, wrap, defaultPP )
  36.  
  37. myfont = "\"-xos4-terminus-medium-r-normal--12-120-72-72-c-60-iso8859-1\""
  38. fgcolor = "black"
  39. bgcolor = "white"
  40.  
  41. statusBarCmd= "dzen2 -e '' -w 660 -h 15 -ta l -xs 1 -fg " ++ fgcolor ++ " -bg " ++ bgcolor ++ " -fn " ++ myfont
  42.  
  43. -- Get ready!
  44. main = do din <- spawnPipe statusBarCmd
  45.           xmonad $ withUrgencyHook dzenUrgencyHook { args = ["-bg", "darkgreen", "-xs", "1"] }
  46.               $ defaultConfig
  47.                 { workspaces     = workspaces'
  48.                 , modMask        = modMask'
  49.                 , numlockMask    = 0
  50.                 , layoutHook     = layoutHook'
  51.                 , terminal       = "urxvtc || urxvt"
  52.     , normalBorderColor = "#dddddd"
  53.     , focusedBorderColor = "#3499dd"
  54.     , defaultGaps = [(15,0,0,0)]
  55.     , logHook = dynamicLogWithPP $ myPP din
  56.                 }
  57.                 `additionalKeys` keys'
  58.  
  59. modMask'    = mod4Mask
  60. workspaces' = map show [1] ++ ["web", "mail", "chat", "code"] ++ map show [6 .. 9 :: Int]
  61.  
  62. layoutHook' =
  63.     configurableNavigation noNavigateBorders $
  64.     layouts
  65. layouts =
  66.         Mirror tiled
  67.     ||| tiled
  68.     ||| Grid
  69.     ||| layoutHints Full
  70.     ||| Dishes 2 (1/5)
  71.     ||| noBorders (tabbed shrinkText
  72.                           defaultTConf { fontName = myfont })
  73.   where
  74.      tiled   = Tall nmaster delta ratio
  75.      nmaster = 2     -- The default number of windows in the master pane
  76.      ratio   = 1/2   -- Default proportion of screen occupied by master pane
  77.      delta   = 3/100 -- Percent of screen to increment by when resizing panes
  78. noFollow CrossingEvent {} = return False
  79. noFollow _                = return True
  80. keys' =
  81.     [ ((modMask' .|. shiftMask, xK_d        ), spawn "date | dzen2 -p 2 -xs 1") -- %! Print current date
  82.      , ((modMask', xK_p), shellPrompt defaultXPConfig)
  83.     ]
  84.     ++
  85.     -- modMask'-[1..0] %! Switch to workspace N
  86.     -- modMask'-shift-[1..0] %! Move client to workspace N
  87.     [((m .|. modMask', k), windows $ f i)
  88.         | (i, k) <- zip workspaces' $ [xK_1 .. xK_9] ++ [xK_0]
  89.         , (f, m) <- [(W.greedyView, 0), (W.shift, shiftMask)]]
  90.     ++
  91.     -- modMask'-{e,r} %! Switch to physical/Xinerama screens 1 or 2
  92.     -- modMask'-shift-{e,r} %! Move client to screen 1 or 2
  93.     [((m .|. modMask', key), screenWorkspace sc>>= flip whenJust (windows . f))
  94.         | (key, sc) <- zip [xK_e, xK_w] [0..]
  95.         , (f, m) <- [(W.view, 0), (W.shift, shiftMask)]]
  96.     ++
  97.     [((modMask' .|. mod1Mask, k), windows $ swapWithCurrent i)
  98.         | (i, k) <- zip workspaces' $ [xK_1 .. xK_9] ++ [xK_0]]
  99.     -- float keys
  100.     ++
  101.     [
  102.       ((modMask',               xK_d     ), withFocused (keysResizeWindow (-10,-10) (1,1)))
  103.     , ((modMask',               xK_s     ), withFocused (keysResizeWindow (10,10) (1,1)))
  104.     , ((modMask',               xK_a     ), withFocused (keysMoveWindowTo (512,384) (1, 0)))
  105.     ]
  106.  
  107.  
  108. myPP h = defaultPP
  109.          { ppCurrent  = dzenColor "white" "#cd8b00" . pad
  110.          , ppVisible  = dzenColor "white" "#666666" . pad
  111.          , ppHidden   = dzenColor "black" "#cccccc" . pad
  112.          , ppHiddenNoWindows = dzenColor "#999999" "#cccccc" . pad
  113.          , ppWsSep    = dzenColor "#bbbbbb" "#cccccc" "^r(1x18)"
  114.          , ppSep      = dzenColor "#bbbbbb" "#cccccc" "^r(1x18)"
  115.          , ppLayout   = dzenColor "black" "#cccccc" .
  116.                         (\ x -> case x of
  117.                                   "TilePrime Horizontal" ->
  118.                                     " ^i(/home/emertens/images/tile_horz.xpm) "
  119.                                   "TilePrime Vertical"   ->
  120.                                     " ^i(/home/emertens/images/tile_vert.xpm) "
  121.                                   "Hinted Full"          ->
  122.                                     " ^i(/home/emertens/images/fullscreen.xpm) "
  123.                                   _                      -> pad x
  124.                         )
  125.          , ppTitle    = (' ':) . escape
  126.          , ppOutput   = hPutStrLn h
  127.          }
  128.   where
  129.   escape = concatMap (\x -> if x == '^' then "^^" else [x])
  130.   pad = wrap " " " "

I use a simple shell script for starting xmonad:

CODE:
  1. ssh-add ~/.ssh/id_dsa </dev/null>/dev/null
  2. Esetroot /usr/share/backgrounds/warty-final-ubuntu.png
  3. unclutter -idle 2 &
  4. urxvtd -f -o
  5. irxevent -d
  6.  
  7. gnome-settings-daemon &
  8. gnome-volume-manager &
  9.  
  10. export PATH=$PATH:`dirname $0`
  11. `dirname $0`/status &
  12.  
  13. xmonad

Finally, the dzen2 status bar is run using this script:

CODE:
  1. #!/bin/sh
  2.  
  3. BG=white
  4. FG=black
  5. FONT="-xos4-terminus-medium-r-normal--12-120-72-72-c-60-iso8859-1"
  6.  
  7. BFG="#444"
  8.  
  9. gcpubar -i 2 -fg '#444' -w 30 -h 10 | dzen2 -e '' -x 1360 -fg $FG \
  10.    -bg $BG -fn $FONT -h 15 -xs 1 &
  11.  
  12. while :; do
  13. MEM=`memstatus.awk /proc/meminfo`
  14. CPU=`cpustatus.awk`
  15. DATE=`date +"%d-%m %k:%M"`
  16.  
  17. REM=`awk '/remaining capacity/ { print $3 }' /proc/acpi/battery/BAT0/state`
  18. LAST=`awk '/last full/ { print $4}' /proc/acpi/battery/BAT0/info`
  19. STATE=`awk '{print $2}' /proc/acpi/ac_adapter/ADP1/state`
  20. if [ "$STATE" = "on-line" ]; then
  21.   BAT=$(echo $REM $LAST | awk '{printf "Bat: %.1f%%, AC", ($1/$2)*100'})
  22. else
  23.   PRESENT=`awk '/present rate/ { print $3}' /proc/acpi/battery/BAT0/state`
  24.   BAT=$(echo $REM $LAST $PRESENT | \
  25.     awk '{printf "Bat: %.1f%%, %d min", ($1/$2)*100, ($1/$3)*60}')
  26. fi
  27.  
  28. LOAD=`awk '{print $1 " " $2 " " $3}' /proc/loadavg`
  29.  
  30. echo "$CPU $MEM | $DATE | $BAT | $LOAD"
  31. sleep 5
  32. done | dzen2 -e '' -x 660 -w 700 -fg $FG -bg $BG -fn $FONT -h 15 -xs 1

Two awk scripts are used - one for the memory usage and one for CPU frequencies. Why awk? No idea, it just seemed like a good choice at the time.

memstatus.awk:

CODE:
  1. #!/usr/bin/awk -f
  2. BEGIN {
  3.   BG="darkgrey";
  4.   FG="#444";
  5.   WIDTH=30;
  6.   HEIGHT=10;
  7. }
  8.  
  9. /MemTotal/ {t=$2};
  10. /MemFree/ {f=$2};
  11. /SwapTotal/ {st=$2};
  12. /SwapFree/ {sf=$2};
  13.  
  14. END {
  15.   mw=int(WIDTH*(t-f)/t);
  16.   fw=WIDTH-mw;
  17.   sw=int(WIDTH*(st-sf)/st);
  18.  
  19.   printf("Mem: ^ib(1)^fg(%s)^r(%dx%d)^fg(%s)^r(%dx%d)" \
  20.     "^fg(%s)^r(2x%d)^fg(%s)^r(%dx%d)^fg(%s)^r(%dx%d)^ib(0)^fg()\n",
  21.     FG, mw, HEIGHT,
  22.     BG, fw, HEIGHT,
  23.     "black",
  24.     HEIGHT, BG, WIDTH-sw,
  25.     HEIGHT, FG, sw, HEIGHT);
  26. }

CODE:
  1. #!/usr/bin/awk -f
  2. BEGIN {
  3.   BG="darkgrey"
  4.   FG="#444"
  5.   WIDTH=30
  6.   HEIGHT=10
  7.   CPUS=0
  8.  
  9.   cmd = "ls /sys/devices/system/cpu"
  10.   while ((cmd | getline)> 0) {
  11.     if ($1 ~ /cpu/) {
  12.       CPUS++
  13.     }
  14.   }
  15.   close(cmd)
  16.  
  17.   printf "CPU: "
  18.   for (i=0; i <CPUS; i++) {
  19.     cfn="/sys/devices/system/cpu/cpu" i "/cpufreq/scaling_cur_freq"
  20.     mfn="/sys/devices/system/cpu/cpu" i "/cpufreq/scaling_max_freq"
  21.     getline cf <cfn
  22.     getline mf <mfn
  23.     cw=int(WIDTH*(mf-cf)/mf)
  24.  
  25.     printf("^ib(1)^fg(%s)^r(%dx%d)^fg(%s)^r(%dx%d)^ib(0)^fg()",
  26.       FG, cw, HEIGHT, BG, WIDTH-cw, HEIGHT)
  27.  
  28.     close(cfn)
  29.     close(mfn)
  30.  
  31.     if (i <CPUS - 1) {
  32.       printf("^ib(0)^fg()^r(5x0)^ib(1)")
  33.     }
  34.  
  35.   }
  36.   printf("\n");
  37. }

 My xmonad start script

  • October 25th, 2007
  • 10:54 pm

After reinstalling xmonad on my laptop using Ubuntu as the base distribution, I've finally got a setup I like, so I thought I'd share it. So, here is my script which starts xmonad:

CODE:
  1. ssh-add ~/.ssh/id_dsa </dev/null>/dev/null
  2.  
  3. Esetroot /usr/share/backgrounds/warty-final-ubuntu.png
  4. unclutter -idle 2 &
  5.  
  6. urxvtd -f -o
  7.  
  8. gnome-settings-daemon &
  9. gnome-power-manager
  10. gnome-volume-manager &
  11.  
  12. BG=white
  13. FG=black
  14. FONT="-xos4-terminus-medium-r-normal--12-120-72-72-c-60-iso8859-1"
  15.  
  16. export PATH=$PATH:`dirname $0`
  17.  
  18. # create a pipe for xmonad to talk to
  19. PIPE=$HOME/.xmonad-status
  20. rm -f $PIPE
  21. mkfifo -m 600 $PIPE
  22. [ -p $PIPE ] || exit
  23.  
  24. # and a workspace status bar, reading's xmonad's stdout
  25. dzen2 -e '' -w 680 -ta l -fg $FG -bg $BG -fn $FONT -h 15 <$PIPE &
  26.  
  27. `dirname $0`/status &
  28.  
  29. xmonad> $PIPE &
  30. wait $!
  31.  
  32. pkill -HUP dzen2
  33.  
  34. wait

This script is launched from ~/.xsession. It uses dzen and some of the dzen gadgets (which must be compiled separately from dzen/gadgets). It also starts some of the Gnome daemons which normally run under Ubuntu. This means that power management and sound volume goes through Gnome, and devices are mounted automatically when they are added to the system.

Two dzens are launched: One for displaying workspaces and one for general status. The general status script looks like this:

CODE:
  1. #!/bin/sh
  2.  
  3. BG=white
  4. FG=black
  5. FONT="-xos4-terminus-medium-r-normal--12-120-72-72-c-60-iso8859-1"
  6.  
  7. while :; do
  8. MEM=`awk '/MemTotal/ {t=$2}; /MemFree/ {f=$2}; END {print t-f " " t}' \
  9.   /proc/meminfo | dbar -s ':' -l 'Mem:' -w 10`
  10. CF0=$(echo `cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq` \
  11.   `cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq` | dbar -w 7 -l 'CPU0:')
  12. CF1=$(echo `cat /sys/devices/system/cpu/cpu1/cpufreq/scaling_cur_freq` \
  13.   `cat /sys/devices/system/cpu/cpu1/cpufreq/scaling_max_freq` | dbar -w 7 -l 'CPU1:')
  14. DATE=`date +"%d-%m %k:%M"`
  15.  
  16. REM=`grep 'remaining capacity' /proc/acpi/battery/BAT0/state | awk '{print $3}'`
  17. LAST=`grep 'last full' /proc/acpi/battery/BAT0/info |awk '{print $4}'`
  18. STATE=`awk '{print $2}' /proc/acpi/ac_adapter/ADP1/state`
  19. if [ "$STATE" = "on-line" ]; then
  20.   BAT=$(echo $REM $LAST | awk '{printf "Bat: %.1f%%, AC", ($1/$2)*100'})
  21. else
  22.   PRESENT=`grep 'present rate' /proc/acpi/battery/BAT0/state | awk '{print $3}'`
  23.   BAT=$(echo $REM $LAST $PRESENT | awk '{printf "Bat: %.1f%%, %d min", ($1/$2)*100, ($1/$3)*60}')
  24. fi
  25.  
  26. LOAD=`awk '{print $1 " " $2 " " $3}' /proc/loadavg`
  27.  
  28. echo "$CF0 $CF1 $MEM | $DATE | $BAT | $LOAD"
  29. sleep 5
  30. done | dzen2 -e '' -x 440 -w 1000 -fg $FG -bg $BG -fn $FONT -h 15

The script is made for a MacBook Pro with a two core processor and acpi. It displays the CPU frequencies in a dbar, memory usage, battery status, and load. I would like to display network status too, but I can't figure out how to dig around in dbus efficiently, so that's still missing.