summaryrefslogtreecommitdiffhomepage
path: root/Runnable.hs
diff options
context:
space:
mode:
authorAndrea Rossato <andrea.rossato@ing.unitn.it>2007-07-12 19:50:34 +0200
committerAndrea Rossato <andrea.rossato@ing.unitn.it>2007-07-12 19:50:34 +0200
commite85b0920a06ad019754e1cb8e72eb6cc34cdeedc (patch)
tree34a28f6a54290bd7347f83efc4a7a5f387419f31 /Runnable.hs
parent14267de1e03841980ce99206c0cf63e40bfa6cca (diff)
downloadxmobar-e85b0920a06ad019754e1cb8e72eb6cc34cdeedc.tar.gz
xmobar-e85b0920a06ad019754e1cb8e72eb6cc34cdeedc.tar.bz2
use of existential types for plugin support
This patch, which *changes the configuration format*, adds easy plugin support by using an existential type for storing the list of commands to be executed. Adding a plugin is just a matter of writing the appropriate instance of the Exec class, after importing Commands.hs. I must thank Claus Reinke for the help in understanding the mysteries of reading existential types. The Read instance of Runnable must be credited to him. See here: http://www.haskell.org/pipermail/haskell-cafe/2007-July/028227.html darcs-hash:20070712175034-d6583-f10174bb3b0a9b4f6e08d05052c18f30e539b319.gz
Diffstat (limited to 'Runnable.hs')
-rw-r--r--Runnable.hs50
1 files changed, 50 insertions, 0 deletions
diff --git a/Runnable.hs b/Runnable.hs
new file mode 100644
index 0000000..90e01af
--- /dev/null
+++ b/Runnable.hs
@@ -0,0 +1,50 @@
+{-# OPTIONS -fglasgow-exts #-}
+module Runnable where
+
+import Control.Monad
+import Text.Read
+import Text.ParserCombinators.ReadPrec
+import Config (runnableTypes)
+import Commands
+
+data Runnable = forall r . (Exec r,Show r, Read r) => Run r
+
+instance Show Runnable where
+ show (Run a) = "Run " ++ show a
+
+instance Exec Runnable where
+ run (Run a) = run a
+ rate (Run a) = rate a
+ alias (Run a) = alias a
+
+instance Read Runnable where
+ readPrec = readRunnable
+
+-- read an existential as any of hidden types ts
+class ReadAsAnyOf ts ex where
+ readAsAnyOf :: ts -> ReadPrec ex
+
+instance ReadAsAnyOf () ex where
+ readAsAnyOf ~() = mzero
+
+instance (Read t, Show t, Exec t, ReadAsAnyOf ts Runnable) => ReadAsAnyOf (t,ts) Runnable where
+ readAsAnyOf ~(t,ts) = r t `mplus` readAsAnyOf ts
+ where r ty = do { m <- readPrec; return (Run (m `asTypeOf` ty)) }
+
+
+
+readRunnable :: ReadPrec Runnable
+readRunnable = prec 10 $ do
+ Ident "Run" <- lexP
+ parens $ readAsAnyOf runnableTypes
+
+
+-- | Reads the configuration files or quits with an error
+readConfig :: FilePath -> IO Runnable
+readConfig f =
+ do s <- readFile f
+ case reads s of
+ [(config,_)] -> return config
+ [] -> error ("Corrupt config file: " ++ f)
+ _ -> error ("Some problem occured. Aborting...")
+