ruby picture

RCR 188: Remove whitespace before here doc contents

Submitted by Paul Brannan (Fri Jan 09 14:01:07 UTC 2004)

Abstract

Here docs are a useful tool, but they are often avoided because they break indentation. To avoid this, extended heredocs should be added that strip whitespace at parse-time; there are many options for doing this, and all of them have their pros and their cons.

Problem

When using here docs, there is no good way to indent the here doc the same way as the code surrounding it. For example, the code:

  def foo
    return <<-END
      This is a test.
    END
  end</pre>

results in a function foo() that returns " This is a test.\n". This is probably not what the author intended the result to be. There are solutions that use regular expressions at run-time to build a here-doc without leading whitespace. For example ,
  def foo

    
    return %Q{
      This is a test.
    }.gsub!(/^\s*/, '')
  end</pre>

which strips all leading whitespace (and therefore probably undesirable). Another option :
  def tabto(n)

    
    if self =~ /^( *)\S/
      tab(n - $1.length)
    else
      self
    end
  end
  def foo
    return %Q{
      This is a test.
    }.tabto(0)
  end</pre>

which is good but IMO is not intuitive when reading code that uses it.
As long as we are missing extended here docs, users will continue to produce ad-hoc solutions like the above. we need a solution that occurs at parse time and is intuitive and easy to use.

Proposal

Nobu Nakada proposed in the following solution:

  p <<-|EOS
    |  foo
    |    bar
  EOS
  # => "  foo\n    bar\n".</pre>

The parser should understand the <<-| syntax to indicate an extended here doc in which the | character is used to indicate the start of the line.

Analysis

This solution is easy to read and to understand, and the parsing of the here doc occurs at parse time, as it should.

Implementation

The patch has already been posted in .
ruby picture
Comments Current voting

Ummmm... I feel a bit bad (and perhaps a little embarrased) for saying this, but IMO, that looks ugly. It really looks like a hack. If I wanted to program things that looked like that, I'd prefer doing it in Perl. ;)

Perhaps we could have an alternate syntax for here docs that would strip only the *common* whitespace from the beginning of each line. For example: (showing tabs as escaped chars (and noting the *3* lessthans))

n = <<<-EOS
\t\t...line one
\t\s\s...line two
EOS
  1. => "\t...line one\n ...line two"

          

This would remove one tab from the front of each line. The goal being to remove as much whitespace as possible, but requiring it to be the same series of whitespace characters from each line.

I've been bitten by the "here doc whitespace problem" myself many times. For me, the problem was that it looked ugly and less readable to have several unindented lines in the midst of (sometimes deeply) indented code.

I don't mean to stir anything up, it's just my opinion. - marc


RabYak: I concur that the leading | notation is non-ideal, IMO. To me the solution is obvious. In the supplied demo code:

 def foo
        return <<-END
                This is a test.
        END
 end

If the user wants their code indented cleanly with respect to their code, they have indented it one tab-stop deeper than the line on which it was called. With some new operator like <<+ (I don't care what it's called) Ruby would see the line on which the <<+ occurred had 1 leading tab character, and would string a single tab from the front of every line within the here doc block.

(Addendum: Uh-oh, I seem to have deleted two people's comments. Where's the history for this Wiki?)

I think it was only one person's comments (I hope :-) and I've restored it. -- David Black


I am going to vote in favor, but I agree that the | notation is not ideal. I prefer the solution proposed by the comment above, where the declaration line determines in the indentation. Nobody is going to want to have to line their HERE document with |s. -- Zachary P. Landau


Strongly opposed 0
Opposed 1
Neutral 1
In favor 12
Strongly advocate 0
ruby picture
If you have registered at RCRchive, you may now sign in below. If you have not registered, you may sign up for a username and password. Registering enables you to submit new RCRs, and vote and leave comments on existing RCRs.
Your username:
Your password:

ruby picture

Powered by .