diff --git a/Erlang.plist b/Erlang.plist
index 3075422..7b4075b 100644
--- a/Erlang.plist
+++ b/Erlang.plist
@@ -536,6 +536,219 @@
+ docstring
+
+ comment
+ It is possible to use more than 3 double quote characters as beginning and closing sequences (must be the same). Cover 3-9 characters here.
+ patterns
+
+
+ include
+ #docstring3
+
+
+ include
+ #docstring4
+
+
+ include
+ #docstring5
+
+
+ include
+ #docstring6
+
+
+ include
+ #docstring7
+
+
+ include
+ #docstring8
+
+
+ include
+ #docstring9
+
+
+
+ docstring3
+
+ begin
+ (?<!")(["]{3}\s*)$
+ beginCaptures
+
+ 1
+
+ name
+ punctuation.definition.docstring.begin.erlang
+
+
+ comment
+ Only whitespace characters are allowed after the beggining and before the closing sequences and those cannot be in the same line
+ end
+ ^(\s*["]{3})(?!")
+ endCaptures
+
+ 1
+
+ name
+ punctuation.definition.docstring.end.erlang
+
+
+ name
+ string.string.docstring.multi.erlang
+
+ docstring4
+
+ begin
+ (?<!")(["]{4}\s*)$
+ beginCaptures
+
+ 1
+
+ name
+ punctuation.definition.docstring.begin.erlang
+
+
+ end
+ ^(\s*["]{4})(?!")
+ endCaptures
+
+ 1
+
+ name
+ punctuation.definition.docstring.end.erlang
+
+
+ name
+ string.string.docstring.multi.erlang
+
+ docstring5
+
+ begin
+ (?<!")(["]{5}\s*)$
+ beginCaptures
+
+ 1
+
+ name
+ punctuation.definition.docstring.begin.erlang
+
+
+ end
+ ^(\s*["]{5})(?!")
+ endCaptures
+
+ 1
+
+ name
+ punctuation.definition.docstring.end.erlang
+
+
+ name
+ string.string.docstring.multi.erlang
+
+ docstring6
+
+ begin
+ (?<!")(["]{6}\s*)$
+ beginCaptures
+
+ 1
+
+ name
+ punctuation.definition.docstring.begin.erlang
+
+
+ end
+ ^(\s*["]{6})(?!")
+ endCaptures
+
+ 1
+
+ name
+ punctuation.definition.docstring.end.erlang
+
+
+ name
+ string.string.docstring.multi.erlang
+
+ docstring7
+
+ begin
+ (?<!")(["]{7}\s*)$
+ beginCaptures
+
+ 1
+
+ name
+ punctuation.definition.docstring.begin.erlang
+
+
+ end
+ ^(\s*["]{7})(?!")
+ endCaptures
+
+ 1
+
+ name
+ punctuation.definition.docstring.end.erlang
+
+
+ name
+ string.string.docstring.multi.erlang
+
+ docstring8
+
+ begin
+ (?<!")(["]{8}\s*)$
+ beginCaptures
+
+ 1
+
+ name
+ punctuation.definition.docstring.begin.erlang
+
+
+ end
+ ^(\s*["]{8})(?!")
+ endCaptures
+
+ 1
+
+ name
+ punctuation.definition.docstring.end.erlang
+
+
+ name
+ string.string.docstring.multi.erlang
+
+ docstring9
+
+ begin
+ (?<!")(["]{9}\s*)$
+ beginCaptures
+
+ 1
+
+ name
+ punctuation.definition.docstring.begin.erlang
+
+
+ end
+ ^(\s*["]{9})(?!")
+ endCaptures
+
+ 1
+
+ name
+ punctuation.definition.docstring.end.erlang
+
+
+ name
+ string.string.docstring.multi.erlang
+
everything-else
patterns
@@ -600,6 +813,10 @@
include
#atom
+
+ include
+ #docstring
+
include
#string
@@ -2593,6 +2810,8 @@
punctuation.definition.escape.erlang
+ comment
+ escape sequence
match
(\\)([bdefnrstv\\'"]|(\^)[@-_a-z]|[0-7]{1,3}|x[\da-fA-F]{2})
name
diff --git a/README.md b/README.md
index c38bee2..961ed3b 100644
--- a/README.md
+++ b/README.md
@@ -56,11 +56,16 @@ from _Ben Hockley_.
from Github and use below commands: (On Windows use e.g. WSL)
```bash
- /path/to/plist_yaml.py Erlang.plist Erlang.yaml
+ /path/to/plistyamlplist.py Erlang.plist Erlang.yaml
# Edit YAML file here ... then if you are ready convert back to PLIST
- /path/to/yaml_plist.py Erlang.yaml Erlang.plist
+ /path/to/plistyamlplist.py Erlang.yaml Erlang.plist
```
+ > Note:
+ > Please read
+ > [Issue with Python 3.11](https://github.com/grahampugh/plist-yaml-plist/issues/15)
+ > if you get a strange error when convert PLIST to YAML or vice versa.
+
Commit your updates on `Erlang.plist` and ignode `Erlang.yaml`.
To test the grammar we use
diff --git a/tests/snap/docstring.erl b/tests/snap/docstring.erl
new file mode 100644
index 0000000..cfb3b0c
--- /dev/null
+++ b/tests/snap/docstring.erl
@@ -0,0 +1,33 @@
+-module(docstring).
+
+-export([f/0]).
+
+-doc """
+ Docstring examples
+ """.
+f() ->
+ """
+ Line "1"
+ Line "2"
+ """ = "Line \"1\"
+Line \"2\"",
+ X = lists:seq(1,3), % just to check is syntax highlight is still ok
+
+ """
+ First line starting with two spaces
+ Not escaped: "\t \r \xFF" and """
+
+ """ = " First line starting with two spaces
+Not escaped: \"\\t \\r \\xFF\" and \"\"\"
+",
+ X = lists:seq(1,3), % just to check is syntax highlight is still ok
+
+ """""
+""""
+FIXME: previous line is not a closing delimiter because opening-closing delimiter have five double quote characters
+""""" = "\"\"\"\"",
+ X = lists:seq(1,3), % just to check is syntax highlight is still ok
+
+ ok.
+
+-define(THIS_IS_THE_END, "end"). % just to check is syntax highlight is still ok
diff --git a/tests/snap/docstring.erl.snap b/tests/snap/docstring.erl.snap
new file mode 100644
index 0000000..492b6c3
--- /dev/null
+++ b/tests/snap/docstring.erl.snap
@@ -0,0 +1,205 @@
+>-module(docstring).
+#^ source.erlang meta.directive.module.erlang punctuation.section.directive.begin.erlang
+# ^^^^^^ source.erlang meta.directive.module.erlang keyword.control.directive.module.erlang
+# ^ source.erlang meta.directive.module.erlang punctuation.definition.parameters.begin.erlang
+# ^^^^^^^^^ source.erlang meta.directive.module.erlang entity.name.type.class.module.definition.erlang
+# ^ source.erlang meta.directive.module.erlang punctuation.definition.parameters.end.erlang
+# ^ source.erlang meta.directive.module.erlang punctuation.section.directive.end.erlang
+>
+>-export([f/0]).
+#^ source.erlang meta.directive.export.erlang punctuation.section.directive.begin.erlang
+# ^^^^^^ source.erlang meta.directive.export.erlang keyword.control.directive.export.erlang
+# ^ source.erlang meta.directive.export.erlang punctuation.definition.parameters.begin.erlang
+# ^ source.erlang meta.directive.export.erlang meta.structure.list.function.erlang punctuation.definition.list.begin.erlang
+# ^ source.erlang meta.directive.export.erlang meta.structure.list.function.erlang entity.name.function.erlang
+# ^ source.erlang meta.directive.export.erlang meta.structure.list.function.erlang punctuation.separator.function-arity.erlang
+# ^ source.erlang meta.directive.export.erlang meta.structure.list.function.erlang constant.numeric.integer.decimal.erlang
+# ^ source.erlang meta.directive.export.erlang meta.structure.list.function.erlang punctuation.definition.list.end.erlang
+# ^ source.erlang meta.directive.export.erlang punctuation.definition.parameters.end.erlang
+# ^ source.erlang meta.directive.export.erlang punctuation.section.directive.end.erlang
+>
+>-doc """
+#^ source.erlang meta.directive.erlang punctuation.section.directive.begin.erlang
+# ^^^ source.erlang meta.directive.erlang keyword.control.directive.erlang
+# ^ source.erlang meta.directive.erlang
+# ^^^^ source.erlang meta.directive.erlang string.string.docstring.multi.erlang punctuation.definition.docstring.begin.erlang
+> Docstring examples
+#^^^^^^^^^^^^^^^^^^^^^^^^ source.erlang meta.directive.erlang string.string.docstring.multi.erlang
+> """.
+#^^^^^^^^ source.erlang meta.directive.erlang string.string.docstring.multi.erlang punctuation.definition.docstring.end.erlang
+# ^ source.erlang meta.directive.erlang punctuation.section.directive.end.erlang
+>f() ->
+#^ source.erlang meta.function.erlang entity.name.function.definition.erlang
+# ^ source.erlang meta.function.erlang meta.expression.parenthesized punctuation.section.expression.begin.erlang
+# ^ source.erlang meta.function.erlang meta.expression.parenthesized punctuation.section.expression.end.erlang
+# ^ source.erlang meta.function.erlang
+# ^ source.erlang meta.function.erlang keyword.operator.symbolic.erlang
+# ^ source.erlang meta.function.erlang keyword.operator.symbolic.erlang
+> """
+#^^^^ source.erlang meta.function.erlang
+# ^^^^ source.erlang meta.function.erlang string.string.docstring.multi.erlang punctuation.definition.docstring.begin.erlang
+> Line "1"
+#^^^^^^^^^^^ source.erlang meta.function.erlang string.string.docstring.multi.erlang
+> Line "2"
+#^^^^^^^^^^^ source.erlang meta.function.erlang string.string.docstring.multi.erlang
+> """ = "Line \"1\"
+#^^^^^ source.erlang meta.function.erlang string.string.docstring.multi.erlang punctuation.definition.docstring.end.erlang
+# ^ source.erlang meta.function.erlang
+# ^ source.erlang meta.function.erlang keyword.operator.symbolic.erlang
+# ^ source.erlang meta.function.erlang
+# ^ source.erlang meta.function.erlang string.quoted.double.erlang punctuation.definition.string.begin.erlang
+# ^^^^^ source.erlang meta.function.erlang string.quoted.double.erlang
+# ^ source.erlang meta.function.erlang string.quoted.double.erlang constant.character.escape.erlang punctuation.definition.escape.erlang
+# ^ source.erlang meta.function.erlang string.quoted.double.erlang constant.character.escape.erlang
+# ^ source.erlang meta.function.erlang string.quoted.double.erlang
+# ^ source.erlang meta.function.erlang string.quoted.double.erlang constant.character.escape.erlang punctuation.definition.escape.erlang
+# ^ source.erlang meta.function.erlang string.quoted.double.erlang constant.character.escape.erlang
+>Line \"2\"",
+#^^^^^ source.erlang meta.function.erlang string.quoted.double.erlang
+# ^ source.erlang meta.function.erlang string.quoted.double.erlang constant.character.escape.erlang punctuation.definition.escape.erlang
+# ^ source.erlang meta.function.erlang string.quoted.double.erlang constant.character.escape.erlang
+# ^ source.erlang meta.function.erlang string.quoted.double.erlang
+# ^ source.erlang meta.function.erlang string.quoted.double.erlang constant.character.escape.erlang punctuation.definition.escape.erlang
+# ^ source.erlang meta.function.erlang string.quoted.double.erlang constant.character.escape.erlang
+# ^ source.erlang meta.function.erlang string.quoted.double.erlang punctuation.definition.string.end.erlang
+# ^ source.erlang meta.function.erlang punctuation.separator.expressions.erlang
+> X = lists:seq(1,3), % just to check is syntax highlight is still ok
+#^^^^ source.erlang meta.function.erlang
+# ^ source.erlang meta.function.erlang variable.other.erlang
+# ^ source.erlang meta.function.erlang
+# ^ source.erlang meta.function.erlang keyword.operator.symbolic.erlang
+# ^ source.erlang meta.function.erlang
+# ^^^^^ source.erlang meta.function.erlang meta.function-call.erlang entity.name.type.class.module.erlang
+# ^ source.erlang meta.function.erlang meta.function-call.erlang punctuation.separator.module-function.erlang
+# ^^^ source.erlang meta.function.erlang meta.function-call.erlang entity.name.function.erlang
+# ^ source.erlang meta.function.erlang meta.function-call.erlang punctuation.definition.parameters.begin.erlang
+# ^ source.erlang meta.function.erlang meta.function-call.erlang constant.numeric.integer.decimal.erlang
+# ^ source.erlang meta.function.erlang meta.function-call.erlang punctuation.separator.parameters.erlang
+# ^ source.erlang meta.function.erlang meta.function-call.erlang constant.numeric.integer.decimal.erlang
+# ^ source.erlang meta.function.erlang meta.function-call.erlang punctuation.definition.parameters.end.erlang
+# ^ source.erlang meta.function.erlang punctuation.separator.expressions.erlang
+# ^ source.erlang meta.function.erlang
+# ^ source.erlang meta.function.erlang comment.line.percentage.erlang punctuation.definition.comment.erlang
+# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ source.erlang meta.function.erlang comment.line.percentage.erlang
+>
+> """
+#^^^^ source.erlang meta.function.erlang
+# ^^^^ source.erlang meta.function.erlang string.string.docstring.multi.erlang punctuation.definition.docstring.begin.erlang
+> First line starting with two spaces
+#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ source.erlang meta.function.erlang string.string.docstring.multi.erlang
+> Not escaped: "\t \r \xFF" and """
+#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ source.erlang meta.function.erlang string.string.docstring.multi.erlang
+>
+> """ = " First line starting with two spaces
+#^^^^^^^ source.erlang meta.function.erlang string.string.docstring.multi.erlang punctuation.definition.docstring.end.erlang
+# ^ source.erlang meta.function.erlang
+# ^ source.erlang meta.function.erlang keyword.operator.symbolic.erlang
+# ^ source.erlang meta.function.erlang
+# ^ source.erlang meta.function.erlang string.quoted.double.erlang punctuation.definition.string.begin.erlang
+# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ source.erlang meta.function.erlang string.quoted.double.erlang
+>Not escaped: \"\\t \\r \\xFF\" and \"\"\"
+#^^^^^^^^^^^^^ source.erlang meta.function.erlang string.quoted.double.erlang
+# ^ source.erlang meta.function.erlang string.quoted.double.erlang constant.character.escape.erlang punctuation.definition.escape.erlang
+# ^ source.erlang meta.function.erlang string.quoted.double.erlang constant.character.escape.erlang
+# ^ source.erlang meta.function.erlang string.quoted.double.erlang constant.character.escape.erlang punctuation.definition.escape.erlang
+# ^ source.erlang meta.function.erlang string.quoted.double.erlang constant.character.escape.erlang
+# ^^ source.erlang meta.function.erlang string.quoted.double.erlang
+# ^ source.erlang meta.function.erlang string.quoted.double.erlang constant.character.escape.erlang punctuation.definition.escape.erlang
+# ^ source.erlang meta.function.erlang string.quoted.double.erlang constant.character.escape.erlang
+# ^^ source.erlang meta.function.erlang string.quoted.double.erlang
+# ^ source.erlang meta.function.erlang string.quoted.double.erlang constant.character.escape.erlang punctuation.definition.escape.erlang
+# ^ source.erlang meta.function.erlang string.quoted.double.erlang constant.character.escape.erlang
+# ^^^ source.erlang meta.function.erlang string.quoted.double.erlang
+# ^ source.erlang meta.function.erlang string.quoted.double.erlang constant.character.escape.erlang punctuation.definition.escape.erlang
+# ^ source.erlang meta.function.erlang string.quoted.double.erlang constant.character.escape.erlang
+# ^^^^^ source.erlang meta.function.erlang string.quoted.double.erlang
+# ^ source.erlang meta.function.erlang string.quoted.double.erlang constant.character.escape.erlang punctuation.definition.escape.erlang
+# ^ source.erlang meta.function.erlang string.quoted.double.erlang constant.character.escape.erlang
+# ^ source.erlang meta.function.erlang string.quoted.double.erlang constant.character.escape.erlang punctuation.definition.escape.erlang
+# ^ source.erlang meta.function.erlang string.quoted.double.erlang constant.character.escape.erlang
+# ^ source.erlang meta.function.erlang string.quoted.double.erlang constant.character.escape.erlang punctuation.definition.escape.erlang
+# ^ source.erlang meta.function.erlang string.quoted.double.erlang constant.character.escape.erlang
+>",
+#^ source.erlang meta.function.erlang string.quoted.double.erlang punctuation.definition.string.end.erlang
+# ^ source.erlang meta.function.erlang punctuation.separator.expressions.erlang
+> X = lists:seq(1,3), % just to check is syntax highlight is still ok
+#^^^^ source.erlang meta.function.erlang
+# ^ source.erlang meta.function.erlang variable.other.erlang
+# ^ source.erlang meta.function.erlang
+# ^ source.erlang meta.function.erlang keyword.operator.symbolic.erlang
+# ^ source.erlang meta.function.erlang
+# ^^^^^ source.erlang meta.function.erlang meta.function-call.erlang entity.name.type.class.module.erlang
+# ^ source.erlang meta.function.erlang meta.function-call.erlang punctuation.separator.module-function.erlang
+# ^^^ source.erlang meta.function.erlang meta.function-call.erlang entity.name.function.erlang
+# ^ source.erlang meta.function.erlang meta.function-call.erlang punctuation.definition.parameters.begin.erlang
+# ^ source.erlang meta.function.erlang meta.function-call.erlang constant.numeric.integer.decimal.erlang
+# ^ source.erlang meta.function.erlang meta.function-call.erlang punctuation.separator.parameters.erlang
+# ^ source.erlang meta.function.erlang meta.function-call.erlang constant.numeric.integer.decimal.erlang
+# ^ source.erlang meta.function.erlang meta.function-call.erlang punctuation.definition.parameters.end.erlang
+# ^ source.erlang meta.function.erlang punctuation.separator.expressions.erlang
+# ^ source.erlang meta.function.erlang
+# ^ source.erlang meta.function.erlang comment.line.percentage.erlang punctuation.definition.comment.erlang
+# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ source.erlang meta.function.erlang comment.line.percentage.erlang
+>
+> """""
+#^^^^ source.erlang meta.function.erlang
+# ^^^^^^ source.erlang meta.function.erlang string.string.docstring.multi.erlang punctuation.definition.docstring.begin.erlang
+>""""
+#^^^^^ source.erlang meta.function.erlang string.string.docstring.multi.erlang
+>FIXME: previous line is not a closing delimiter because opening-closing delimiter have five double quote characters
+#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ source.erlang meta.function.erlang string.string.docstring.multi.erlang
+>""""" = "\"\"\"\"",
+#^^^^^ source.erlang meta.function.erlang string.string.docstring.multi.erlang punctuation.definition.docstring.end.erlang
+# ^ source.erlang meta.function.erlang
+# ^ source.erlang meta.function.erlang keyword.operator.symbolic.erlang
+# ^ source.erlang meta.function.erlang
+# ^ source.erlang meta.function.erlang string.quoted.double.erlang punctuation.definition.string.begin.erlang
+# ^ source.erlang meta.function.erlang string.quoted.double.erlang constant.character.escape.erlang punctuation.definition.escape.erlang
+# ^ source.erlang meta.function.erlang string.quoted.double.erlang constant.character.escape.erlang
+# ^ source.erlang meta.function.erlang string.quoted.double.erlang constant.character.escape.erlang punctuation.definition.escape.erlang
+# ^ source.erlang meta.function.erlang string.quoted.double.erlang constant.character.escape.erlang
+# ^ source.erlang meta.function.erlang string.quoted.double.erlang constant.character.escape.erlang punctuation.definition.escape.erlang
+# ^ source.erlang meta.function.erlang string.quoted.double.erlang constant.character.escape.erlang
+# ^ source.erlang meta.function.erlang string.quoted.double.erlang constant.character.escape.erlang punctuation.definition.escape.erlang
+# ^ source.erlang meta.function.erlang string.quoted.double.erlang constant.character.escape.erlang
+# ^ source.erlang meta.function.erlang string.quoted.double.erlang punctuation.definition.string.end.erlang
+# ^ source.erlang meta.function.erlang punctuation.separator.expressions.erlang
+> X = lists:seq(1,3), % just to check is syntax highlight is still ok
+#^^^^ source.erlang meta.function.erlang
+# ^ source.erlang meta.function.erlang variable.other.erlang
+# ^ source.erlang meta.function.erlang
+# ^ source.erlang meta.function.erlang keyword.operator.symbolic.erlang
+# ^ source.erlang meta.function.erlang
+# ^^^^^ source.erlang meta.function.erlang meta.function-call.erlang entity.name.type.class.module.erlang
+# ^ source.erlang meta.function.erlang meta.function-call.erlang punctuation.separator.module-function.erlang
+# ^^^ source.erlang meta.function.erlang meta.function-call.erlang entity.name.function.erlang
+# ^ source.erlang meta.function.erlang meta.function-call.erlang punctuation.definition.parameters.begin.erlang
+# ^ source.erlang meta.function.erlang meta.function-call.erlang constant.numeric.integer.decimal.erlang
+# ^ source.erlang meta.function.erlang meta.function-call.erlang punctuation.separator.parameters.erlang
+# ^ source.erlang meta.function.erlang meta.function-call.erlang constant.numeric.integer.decimal.erlang
+# ^ source.erlang meta.function.erlang meta.function-call.erlang punctuation.definition.parameters.end.erlang
+# ^ source.erlang meta.function.erlang punctuation.separator.expressions.erlang
+# ^ source.erlang meta.function.erlang
+# ^ source.erlang meta.function.erlang comment.line.percentage.erlang punctuation.definition.comment.erlang
+# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ source.erlang meta.function.erlang comment.line.percentage.erlang
+>
+> ok.
+#^^^^ source.erlang meta.function.erlang
+# ^^ source.erlang meta.function.erlang constant.other.symbol.unquoted.erlang
+# ^ source.erlang meta.function.erlang punctuation.terminator.function.erlang
+>
+>-define(THIS_IS_THE_END, "end"). % just to check is syntax highlight is still ok
+#^ source.erlang meta.directive.define.erlang punctuation.section.directive.begin.erlang
+# ^^^^^^ source.erlang meta.directive.define.erlang keyword.control.directive.define.erlang
+# ^ source.erlang meta.directive.define.erlang punctuation.definition.parameters.begin.erlang
+# ^^^^^^^^^^^^^^^ source.erlang meta.directive.define.erlang entity.name.function.macro.definition.erlang
+# ^^ source.erlang meta.directive.define.erlang
+# ^ source.erlang meta.directive.define.erlang string.quoted.double.erlang punctuation.definition.string.begin.erlang
+# ^^^ source.erlang meta.directive.define.erlang string.quoted.double.erlang
+# ^ source.erlang meta.directive.define.erlang string.quoted.double.erlang punctuation.definition.string.end.erlang
+# ^ source.erlang meta.directive.define.erlang punctuation.definition.parameters.end.erlang
+# ^ source.erlang meta.directive.define.erlang punctuation.section.directive.end.erlang
+# ^ source.erlang
+# ^ source.erlang comment.line.percentage.erlang punctuation.definition.comment.erlang
+# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ source.erlang comment.line.percentage.erlang
+>
\ No newline at end of file