1 {-# LANGUAGE DeriveFunctor #-}
2 {-# LANGUAGE DeriveGeneric #-}
3 {-# LANGUAGE LambdaCase #-}
5 -----------------------------------------------------------------------------
8 -- Module : Distribution.Simple.Glob.Internal
9 -- Copyright : Isaac Jones, Simon Marlow 2003-2004
11 -- portions Copyright (c) 2007, Galois Inc.
13 -- Maintainer : cabal-devel@haskell.org
14 -- Portability : portable
16 -- Internal module for simple file globbing.
17 -- Please import "Distribution.Simple.Glob" instead.
18 module Distribution
.Simple
.Glob
.Internal
where
20 import Distribution
.Compat
.Prelude
23 import qualified Distribution
.Compat
.CharParsing
as P
24 import Distribution
.Parsec
25 import Distribution
.Pretty
26 import qualified Text
.PrettyPrint
as Disp
28 --------------------------------------------------------------------------------
30 -- | A filepath specified by globbing.
32 = -- | @<dirGlob>/<glob>@
33 GlobDir
!GlobPieces
!Glob
34 |
-- | @**/<glob>@, where @**@ denotes recursively traversing
35 -- all directories and matching filenames on <glob>.
36 GlobDirRecursive
!GlobPieces
39 |
-- | Trailing dir; a glob ending in @/@.
41 deriving (Eq
, Show, Generic
)
44 instance Structured Glob
46 -- | A single directory or file component of a globbed path
47 type GlobPieces
= [GlobPiece
]
49 -- | A piece of a globbing pattern
53 |
-- | A literal string @dirABC@
55 |
-- | A union of patterns, e.g. @dir/{a,*.txt,c}/...@
57 deriving (Eq
, Show, Generic
)
59 instance Binary GlobPiece
60 instance Structured GlobPiece
62 --------------------------------------------------------------------------------
63 -- Parsing & pretty-printing
65 instance Pretty Glob
where
66 pretty
(GlobDir glob pathglob
) =
69 Disp
.<> pretty pathglob
70 pretty
(GlobDirRecursive glob
) =
72 Disp
.<> dispGlobPieces glob
73 pretty
(GlobFile glob
) = dispGlobPieces glob
74 pretty GlobDirTrailing
= Disp
.empty
76 instance Parsec Glob
where
79 parsecPath
:: CabalParsing m
=> m Glob
82 dirSep
*> (GlobDir glob
<$> parsecPath
<|
> pure
(GlobDir glob GlobDirTrailing
)) <|
> pure
(GlobFile glob
)
83 -- We could support parsing recursive directory search syntax
84 -- @**@ here too, rather than just in 'parseFileGlob'
86 dirSep
:: CabalParsing m
=> m
()
92 -- check this isn't an escape code
93 P
.notFollowedBy
(P
.satisfy isGlobEscapedChar
)
96 parsecGlob
:: CabalParsing m
=> m GlobPieces
97 parsecGlob
= some parsecPiece
99 parsecPiece
= P
.choice
[literal
, wildcard
, union]
101 wildcard
= WildCard
<$ P
.char
'*'
102 union = Union
. toList
<$> P
.between
(P
.char
'{') (P
.char
'}') (P
.sepByNonEmpty parsecGlob
(P
.char
','))
103 literal
= Literal
<$> some litchar
105 litchar
= normal
<|
> escape
107 normal
= P
.satisfy
(\c
-> not (isGlobEscapedChar c
) && c
/= '/' && c
/= '\\')
108 escape
= P
.try $ P
.char
'\\' >> P
.satisfy isGlobEscapedChar
110 dispGlobPieces
:: GlobPieces
-> Disp
.Doc
111 dispGlobPieces
= Disp
.hcat
. map dispPiece
113 dispPiece WildCard
= Disp
.char
'*'
114 dispPiece
(Literal str
) = Disp
.text
(escape str
)
115 dispPiece
(Union globs
) =
120 (map dispGlobPieces globs
)
125 | isGlobEscapedChar c
= '\\' : c
: escape cs
126 |
otherwise = c
: escape cs
128 isGlobEscapedChar
:: Char -> Bool
129 isGlobEscapedChar
'*' = True
130 isGlobEscapedChar
'{' = True
131 isGlobEscapedChar
'}' = True
132 isGlobEscapedChar
',' = True
133 isGlobEscapedChar _
= False