Besides an standalone program, xmobar
is also a Haskell library providing
an interface to write your own status bar. You can write, instead of a
configuration file, a real Haskell program that will be compiled and run
when you invoke xmobar
.
Make sure that ghc
will be able to locate the xmobar library, e.g. with
cabal install --lib xmobar
and then write your Haskell configuration and main function using the functions and types exported in the library, which closely resemble those used in configuration files. Here’s a small example:
import Xmobar
config :: Config
config =
defaultConfig
{ font = "xft:Terminus-8",
allDesktops = True,
alpha = 200,
commands =
[ Run XMonadLog,
Run $ Memory ["t", "Mem: <usedratio>%"] 10,
Run $ Kbd [],
Run $ Date "%a %_d %b %Y <fc=#ee9a00>%H:%M:%S</fc>" "date" 10
],
template = "%XMonadLog% }{ %kbd% | %date% | %memory%",
alignSep = "}{"
}
main :: IO ()
main = xmobar config
You can then for instance run ghc --make xmobar.hs
to create a new xmobar
executable running exactly the monitors defined above. Or put your
xmobar.hs
program in ~/.config/xmobar/xmobar.hs
and, when running the
system-wide xmobar, it will notice that you have your own implementation
and (re)compile and run it as needed.
First, you need to create a data type with at least one constructor. Next
you must declare this data type an instance of the Exec
class, by defining
the one needed method (alternatively start
or run
) and 3 optional ones
(alias
, rate
, and trigger
):
start :: e -> (String -> IO ()) -> IO ()
run :: e -> IO String
rate :: e -> Int
alias :: e -> String
trigger :: e -> (Maybe SignalType -> IO ()) -> IO ()
start
must receive a callback to be used to display the String
produced by
the plugin. This method can be used for plugins that need to perform
asynchronous actions. See src/Xmobar/Plugins/PipeReader.hs
for an example.
run
can be used for simpler plugins. If you define only run
the plugin
will be run every second. To overwrite this default you just need to
implement rate
, which must return the number of tenth of seconds between
every successive runs. See examples/xmobar.hs for an example of a plugin
that runs just once, and src/Xmobar/Plugins/Date.hs for one that
implements rate
.
Notice that Date could be implemented as:
instance Exec Date where
alias (Date _ a _) = a
start (Date f _ r) = date f r
date :: String -> Int -> (String -> IO ()) -> IO ()
date format r callback = do go
where go = do
t <- toCalendarTime =<< getClockTime
callback $ formatCalendarTime defaultTimeLocale format t
tenthSeconds r >> go
Modulo some technicalities like refreshing the time-zone in a clever way,
this implementation is equivalent to the one you can read in
Plugins/Date.hs
.
alias
is the name to be used in the output template. Default alias will be
the data type constructor.
After that your type constructor can be used as an argument for the
Runnable type constructor Run
in the commands
list of the configuration
options.
If your plugin only implements alias
and start
, then it is advisable to
put it into the Xmobar/Plugins/Monitors
directory and use one of the many
run*
functions in Xmobar.Plugins.Monitors.Run in order to define
start
. The Exec
instance should then live in Xmobar.Plugins.Monitors.
To use your new plugin, you just need to use a pure Haskell configuration
for xmobar (as explained above) and load your definitions in your xmobar.hs
file. You can see an example in examples/xmobar.hs showing you how to write
a Haskell configuration that uses a new plugin, all in one file.
When xmobar runs with the full path to that Haskell file as its argument
(or if you put it in ~/.config/xmobar/xmobar.hs
), and with the xmobar
library installed (e.g., with cabal install --lib xmobar
), the Haskell
code will be compiled as needed, and the new executable spawned for you.
That’s it!
For an elaborated, experimental and underdocumented example of writing your own repos and status bars using xmobar, see this repo at jao/xmobar-config.