https://redmine.ruby-lang.org/https://redmine.ruby-lang.org/favicon.ico?17113305112013-11-13T15:21:31ZRuby Issue Tracking SystemRuby master - Feature #9098: Indent heredoc against the left margin by default when "indented closing identifier" is turned on.https://redmine.ruby-lang.org/issues/9098?journal_id=428982013-11-13T15:21:31Zdrbrain (Eric Hodel)drbrain@segment7.net
<ul><li><strong>Status</strong> changed from <i>Open</i> to <i>Assigned</i></li><li><strong>Assignee</strong> changed from <i>sikachu (Prem Sichanugrist)</i> to <i>matz (Yukihiro Matsumoto)</i></li><li><strong>Target version</strong> set to <i>3.0</i></li></ul><p>Why not make your content flush left?</p> Ruby master - Feature #9098: Indent heredoc against the left margin by default when "indented closing identifier" is turned on.https://redmine.ruby-lang.org/issues/9098?journal_id=429112013-11-14T03:26:46Zsikachu (Prem Sichanugrist)s+ruby@sikac.hu
<ul></ul><p><a class="user active user-mention" href="https://redmine.ruby-lang.org/users/47">@drbrain (Eric Hodel)</a> I could, but then the code would look ugly when the non-heredoc section is well-indented, and especially if the heredoc is pretty long. Consider this example code:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">module</span> <span class="nn">Rails</span>
<span class="k">class</span> <span class="nc">CommandsTasks</span> <span class="c1"># :nodoc:</span>
<span class="nb">attr_reader</span> <span class="ss">:argv</span>
<span class="no">HELP_MESSAGE</span> <span class="o">=</span> <span class="o"><<-</span><span class="no">EOT</span><span class="sh">
Usage: rails COMMAND [ARGS]
The most common rails commands are:
generate Generate new code (short-cut alias: "g")
console Start the Rails console (short-cut alias: "c")
server Start the Rails server (short-cut alias: "s")
dbconsole Start a console for the database specified in config/database.yml
(short-cut alias: "db")
new Create a new Rails application. "rails new my_app" creates a
new application called MyApp in "./my_app"
In addition to those, there are:
application Generate the Rails application code
destroy Undo code generated with "generate" (short-cut alias: "d")
plugin new Generates skeleton for developing a Rails plugin
runner Run a piece of code in the application environment (short-cut alias: "r")
All commands can be run with -h (or --help) for more information.
</span><span class="no">EOT</span>
<span class="no">COMMAND_WHITELIST</span> <span class="o">=</span> <span class="sx">%(plugin generate destroy console server dbconsole application runner new version help)</span>
</code></pre>
<p>Compared to this:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">module</span> <span class="nn">Rails</span>
<span class="k">class</span> <span class="nc">CommandsTasks</span> <span class="c1"># :nodoc:</span>
<span class="nb">attr_reader</span> <span class="ss">:argv</span>
<span class="no">HELP_MESSAGE</span> <span class="o">=</span> <span class="o"><<-</span><span class="no">EOT</span><span class="sh">
Usage: rails COMMAND [ARGS]
The most common rails commands are:
generate Generate new code (short-cut alias: "g")
console Start the Rails console (short-cut alias: "c")
server Start the Rails server (short-cut alias: "s")
dbconsole Start a console for the database specified in config/database.yml
(short-cut alias: "db")
new Create a new Rails application. "rails new my_app" creates a
new application called MyApp in "./my_app"
In addition to those, there are:
application Generate the Rails application code
destroy Undo code generated with "generate" (short-cut alias: "d")
plugin new Generates skeleton for developing a Rails plugin
runner Run a piece of code in the application environment (short-cut alias: "r")
All commands can be run with -h (or --help) for more information.
</span><span class="no"> EOT</span>
<span class="no">COMMAND_WHITELIST</span> <span class="o">=</span> <span class="sx">%(plugin generate destroy console server dbconsole application runner new version help)</span>
</code></pre>
<p>From the code example, you could see that it looks much nicer when it's properly indented based on the level. The heredoc doesn't feel foreign and stand out-of-place anymore.</p> Ruby master - Feature #9098: Indent heredoc against the left margin by default when "indented closing identifier" is turned on.https://redmine.ruby-lang.org/issues/9098?journal_id=429142013-11-14T08:08:15Zdrbrain (Eric Hodel)drbrain@segment7.net
<ul></ul><p>I can see the second is worse, not better, because it runs over 80 columns on more lines which wrap in my editor.</p> Ruby master - Feature #9098: Indent heredoc against the left margin by default when "indented closing identifier" is turned on.https://redmine.ruby-lang.org/issues/9098?journal_id=429152013-11-14T08:10:25Zsikachu (Prem Sichanugrist)s+ruby@sikac.hu
<ul></ul><p>I can see that. I actually just indented the example in without looking at the line width. My bad. :)</p>
<p>If the second example is <em>not</em> over 80 columns, would that still be consider worse for you?</p> Ruby master - Feature #9098: Indent heredoc against the left margin by default when "indented closing identifier" is turned on.https://redmine.ruby-lang.org/issues/9098?journal_id=429172013-11-14T10:45:43Zdrbrain (Eric Hodel)drbrain@segment7.net
<ul></ul><p>I prefer Avdi's idea in <a href="/issues/9098">[ruby-core:58322]</a> as it does not introduce incompatibility.</p> Ruby master - Feature #9098: Indent heredoc against the left margin by default when "indented closing identifier" is turned on.https://redmine.ruby-lang.org/issues/9098?journal_id=429182013-11-14T10:53:18Zavdi (Avdi Grimm)avdi@avdi.codes
<ul></ul><p>On Sat, Nov 9, 2013 at 4:18 PM, sikachu (Prem Sichanugrist) <a href="mailto:s@sikac.hu" class="email">s@sikac.hu</a><br>
wrote:</p>
<p>I've been using here document (heredoc) for a while, and I've found out</p>
<blockquote>
<p>that it's very annoying that the content is always treated as flushed left.</p>
</blockquote>
<p>This has actually bugged me for a very long time. Other languages have<br>
triple-quoted strings where the indent of the opening triple-quote is taken<br>
into account, and automatically stripped from the resulting text. In Ruby<br>
if I don’t want leading spaces I have to break the visual flow of my<br>
indentation (or resort to something like #strip_heredoc).</p>
<p>I don’t agree with changing the existing heredocs to have new semantics.<br>
But I could see adding e.g. a "squiggly-heredoc":</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">class</span> <span class="nc">Foo</span>
<span class="no">BAR</span> <span class="o">=</span> <span class="o"><<~</span><span class="no">EOF</span><span class="sh">
This line is
cleanly indented
</span><span class="no"> EOF</span>
<span class="k">end</span>
<span class="no">Foo</span><span class="o">::</span><span class="no">BAR</span> <span class="c1"># => "This line is\ncleanly indented"</span>
</code></pre>
<h2>Note that the way I imagine it, this would work a little different than<br>
triple-quoted strings in other languages, since the indentation wouldn’t be<br>
determined by the location of the opening signifier. Instead, it would be<br>
determined by indentation of the first non-whitespace character inside the<br>
heredoc.</h2>
<p>Avdi Grimm<br>
<a href="http://avdi.org" class="external">http://avdi.org</a></p>
<p>I only check email twice a day. to reach me sooner, go to<br>
<a href="http://awayfind.com/avdi" class="external">http://awayfind.com/avdi</a></p> Ruby master - Feature #9098: Indent heredoc against the left margin by default when "indented closing identifier" is turned on.https://redmine.ruby-lang.org/issues/9098?journal_id=429202013-11-14T12:10:40Zsikachu (Prem Sichanugrist)s+ruby@sikac.hu
<ul></ul><p>Oh, that's an awesome suggestion, <a class="user active user-mention" href="https://redmine.ruby-lang.org/users/169">@avdi (Avdi Grimm)</a>. I like it. That way, it wouldn't be introducing backward incompatibility. Maybe we can target next minor (since it's a new feature) as well?</p>
<p><a class="user active user-mention" href="https://redmine.ruby-lang.org/users/47">@drbrain (Eric Hodel)</a>, so I think I'll want to change this ticket to be adding <code><<~</code> to do this functionality instead. Should I go ahead and try to implement it, or do I have to wait for <a class="user active user-mention" href="https://redmine.ruby-lang.org/users/13">@matz (Yukihiro Matsumoto)</a> to +1?</p> Ruby master - Feature #9098: Indent heredoc against the left margin by default when "indented closing identifier" is turned on.https://redmine.ruby-lang.org/issues/9098?journal_id=429232013-11-14T13:01:55Zdrbrain (Eric Hodel)drbrain@segment7.net
<ul><li><strong>Target version</strong> changed from <i>3.0</i> to <i>2.6</i></li></ul><p>Creating a patch will help, but it can't be committed without the approval of matz.</p> Ruby master - Feature #9098: Indent heredoc against the left margin by default when "indented closing identifier" is turned on.https://redmine.ruby-lang.org/issues/9098?journal_id=429282013-11-14T19:41:41Zrosenfeld (Rodrigo Rosenfeld Rosas)rr.rosas@gmail.com
<ul></ul><p>+1 to Avdi's idea. I mostly miss this when I'm writing my specs. Sometimes I have to compare some processed HTML with the expected result and it's not easy to write the expected string without compromising indentation. Usually I end up with something like:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="p">[</span>
<span class="s1">'First line'</span><span class="p">,</span>
<span class="s1">'Second line'</span><span class="p">,</span>
<span class="o">...</span>
<span class="p">].</span><span class="nf">join</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span>
</code></pre>
<p>Having something like what Avdi described would help me a lot to write some of my specs.</p> Ruby master - Feature #9098: Indent heredoc against the left margin by default when "indented closing identifier" is turned on.https://redmine.ruby-lang.org/issues/9098?journal_id=429392013-11-15T01:07:23Zsikachu (Prem Sichanugrist)s+ruby@sikac.hu
<ul></ul><p>Sweet. I'll go ahead and start cooking up the patch. Thanks all for the preliminary feedback.</p> Ruby master - Feature #9098: Indent heredoc against the left margin by default when "indented closing identifier" is turned on.https://redmine.ruby-lang.org/issues/9098?journal_id=522012015-04-20T11:42:43Zbjmllr (Ben Miller)bjmllr@gmail.com
<ul></ul><p>This feature request has been silent for a year, so I submitted a patch for it: <a href="https://github.com/ruby/ruby/pull/878" class="external">https://github.com/ruby/ruby/pull/878</a></p> Ruby master - Feature #9098: Indent heredoc against the left margin by default when "indented closing identifier" is turned on.https://redmine.ruby-lang.org/issues/9098?journal_id=547632015-11-09T06:36:39Zko1 (Koichi Sasada)
<ul></ul><p>Discussion: <a href="https://docs.google.com/document/d/1D0Eo5N7NE_unIySOKG9lVj_eyXf66BQPM4PKp7NvMyQ/pub" class="external">https://docs.google.com/document/d/1D0Eo5N7NE_unIySOKG9lVj_eyXf66BQPM4PKp7NvMyQ/pub</a></p>
<p>Feel free to continue discussion on this ticket.</p> Ruby master - Feature #9098: Indent heredoc against the left margin by default when "indented closing identifier" is turned on.https://redmine.ruby-lang.org/issues/9098?journal_id=547652015-11-09T06:52:44Zmatz (Yukihiro Matsumoto)matz@ruby.or.jp
<ul></ul><p>Accepted. We have to define the behavior on (hard) tabs. As a UNIX user, I'd like to tak 8 spaces for tab stops.</p>
<p>Matz.</p> Ruby master - Feature #9098: Indent heredoc against the left margin by default when "indented closing identifier" is turned on.https://redmine.ruby-lang.org/issues/9098?journal_id=547872015-11-09T15:00:56ZAjedi32 (Andrew M)andrewm.bpi@gmail.com
<ul></ul><p>What do you mean? Isn't the number of spaces a tab is equivalent to only relevant when the first line is indented with tabs, while the following lines are indented with spaces (or vice-versa)?</p>
<p>Shouldn't it just throw an error in that case?</p> Ruby master - Feature #9098: Indent heredoc against the left margin by default when "indented closing identifier" is turned on.https://redmine.ruby-lang.org/issues/9098?journal_id=551222015-11-28T01:31:08Zbjmllr (Ben Miller)bjmllr@gmail.com
<ul><li><strong>File</strong> <a href="/attachments/5602">dedent_heredoc.patch</a> <a class="icon-only icon-download" title="Download" href="/attachments/download/5602/dedent_heredoc.patch">dedent_heredoc.patch</a> added</li></ul><p>I updated the patch to treat tabs as equal to 8 spaces.</p>
<p>This seems to work fine with the indentation produced by popular text editors (only tabs, only spaces, or tabs-then-spaces), with only one corner case I noticed, which is demonstrated in test_dedented_heredoc_with_inconsistent_indentation_preserves_tab (in test/ruby/test_syntax.rb), in which case we try backing up to the previous tab stop and starting over, to avoid breaking the hard tab. Do we need to handle spaces-then-tabs?</p>
<p>I attached the patch here so that more people are able to see it.</p> Ruby master - Feature #9098: Indent heredoc against the left margin by default when "indented closing identifier" is turned on.https://redmine.ruby-lang.org/issues/9098?journal_id=551232015-11-28T03:14:51ZAjedi32 (Andrew M)andrewm.bpi@gmail.com
<ul></ul><p>I'm confused. Why are tabs being treated as equivalent to spaces at all? E.g. If I write:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">def</span> <span class="nf">hello</span>
<span class="nb">puts</span> <span class="o"><<~</span><span class="no">README</span><span class="p">.</span><span class="nf">inspect</span><span class="sh">
<tab>Hello
<space><space><space><space><space><space><space><space>World!
</span><span class="no"> README</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<p>Are you saying that should be accepted by the compiler? Why? Why should that be any less invalid than:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">def</span> <span class="nf">hello</span>
<span class="nb">puts</span> <span class="o"><<~</span><span class="no">README</span><span class="p">.</span><span class="nf">inspect</span><span class="sh">
<tab>Hello
<space><space><space><space>World!
</span><span class="no"> README</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<p>or</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">def</span> <span class="nf">hello</span>
<span class="nb">puts</span> <span class="o"><<~</span><span class="no">README</span><span class="p">.</span><span class="nf">inspect</span><span class="sh">
<space><space><space><space>Hello
<space><space>World!
</span><span class="no"> README</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<p>Shouldn't we just throw an error in all of those cases? Is there ever a legitimate reason why you'd want to allow inconsistent indentation in one of these blocks? What happens when someone has their editor set to display tabs as 4 spaces, and writes:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">def</span> <span class="nf">hello</span>
<span class="nb">puts</span> <span class="o"><<~</span><span class="no">README</span><span class="p">.</span><span class="nf">inspect</span><span class="sh">
<space><space><space><space>Hello
<tab>World!
</span><span class="no"> README</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<p>Why should that result in:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">hello</span> <span class="c1">#=> " Hello\n\n\tWorld!"</span>
</code></pre>
<p>I certainly wouldn't expect that result intuitively. In such a case, wouldn't a well-written error message explaining that I'm mixing tabs and spaces be much more helpful for me as a developer?</p>
<p>(Note: I also cross-posted to the PR. I'm not really sure where the canonical place is for discussion on this feature.)</p> Ruby master - Feature #9098: Indent heredoc against the left margin by default when "indented closing identifier" is turned on.https://redmine.ruby-lang.org/issues/9098?journal_id=551242015-11-28T03:37:14Zmatz (Yukihiro Matsumoto)matz@ruby.or.jp
<ul></ul><p>Because we can not distinguish tabs and spaces on most editors, while we can distinguish 4 spaces and 8 spaces.<br>
It's weird but has historical reason.</p>
<p>Matz.</p> Ruby master - Feature #9098: Indent heredoc against the left margin by default when "indented closing identifier" is turned on.https://redmine.ruby-lang.org/issues/9098?journal_id=551282015-11-28T17:37:44ZAjedi32 (Andrew M)andrewm.bpi@gmail.com
<ul></ul><p>Right. I guess what I'm saying is that tabs shouldn't be treated as equivalent to spaces at all, since the number of spaces they are "equivalent" to is different for every developer, depending on what they have their editor set to display.</p>
<p>This can and will result in unexpected behavior (aka bugs) when tabs and spaces are mixed in indentation by mistake. I'd much rather these bugs be caught by the compiler and brought to the developer's attention with a clearly-worded error message then simply ignored and left for the developer to find out about later.</p>
<p>Tabs should be treated as tabs, and spaces should be treated as spaces. I'm not really sure what the argument is for treating one character as equivalent to another in the first place. Is there any situation where a developer might <em>want</em> that behavior? What's the use-case here? I honestly can't think of one.</p>
<p>To me, this just feels like a way to make it easy for developers to unknowingly create bugs in their code.</p> Ruby master - Feature #9098: Indent heredoc against the left margin by default when "indented closing identifier" is turned on.https://redmine.ruby-lang.org/issues/9098?journal_id=551832015-12-01T06:20:33Znobu (Nobuyoshi Nakada)nobu@ruby-lang.org
<ul></ul><p>"8 spaces for tab stops" is not enough to make the spec.</p>
<p>When tabs and spaces are mixed, e.g., there are<code>"\t"*2+"2 tabs"</code> line and <code>" "*10+"10 spaces"</code> line, what should be expected?</p>
<ol>
<li>
<p>dedent at the greatest indent column where all lines have a white space.</p>
<p>a tab which includes the column will remain, but spaces between previous tab stop and the column will be removed.<br>
this is the implementation by <a class="user active user-mention" href="https://redmine.ruby-lang.org/users/8977">@bjmllr (Ben Miller)</a>, and results<br>
<code>"\t"+"2 tabs"</code> line and <code>" "*2+"10 spaces"</code> line.</p>
</li>
<li>
<p>dedent at the greatest indent column exclusively tabs</p>
<p>a tab which includes the column will remain, and also spaces before the column will be removed.<br>
this is like <code>kill-rectangle</code> of Emacs, and I've thought this, and results<br>
<code>"\t"+"2 tabs"</code> line and <code>"10 spaces"</code> line.</p>
</li>
<li>
<p>expand tabs first</p>
<p>tabs are expanded first before dedent, and results<br>
<code>" "*6+"2 tabs"</code> line and <code>"10 spaces"</code> line.</p>
</li>
<li>
<p>or, like Andrew M claims, dedent of byte-wise common parts can be an option, I think now.</p>
</li>
</ol> Ruby master - Feature #9098: Indent heredoc against the left margin by default when "indented closing identifier" is turned on.https://redmine.ruby-lang.org/issues/9098?journal_id=552682015-12-07T06:45:14Zmatz (Yukihiro Matsumoto)matz@ruby.or.jp
<ul><li><strong>Assignee</strong> changed from <i>matz (Yukihiro Matsumoto)</i> to <i>nobu (Nobuyoshi Nakada)</i></li></ul><p>Alternative 2 looks good to me.</p>
<p>Matz.</p> Ruby master - Feature #9098: Indent heredoc against the left margin by default when "indented closing identifier" is turned on.https://redmine.ruby-lang.org/issues/9098?journal_id=553112015-12-07T14:40:09Znobu (Nobuyoshi Nakada)nobu@ruby-lang.org
<ul><li><strong>Status</strong> changed from <i>Assigned</i> to <i>Closed</i></li></ul><p>Applied in changeset r52916.</p>
<hr>
<p>parse.y: indented hereoc</p>
<ul>
<li>parse.y: add heredoc <<~ syntax. [Feature <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Feature: Indent heredoc against the left margin by default when "indented closing identifier" is turned on. (Closed)" href="https://redmine.ruby-lang.org/issues/9098">#9098</a>]</li>
</ul> Ruby master - Feature #9098: Indent heredoc against the left margin by default when "indented closing identifier" is turned on.https://redmine.ruby-lang.org/issues/9098?journal_id=553142015-12-07T15:19:03ZAjedi32 (Andrew M)andrewm.bpi@gmail.com
<ul></ul><p>Ah, for some reason I was under the impression that the plan was to use the indentation from the first non-blank line to determine how much to dedent the entire string.</p>
<p>If the plan instead is to use the least-indented non-blank line for that, then the other options make much more sense IMO since there's no way to determine definitively whether leading indention was intended to be removed by Ruby vs used in the string. I actually like this way better come to think of it, since it makes it possible to indent the first line in the string, whereas with the method I was envisioning that would be impossible.</p>
<p>For the record, I'm still in favor of option 4 (or rather, some combination of 4 and 2 which throws an error when their behaviors differ) as I think it's the least likely to result in unexpected behavior for developers, but if Matz has made up his mind I guess there's not much I can do about it. I suppose I'll just have to add a rule to my linter to help prevent those kinds of mistakes.</p>
<p>The results from methods 1, 2, and 4 should always be the same in practice. If they're not, it's almost certainly a case of the developer doing something they didn't intend (a bug).</p> Ruby master - Feature #9098: Indent heredoc against the left margin by default when "indented closing identifier" is turned on.https://redmine.ruby-lang.org/issues/9098?journal_id=553272015-12-08T00:10:00Zusa (Usaku NAKAMURA)usa@garbagecollect.jp
<ul></ul><p>Hey, nobu, write NEWS!!</p> Ruby master - Feature #9098: Indent heredoc against the left margin by default when "indented closing identifier" is turned on.https://redmine.ruby-lang.org/issues/9098?journal_id=553372015-12-08T03:43:39Zmame (Yusuke Endoh)mame@ruby-lang.org
<ul></ul><p>This change actually introduces a syntactic incompatibility. Is this okay? I have not seen any real-life use-case that suffers from this incompatibility, though.</p>
<pre><code>def foo
42
end
BAR = -10
p foo <<~BAR
</code></pre>
<pre><code>$ ruby -v
ruby 2.2.3p173 (2015-08-18 revision 51636) [x86_64-linux]
$ ruby t.rb
21504
</code></pre>
<pre><code>$ ./miniruby -v
ruby 2.3.0dev (2015-12-08 master 52936) [x86_64-linux]
$ ./miniruby t.rb
t.rb:5: can't find string "BAR" anywhere before EOF
t.rb:5: syntax error, unexpected end-of-input
</code></pre>
<p>Ruby syntax is a chaos.</p>
<p>--<br>
Yusuke Endoh <a href="mailto:mame@ruby-lang.org" class="email">mame@ruby-lang.org</a></p>