diff --git a/spec/Configuration/Dotenv/TextSpec.hs b/spec/Configuration/Dotenv/TextSpec.hs index 373b2709..ac503348 100644 --- a/spec/Configuration/Dotenv/TextSpec.hs +++ b/spec/Configuration/Dotenv/TextSpec.hs @@ -27,3 +27,11 @@ spec = it "recognizes unicode characters" $ liftM (!! 1) (parseFile "spec/fixtures/.dotenv") `shouldReturn` (T.pack "UNICODE_TEST", T.pack "ManabĂ­") + + it "handles newline characters correctly" $ do + liftM (!! 6) (parseFile "spec/fixtures/.dotenv") `shouldReturn` + (T.pack "NEWLINE_TEST", T.pack "Hello\nWorld\nThis is a test\n") + + it "handles manual line breaks correctly" $ do + liftM (!! 7) (parseFile "spec/fixtures/.dotenv") `shouldReturn` + (T.pack "MULTILINE_TEST", T.pack "Roses are red\nViolets are blue\nCode is my art\nAnd bugs are my glue\n") diff --git a/spec/fixtures/.dotenv b/spec/fixtures/.dotenv index 1aeaf37d..eeeb3d6c 100644 --- a/spec/fixtures/.dotenv +++ b/spec/fixtures/.dotenv @@ -4,3 +4,9 @@ ENVIRONMENT="$HOME" PREVIOUS="$DOTENV" ME="$(whoami)" BLANK= +NEWLINE_TEST="Hello\nWorld\nThis is a test\n" +MULTILINE_TEST="Roses are red +Violets are blue +Code is my art +And bugs are my glue +" diff --git a/src/Configuration/Dotenv/Parse.hs b/src/Configuration/Dotenv/Parse.hs index f1b2c46d..5a975a5a 100644 --- a/src/Configuration/Dotenv/Parse.hs +++ b/src/Configuration/Dotenv/Parse.hs @@ -25,7 +25,7 @@ import Text.Megaparsec (Parsec, anySingle, between, eof, noneOf, oneOf, sepEndBy, ()) import Text.Megaparsec.Char (char, digitChar, eol, - letterChar, spaceChar) + letterChar, spaceChar, string) import qualified Text.Megaparsec.Char.Lexer as L type Parser = Parsec Void String @@ -85,8 +85,9 @@ interpolatedValueCommandInterpolation = do symbol = L.symbol sc literalValueFragment :: String -> Parser VarFragment -literalValueFragment charsToEscape = VarLiteral <$> some (escapedChar <|> normalChar) +literalValueFragment charsToEscape = VarLiteral <$> some (newlineChar <|> escapedChar <|> normalChar) where + newlineChar = string "\\n" >> return '\n' escapedChar = (char '\\' *> anySingle) "escaped character" normalChar = noneOf charsToEscape "unescaped character"