Skip to content

Instantly share code, notes, and snippets.

@DevAndArtist
Last active May 18, 2017 14:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DevAndArtist/d9282e032ee241cfd1a403961cedffdf to your computer and use it in GitHub Desktop.
Save DevAndArtist/d9282e032ee241cfd1a403961cedffdf to your computer and use it in GitHub Desktop.
Aligned String Literal Model in Swift

Motivation

In Swift 3 the string literal is a simple stream of characters that is enclosed by starting and ending " delimiters without new lines after and before the delimiters.

// Example #1
"\"Title\"\n\nLorem ipsum dolor sit amet, consectetur adipiscing elit. Integer elementum commodo sem, a congue orci porta sit amet.\nDuis facilisis, est et vehicula congue, turpis dui ultricies nunc, ut elementum quam elit nec felis."

This issue makes it very hard to write code that has a fixed line width.

Proposed Solution

Step #1

We can solve this issue by introducing an additional form of string literals with an easy way for hard wrapping very long strings. Leading whitespaces are trimmed by the whitespace-prefix calculated from the ending delimiter. Trailing whitespaces also need an explicit annotation, we'll choose the \ character (almost as a shorthand for \(""), but not entirely - later we'll explain why):

// Example #1.1
"
\"Title\"\n
\n
Lorem ipsum dolor sit amet, consectetur adipiscing elit. \
Integer elementum commodo sem, a congue orci porta sit amet.\n
Duis facilisis, est et vehicula congue, turpis dui \
ultricies nunc, ut elementum quam elit nec felis.
"

Note that blank lines are not allowed and will be an error.

The syntax is simple to learn and the issue with the trailing whitespaces becomes clear to reason about. Now let's enhance that syntax by simplifying the inner content:

Step #2

Let's come up with a syntax that is able to inject new lines automatically, but still allows us to hard wrap long lines. As a consequence we can also allow blank lines. For now, let's use $ for its delimiters.

// Example #2
$
abc

def
$ == "abc\n\ndef"

In fact we run into a corner here, because if we now inject new lines automatically when an actual new line occurs, how would we be able to hard wrap long lines? Keep in mind that we're still only simplifying the multi-line form for the single quoted syntax from above. This implies that we have to be explicit about the trailing whitespaces. Well that's an interesting hint, because we could reuse the trailing backslash for hard wrapping such a string literal, which also means that we can escape new line injection if desired (this syntax is very similar to other programming languages). This is also the reason why the trailing backslash is not a simple replacement for \("")!

// Example #3
$
000 \
\"abc\"
000
$ == "000 \"abc\"\n000"

We can adopt the lorem example from above like this:

// Example #1.2
$
\"Title\"

Lorem ipsum dolor sit amet, consectetur adipiscing elit. \
Integer elementum commodo sem, a congue orci porta sit amet.
Duis facilisis, est et vehicula congue, turpis dui \
ultricies nunc, ut elementum quam elit nec felis.
$

Step #3

Let's come up with a syntax that is able to have " character without the need to escape them. For now, let's use # for its delimiters.

// Example #4
#"abc"# == "\"abc\""

// Example #2.1
#
"abc" \
\n
"def"
# == "\"abc\" \n\"def\""

As for an experiment let's try a different delimiter, which would be similar to the double quoted one from above. We'll choose "" here.

// Example #4.1
"""abc""" == "\"abc\""

// Example #2.2
""
"abc" \
\n
"def"
"" == "\"abc\" \n\"def\""

This works fine except for one common edge case where the actual string is "".

// Example #5
""\"""" == """\""" == "\"\""

// Example #6
""
\""
"" == "\"\""

// Example #6.1
""
"\"
"" == "\"\""

To solve that particular issue we could increase the amount of double quotes once again to """.

// Example #5.1
"""""""" == "\"\""

// Example #6.2
"""
""
""" == "\"\""

Step #4

Let's merge the syntaxes from step (2) and step (3) into a single syntax. As for this step we decide to go with the """ delimiter.

// Example #5.2
"""""""" == "\"\""

// Example #6.3
"""
""
""" == "\"\""

// Example #4.2
""""abc"""" == "\"abc\""

// Example #2.3
"""
"abc" \

"def"
""" == "\"abc\" \n\"def\""

// Example #3.1
"""
000 \
"abc"
000
""" == "000 \"abc\"\n000"

// Example #1.3
"""
"Title"

Lorem ipsum dolor sit amet, consectetur adipiscing elit. \
Integer elementum commodo sem, a congue orci porta sit amet.
Duis facilisis, est et vehicula congue, turpis dui \
ultricies nunc, ut elementum quam elit nec felis.
"""

Issue

The evolution process jumped directly to step (4). Futhermore, SE-0168 accepted a half baked version of step (4) and ripped apart hard wrapping, ignored trailing whitespaces and the single lined version of the syntax such as """abc""".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment