forked from fosskers/aura
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathUtilities.hs
157 lines (127 loc) · 4.66 KB
/
Utilities.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
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
-- Utility functions that don't fit in a particular library.
module Utilities where
-- System Libraries
import System.Directory (getCurrentDirectory, setCurrentDirectory)
import Distribution.Simple.Utils (withTempDirectory)
import Control.Concurrent (threadDelay)
import System.FilePath (dropExtensions)
import Distribution.Verbosity (silent)
import System.IO (stdout, hFlush)
import Data.List (dropWhileEnd)
import Text.Regex.Posix ((=~))
import Text.Printf (printf)
-- Custom Libraries
import Shell
type Pattern = (String,String)
type Regex = String
----------------
-- CUSTOM OUTPUT
----------------
putStrLnA :: Colouror -> String -> IO ()
putStrLnA colour s = putStrA colour $ s ++ "\n"
putStrA :: Colouror -> String -> IO ()
putStrA colour s = putStr $ "aura >>= " ++ colour s
printList :: Colouror -> Colouror -> String -> [String] -> IO ()
printList _ _ _ [] = return ()
printList titleColour itemColour msg items = do
putStrLnA titleColour msg
mapM_ (putStrLn . itemColour) items
putStrLn ""
-----------
-- PLUMBING
-----------
-- A traditional `split` function.
split :: Eq a => a -> [a] -> [[a]]
split _ [] = []
split x xs = fst xs' : split x (snd xs')
where xs' = hardBreak (== x) xs
-- Like break, but kills the element that triggered the break.
hardBreak :: (a -> Bool) -> [a] -> ([a],[a])
hardBreak _ [] = ([],[])
hardBreak p xs = (firstHalf, secondHalf')
where firstHalf = takeWhile (not . p) xs
secondHalf = dropWhile (not . p) xs
secondHalf' = if null secondHalf then [] else tail secondHalf
lStrip :: String -> String
lStrip xs = dropWhile (== ' ') xs
rStrip :: String -> String
rStrip xs = dropWhileEnd (== ' ') xs
tripleFst :: (a,b,c) -> a
tripleFst (a,_,_) = a
tripleSnd :: (a,b,c) -> b
tripleSnd (_,b,_) = b
tripleThrd :: (a,b,c) -> c
tripleThrd (_,_,c) = c
-- Replaces a (p)attern with a (t)arget in a line if possible.
replaceByPatt :: [Pattern] -> String -> String
replaceByPatt [] line = line
replaceByPatt ((p,t):ps) line | p == m = replaceByPatt ps (b ++ t ++ a)
| otherwise = replaceByPatt ps line
where (b,m,a) = line =~ p :: (String,String,String)
withTempDir :: FilePath -> IO a -> IO a
withTempDir name action = do
originalDirectory <- getCurrentDirectory
withTempDirectory silent originalDirectory name (\dir -> do
setCurrentDirectory dir
result <- action
setCurrentDirectory originalDirectory
return result)
-- Given a number of selections, allows the user to choose one.
getSelection :: [String] -> IO String
getSelection [] = return ""
getSelection choiceLabels = do
let quantity = length choiceLabels
valids = map show [1..quantity]
padding = show . length . show $ quantity
choices = zip valids choiceLabels
mapM_ (\(n,c)-> printf ("%" ++ padding ++ "s. %s\n") n c) choices
putStr ">> "
hFlush stdout
userChoice <- getLine
case userChoice `lookup` choices of
Just valid -> return valid
Nothing -> getSelection choiceLabels -- Ask again.
timedMessage :: Int -> [String] -> IO ()
timedMessage delay msgs = mapM_ printMessage msgs
where printMessage msg = putStr msg >> hFlush stdout >> threadDelay delay
-- Takes a prompt message and a regex of valid answer patterns.
yesNoPrompt :: String -> IO Bool
yesNoPrompt msg = do
putStrA yellow $ msg ++ " [Y/n] "
hFlush stdout
response <- getLine
return (response =~ "y|Y|\\B" :: Bool)
optionalPrompt :: Bool -> String -> IO Bool
optionalPrompt True msg = yesNoPrompt msg
optionalPrompt False _ = return True
searchLines :: Regex -> [String] -> [String]
searchLines pat allLines = filter (\line -> line =~ pat) allLines
wordsLines :: String -> [String]
wordsLines ls = lines ls >>= words
notNull :: [a] -> Bool
notNull = not . null
-- Opens the editor of the user's choice.
openEditor :: String -> String -> IO ()
openEditor editor file = shellCmd editor [file] >> return ()
-- Is there a more built-in replacement for `tar` that wouldn't be
-- required as a listed dependency in the PKGBUILD?
uncompress :: FilePath -> IO FilePath
uncompress file = do
_ <- quietShellCmd' "bsdtar" ["-zxvf",file]
return $ dropExtensions file
fromRight :: Either a b -> b
fromRight (Right x) = x
fromRight (Left _) = error "Value given was a Left."
-- The Int argument is the final length of the padded String,
-- not the length of the pad.
postPad :: [a] -> a -> Int -> [a]
postPad xs x len = take len $ xs ++ repeat x
prePad :: [a] -> a -> Int -> [a]
prePad xs x len = take (len - length xs) (repeat x) ++ xs
inDir :: FilePath -> IO a -> IO a
inDir dir action = do
curr <- getCurrentDirectory
setCurrentDirectory dir
result <- action
setCurrentDirectory curr
return result