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 24, 2024
1 parent 4e32ddc commit 6f7b806
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 5 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
2 changes: 1 addition & 1 deletion src/Yaml/Parser.elm
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ quotedString indent =
withQuote quote =
P.oneOf
[ recordProperty indent quote
, P.succeed (Ast.String_ <| U.postProcessString quote)
, P.succeed (Ast.String_ <| U.postProcessFoldedString quote)
]
in
P.succeed identity
Expand Down
94 changes: 91 additions & 3 deletions src/Yaml/Parser/Util.elm
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ module Yaml.Parser.Util exposing
, multiline
, neither
, neither3
, postProcessFoldedString
, postProcessLiteralString
, postProcessString
, remaining
, singleQuotes
Expand Down Expand Up @@ -196,11 +198,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 +215,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,6 +303,17 @@ remaining =

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

else
str
|> String.replace "\n" " "
|> postProcessFoldedString


postProcessFoldedString : String -> String
postProcessFoldedString str =
let
regexFromString : String -> Regex
regexFromString =
Expand All @@ -298,6 +330,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
28 changes: 27 additions & 1 deletion tests/TestParser.elm
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ suite =
Ast.Float_ x
, Test.test "a single-quoted string" <|
\_ ->
-- TODO is this right?
expectValue """'hey
i am a
Expand Down Expand Up @@ -109,6 +108,33 @@ suite =
"""
<|
Ast.String_ "how does one teach self-respect? how does one teach curiousity? if you have the answers, call me"
, Test.test
"a literal multi-line string"
<|
\_ ->
expectValue "|\n literal\n \ttext" <|
Ast.String_ "literal\n\ttext"
, Test.test "a record with literal string" <|
\_ ->
expectValue
"""
aaa: |
hello
world
"""
<|
Ast.Record_ (Dict.fromList [ ( "aaa", Ast.String_ "hello\nworld" ) ])
, Test.test "a record with literal string with empty lines" <|
\_ ->
expectValue
"""
aaa: |
hello
world
"""
<|
Ast.Record_ (Dict.fromList [ ( "aaa", Ast.String_ "hello\n\nworld" ) ])
, Test.test "a empty inline list" <|
\_ ->
expectValue "[]" <|
Expand Down

0 comments on commit 6f7b806

Please sign in to comment.