packages feed

htalkat-0.1.2: Opts.hs

-- This file is part of htalkat
-- Copyright (C) 2021 Martin Bays <mbays@sdf.org>
--
-- 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