{-# LANGUAGE TemplateHaskell, BangPatterns, OverloadedStrings #-} {-| Module : Client.Commands Description : Implementation of slash commands Copyright : (c) Eric Mertens, 2016 License : ISC Maintainer : emertens@gmail.com This module renders the lines used in the channel mask list. A mask list can show channel bans, quiets, invites, and exceptions. -} module Client.Commands.Exec where import Control.Exception import Control.Lens import System.Console.GetOpt import System.Process data ExecCmd = ExecCmd { _execOutputNetwork :: Maybe String , _execOutputChannel :: Maybe String , _execCommand :: String , _execStdIn :: String , _execArguments :: [String] } deriving (Read,Show) makeLenses ''ExecCmd emptyExecCmd :: ExecCmd emptyExecCmd = ExecCmd { _execOutputNetwork = Nothing , _execOutputChannel = Nothing , _execCommand = error "no default command" , _execStdIn = "" , _execArguments = [] } options :: [OptDescr (ExecCmd -> ExecCmd)] options = [ Option "n" ["network"] (ReqArg (set execOutputNetwork . Just) "NETWORK") "Set network target" , Option "c" ["channel"] (ReqArg (set execOutputChannel . Just) "CHANNEL") "Set channel target" , Option "i" ["input"] (ReqArg (set execStdIn) "INPUT") "Use string as stdin" ] -- TODO: support quoted strings parseExecCmd :: String -> Either [String] ExecCmd parseExecCmd str = case getOpt RequireOrder options (words str) of (_, [] , errs) -> Left ("No command specified":errs) (fs, cmd:args, []) -> Right $ foldl (\x f -> f x) ?? fs $ set execCommand cmd $ set execArguments args $ emptyExecCmd (_,_, errs) -> Left errs runExecCmd :: ExecCmd -> IO (Either [String] [String]) runExecCmd e = do res <- try (readProcess (view execCommand e) (view execArguments e) (view execStdIn e)) return $ case res of Left er -> Left [show (er :: IOError)] Right x -> Right (lines x)