【问题标题】:How do I remove leading whitespace from a Ruby Heredoc, while maintaing 2 leading spaces如何从 Ruby Heredoc 中删除前导空格,同时保持 2 个前导空格
【发布时间】:2012-07-15 15:01:33
【问题描述】:

How do I remove leading whitespace chars from Ruby HEREDOC? 部分回答了这个问题

在 Rails 3 中有一个方法#strip_heredoc,可以去除所有空格。 但是在现有文件中插入行时,已经有标识,这不太好用。一个例子:

begin
  insert_into_file "#{app_name}/config/environments/production.rb", <<-DEVISE_MAILER_STUFF.strip_heredoc, :before => "end\n"
    # for devise
    config.action_mailer.default_url_options = { :protocol => 'https', :host => 'YOURHOSTNAME' }
    config.action_mailer.delivery_method = :smtp
    something.each do |x|
      do stuff
    end
  DEVISE_MAILER_STUFF
end

添加'begin'和'end'只是为了表明源代码有缩进。 heredoc 在“# for devise”行之前有 4 个空格。 @strip_heredoc 将删除所有这些空格,但会保留 'do stuff' 行中的两个额外空格。

environments/production.rb 中,这将如下所示:

MyApp::Application.configure do
  # Settings specified here will take precedence over those in config/application.rb
  # *** Identation here is two spaces! (We are in a block.) ***

# for devise
config.action_mailer.default_url_options = { :protocol => 'https', :host => 'YOURHOSTNAME' }
config.action_mailer.delivery_method = :smtp
something.each do |x|
  do stuff
end

  # back to original identation of this file
end # MyApp::Application.configure block!

如何解决这个问题? 也许还有其他方法而不是heredoc? 我想也许strip_heredoc(min) 其中min 是要保留的最小空间,但我猜这不适用于制表符。或者让heredoc的第一行确定左边距,像这样:

puts <<-HEREDOC
  FIRST_LINE
    Real code here
HEREDOC

strip_heredoc 将删除“FIRST_LINE”,但它也会设置需要删除的空格/空白的数量。所以输出会在'Real code here'前面有2个空格。

更新:可能是这样的:

String.class_eval do
  def strip_heredoc_with_indent(indent=0)
    new_indent = ( self.empty? ? 0 : ( scan(/^[ \t]*(?=\S)/).min.size - indent ) )
    gsub(/^[ \t]{#{new_indent}}/, '')
  end
end

【问题讨论】:

标签: ruby whitespace heredoc thor


【解决方案1】:

按照here 的描述,我选择了strip_heredoc_with_indent(indent)

【讨论】:

  • These techniques 也是值得注意的,不要介意语言障碍。我在页面上的最后一个解决方案上取得了成功(搜索 Twitter 提及)。
【解决方案2】:

自己剥。

insert_into_file "#{app_name}/config/environments/production.rb",
                 <<-DEVISE_MAILER_STUFF.gsub(/^  /, ''), :before => "end\n"
  ...
DEVISE_MAILER_STUFF

这表示在每一行的开头,用空字符串替换两个空格。它很简单,很容易理解,很容易修复或改变。


或者,您可以在模板中执行此操作,但我不知道您是否真的在使用模板,或者您是否正在以某种方式解析文件并替换行(提示,您可能应该使用模板)。


“我想可能是 strip_heredoc(min),其中 min 是要保留的最小空格,但我猜这不适用于制表符。”

Ruby 标准是两个空格。即使不是,标签总是把一切搞砸。使用空格。


关于您的更新

这很复杂。您需要这样的通用解决方案吗?你在很多地方都这样做吗?或者在你不能只看一眼就看gsub多少的地方?此外,扩展核心类是一种危险的游戏,我看到代码库卡在 Rails 1 和定制的 Ruby 1.8 上,因为它们对改变内置行为过于漫不经心。当它改变时,他们无法随之改变。我知道 Rails 可以做到,但 Rails 并不是最佳实践的良好参考。

它也有一些潜在的错误:

  • 当给定这个字符串并且不传递任何参数时,它应该怎么做? " a\n\n b" 我什么也不期待,因为最短的行是空行,所以你的 new_indent 应该是零,但它会是一。
  • 当他们传入的缩进超过scan(...).min.size时会发生什么?
  • 如果他们传递了负面的东西会发生什么?

在我看来,这最终似乎是一个复杂的解决方案,而且永远不可能真正正确,它将使用它的任何代码与这个应用程序相结合,而所有这些实际上可能并不是必需的。

【讨论】:

  • 感谢您抽出宝贵时间回答这个问题。但是,当我将代码包装在一个模块中时,在我的 IDE 中按 Alt-Shift-F,然后所有内容都会向右移动 2 个间隔。这意味着 gsub(/^ /, '') 不会再切蛋糕了。如果有人输入负数,或者缩进超过计算的最小缩进,你是对的。这将导致负 new_indent,这可能在正则表达式中没有任何作用。不给定参数时,缩进默认为 0。根据最短的行,new_indent 将为 1,但空行没有空格,因此正则表达式不会做任何事情。
  • 实际上,要让第一行成为“空”行,需要添加空格。这也是 AFAIK 的 rails strip_heredoc 中的一个奇怪之处。
【解决方案3】:

您可以使用某种分隔符来指示左边距。

def heredoc_with_margin()
  doc = <<-EOT.gsub(/^\s*\|/, '')
    |top:
    |  sub-one:
    |    sub-sub-one
    |  sub-two:
    |    sub-sub-two
    EOT
  return doc
end

【讨论】:

    猜你喜欢
    • 2011-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-12
    • 2014-08-22
    相关资源
    最近更新 更多