htalkat-0.1.1: Config.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/.
module Config where
import System.Directory (doesFileExist)
import System.Exit (exitFailure)
import System.FilePath ((</>))
import Util
data Config = Config
{ listen_host :: String
, listen_port :: Int
, accept_unnamed :: Bool
, curses_local_top :: Bool
, curses_log :: Bool
, interactive_client :: [String]
} deriving (Read)
confFilePath :: FilePath -> FilePath
confFilePath = (</> "htalkat.conf")
defaultConfigFile :: String
defaultConfigFile = unlines
[ "Config"
, " { listen_host = \"\" # Empty means bind all available hosts"
, " , listen_port = 5518"
, " , accept_unnamed = True # Accept connections even from unnamed users"
, ""
, " , curses_local_top = True # Display you above remote in curses client"
, " , curses_log = False # Log conversations to files in ~/.htalkat/logs/"
, ""
, " # interactive_client: if non-empty, run in place of built-in client."
, " # First string is the command to run, and subsequent strings are arguments."
, " # It will be executed with two further arguments:"
, " # the name of the remote user,"
, " # and the path to a unix domain socket to interact with."
, " # Minimal example:"
, " #, interactive_client = [\"sh\", \"-c\","
, " # \"socat unix-connect:\\\"$2\\\" stdio\", \"talkatc\"]"
, " , interactive_client = []"
, " }"
]
createConfigFileIfNecessary :: FilePath -> IO ()
createConfigFileIfNecessary ddir =
let cpath = confFilePath ddir
in doesFileExist cpath >>! writeFile cpath defaultConfigFile
loadConfig :: FilePath -> IO Config
loadConfig ddir = do
createConfigFileIfNecessary ddir
s <- readFile (confFilePath ddir)
case readReadConfig (confFilePath ddir) s of
Left err -> putStrLn err >> exitFailure >> undefined
Right conf -> pure conf
readReadConfig :: FilePath -> String -> Either String Config
readReadConfig path s =
-- Based on https://hackage.haskell.org/package/tce-conf by Dino Morelli
case reads $ removeComments s of
[(c, _) ] -> Right c
((_, x) : _) -> Left $ "ERROR parsing config file: " <> x <> hint
[ ] -> Left $ "ERROR parsing config file" <> hint
where
hint = "; to recreate, remove " <> path <> " and try again."
removeComments :: String -> String
removeComments = unlines . map removeComment . lines
removeComment = takeWhile (/= '#')