In Progress
Unit 1, Lesson 1
In Progress

Squiggly Heredoc

Video transcript & code

Hey, remember back in episode #250 when we talked about unindenting text? The context of that episode was code like this, where we want to include a literal string that consists of multi-line, formatted text in our code.

module Wonderland
  JABBERWOCKY = <<-EOF
      'Twas brillig, and the slithy toves
      Did gyre and gimble in the wabe;
      All mimsy were the borogoves,
      And the mome raths outgrabe.

    -- From "jabberwocky", by Lewis Carroll
  EOF
end

We're using a heredoc, and we've indented the text to the right because we want it to be consistent with our overall code indenting style. The problem is, Ruby includes that indenting space in the resulting string object. The consequence is that, when we dump the string, the whole passage is still indented by four spaces.

require "./wonderland"
puts Wonderland::JABBERWOCKY

# >>       'Twas brillig, and the slithy toves
# >>       Did gyre and gimble in the wabe;
# >>       All mimsy were the borogoves,
# >>       And the mome raths outgrabe.
# >>
# >>     -- From "jabberwocky", by Lewis Carroll

I'm very happy to say that starting with version 2.3, we no longer have to worry about how to unindent multiline literal strings. At long last, Ruby has finally added an auto-unindenting version of heredocs. All we have to do is change the dash in the heredoc opener, to a tilde instead.

module Wonderland
  JABBERWOCKY = <<~EOF
      'Twas brillig, and the slithy toves
      Did gyre and gimble in the wabe;
      All mimsy were the borogoves,
      And the mome raths outgrabe.

    -- From "jabberwocky", by Lewis Carroll
  EOF
end

When we dump it out, Ruby strips off indentation until the least-indented line in the text is touching the lefthand margin. As you can see in this example, the least indented line was the attribution line at the end. The whole poem has been unindented to the point where that line is up against the margin, but no further. This has left the poem's verse correctly indented relative to the attribution.

require "./wonderland2"
puts Wonderland::JABBERWOCKY

# >>   'Twas brillig, and the slithy toves
# >>   Did gyre and gimble in the wabe;
# >>   All mimsy were the borogoves,
# >>   And the mome raths outgrabe.
# >>
# >> -- From "jabberwocky", by Lewis Carroll

The term for this new type of heredoc is a "squiggly heredoc", because of the tilde character. I'm a little bit proud to say that the syntax for the squiggly heredoc was based on a suggestion I made a couple of years ago on the Ruby Core mailing list.

If you're looking for a way to remember this syntax, think of it this way: it's like the dash version of a heredoc, except the indenting whitespace has been squished over to the left. Along with it, the dash has been "squished" as well, leaving it squiggly. I probably should have called it the "squished heredoc" when I came up with the syntax. Oh well!

Anyway, that's all for today. Happy hacking!

Responses