aboutsummaryrefslogtreecommitdiffstats
path: root/XMonad/Hooks/DynamicLog.hs
diff options
context:
space:
mode:
Diffstat (limited to 'XMonad/Hooks/DynamicLog.hs')
-rw-r--r--XMonad/Hooks/DynamicLog.hs218
1 files changed, 155 insertions, 63 deletions
diff --git a/XMonad/Hooks/DynamicLog.hs b/XMonad/Hooks/DynamicLog.hs
index ed0b1ef..77fece5 100644
--- a/XMonad/Hooks/DynamicLog.hs
+++ b/XMonad/Hooks/DynamicLog.hs
@@ -21,16 +21,15 @@ module XMonad.Hooks.DynamicLog (
-- $usage
-- * Drop-in loggers
- makeSimpleDzenConfig,
dzen,
dynamicLog,
- dynamicLogString,
dynamicLogDzen,
dynamicLogXmobar,
- dynamicLogWithPP,
dynamicLogXinerama,
-- * Build your own formatter
+ dynamicLogWithPP,
+ dynamicLogString,
PP(..), defaultPP, dzenPP, sjanssenPP, byorgeyPP,
-- * Formatting utilities
@@ -41,13 +40,16 @@ module XMonad.Hooks.DynamicLog (
pprWindowSet,
pprWindowSetXinerama
+ -- * To Do
+ -- $todo
+
) where
--
-- Useful imports
--
import XMonad
-import Data.Maybe ( isJust )
+import Data.Maybe ( isJust, catMaybes )
import Data.List
import Data.Ord ( comparing )
import qualified XMonad.StackSet as S
@@ -63,41 +65,80 @@ import XMonad.Hooks.UrgencyHook
-- > import XMonad
-- > import XMonad.Hooks.DynamicLog
--
--- Then set your logHook to an appropriate function, for example
+-- If you just want a quick-and-dirty status bar with zero effort, try
+-- the 'dzen' function, which sets up a dzen status bar with a default
+-- format:
+--
+-- > main = dzen xmonad
+--
+-- or, to use this with your own custom xmonad configuration,
+--
+-- > main = dzen $ \conf -> xmonad $ conf { <your customizations> }
--
+-- Alternatively, you can choose among several default status bar
+-- formats ('dynamicLog', 'dynamicLogDzen', 'dynamicLogXmobar', or
+-- 'dynamicLogXinerama') by simply setting your logHook to the
+-- appropriate function, for instance:
+--
+-- > main = xmonad $ defaultConfig {
+-- > ...
-- > logHook = dynamicLog
+-- > ...
+-- > }
+--
+-- For more flexibility, you can also use 'dynamicLogWithPP' and supply
+-- your own pretty-printing format (by either defining one from scratch,
+-- or customizing one of the provided examples).
+-- For example:
--
--- or, for more flexibility, something like
+-- > -- use sjanssen's pretty-printer format, but with the sections
+-- > -- in reverse
+-- > logHook = dynamicLogWithPP $ sjanssenPP { ppOrder = reverse }
--
--- > logHook = dynamicLogWithPP myDynamicLogPP
--- > ...
--- > myDynamicLogPP = defaultPP { ... -- override pretty-printer with specific settings
+-- Note that setting the @logHook@ only sets up xmonad's output; you
+-- are responsible for starting your own status bar program (e.g. dzen
+-- or xmobar) and making sure xmonad's output is piped into it
+-- appropriately, either by putting it in your @.xsession@ or similar
+-- file, or by using @spawnPipe@ in your @main@ function, for example:
--
--- If you don't use statusbar, you can use dynamicLogString to show on-screen
--- notifications in response to some events. E.g. to show current layout when
--- it's changed create apropriate PP and add to keybindings:
+-- > main = do
+-- > h <- spawnPipe "xmobar -options -foo -bar"
+-- > xmonad $ defaultConfig {
+-- > ...
+-- > logHook = dynamicLogWithPP $ defaultPP { ppOutput = hPutStrLn h }
+--
+-- If you use @spawnPipe@, be sure to redefine the 'ppOutput' field of
+-- your pretty-printer as in the example above; by default the status
+-- will be printed to stdout rather than the pipe you create.
+--
+-- Even if you don't use a statusbar, you can still use
+-- 'dynamicLogString' to show on-screen notifications in response to
+-- some events. For example, to show the current layout when it
+-- changes, you could make a keybinding to cycle the layout and
+-- display the current status:
--
-- > , ((mod1Mask, xK_a ), sendMessage NextLayout >> (dynamicLogString myPP >>= \d->spawn $"xmessage "++d))
+--
--- | An example xmonad config that spawns a new dzen toolbar and uses
--- the default dynamic log output.
-makeSimpleDzenConfig :: IO (XConfig (Choose Tall (Choose (Mirror Tall) Full)))
-makeSimpleDzenConfig = do
- h <- spawnPipe "dzen2"
- return defaultConfig
- { defaultGaps = [(18,0,0,0)]
- , logHook = dynamicLogWithPP dzenPP
- { ppOutput = hPutStrLn h } }
-
--- |
+-- $todo
+--
+-- * incorporate dynamicLogXinerama into the PP framework somehow
--
--- Run xmonad with a dzen status bar set to some nice defaults. Output
+-- * add an xmobarEscape function
+
+-- | Run xmonad with a dzen status bar set to some nice defaults. Output
-- is taken from the dynamicLogWithPP hook.
--
-- > main = dzen xmonad
--
--- The intent is that the above config file should provide a nice status
--- bar with minimal effort.
+-- The intent is that the above config file should provide a nice
+-- status bar with minimal effort. If you want to customize your xmonad
+-- configuration while using this, you'll have to do something like
+--
+-- > main = dzen $ \conf -> xmonad $ conf { <your customized settings...> }
+--
+-- If you wish to customize the status bar format at all, you'll have to
+-- use something like 'dynamicLogWithPP' instead.
--
dzen :: (XConfig (Choose Tall (Choose (Mirror Tall) Full)) -> IO ()) -> IO ()
dzen f = do
@@ -111,51 +152,68 @@ dzen f = do
bg = "'#3f3c6d'"
flags = "-e '' -w 400 -ta l -fg " ++ fg ++ " -bg " ++ bg
--- |
--- An example log hook, print a status bar output to stdout, in the form:
+-- | An example log hook, which prints status information to stdout in
+-- the default format:
--
-- > 1 2 [3] 4 7 : full : title
--
-- That is, the currently populated workspaces, the current
-- workspace layout, and the title of the focused window.
--
+-- To customize the output format, see 'dynamicLogWithPP'.
+--
dynamicLog :: X ()
dynamicLog = dynamicLogWithPP defaultPP
--- |
--- Returns formatted log message.
+-- | An example log hook that emulates dwm's status bar, using colour
+-- codes printed to dzen. Requires dzen. Workspaces, xinerama,
+-- layouts and the window title are handled.
+dynamicLogDzen :: X ()
+dynamicLogDzen = dynamicLogWithPP dzenPP
+
+-- | These are good defaults to be used with the xmobar status bar.
+dynamicLogXmobar :: X ()
+dynamicLogXmobar = dynamicLogWithPP xmobarPP
+
+-- | Format the current status using the supplied pretty-printing format,
+-- and write it to stdout.
+dynamicLogWithPP :: PP -> X ()
+dynamicLogWithPP pp = dynamicLogString pp >>= io . ppOutput pp
+
+-- | The same as 'dynamicLogWithPP', except it simply returns the status
+-- as a formatted string without actually printing it to stdout, to
+-- allow for further processing, or use in some application other than
+-- a status bar.
dynamicLogString :: PP -> X String
dynamicLogString pp = do
+
winset <- gets windowset
urgents <- readUrgents
sort' <- ppSort pp
+
-- layout description
let ld = description . S.layout . S.workspace . S.current $ winset
+
-- workspace list
let ws = pprWindowSet sort' urgents pp winset
+
-- window title
wt <- maybe (return "") (fmap show . getName) . S.peek $ winset
+ -- run extra loggers, ignoring any that generate errors.
+ extras <- sequence $ map (flip catchX (return Nothing)) $ ppExtras pp
+
return $ sepBy (ppSep pp) . ppOrder pp $
[ ws
, ppLayout pp ld
, ppTitle pp wt
]
+ ++ catMaybes extras
--- |
--- A log function that uses the 'PP' hooks to customize output.
-dynamicLogWithPP :: PP -> X ()
-dynamicLogWithPP pp = dynamicLogString pp >>= io . ppOutput pp
-
--- | An example log hook that emulates dwm's status bar, using colour
--- codes printed to dzen. Requires dzen. Workspaces, xinerama,
--- layouts and the window title are handled.
---
-dynamicLogDzen :: X ()
-dynamicLogDzen = dynamicLogWithPP dzenPP
-
--- | Do the actual status formatting, using a pretty-printer.
-pprWindowSet :: ([WindowSpace] -> [WindowSpace]) -> [Window] -> PP -> WindowSet -> String
+-- | Format the workspace information, given a workspace sorting function,
+-- a list of urgent windows, a pretty-printer format, and the current
+-- WindowSet.
+pprWindowSet :: WorkspaceSort -> [Window] -> PP -> WindowSet -> String
pprWindowSet sort' urgents pp s = sepBy (ppWsSep pp) . map fmt . sort' $
map S.workspace (S.current s : S.visible s) ++ S.hidden s
where this = S.tag (S.workspace (S.current s))
@@ -176,6 +234,10 @@ pprWindowSet sort' urgents pp s = sepBy (ppWsSep pp) . map fmt . sort' $
-- where 1, 9, and 3 are the workspaces on screens 1, 2 and 3, respectively,
-- and 2 and 7 are non-visible, non-empty workspaces.
--
+-- Unfortunately, at the present time, the current layout and window title
+-- are not shown, and there is no way to incorporate the xinerama
+-- workspace format shown above with 'dynamicLogWithPP'. Hopefully this
+-- will change soon.
dynamicLogXinerama :: X ()
dynamicLogXinerama = withWindowSet $ io . putStrLn . pprWindowSetXinerama
@@ -237,21 +299,28 @@ xmobarColor :: String -- ^ foreground color: a color name, or #rrggbb format
xmobarColor fg bg = wrap t "</fc>"
where t = concat ["<fc=", fg, if null bg then "" else "," ++ bg, ">"]
--- | The 'PP' type allows the user to customize various behaviors of
--- dynamicLogPP.
+-- ??? add an xmobarEscape function?
+
+-- | The 'PP' type allows the user to customize the formatting of
+-- status information.
data PP = PP { ppCurrent :: WorkspaceId -> String
- -- ^ how to print the tag of the currently focused workspace
+ -- ^ how to print the tag of the currently focused
+ -- workspace
, ppVisible :: WorkspaceId -> String
- -- ^ how to print tags of visible but not focused workspaces (xinerama only)
+ -- ^ how to print tags of visible but not focused
+ -- workspaces (xinerama only)
, ppHidden :: WorkspaceId -> String
- -- ^ how to print tags of hidden workspaces which contain windows
+ -- ^ how to print tags of hidden workspaces which
+ -- contain windows
, ppHiddenNoWindows :: WorkspaceId -> String
-- ^ how to print tags of empty hidden workspaces
, ppUrgent :: WorkspaceId -> String
-- ^ format to be applied to tags of urgent workspaces.
- -- NOTE that 'ppUrgent' is applied /in addition to/ 'ppHidden'!
+ -- NOTE that 'ppUrgent' is applied /in addition to/
+ -- 'ppHidden'!
, ppSep :: String
- -- ^ separator to use between different log sections (window name, layout, workspaces)
+ -- ^ separator to use between different log sections
+ -- (window name, layout, workspaces)
, ppWsSep :: String
-- ^ separator to use between workspace tags
, ppTitle :: String -> String
@@ -259,11 +328,32 @@ data PP = PP { ppCurrent :: WorkspaceId -> String
, ppLayout :: String -> String
-- ^ layout name format
, ppOrder :: [String] -> [String]
- -- ^ how to order the different log sections
+ -- ^ how to order the different log sections. By
+ -- default, this function receives a list with three
+ -- formatted strings, representing the workspaces,
+ -- the layout, and the current window title,
+ -- respectively. If you have specified any extra
+ -- loggers in 'ppExtras', their output will also be
+ -- appended to the list. To get them in the reverse
+ -- order, you can just use @ppOrder = reverse@. If
+ -- you don't want to display the current layout, you
+ -- could use something like @ppOrder = \\(ws:_:t:_) ->
+ -- [ws,t]@, and so on.
, ppSort :: X ([WindowSpace] -> [WindowSpace])
- -- ^ how to sort the workspaces. See "XMonad.Util.WorkspaceCompare" for some useful sorts.
+ -- ^ how to sort the workspaces. See
+ -- "XMonad.Util.WorkspaceCompare" for some useful
+ -- sorts.
+ , ppExtras :: [X (Maybe String)]
+ -- ^ loggers for generating extra information such as
+ -- time and date, system load, battery status, and so
+ -- on. See "XMonad.Util.Loggers" for examples, or create
+ -- your own!
, ppOutput :: String -> IO ()
- -- ^ formatter that gets applied to the entire log string before it is output.
+ -- ^ applied to the entire formatted string in order to
+ -- output it. Can be used to specify an alternative
+ -- output method (e.g. write to a pipe instead of
+ -- stdout), and/or to perform some last-minute
+ -- formatting.
}
-- | The default pretty printing options, as seen in 'dynamicLog'.
@@ -280,6 +370,7 @@ defaultPP = PP { ppCurrent = wrap "[" "]"
, ppOrder = id
, ppOutput = putStrLn
, ppSort = getSortByIndex
+ , ppExtras = []
}
-- | Settings to emulate dwm's statusbar, dzen only.
@@ -301,8 +392,16 @@ dzenPP = defaultPP { ppCurrent = dzenColor "white" "#2b4f98" . pad
, ppTitle = ("^bg(#324c80) " ++) . dzenEscape
}
--- | The options that sjanssen likes to use, as an example. Note the use of
--- 'xmobarColor' and the record update on 'defaultPP'.
+-- | Some nice xmobar defaults.
+xmobarPP :: PP
+xmobarPP = defaultPP { ppCurrent = xmobarColor "yellow" "" . wrap "[" "]"
+ , ppTitle = xmobarColor "green" "" . shorten 40
+ , ppVisible = wrap "(" ")"
+ }
+
+-- | The options that sjanssen likes to use with xmobar, as an
+-- example. Note the use of 'xmobarColor' and the record update on
+-- 'defaultPP'.
sjanssenPP :: PP
sjanssenPP = defaultPP { ppCurrent = xmobarColor "white" "#ff000000"
, ppTitle = xmobarColor "#00ee00" "" . shorten 80
@@ -323,10 +422,3 @@ byorgeyPP = defaultPP { ppHiddenNoWindows = showNamedWorkspaces
then pad wsId
else ""
--- | These are good defaults to be used with the xmobar status bar.
-dynamicLogXmobar :: X ()
-dynamicLogXmobar =
- dynamicLogWithPP defaultPP { ppCurrent = xmobarColor "yellow" "" . wrap "[" "]"
- , ppTitle = xmobarColor "green" "" . shorten 40
- , ppVisible = wrap "(" ")"
- }