-- 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/. 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 (/= '#')