4
4
- SPDX-License-Identifier: MPL-2.0
5
5
-}
6
6
7
+ {-# LANGUAGE TupleSections #-}
8
+
7
9
module Nixfmt.Util
8
10
( manyP
9
11
, someP
@@ -15,14 +17,18 @@ module Nixfmt.Util
15
17
, identChar
16
18
, isSpaces
17
19
, pathChar
20
+ , replaceMultiple
18
21
, schemeChar
19
22
, uriChar
20
23
) where
21
24
25
+ import Control.Applicative ((<|>) )
22
26
import Data.Char (isAlpha , isDigit , isSpace )
27
+ import Data.Foldable (asum )
28
+ import Data.List (unfoldr )
23
29
import Data.Maybe (fromMaybe )
24
30
import Data.Text as Text
25
- (Text , all , commonPrefixes , concat , empty , stripEnd , stripPrefix , takeWhile )
31
+ (Text , all , commonPrefixes , concat , empty , null , splitAt , stripEnd , stripPrefix , takeWhile )
26
32
import Text.Megaparsec
27
33
(ParsecT , Stream , Token , Tokens , many , some , takeWhile1P , takeWhileP )
28
34
@@ -82,3 +88,20 @@ dropCommonIndentation unstrippedLines =
82
88
83
89
isSpaces :: Text -> Bool
84
90
isSpaces = Text. all (== ' ' )
91
+
92
+ -- | Apply multiple independent replacements. This function passes over the text
93
+ -- once and applies the first replacement it can find at each position. After a
94
+ -- replacement is matched, the function continues after the replacement, not
95
+ -- inside it.
96
+ replaceMultiple :: [(Text , Text )] -> Text -> Text
97
+ replaceMultiple replacements = mconcat . unfoldr replaceAny
98
+ where
99
+ -- | replaceAny assumes input is nonempty
100
+ replaceAny :: Text -> Maybe (Text , Text )
101
+ replaceAny t
102
+ | Text. null t = Nothing
103
+ | otherwise = asum (map (replaceStart t) replacements)
104
+ <|> Just (Text. splitAt 1 t)
105
+
106
+ replaceStart :: Text -> (Text , Text ) -> Maybe (Text , Text )
107
+ replaceStart t (pat, rep) = (rep,) <$> Text. stripPrefix pat t
0 commit comments