【问题标题】:Multiline strings with no indent没有缩进的多行字符串
【发布时间】:2016-02-05 06:07:14
【问题描述】:

你如何有一个没有前导空格的多行字符串并且仍然与方法正确对齐?以下是我的一些尝试。工作的那个不是很好玩……

module Something
  def welcome
"
Hello

This is an example.  I have to write this multiline string outside the welcome method
indentation in order for it to be properly formatted on screen. :(
"
  end
end

module Something
  def welcome
    "
    Hello

    This is an example.  I am inside welcome method indentation but for some reason
    I am not working...
    ".ljust(12)
  end
end

module Something
  def welcome
    "Hello\n\n"+
    "This is an example.  I am inside welcome method indentation and properly"+
    "formatted but isn't there a better way?"
  end
end

更新

这是method from the ruby style guide

code = <<-END.gsub(/^\s+\|/, '')
  |def test
  |  some_method
  |  other_method
  |end
END
# => "def test\n  some_method\n  other_method\nend\n"

【问题讨论】:

  • 我认为你不能。这个stackoverflow.com/questions/2337510/… 可能会有所帮助
  • “好玩”有没有关系?是的!
  • 我认为风格指南中的解决方案很好。尽管 Active Record 实现了strip_heredoc,这减轻了痛苦,但它并不能缓解向块中添加新内容的长期问题。使用| 可以很容易地看到边距在哪里。当多人在一个项目上工作时,很容易找到利润是一件好事。不过,我会稍微改变一下模式,改为/^\s*\|/,即使块没有从左边距缩进,它也能工作。

标签: ruby multilinestring


【解决方案1】:

从 Ruby 2.3.0 开始,有一个内置方法:[&lt;&lt;~]

indented = 
<<-EOS
  Hello

  This is an example. I have to write this multiline string outside the welcome method indentation in order for it to be properly formatted on screen. :(
EOS

unindented =
<<~EOS
  Hello

  This is an example. I have to write this multiline string outside the welcome method indentation in order for it to be properly formatted on screen. :(
EOS

puts indented #=>

  Hello

  This is an example. I have to write this multiline string outside the welcome method indentation in order for it to be properly formatted on screen. :(

puts unindented #=>

Hello

This is an example. I have to write this multiline string outside the welcome method indentation in order for it to be properly formatted on screen. :(

Multiline strings in Ruby 2.3 - the squiggly heredoc

【讨论】:

  • 最好强调结束 EOS 也不需要位于行首,因此可以很好地保留周围的缩进。
  • ruby 3 语法更简洁优雅?
【解决方案2】:

RubyTapas Episode 249 中,Avdi Grimm 描述了一种从多行字符串中去除前导空格的技术:

def unindent(s)
  s.gsub(/^#{s.scan(/^[ \t]+(?=\S)/).min}/, '')
end

它的行为与此问题的其他现有解决方案兼容,例如ActiveSupport / Rails 中的String#strip_heredoc 或独立的unindent gem

您可以将此方法与 heredoc 一起使用,这是 ruby​​(和许多其他语言)中的特殊语法来编写多行字符串。

module Something
  def unindent(s)
    s.gsub(/^#{s.scan(/^[ \t]+(?=\S)/).min}/, '')
  end

  def welcome
    unindent(<<-TEXT)
      Hello

      This is an example. This multiline string works
        - even with deeper nestings...
      All is OK here :)
    TEXT
  end
end

【讨论】:

  • 虽然我可以轻松使用active_support/core_ext,但我将使用这种方法。我喜欢它的干爽和直截了当,我可以少一点依赖。阿夫迪就是那个人。感谢@Holger 提出这个问题。
  • @m8ss 既然你提到了 DRYness,只是想指出将方法添加到 String 类实际上是 DRYer(并且更简洁)。这样你就可以在任何地方使用它,而不必需要一个可能与你想在其中使用unindent 方法的模块没有任何关系的模块。附加奖励:就像unindent,它不是一个额外的依赖项 - 只是你的您添加到 String 的自己的方法。
  • 太棒了。感谢您的帮助@jeffdill2。我一定会用这个向前迈进。感谢您自愿抽出时间帮助其他程序员!
  • 标签不会把它扔掉吗?一个制表符是 ASCII 9,而一个空格是 32,所以[" ", " \t "].min #= "\t "。 (" \t" 后面应该有 10 个空格,但 SO 会缩小。)
  • 好吧,如果你在你的公共前缀中混合制表符和空格,这样你的行就有不同的空格前缀,那么无论如何,所有的赌注都没有了,你应该得到你得到的混乱。所以不要使用它并坚持 2 个空格缩进的公认 ruby​​ 标准。无论如何:emacswiki.org/pics/static/TabsSpacesBoth.png
【解决方案3】:

您可以使用 HEREDOC - http://ruby-doc.org/docs/ruby-doc-bundle/Manual/man-1.4/syntax.html#here_doc - 像这样:

def welcome
  <<-"welcome".strip_heredoc
    "
    Hello

    This is an example.  I have to write this multiline string outside the welcome method indentation in order for it to be properly formatted on screen. :(
    "
  welcome
end

并使用strip_heredoc 删除缩进 - http://apidock.com/rails/String/strip_heredoc

注意:

strip_heredoc 仅在您使用 Ruby on Rails(它是 Rails 助手)时可用。如果您只是在纯 Ruby 中构建它,那么很遗憾,strip_heredoc 对您不可用。 :-(

但不要害怕纯粹的 Ruby 用户!您可以简单地从 Rails 中提取 strip_heredoc 的源代码,并通过重新定义 String 类将其添加到 Ruby 中。在这种情况下,您也可以随意调用该方法。 :-)

像这样:

class String
  def strip_it_real_good
    indent = scan(/^[ \t]*(?=\S)/).min.try(:size) || 0
    gsub(/^[ \t]{#{indent}}/, '')
  end
end

def welcome
  <<-"welcome".strip_it_real_good
    "
    Hello

    This is an example.  I have to write this multiline string outside the welcome method indentation in order for it to be properly formatted on screen. :(
    "
  welcome
end

【讨论】:

  • 貌似是关于前导空格的问题
  • 哎呀!对不起,我遗漏了一个重要的部分。答案已更新。
  • 直到strip_heredoc。 ¯\_(ツ)_/¯
  • @m8ss - strip_heredoc 是 Rail 的 Active Support core extensions 的一部分,因此很容易添加到任何 Ruby 脚本中。核心扩展非常有用,应该是任何“普通”Rubyist 工具箱的一部分。
  • 核心扩展的想法是你不必拉入整个库,如果你使用require 'active_support/core_ext',就会发生这种情况。相反,使用 gem 的显式路径并只挑选您想要的添加:require 'active_support/core_ext/string/strip'。这是在每个 AS 方法的文档之后指定的。
【解决方案4】:

我不确定我是否理解这个问题。这个(纯 Ruby)解决方案能满足您的需求吗?

arr = <<-BITTER_END.split("\n")
  Hello
         Testing, testing.
       I assume the least-indented line is to be left-adjusted and the same amount of leading whitespace is to be removed from all other lines.
BITTER_END
undent = arr.map { |line| line[/^\s*/].size }.min
str = arr.map { |s| s[undent..-1] }.join("\n")

puts str
Hello
     Testing, testing.
   I assume the least-indented line is to be left-adjusted and the same amount of leading whitespace is to be removed from all other lines.

【讨论】:

  • 如果您的行具有不同数量的前导空格,则会中断。这通常应该保留以仅删除所有行共有的那部分空白。
  • 谢谢@Holger。正如我所怀疑的那样,我误解了这个问题。我编辑了我的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-04-02
  • 2011-01-31
  • 1970-01-01
  • 1970-01-01
  • 2019-02-04
  • 2019-06-23
相关资源
最近更新 更多