From 80913aeed46fc607f057a77ffdd884b5db77a0bc Mon Sep 17 00:00:00 2001 From: Pavan Rikhi Date: Thu, 9 Apr 2020 13:51:37 -0400 Subject: 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. --- src/Xmobar/Plugins/HandleReader.hs | 70 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 src/Xmobar/Plugins/HandleReader.hs (limited to 'src/Xmobar/Plugins') 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 +-- 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 -- cgit v1.2.3