Skip to content

Commit

Permalink
add support for literal multi-line strings
Browse files Browse the repository at this point in the history
  • Loading branch information
lovebug356 committed Feb 23, 2024
1 parent 4e32ddc commit 587b7c0
Show file tree
Hide file tree
Showing 3 changed files with 231 additions and 118 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]
### Fixed
- Added support for literal multi-line strings ([#36](https://github.com/MaybeJustJames/yaml/pull/36))

## [2.1.4]
### Changed
Expand Down
92 changes: 89 additions & 3 deletions src/Yaml/Parser/Util.elm
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ module Yaml.Parser.Util exposing
, multiline
, neither
, neither3
, postProcessLiteralString
, postProcessString
, remaining
, singleQuotes
Expand Down Expand Up @@ -196,11 +197,14 @@ multilineStep indent lines =
let
multilineString : List String -> String
multilineString lines_ =
String.join " " (List.reverse lines_)
String.join "\n" (List.reverse lines_)

conclusion line indent_ =
conclusion line emptyLineCount indent_ =
if indent_ > indent then
P.Loop (line :: lines)
P.Loop
((line ++ String.repeat emptyLineCount "\n")
:: lines
)

else
P.Done (multilineString (line :: lines))
Expand All @@ -210,11 +214,27 @@ multilineStep indent lines =
|= characters (not << isNewLine)
|. P.chompIf isNewLine
|. spaces
|= emptyLines
|= P.getCol
, P.succeed (P.Done <| multilineString lines)
]


emptyLines : P.Parser Int
emptyLines =
P.loop 0 emptyLinesStep


emptyLinesStep : Int -> P.Parser (P.Step Int Int)
emptyLinesStep count =
P.oneOf
[ P.succeed (P.Loop (count + 1))
|. P.chompIf isNewLine
|. spaces
, P.succeed (P.Done count)
]


{-| -}
characters : (Char -> Bool) -> P.Parser String
characters isOk =
Expand Down Expand Up @@ -282,12 +302,22 @@ remaining =

postProcessString : String -> String
postProcessString str =
if isLiteralString str then
postProcessLiteralString str

else
postProcessFoldedString str


postProcessFoldedString : String -> String
postProcessFoldedString str =
let
regexFromString : String -> Regex
regexFromString =
Regex.fromString >> Maybe.withDefault Regex.never
in
str
|> String.replace "\n" " "
|> Regex.replace (regexFromString "\\s\\s+")
(\match ->
if String.contains "\n\n" match.match then
Expand All @@ -298,6 +328,62 @@ postProcessString str =
)


isLiteralString : String -> Bool
isLiteralString str =
str
|> String.split "\n"
|> List.head
|> (==) (Just "|")


postProcessLiteralString : String -> String
postProcessLiteralString str =
case String.left 2 str of
"|\n" ->
let
content =
String.dropLeft 2 str
in
content
|> countLeadingSpacesInMultiline
|> removeLeadingSpaces content

_ ->
str


removeLeadingSpaces : String -> Int -> String
removeLeadingSpaces str count =
str
|> String.split "\n"
|> List.map (String.dropLeft count)
|> String.join "\n"


countLeadingSpacesInMultiline : String -> Int
countLeadingSpacesInMultiline str =
str
|> String.split "\n"
|> List.head
|> Maybe.withDefault ""
|> countLeadingSpacesInString


countLeadingSpacesInString : String -> Int
countLeadingSpacesInString str =
let
countHelper : String -> Int -> Int
countHelper s count =
case String.uncons s of
Just ( ' ', rest ) ->
countHelper rest (count + 1)

_ ->
count
in
countHelper str 0



-- INDENT

Expand Down
Loading

0 comments on commit 587b7c0

Please sign in to comment.