| Safe Haskell | None |
|---|---|
| Language | GHC2021 |
Yamlet.Syntax
Description
The representation of a YAML stream that keeps every detail of the
presentation: the styles of scalars and collections, the lines of
scalars, anchors, aliases, unresolved tags, comments and empty lines. The
FromYaml and ToYaml classes read and
write the nodes of this tree.
Most texts in the tree share the memory of the input, so a node keeps the
whole input alive. To keep a text longer than the tree, copy it with
copy, or copy the whole tree with copyDocument. Copy only
what the program keeps: a copy of a whole tree usually needs more memory
than the input it frees.
A document that the renderer writes back keeps its comments, empty lines and styles:
>>>input = "# The server.\nhost: localhost # only local\n\nports: [80, 443]\n"
>>>:{case parseDocumentsText input of Left err -> putStrLn (prettyError "input.yaml" err) Right docs -> T.putStr (renderSyntax defaultRenderOptions docs) :} # The server. host: localhost # only local ports: [80, 443]
The section Comments gives the rules that decide the node of each comment.
Synopsis
- parseDocuments :: ByteString -> Either Error [Document]
- parseDocumentsText :: Text -> Either Error [Document]
- decodeInput :: ByteString -> Either Error Text
- copyDocument :: Document -> Document
- copyNode :: Node -> Node
- renderSyntax :: RenderOptions -> [Document] -> Text
- data RenderOptions = RenderOptions {
- forceBlock :: !Bool
- defaultRenderOptions :: RenderOptions
- data Document = Document {
- version :: !(Maybe YamlVersion)
- explicitStart :: !Bool
- explicitEnd :: !Bool
- docComments :: !Comments
- root :: !Node
- data YamlVersion = YamlVersion {}
- document :: Node -> Document
- data Node = Node {}
- data Content where
- ScalarLinesContent !ScalarStyle !Text ![Int]
- SequenceContent !CollectionStyle ![Node]
- MappingContent !CollectionStyle ![(Node, Node)]
- AliasContent !Text
- pattern ScalarContent :: ScalarStyle -> Text -> Content
- data Props = Props {}
- noProps :: Props
- data Tag
- = NoTag
- | NonSpecificTag
- | Tag !Text
- data ScalarStyle
- data CollectionStyle
- contentNode :: Content -> Node
- scalarNode :: ScalarStyle -> Text -> Node
- plainNode :: Text -> Node
- foldedNode :: [Text] -> Node
- sequenceNode :: [Node] -> Node
- mappingNode :: [(Node, Node)] -> Node
- newtype Offset = Offset Int
- noOffset :: Offset
- data Comments = Comments {}
- noComments :: Comments
- withComments :: Comments -> Node -> Node
- data Line where
- EmptyLine
- CommentLine !Int !Text
- pattern Comment :: Text -> Line
Parsing
parseDocuments :: ByteString -> Either Error [Document] Source #
Parse the documents of a stream. The encoding is UTF-8, UTF-16 or UTF-32, detected as the YAML specification describes.
errorAt and decodeDocument need the text of the input. To report
errors with the lines of the input, decode the input with decodeInput and
parse it with parseDocumentsText.
parseDocumentsText :: Text -> Either Error [Document] Source #
Parse the documents of a stream.
>>>length <$> parseDocumentsText "a\n---\nb\n"Right 2
decodeInput :: ByteString -> Either Error Text Source #
Decode the bytes of a stream to text. The encoding is UTF-8, UTF-16 or UTF-32, detected as the YAML specification describes.
copyDocument :: Document -> Document Source #
Copy every text of a document, so that the document does not keep the input alive.
copyNode :: Node -> Node Source #
Copy every text of a node, so that the node does not keep the input alive.
Rendering
renderSyntax :: RenderOptions -> [Document] -> Text Source #
Render documents with their comments and empty lines.
The output differs from the tree where YAML cannot hold it:
- A
---marker is on a line of its own, with at most a comment after it. - A scalar keeps its style if the style can hold its text, otherwise it gets quotes. A block scalar that is a key or an entry of a flow collection gets double quotes. A block scalar at the root gets quotes in a few more cases, e.g. if its text starts with a space.
- The empty lines from the comments right after a block scalar with the
+indicator go away, because they would become part of the scalar. - A flow collection with comments inside becomes a block collection, so that every comment has a line.
- A flow collection without comments is on one line, apart from the line breaks of its multi-line scalars, so the empty lines between its entries go away.
- A key of more than 1024 characters in a flow mapping becomes an explicit
key, e.g.
{? key : value}, because YAML 1.1 parsers reject a longer implicit key there too. - A comment that has no place at its node moves to a place that has one, e.g. the lines above the value of a key go above the key if the value is on the line of the key.
- In the text of a comment, a character that YAML does not allow becomes
U+FFFD, and the white space at the end goes away. A line break starts a
new comment in a
CommentLine, and becomes a space in an inline comment. - An anchor name with a character that YAML does not allow in it, e.g. a
space, or that YAML 1.1 parsers read as the end of the name, e.g.
:or a line separator, becomes a new name in the anchor and in its aliases. Names that only some parsers reject stay, e.g.é, which libyaml rejects. - A version that the parser does not support, e.g. 2.0, has no
%YAMLdirective.
With forceBlock, the flow collections become block
collections:
>>>:{case parseDocumentsText "a: [1, {b: 2}]\n" of Left err -> putStrLn (prettyError "input.yaml" err) Right docs -> T.putStr (renderSyntax defaultRenderOptions {forceBlock = True} docs) :} a: - 1 - b: 2
data RenderOptions Source #
The options of renderSyntax.
Constructors
| RenderOptions | |
Fields
| |
Instances
| Generic RenderOptions Source # | |||||
Defined in Yamlet.Internal.Render Associated Types
| |||||
| Show RenderOptions Source # | |||||
Defined in Yamlet.Internal.Render Methods showsPrec :: Int -> RenderOptions -> ShowS show :: RenderOptions -> String showList :: [RenderOptions] -> ShowS | |||||
| Eq RenderOptions Source # | |||||
Defined in Yamlet.Internal.Render | |||||
| type Rep RenderOptions Source # | |||||
Defined in Yamlet.Internal.Render type Rep RenderOptions = D1 ('MetaData "RenderOptions" "Yamlet.Internal.Render" "yamlet-1.0.0.1-2nRkbEnNUrLFBALTocq2AS" 'False) (C1 ('MetaCons "RenderOptions" 'PrefixI 'True) (S1 ('MetaSel ('Just "forceBlock") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Bool))) | |||||
defaultRenderOptions :: RenderOptions Source #
Keep the collection styles of the tree.
Documents
A document of a YAML stream.
Constructors
| Document | |
Fields
| |
Instances
| NFData Document Source # | |||||
Defined in Yamlet.Internal.Syntax | |||||
| Generic Document Source # | |||||
Defined in Yamlet.Internal.Syntax Associated Types
| |||||
| Show Document Source # | |||||
| Eq Document Source # | |||||
| type Rep Document Source # | |||||
Defined in Yamlet.Internal.Syntax type Rep Document = D1 ('MetaData "Document" "Yamlet.Internal.Syntax" "yamlet-1.0.0.1-2nRkbEnNUrLFBALTocq2AS" 'False) (C1 ('MetaCons "Document" 'PrefixI 'True) ((S1 ('MetaSel ('Just "version") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 (Maybe YamlVersion)) :*: S1 ('MetaSel ('Just "explicitStart") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Bool)) :*: (S1 ('MetaSel ('Just "explicitEnd") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Bool) :*: (S1 ('MetaSel ('Just "docComments") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Comments) :*: S1 ('MetaSel ('Just "root") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Node))))) | |||||
data YamlVersion Source #
The version of YAML that a document declares.
Constructors
| YamlVersion | |
Instances
| NFData YamlVersion Source # | |||||
Defined in Yamlet.Internal.Syntax Methods rnf :: YamlVersion -> () | |||||
| Generic YamlVersion Source # | |||||
Defined in Yamlet.Internal.Syntax Associated Types
| |||||
| Show YamlVersion Source # | |||||
Defined in Yamlet.Internal.Syntax Methods showsPrec :: Int -> YamlVersion -> ShowS show :: YamlVersion -> String showList :: [YamlVersion] -> ShowS | |||||
| Eq YamlVersion Source # | |||||
Defined in Yamlet.Internal.Syntax | |||||
| Ord YamlVersion Source # | |||||
Defined in Yamlet.Internal.Syntax Methods compare :: YamlVersion -> YamlVersion -> Ordering (<) :: YamlVersion -> YamlVersion -> Bool (<=) :: YamlVersion -> YamlVersion -> Bool (>) :: YamlVersion -> YamlVersion -> Bool (>=) :: YamlVersion -> YamlVersion -> Bool max :: YamlVersion -> YamlVersion -> YamlVersion min :: YamlVersion -> YamlVersion -> YamlVersion | |||||
| type Rep YamlVersion Source # | |||||
Defined in Yamlet.Internal.Syntax type Rep YamlVersion = D1 ('MetaData "YamlVersion" "Yamlet.Internal.Syntax" "yamlet-1.0.0.1-2nRkbEnNUrLFBALTocq2AS" 'False) (C1 ('MetaCons "YamlVersion" 'PrefixI 'True) (S1 ('MetaSel ('Just "major") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Int) :*: S1 ('MetaSel ('Just "minor") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Int))) | |||||
document :: Node -> Document Source #
A document with the given root, without directives, markers and comments.
Nodes
A node of a document.
Constructors
| Node | |
Instances
| NFData Node Source # | |||||
Defined in Yamlet.Internal.Syntax | |||||
| Generic Node Source # | |||||
Defined in Yamlet.Internal.Syntax Associated Types
| |||||
| Show Node Source # | |||||
| Eq Node Source # | |||||
| FromYaml Node Source # | The node of the syntax tree, with its styles and comments, e.g. to write a part of a document back as it was written. An alias in the input gives a copy of the node that it refers to. The texts of the node are copies, so that a small part of a document does
not keep the whole input alive. For a whole document without a copy, use
| ||||
| ToYaml Node Source # | |||||
| type Rep Node Source # | |||||
Defined in Yamlet.Internal.Syntax type Rep Node = D1 ('MetaData "Node" "Yamlet.Internal.Syntax" "yamlet-1.0.0.1-2nRkbEnNUrLFBALTocq2AS" 'False) (C1 ('MetaCons "Node" 'PrefixI 'True) ((S1 ('MetaSel ('Just "offset") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Offset) :*: S1 ('MetaSel ('Just "endOffset") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Offset)) :*: (S1 ('MetaSel ('Just "props") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Props) :*: (S1 ('MetaSel ('Just "comments") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Comments) :*: S1 ('MetaSel ('Just "content") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Content))))) | |||||
The content of a node.
Constructors
| ScalarLinesContent !ScalarStyle !Text ![Int] | A scalar with the positions in its text where the source continues on a new line. A position counts the characters from the start of the text, and the positions are in ascending order. The parser gives them for the plain, quoted and folded styles, which join the lines of the source, so that the renderer can write the text on the same lines. The renderer ignores a position where the style of the output cannot start a new line and keep the text. |
| SequenceContent !CollectionStyle ![Node] | |
| MappingContent !CollectionStyle ![(Node, Node)] | |
| AliasContent !Text | An alias, with the name of its anchor. An alias has no properties. |
Bundled Patterns
| pattern ScalarContent :: ScalarStyle -> Text -> Content | A scalar without positions of new lines. As a pattern, it matches every scalar and ignores its positions. |
Instances
| NFData Content Source # | |||||
Defined in Yamlet.Internal.Syntax | |||||
| Generic Content Source # | |||||
Defined in Yamlet.Internal.Syntax Associated Types
| |||||
| Show Content Source # | |||||
| Eq Content Source # | |||||
| type Rep Content Source # | |||||
Defined in Yamlet.Internal.Syntax type Rep Content = D1 ('MetaData "Content" "Yamlet.Internal.Syntax" "yamlet-1.0.0.1-2nRkbEnNUrLFBALTocq2AS" 'False) ((C1 ('MetaCons "ScalarLinesContent" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 ScalarStyle) :*: (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Text) :*: S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 [Int]))) :+: C1 ('MetaCons "SequenceContent" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 CollectionStyle) :*: S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 [Node]))) :+: (C1 ('MetaCons "MappingContent" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 CollectionStyle) :*: S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 [(Node, Node)])) :+: C1 ('MetaCons "AliasContent" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Text)))) | |||||
The properties of a node.
Instances
| NFData Props Source # | |||||
Defined in Yamlet.Internal.Syntax | |||||
| Generic Props Source # | |||||
Defined in Yamlet.Internal.Syntax Associated Types
| |||||
| Show Props Source # | |||||
| Eq Props Source # | |||||
| type Rep Props Source # | |||||
Defined in Yamlet.Internal.Syntax type Rep Props = D1 ('MetaData "Props" "Yamlet.Internal.Syntax" "yamlet-1.0.0.1-2nRkbEnNUrLFBALTocq2AS" 'False) (C1 ('MetaCons "Props" 'PrefixI 'True) (S1 ('MetaSel ('Just "anchor") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 (Maybe Text)) :*: S1 ('MetaSel ('Just "tag") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Tag))) | |||||
The tag of a node after the tag handles are expanded.
Constructors
| NoTag | The node has no tag. |
| NonSpecificTag | The |
| Tag !Text | A specific tag, e.g. |
Instances
| NFData Tag Source # | |||||
Defined in Yamlet.Internal.Syntax | |||||
| Generic Tag Source # | |||||
Defined in Yamlet.Internal.Syntax Associated Types
| |||||
| Show Tag Source # | |||||
| Eq Tag Source # | |||||
| Ord Tag Source # | |||||
| type Rep Tag Source # | |||||
Defined in Yamlet.Internal.Syntax type Rep Tag = D1 ('MetaData "Tag" "Yamlet.Internal.Syntax" "yamlet-1.0.0.1-2nRkbEnNUrLFBALTocq2AS" 'False) (C1 ('MetaCons "NoTag" 'PrefixI 'False) (U1 :: Type -> Type) :+: (C1 ('MetaCons "NonSpecificTag" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "Tag" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Text)))) | |||||
data ScalarStyle Source #
The style of a scalar: without quotes, in single or double quotes, or a
literal (|) or folded (>) block scalar.
Constructors
| Plain | |
| SingleQuoted | |
| DoubleQuoted | |
| Literal | |
| Folded |
Instances
| NFData ScalarStyle Source # | |||||
Defined in Yamlet.Internal.Syntax Methods rnf :: ScalarStyle -> () | |||||
| Bounded ScalarStyle Source # | |||||
Defined in Yamlet.Internal.Syntax | |||||
| Enum ScalarStyle Source # | |||||
Defined in Yamlet.Internal.Syntax Methods succ :: ScalarStyle -> ScalarStyle pred :: ScalarStyle -> ScalarStyle toEnum :: Int -> ScalarStyle fromEnum :: ScalarStyle -> Int enumFrom :: ScalarStyle -> [ScalarStyle] enumFromThen :: ScalarStyle -> ScalarStyle -> [ScalarStyle] enumFromTo :: ScalarStyle -> ScalarStyle -> [ScalarStyle] enumFromThenTo :: ScalarStyle -> ScalarStyle -> ScalarStyle -> [ScalarStyle] | |||||
| Generic ScalarStyle Source # | |||||
Defined in Yamlet.Internal.Syntax Associated Types
| |||||
| Show ScalarStyle Source # | |||||
Defined in Yamlet.Internal.Syntax Methods showsPrec :: Int -> ScalarStyle -> ShowS show :: ScalarStyle -> String showList :: [ScalarStyle] -> ShowS | |||||
| Eq ScalarStyle Source # | |||||
Defined in Yamlet.Internal.Syntax | |||||
| Ord ScalarStyle Source # | |||||
Defined in Yamlet.Internal.Syntax Methods compare :: ScalarStyle -> ScalarStyle -> Ordering (<) :: ScalarStyle -> ScalarStyle -> Bool (<=) :: ScalarStyle -> ScalarStyle -> Bool (>) :: ScalarStyle -> ScalarStyle -> Bool (>=) :: ScalarStyle -> ScalarStyle -> Bool max :: ScalarStyle -> ScalarStyle -> ScalarStyle min :: ScalarStyle -> ScalarStyle -> ScalarStyle | |||||
| type Rep ScalarStyle Source # | |||||
Defined in Yamlet.Internal.Syntax type Rep ScalarStyle = D1 ('MetaData "ScalarStyle" "Yamlet.Internal.Syntax" "yamlet-1.0.0.1-2nRkbEnNUrLFBALTocq2AS" 'False) ((C1 ('MetaCons "Plain" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "SingleQuoted" 'PrefixI 'False) (U1 :: Type -> Type)) :+: (C1 ('MetaCons "DoubleQuoted" 'PrefixI 'False) (U1 :: Type -> Type) :+: (C1 ('MetaCons "Literal" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "Folded" 'PrefixI 'False) (U1 :: Type -> Type)))) | |||||
data CollectionStyle Source #
The style of a collection: with indentation, or with brackets and commas.
Instances
Construction
contentNode :: Content -> Node Source #
A node with the given content, without properties and comments.
scalarNode :: ScalarStyle -> Text -> Node Source #
A scalar in the given style. renderSyntax uses quotes if
the style cannot hold the text, and for a block scalar that is a key or an
entry of a flow collection.
>>>T.putStr (renderSyntax defaultRenderOptions [document (mappingNode [(plainNode "key", scalarNode Plain "a: b")])])key: 'a: b'
foldedNode :: [Text] -> Node Source #
A folded block scalar (>-) with the given lines. The empty lines at the
end are dropped, because >- strips them.
>>>T.putStr (renderSyntax defaultRenderOptions [document (mappingNode [(plainNode "options", foldedNode ["--health-cmd pg_isready", "--health-interval 5s"])])])options: >- --health-cmd pg_isready --health-interval 5s
sequenceNode :: [Node] -> Node Source #
A block sequence.
Positions
The offset of a byte in the input text, in its UTF-8 encoding. For an
input in UTF-16 or UTF-32, the offset counts the bytes of the text after
decodeInput, not the bytes of the input.
Constructors
| Offset Int |
Instances
| NFData Offset Source # | |||||
Defined in Yamlet.Internal.Syntax | |||||
| Generic Offset Source # | |||||
Defined in Yamlet.Internal.Syntax Associated Types
| |||||
| Show Offset Source # | |||||
| Eq Offset Source # | |||||
| Ord Offset Source # | |||||
| type Rep Offset Source # | |||||
Defined in Yamlet.Internal.Syntax type Rep Offset = D1 ('MetaData "Offset" "Yamlet.Internal.Syntax" "yamlet-1.0.0.1-2nRkbEnNUrLFBALTocq2AS" 'True) (C1 ('MetaCons "Offset" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Int))) | |||||
Comments
The parser gives each comment to one node or document, and the renderer writes it back at that place. A stream without documents, e.g. a stream of only comments, has no such place. The parser drops its comments.
In the examples below, printComments parses a text and prints each node
that has comments, with its path and the fields of Comments. The key and
the value of an entry have the same path, with (key) or (value) after
it.
The comments and the empty lines that belong to a node.
Constructors
| Comments | |
Fields
| |
Instances
| NFData Comments Source # | |||||
Defined in Yamlet.Internal.Syntax | |||||
| Generic Comments Source # | |||||
Defined in Yamlet.Internal.Syntax Associated Types
| |||||
| Show Comments Source # | |||||
| Eq Comments Source # | |||||
| Ord Comments Source # | |||||
Defined in Yamlet.Internal.Syntax | |||||
| type Rep Comments Source # | |||||
Defined in Yamlet.Internal.Syntax type Rep Comments = D1 ('MetaData "Comments" "Yamlet.Internal.Syntax" "yamlet-1.0.0.1-2nRkbEnNUrLFBALTocq2AS" 'False) (C1 ('MetaCons "Comments" 'PrefixI 'True) (S1 ('MetaSel ('Just "before") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 [Line]) :*: (S1 ('MetaSel ('Just "inline") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 (Maybe Text)) :*: S1 ('MetaSel ('Just "after") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 [Line])))) | |||||
noComments :: Comments Source #
No comments and no empty lines.
withComments :: Comments -> Node -> Node Source #
The node with the comments in place of its own. A record update of the
field is ambiguous where Commented is in scope.
A line of comments.
Constructors
| EmptyLine | |
| CommentLine !Int !Text | The number of The comment at the end of a line in |
Bundled Patterns
| pattern Comment :: Text -> Line | A comment with one |
Instances
| NFData Line Source # | |||||
Defined in Yamlet.Internal.Syntax | |||||
| Generic Line Source # | |||||
Defined in Yamlet.Internal.Syntax Associated Types
| |||||
| Show Line Source # | |||||
| Eq Line Source # | |||||
| Ord Line Source # | |||||
| type Rep Line Source # | |||||
Defined in Yamlet.Internal.Syntax type Rep Line = D1 ('MetaData "Line" "Yamlet.Internal.Syntax" "yamlet-1.0.0.1-2nRkbEnNUrLFBALTocq2AS" 'False) (C1 ('MetaCons "EmptyLine" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "CommentLine" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Int) :*: S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Text))) | |||||
Lines above a node
A comment on a line of its own belongs to the node below it. Above the first entry of a block collection, the lines up to the last empty line belong to the collection, e.g. a comment at the top of a file.
>>>input = "# The server.\n\n# The host.\nhost: localhost\n# The port.\nport: 80\n"
>>>T.putStr input# The server. # The host. host: localhost # The port. port: 80
>>>printComments inputroot before: [Comment "The server.",EmptyLine] root.host (key) before: [Comment "The host."] root.port (key) before: [Comment "The port."]
A block collection after - on the same line keeps all the lines above
it, so that a comment above an item belongs to the item.
>>>input = "# The first server.\n- host: localhost\n# The second server.\n- host: example.com\n"
>>>T.putStr input# The first server. - host: localhost # The second server. - host: example.com
>>>printComments inputroot[0] before: [Comment "The first server."] root[1] before: [Comment "The second server."]
The rules in the sections below give some of these lines to a document or
to the end of a collection instead, e.g. # a and # b below. The node
below still gets # c.
>>>input = "# a\n---\nserver:\n host: localhost\n # b\n# c\nuser: admin\n"
>>>T.putStr input# a --- server: host: localhost # b # c user: admin
>>>printComments inputdocument before: [Comment "a"] root.server (value) after: [Comment "b"] root.user (key) before: [Comment "c"]
Comments at the end of a line
A comment at the end of a line belongs to the node that ends last before
it on that line, if only spaces, a colon or a comma come between them.
E.g. the value gets the comment in key: value # comment. In
key: # comment, the key gets it if the value starts on a later line.
Otherwise the value is empty and ends after the colon, so it gets the
comment. A comment on the line of a block scalar header belongs to the
block scalar.
>>>input = "host: localhost # a\nports: # b\n- 80\nproxy: # c\ntext: | # d\n Hello.\n"
>>>T.putStr inputhost: localhost # a ports: # b - 80 proxy: # c text: | # d Hello.
>>>printComments inputroot.host (value) inline: "a" root.ports (key) inline: "b" root.proxy (value) inline: "c" root.text (value) inline: "d"
A comment at the end of a line that the rule above does not give to a
node, e.g. after - , belongs to the node below it. If that node also has
a comment at the end of its line, the first comment becomes a line above
the node, e.g. # c below.
>>>input = "- # a\n host: localhost # b\n- # c\n 'a string' # d\n"
>>>T.putStr input- # a host: localhost # b - # c 'a string' # d
>>>printComments inputroot[0] inline: "a" root[0].host (value) inline: "b" root[1] before: [Comment "c"] root[1] inline: "d"
The same holds for a comment after the tag of a block collection.
>>>input = "server: !!map # a\n host: localhost\n"
>>>T.putStr inputserver: !!map # a host: localhost
>>>printComments inputroot.server (value) inline: "a"
On the line of the --- marker, the document gets such a comment.
>>>input = "--- !!map # a\nhost: localhost\n"
>>>T.putStr input--- !!map # a host: localhost
>>>printComments inputdocument inline: "a"
Lines at the end of a collection
A comment below a scalar or an alias in a block collection belongs to the
end of that node if it is indented deeper than the key or the - of its
entry. Below the last item of a list without indentation, it belongs to
the end of the list, by the rule below.
>>>input = "host: localhost\n # a\n# b\nports:\n- 80\n # c\n# d\n- 443\n # e\n# f\nuser: admin\n"
>>>T.putStr inputhost: localhost # a # b ports: - 80 # c # d - 443 # e # f user: admin
>>>printComments inputroot.host (value) after: [Comment "a"] root.ports (key) before: [Comment "b"] root.ports (value) after: [Comment "e"] root.ports[0] after: [Comment "c"] root.ports[1] before: [Comment "d"] root.user (key) before: [Comment "f"]
Below a block scalar, such a line is part of the scalar if it is indented
as deep as the content. Otherwise it belongs to the node below. E.g.
# a below is a line of the text, and user gets # b.
>>>input = "text: |\n Hello.\n # a\n # b\nuser: admin\n"
>>>T.putStr inputtext: | Hello. # a # b user: admin
>>>printComments inputroot.user (key) before: [Comment "b"]
Thus the text has no place for the lines after a block scalar. They read back as the lines of the node below, or of the end of an outer collection.
Below a scalar or an alias key after ?, such a line belongs to the value:
as a line above it if the : of the value follows, and as a line after it
if the key has no value. A list or a mapping as the key keeps it. E.g. the
value of a gets # b above it, the empty value of e gets # f after
it, and the list key gets # d.
>>>input = "? a\n # b\n: x\n? e\n # f\n? - c\n # d\n: y\n"
>>>T.putStr input? a # b : x ? e # f ? - c # d : y
>>>printComments inputroot.a (value) before: [Comment "b"] root.e (value) after: [Comment "f"] root.? (key) after: [Comment "d"]
Thus the text has no place for the lines after a scalar or an alias key. They read back as lines of the value.
A comment after the last entry of a block collection belongs to the end of the collection if it is indented at least as deep as the entries, and deeper than the key of the collection. Otherwise it belongs to the node below it, or to the end of an outer collection if no node is below it.
>>>input = "server:\n ports:\n - 80\n # a\n # b\n# c\nuser: admin\n"
>>>T.putStr inputserver: ports: - 80 # a # b # c user: admin
>>>printComments inputroot.server (value) after: [Comment "a",Comment "b"] root.user (key) before: [Comment "c"]
A comment before the closing bracket of a flow collection belongs to the end of the collection.
>>>input = "ports: [80, 443,\n # a\n ]\n"
>>>T.putStr inputports: [80, 443, # a ]
>>>printComments inputroot.ports (value) after: [Comment "a"]
Documents
The optional --- marker starts a document, and the optional ... marker
ends it. The lines above the directives or the --- marker belong to the
document. So do the comment on the line of the ... marker and the lines
below it. Without the markers, the root gets these lines.
A comment on the line of the --- marker belongs to the document, unless
the rule for comments at the end of a line gives it to a node.
>>>input = "# a\n--- # b\n# c\n\nentry: value\n\n# e\n...\n# f\n"
>>>T.putStr input# a --- # b # c entry: value # e ... # f
>>>printComments inputdocument before: [Comment "a"] document inline: "b" root before: [Comment "c",EmptyLine] root after: [EmptyLine,Comment "e"] document after: [Comment "f"]
Between two documents, the first empty line below the ... marker ends
the lines of the first document. The empty line and the lines below it
belong to the second document: to the lines above its --- marker, or to
its root without the marker.
>>>input = "x: 1\n...\n# a\n\n# b\n---\ny: 2\n"
>>>T.putStr inputx: 1 ... # a # b --- y: 2
>>>printComments inputdocument after: [Comment "a"] next document document before: [EmptyLine,Comment "b"]
Without the ... marker, the first empty line below the root ends the
lines of the root in the same way.
>>>input = "x: 1\n# a\n\n# b\n---\ny: 2\n"
>>>T.putStr inputx: 1 # a # b --- y: 2
>>>printComments inputroot after: [Comment "a"] next document document before: [EmptyLine,Comment "b"]
The lines of a flow collection are between its brackets, so the lines
below a flow collection root belong to the document, also without the
... marker.
>>>input = "[80, 443]\n# a\n"
>>>T.putStr input[80, 443] # a
>>>printComments inputdocument after: [Comment "a"]
The renderer writes the markers and the empty lines that these rules need, so that the lines read back at the same places. One exception: the empty lines at the end of a document can read back as the lines of the next document.
Empty lines
Empty lines go with the node below them, or with the end of the document. Thus, if a program removes an entry, the gap below the entry stays.
>>>input = "server:\n host: localhost\n # The end of the server.\n\nuser: admin\n"
>>>T.putStr inputserver: host: localhost # The end of the server. user: admin
>>>printComments inputroot.server (value) after: [Comment "The end of the server."] root.user (key) before: [EmptyLine]
Empty lines above a comment go with the comment. Each empty line is a line of its own.
>>>input = "host: localhost\n\n\n# The port.\nport: 80\n\nuser: admin\n"
>>>T.putStr inputhost: localhost # The port. port: 80 user: admin
>>>printComments inputroot.port (key) before: [EmptyLine,EmptyLine,Comment "The port."] root.user (key) before: [EmptyLine]
One place is an exception. Above the first entry of a block collection, the last empty line stays with the collection. If the lines of a block collection do not end with an empty line, e.g. lines that a program added, the renderer can write one below them, so that they read back as the lines of the collection. The added empty line reads back as their last line.
>>>input = "# The file.\n\nhost: localhost\n"
>>>T.putStr input# The file. host: localhost
>>>printComments inputroot before: [Comment "The file.",EmptyLine]