summaryrefslogtreecommitdiffhomepage
path: root/src/Xmobar/App/Config.hs
blob: d17577ed78bb77b4fd07a5f0192bc708e496f037 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
------------------------------------------------------------------------------
-- |
-- Module: Xmobar.Config.Defaults
-- Copyright: (c) 2018, 2019, 2020 Jose Antonio Ortega Ruiz
-- License: BSD3-style (see LICENSE)
--
-- Maintainer: jao@gnu.org
-- Stability: unstable
-- Portability: portable
-- Created: Sun Nov 25, 2018 22:26
--
--
-- Default values for Xmobar configurations and functions to access
-- configuration files and directories.
--
------------------------------------------------------------------------------


module Xmobar.App.Config (defaultConfig,
                          xmobarDataDir,
                          xmobarConfigFile) where

import Control.Monad (when, filterM)
import Data.Functor ((<&>))

import System.Environment
import System.Directory
import System.FilePath ((</>))
import System.Posix.Files (fileExist)

import Xmobar.Plugins.Date
import Xmobar.Plugins.StdinReader
import Xmobar.Config.Types
import Xmobar.Run.Runnable

-- | The default configuration values
defaultConfig :: Config
defaultConfig =
    Config { font = "-misc-fixed-*-*-*-*-10-*-*-*-*-*-*-*"
           , additionalFonts = []
           , wmClass = "xmobar"
           , wmName = "xmobar"
           , bgColor = "#000000"
           , fgColor = "#BFBFBF"
           , alpha   = 255
           , position = Top
           , border = NoBorder
           , borderColor = "#BFBFBF"
           , borderWidth = 1
           , textOffset = -1
           , iconOffset = -1
           , textOffsets = []
           , hideOnStart = False
           , lowerOnStart = True
           , persistent = False
           , allDesktops = True
           , overrideRedirect = True
           , pickBroadest = False
           , iconRoot = "."
           , commands = [ Run $ Date "%a %b %_d %Y * %H:%M:%S" "theDate" 10
                        , Run StdinReader]
           , sepChar = "%"
           , alignSep = "}{"
           , template = "%StdinReader% }{ " ++
                        "<fc=#00FF00>%uname%</fc> * <fc=#FF0000>%theDate%</fc>"
           , verbose = False
           }

-- | Return the path to the xmobar data directory.  This directory is
-- used by Xmobar to store data files such as the run-time state file
-- and the configuration binary generated by GHC.
--
-- Several directories are considered.  In order of preference:
--
--   1. The directory specified in the @XMOBAR_DATA_DIR@ environment variable.
--   2. The @XDG_DATA_HOME/xmobar@ directory.
--   3. The @~\/.xmobar@ directory.
--
-- The first directory that exists will be used.  If none of the
-- directories exist then (1) will be used if it is set, otherwise (2)
-- will be used.  Either way, a directory will be created if
-- necessary.
xmobarDataDir :: IO String
xmobarDataDir =
    findFirstDirWithEnv True "XMOBAR_DATA_DIR"
      [ getXdgDirectory XdgData "xmobar"
      , getAppUserDataDirectory "xmobar"
      ]

-- | Helper function that will find the first existing directory and
-- return its path.  If none of the directories can be found,
-- optionally create and return the first from the list.  If the list
-- is empty this function returns the historical @~\/.xmobar@
-- directory.
findFirstDirOf :: Bool -> [IO FilePath] -> IO FilePath
findFirstDirOf create [] = findFirstDirOf create [getAppUserDataDirectory "xmobar"]
findFirstDirOf create possibles = do
    found <- go possibles
    case found of
      Just path -> return path
      Nothing ->  do
        primary <- head possibles
        when create (createDirectoryIfMissing True primary)
        return primary
  where
    go [] = return Nothing
    go (x:xs) = do
      exists <- x >>= doesDirectoryExist
      if exists then x <&> Just else go xs

-- | Simple wrapper around @findFirstDirOf@ that allows the primary
-- path to be specified by an environment variable.
findFirstDirWithEnv :: Bool -> String -> [IO FilePath] -> IO FilePath
findFirstDirWithEnv create envName paths = do
    envPath' <- lookupEnv envName
    case envPath' of
      Nothing -> findFirstDirOf create paths
      Just envPath -> findFirstDirOf create (return envPath:paths)

xmobarInConfigDirs :: FilePath -> IO (Maybe FilePath)
xmobarInConfigDirs fn  = do
    env <- lookupEnv "XMOBAR_CONFIG_DIR"
    xdg <- getXdgDirectory XdgConfig "xmobar"
    app <- getAppUserDataDirectory "xmobar"
    hom <- getHomeDirectory
    let candidates = case env of
                       Nothing -> [app, xdg, hom]
                       Just p -> [p, app, xdg, hom]
    fs <- filterM (\d -> fileExist (d </> fn)) candidates
    return $ if null fs then Nothing else Just (head fs </> fn)

xmobarConfigFile :: IO (Maybe FilePath)
xmobarConfigFile =
  fmap ffirst $ mapM xmobarInConfigDirs ["xmobar.hs", ".xmobarrc", "xmobarrc"]
  where ffirst [] = Nothing
        ffirst (Nothing:fs) = ffirst fs
        ffirst (p:_) = p