3

我正在尝试使用“method_missing”格式化标签,我想要的结果如下所示。

<foo>\n
    <bar>\n
        <ab/>\n
    </bar>\n
</foo>\n

我认为需要运行索引,但我不清楚最好把它放在哪里,或者这是否是最好的方法。我将如何添加缩进?

def method_missing(meth, *args, &block)
    if args.length > 0
        my_other_method(args)
    else
        my_method(meth.to_s, &block)
    end
end

def my_other_method(args)
    "<#{args}/>"
end

def my_method(meth)     
    s = "<#{meth}>\n"
    s << "#{_indentation}"
    s << yield.to_s << "\n"
    s << "#{_indentation}"
    s << "</#{meth}>\n"
end

def _indentation
    ("--" * _level.to_i)    # dashes added to more easily infer spacing
end

def _level
    caller.rindex {|val| val.scan('my_method')} / 3
end

p foo{bar{baz(:a => "b"){}}}

我得到这个错误的输出(不确定是什么导致了额外的 \n)

<foo>\n
--<bar>\n
----<ab>\n
----</bar>\n
\n
--</foo>\n
4

1 回答 1

1

您可以使用调用堆栈来获取缩进级别。见caller我的代码。我还建议将您的代码隔离在某个类中,以便您可以使用更多标签,因为其中可能定义了很多方法main 所以,我对您的代码进行了一些修改:

class TagFormatter
  def method_missing(method_name, *args, &block)
    _tagify method_name, args, &block
  end

  def _tagify(tag_name, args)
    if block_given?
      s = "#{_indentation}<#{tag_name}#{_attrs args}>\n"
      s << (yield || "")
      s << "#{_indentation}</#{tag_name}>\n"
    else
      "#{_indentation}<#{tag_name}#{_attrs args}/>\n"
    end
  end

  def _indentation
    "    " * _level
  end

  def _level
    caller.index { |val| val =~ /instance_eval/ } / 3 - 1
  end

  def _attrs(args)
    args.map { |arg| _to_attr arg }.join if args
  end

  def _to_attr(arg)
    if arg.kind_of? Hash
      arg.map { |k, v| %Q{ #{k}="#{v}"}}
    else
      %Q{ #{arg.to_s}}
    end
  end
end

例子:

> tf = TagFormatter.new
> puts tf.instance_eval 'foo{bar{baz(:a => "b"){}}}'
<foo>
    <bar>
        <baz a="b">
        </baz>
    </bar>
</foo>
> puts tf.instance_eval 'foo{bar{baz(:a => "b")}}' # no block given in baz
<foo>
    <bar>
        <baz a="b"/>
    </bar>
</foo>
> puts tf.instance_eval 'foo{bar{baz("disabled", :readonly, :a=>"b")}}'
<foo>
    <bar>
        <baz disabled readonly a="b"/>
    </bar>
</foo>
于 2013-06-12T12:03:34.087 回答