summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorPavan Rikhi <pavan.rikhi@gmail.com>2020-04-09 13:51:37 -0400
committerjao <jao@gnu.org>2020-04-12 01:31:51 +0100
commit80913aeed46fc607f057a77ffdd884b5db77a0bc (patch)
treeb81dbe7fa9cea64d1431c13bb813e7043bc8faaa /src
parentdcbbf50dd474d8ea2822a31ed2c8affad828d8d1 (diff)
downloadxmobar-80913aeed46fc607f057a77ffdd884b5db77a0bc.tar.gz
xmobar-80913aeed46fc607f057a77ffdd884b5db77a0bc.tar.bz2
Add a HandleReader Plugin
This adds a new `HandleReader` plugin, which displays data from a Haskell `Handle`. This is really only useful if you are running xmobar from within another Haskell program, but lets you avoid the mechanics of creating a named pipe with the proper file permissions. Instead, you can use `System.Process.createPipe` to make a pair of read & write Handles. If you pass the read handle to HandleReader, you can use hPutStr on the write Handle to send data to xmobar from your application code.
Diffstat (limited to 'src')
-rw-r--r--src/Xmobar.hs2
-rw-r--r--src/Xmobar/Plugins/HandleReader.hs70
2 files changed, 72 insertions, 0 deletions
diff --git a/src/Xmobar.hs b/src/Xmobar.hs
index 491aa8d..d2e4126 100644
--- a/src/Xmobar.hs
+++ b/src/Xmobar.hs
@@ -32,6 +32,7 @@ module Xmobar (xmobar
, module Xmobar.Plugins.DateZone
#endif
, module Xmobar.Plugins.EWMH
+ , module Xmobar.Plugins.HandleReader
, module Xmobar.Plugins.Kbd
, module Xmobar.Plugins.Locks
#ifdef INOTIFY
@@ -57,6 +58,7 @@ import Xmobar.Plugins.Date
import Xmobar.Plugins.DateZone
#endif
import Xmobar.Plugins.EWMH
+import Xmobar.Plugins.HandleReader
import Xmobar.Plugins.Kbd
import Xmobar.Plugins.Locks
#ifdef INOTIFY
diff --git a/src/Xmobar/Plugins/HandleReader.hs b/src/Xmobar/Plugins/HandleReader.hs
new file mode 100644
index 0000000..e1ee6a5
--- /dev/null
+++ b/src/Xmobar/Plugins/HandleReader.hs
@@ -0,0 +1,70 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module : Plugins.HandleReader
+-- Copyright : (c) Pavan Rikhi
+-- License : BSD-style (see LICENSE)
+--
+-- Maintainer : Pavan Rikhi <pavan.rikhi@gmail.com>
+-- Stability : unstable
+-- Portability : portable
+--
+-- A plugin for reading from 'Handle's
+--
+-----------------------------------------------------------------------------
+
+module Xmobar.Plugins.HandleReader
+ ( HandleReader(..)
+ )
+where
+
+import System.IO ( Handle
+ , hIsEOF
+ )
+
+import Xmobar.Run.Exec ( Exec(..) )
+import Xmobar.System.Utils ( hGetLineSafe )
+
+
+-- | A HandleReader displays any text received from a Handle.
+--
+-- This is only useful if you are running @xmobar@ from other Haskell code.
+-- You can create a pair of @(read, write)@ 'Handle's using
+-- 'System.Process.createPipe'. Pass the @read@ 'Handle' to HandleReader
+-- and write your desired output to the @write@ 'Handle'.
+--
+-- @
+-- (readHandle, writeHandle) <- 'System.Process.createPipe'
+-- xmobarProcess <- 'System.Posix.Process.forkProcess' $ 'Xmobar.xmobar' myConfig
+-- { commands =
+-- 'Xmobar.Run' ('HandleReader' readHandle "handle") : 'Xmobar.commands' myConfig
+-- }
+-- 'System.IO.hPutStr' writeHandle "Hello World"
+-- @
+data HandleReader
+ = HandleReader
+ Handle
+ -- ^ The Handle to read from.
+ String
+ -- ^ Alias for the HandleReader
+ deriving (Show)
+
+-- | WARNING: This Read instance will throw an exception if used! It is
+-- only implemented because it is required to use HandleReader with
+-- 'Xmobar.Run' in 'Xmobar.commands'.
+instance Read HandleReader where
+ -- | Throws an 'error'!
+ readsPrec = error "HandleReader: Read instance is stub"
+
+-- | Asynchronously read from the 'Handle'.
+instance Exec HandleReader where
+ -- | Read from the 'Handle' until it is closed.
+ start (HandleReader handle _) cb =
+ untilM (hIsEOF handle) $ hGetLineSafe handle >>= cb
+ -- | Use the 2nd argument to HandleReader as its alias.
+ alias (HandleReader _ a) = a
+
+-- Loop the action until predicateM returns True.
+untilM :: Monad m => m Bool -> m () -> m ()
+untilM predicateM action = do
+ predicate <- predicateM
+ if predicate then return () else action >> untilM predicateM action