blob: 5834f1155c428b6b6fd57f5edd7ee6e273e96f27 (
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
|
-- |
-- 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 (filterM)
import Control.Monad.Trans.Class (lift)
import Control.Monad.Trans.Except (ExceptT, runExceptT)
import Data.Maybe (fromMaybe)
import System.Directory (doesDirectoryExist)
import System.Environment (lookupEnv)
import System.IO.Error (ioError)
import Options.Applicative
import qualified WindowsEnv
data WhichPaths = All | ExistingOnly | MissingOnly
deriving (Eq, Show)
shouldListPath :: WhichPaths -> WindowsEnv.VarValue -> IO Bool
shouldListPath All = return . const True
shouldListPath ExistingOnly = doesDirectoryExist
shouldListPath MissingOnly = fmap not . doesDirectoryExist
data Source = Environment | Registry WindowsEnv.Profile
deriving (Eq, Show)
data Options = Options
{ optName :: WindowsEnv.VarName
, optWhichPaths :: WhichPaths
, optSource :: Source
} deriving (Eq, Show)
optionParser :: Parser Options
optionParser = Options
<$> optNameDesc
<*> optWhichPathsDesc
<*> optSourceDesc
where
optNameDesc = strOption
$ long "name" <> short 'n'
<> metavar "NAME" <> value "PATH"
<> help "Variable name ('PATH' by default)"
optWhichPathsDesc = pure All
<|> flag' ExistingOnly (long "existing" <> short 'e'
<> help "List existing paths only")
<|> flag' MissingOnly (long "missing" <> short 'm'
<> help "List missing paths only")
optSourceDesc = pure Environment
<|> flag' (Registry WindowsEnv.CurrentUser) (long "user" <> short 'u'
<> help "List current user's paths only")
<|> flag' (Registry WindowsEnv.AllUsers) (long "global" <> short 'g'
<> help "List global (all users') paths only")
main :: IO ()
main = execParser parser >>= listPaths
where
parser = info (helper <*> optionParser) $
fullDesc <> progDesc "List directories in your PATH"
data ExpandedPath = ExpandedPath
{ pathOriginal :: WindowsEnv.VarValue
, pathExpanded :: WindowsEnv.VarValue
} deriving (Eq, Show)
splitAndExpand :: WindowsEnv.VarValue -> ExceptT IOError IO [ExpandedPath]
splitAndExpand pathValue = do
expandedOnce <- expandOnce
zipWith ExpandedPath originalPaths <$>
if length expandedOnce == length originalPaths
then return expandedOnce
else expandEach
where
originalPaths = WindowsEnv.pathSplit pathValue
expandOnce = WindowsEnv.pathSplit <$> WindowsEnv.expand pathValue
expandEach = mapM WindowsEnv.expand originalPaths
listPaths :: Options -> IO ()
listPaths options = runExceptT doListPaths >>= either ioError return
where
varName = optName options
whichPaths = optWhichPaths options
query = queryFrom $ optSource options
queryFrom Environment = lift $ fromMaybe "" <$> lookupEnv varName
queryFrom (Registry profile) = WindowsEnv.query profile varName
filterPaths = filterM (shouldListPath whichPaths . pathExpanded)
doListPaths = do
paths <- query >>= splitAndExpand
lift $ do
pathsToPrint <- filterPaths paths
mapM_ (putStrLn . pathOriginal) pathsToPrint
|