This repository was archived by the owner on Nov 1, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathProfile.hs
77 lines (51 loc) · 2.04 KB
/
Profile.hs
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
module Make.Profile(loadProfile, saveProfile, ask, setProfile, argsProfiles) where
import qualified Data.Map as Map
import Data.IORef
import System.Directory
import Control.Monad
import Data.List
import Data.Char
import Foreign
i :: IORef Profile
i = unsafePerformIO (newIORef Map.empty)
loadProfile x = readProfile x >>= writeIORef i
saveProfile = readIORef i >>= writeProfile ""
type Profile = Map.Map String String
fileProfile :: String -> FilePath
fileProfile x = "profiles/" ++ (if null x then "default" else x) ++ ".txt"
readProfile :: String -> IO Profile
readProfile x = do
let file = fileProfile x
b <- doesFileExist file
if b then liftM parseProfile $ readFile file
else if null x then return Map.empty
else error $ "Could not find the specified profile, " ++ x
writeProfile :: String -> Profile -> IO ()
writeProfile x p = do
b <- doesDirectoryExist "profiles"
when (not b) $ createDirectory "profiles"
let file = fileProfile x
f (a,b) = [a ++ "=" ++ b | not $ "!" `isPrefixOf` a]
writeFile file $ unlines $ concatMap f $ Map.toList p
ltrim = dropWhile isSpace
trim = reverse . ltrim . reverse . ltrim
unquote x = if nx >= 2 && head x == '\"' && last x == '\"' then take (nx-2) (tail x) else x
where nx = length x
parseProfile :: String -> Map.Map String String
parseProfile = Map.fromList . concatMap (parseSetting . dropComment . ltrim) . lines
where dropComment x = if "--" `isPrefixOf` x then "" else x
parseSetting :: String -> [(String,String)]
parseSetting = f . unquote . trim
where
f x | null value = []
| otherwise = [(unquote $ trim key, unquote $ trim $ tail value)]
where (key,value) = break (== '=') x
ask :: String -> IO String
ask x = do
p <- readIORef i
return $ Map.findWithDefault "" x p
argsProfiles :: [String] -> IO ()
argsProfiles = mapM_ (uncurry setProfile) . concatMap (force . parseSetting)
where force x = x ++ [('!':a,b) | (a,b) <- x]
setProfile :: String -> String -> IO ()
setProfile k v = modifyIORef i (Map.insert k v)