hdmenu-0.3.0: src/Core/Toml.hs
module Core.Toml
( Config(..)
, getUserConfig -- :: IO Config
) where
import Core.Util
import Data.Text.IO qualified as T
import Toml qualified
import Toml (Codec (Codec, codecRead), TomlCodec, (.=), (<!>))
-- | Hdmenu's config file.
type Config :: Type
data Config = Config
{ files :: [ByteString]
, open :: ShowBS
, dmenuExe :: FilePath
, term :: ShowBS
, tty :: [ByteString]
, decay :: Double
, histPath :: FilePath
-- ^ Command line option, NOT specifiable in the config file.
}
-- | Empty config type with all the default values.
defaultCfg :: Config
defaultCfg = Config
{ files = []
, dmenuExe = "dmenu"
, open = ("xdg-open" <>)
, term = ("xterm" <>)
, tty = []
, decay = 1
, histPath = ""
}
-- | Parse the config file.
configCodec :: TomlCodec Config
configCodec = Config
<$> defFiles (Toml.arrayOf Toml._ByteString "files") .= files
<*> toDL (defOpen (Toml.byteString "open")) .= open
<*> defDmenu (Toml.string "executable") .= dmenuExe
<*> toDL (defTerm (Toml.byteString "terminal")) .= term
<*> defTtyProgs (Toml.arrayOf Toml._ByteString "tty-programs") .= tty
<*> defDecay (Toml.double "decay") .= decay
<*> pure ""
where
-- Parse an option or—in case it's missing—return a default value.
tomlWithDefault :: a -> TomlCodec a -> TomlCodec a
tomlWithDefault def codec@Codec{ codecRead } =
codec { codecRead = codecRead <!> const (pure def) }
toDL :: TomlCodec ByteString -> TomlCodec ShowBS
= Toml.dimap ($ "") (<>)
defFiles = tomlWithDefault (files defaultCfg)
defOpen = tomlWithDefault (open defaultCfg "")
defDmenu = tomlWithDefault (dmenuExe defaultCfg)
defTerm = tomlWithDefault (term defaultCfg "")
defTtyProgs = tomlWithDefault (tty defaultCfg)
defDecay = tomlWithDefault (decay defaultCfg)
-- | Try to find a user config and, if it exists, parse it.
getUserConfig :: IO Config
getUserConfig = do
-- Default path where to look for the config file:
-- ~/.config/hdmenu/hdmenu.toml
cfgFile <- hdmenuPath <</>> "hdmenu.toml"
ifM (doesFileExist cfgFile)
(fromRight defaultCfg . Toml.decode configCodec <$> T.readFile cfgFile)
(pure defaultCfg)