aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/apps/RemovePath.hs
blob: 55e03f1b769b9716508332d5ee7afee56487321c (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
-- |
-- Copyright   : (c) 2015 Egor Tensin <Egor.Tensin@gmail.com>
-- License     : MIT
-- Maintainer  : Egor.Tensin@gmail.com
-- Stability   : experimental

module Main (main) where

import Control.Monad   (void, when)
import Control.Monad.Trans.Except (catchE, runExceptT, throwE)
import Data.List       ((\\))
import System.IO.Error (ioError, isDoesNotExistError)

import Options.Applicative

import qualified Windows.Environment as Env

import Prompt
import PromptMessage

data Options = Options
    { optName   :: Env.VarName
    , optYes    :: Bool
    , optGlobal :: Bool
    , optPaths  :: [Env.VarValue]
    } deriving (Eq, Show)

optionParser :: Parser Options
optionParser = Options
    <$> optNameDesc
    <*> optYesDesc
    <*> optGlobalDesc
    <*> 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 "Remove for all users"
    optPathsDesc = many $ argument str
         $ metavar "PATH"
        <> help "Directories to remove"

main :: IO ()
main = execParser parser >>= removePath
  where
    parser = info (helper <*> optionParser) $
        fullDesc <> progDesc "Remove directories from your PATH"

removePath :: Options -> IO ()
removePath options = runExceptT doRemovePath >>= either ioError return
  where
    varName = optName options
    pathsToRemove = optPaths options

    forAllUsers = optGlobal options

    skipPrompt = optYes options

    emptyIfMissing e
        | isDoesNotExistError e = return ""
        | otherwise = throwE e

    doRemovePath = do
        removePathFrom Env.CurrentUser
        when forAllUsers $
            removePathFrom Env.AllUsers

    removePathFrom profile = do
        oldValue <- Env.query profile varName `catchE` emptyIfMissing
        let oldPaths = Env.pathSplit oldValue
        let newPaths = oldPaths \\ pathsToRemove
        when (length oldPaths /= length newPaths) $ do
            let newValue = Env.pathJoin newPaths
            let promptAnd = if skipPrompt
                then withoutPrompt
                else withPrompt $ oldNewMessage profile varName oldValue newValue
            let engrave = Env.engrave profile varName newValue
            void $ promptAnd engrave