-- This file is part of htalkat -- Copyright (C) 2021 Martin Bays -- -- This program is free software: you can redistribute it and/or modify -- it under the terms of version 3 of the GNU General Public License as -- published by the Free Software Foundation, or any later version. -- -- You should have received a copy of the GNU General Public License -- along with this program. If not, see http://www.gnu.org/licenses/. {-# LANGUAGE Safe #-} module Opts (globalHelp, localHelp, parseGlobal, parseLocal, Opt(..)) where import System.Console.GetOpt import qualified Command as C data Opt -- global: = DataDir FilePath | SocksHost String | SocksPort String | Help | Version -- local: | Port String | Host String | BlockUnnamed | AcceptUnnamed | ListPending | SpawnInteractive FilePath | DumbClient | CursesClient | LocalTop | LocalBottom | Log | NoLog deriving (Eq, Ord, Show) globalOptions :: [OptDescr Opt] globalOptions = [ Option ['d'] ["datadir"] (ReqArg DataDir "PATH") "default: ~/.htalkat, or $HTALKAT_DIR if set" , Option ['S'] ["socks-host"] (ReqArg SocksHost "HOST") "use SOCKS5 proxy" , Option ['P'] ["socks-port"] (ReqArg SocksPort "PORT") "port for SOCKS5 proxy (default: 1080)" , Option ['v'] ["version"] (NoArg Version) "show version information" , Option ['h'] ["help"] (NoArg Help) "show usage information" ] localOptions :: C.Command -> [OptDescr Opt] localOptions com = Option ['h'] ["help"] (NoArg Help) "show usage information" : case com of C.Listen -> [ Option ['p'] ["port"] (ReqArg Port "PORT") "Port to listen on (default: 5518)" , Option ['H'] ["host"] (ReqArg Host "HOST") "Host to listen on (empty means bind all available)" , Option ['b'] ["block-unnamed"] (NoArg BlockUnnamed) "Reject connections from unnamed users" , Option ['a'] ["accept-unnamed"] (NoArg AcceptUnnamed) "Accept connections from unnamed users (default)" ] C.Answer -> [ Option ['l'] ["list"] (NoArg ListPending) "List unanswered incoming connections" , Option ['i'] ["interactive-client"] (ReqArg SpawnInteractive "SOCKET_PATH") "Directly invoke interactive client" ] <> interactiveClientOptions C.Connect -> interactiveClientOptions _ -> [] where interactiveClientOptions = [ Option ['d'] ["dumb"] (NoArg DumbClient) "Use dumb line-based client" , Option ['c'] ["curses"] (NoArg CursesClient) "Use curses client (default)" , Option ['t'] ["top"] (NoArg LocalTop) "Put you on top in curses client" , Option ['b'] ["bottom"] (NoArg LocalBottom) "Put you on bottom in curses client (default)" , Option ['L'] ["log"] (NoArg Log) "Log conversation" , Option ['N'] ["no-log"] (NoArg NoLog) "Don't log conversation (default)" ] globalHelp :: String -> String globalHelp = (`usageInfo` globalOptions) localHelp :: C.Command -> String -> String localHelp c = (`usageInfo` localOptions c) parseArgs :: [OptDescr Opt] -> [String] -> IO ([Opt],[String]) parseArgs opts argv = case getOpt RequireOrder opts argv of (o,n,[]) -> return (o,n) (_,_,errs) -> ioError . userError $ concat errs parseGlobal :: [String] -> IO ([Opt],[String]) parseGlobal = parseArgs globalOptions parseLocal :: C.Command -> [String] -> IO ([Opt],[String]) parseLocal = parseArgs . localOptions