blob: 27ec0edcfdb435bb9753caeabd245cfb08c55e46 (
plain) (
blame)
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
|
-- |
-- Copyright : (c) 2015 Egor Tensin <Egor.Tensin@gmail.com>
-- License : MIT
-- Maintainer : Egor.Tensin@gmail.com
-- Stability : experimental
-- Portability : Windows-only
module Main (main) where
import Control.Monad (when, void)
import Control.Monad.Trans.Except (catchE, runExceptT, throwE)
import Data.List (nub)
import System.IO.Error (ioError, isDoesNotExistError)
import Options.Applicative
import qualified WindowsEnv
import Utils.Path
import Utils.Prompt
import Utils.PromptMessage
data Options = Options
{ optName :: WindowsEnv.Name
, optYes :: Bool
, optGlobal :: Bool
, optPrepend :: Bool
, optPaths :: [String]
} deriving (Eq, Show)
optionParser :: Parser Options
optionParser = Options
<$> optNameDesc
<*> optYesDesc
<*> optGlobalDesc
<*> optPrependDesc
<*> optPathsDesc
where
optNameDesc = strOption
$ long "name" <> short 'n'
<> metavar "NAME" <> value "PATH"
<> help "Variable name ('PATH' by default)"
optYesDesc = switch
$ long "yes" <> short 'y'
<> help "Skip confirmation prompt"
optGlobalDesc = switch
$ long "global" <> short 'g'
<> help "Add for all users"
optPrependDesc = switch
$ long "prepend" <> short 'p'
<> help "Prepend to the variable (instead of appending)"
optPathsDesc = many $ argument str
$ metavar "PATH"
<> help "Directories to add"
main :: IO ()
main = execParser parser >>= addPath
where
parser = info (helper <*> optionParser) $
fullDesc <> progDesc "Add directories to your PATH"
addPath :: Options -> IO ()
addPath options = runExceptT doAddPath >>= either ioError return
where
varName = optName options
pathsToAdd = nub $ optPaths options
forAllUsers = optGlobal options
skipPrompt = optYes options
profile
| forAllUsers = WindowsEnv.AllUsers
| otherwise = WindowsEnv.CurrentUser
prepend = optPrepend options
appendPaths old new
| prepend = new ++ old
| otherwise = old ++ new
emptyIfMissing e
| isDoesNotExistError e = return $ WindowsEnv.Value False ""
| otherwise = throwE e
doAddPath = do
newPaths <- pathExpandAll pathsToAdd
let newExpandable = pathAnyExpanded newPaths
srcValue <- WindowsEnv.query profile varName `catchE` emptyIfMissing
let srcExpandable = WindowsEnv.valueExpandable srcValue
let destExpandable = newExpandable || srcExpandable
srcPaths <- pathExpandValue srcValue
{ WindowsEnv.valueExpandable = destExpandable }
let destPaths = appendPaths srcPaths $ filter (`notElem` srcPaths) newPaths
let destPathsJoined = WindowsEnv.pathJoin $ map pathOriginal destPaths
let destValue = WindowsEnv.Value destExpandable destPathsJoined
when (srcValue /= destValue) $ promptAndEngrave srcValue destValue
promptAndEngrave oldValue newValue = do
let promptAnd = if skipPrompt
then withoutPrompt
else withPrompt $ oldNewMessage profile varName oldValue newValue
let engrave = WindowsEnv.engrave profile varName newValue
void $ promptAnd engrave
|