Can Ruby's YAML module be used to embed comments?

淺唱寂寞╮ 提交于 2020-01-02 05:12:32

问题


The to_yaml method produces nice YAML output, but I would like to include comment lines before some of the elements. Is there a way to do so?

For example, I would like to produce:

# hostname or IP address of client
client: host4.example.com
# hostname or IP address of server
server: 192.168.222.222

From something similar to:

{
  :client => 'host4.example.com',
  :server => '192.168.222.222',
}.to_yaml

... but am not sure if the YAML module even has a way to accomplish.

UPDATE: I ended up not using the solution which used regexes to insert the comments, since it required the separation of the data from the comments. The easiest and most understandable solution for me is:

require 'yaml'

source = <<SOURCE
# hostname or IP address of client
client: host4.example.com
# hostname or IP address of server
server: 192.168.222.222
SOURCE

conf = YAML::load(source)

puts source

The benefit to me is that nothing is repeated (for example, 'client:' is only specified once), the data and comments are together, the source can be outputted as YAML, and the data structure (available in conf) is available for use.


回答1:


You can do a string replace on all the insertions:

require 'yaml'

source = {
  :client => 'host4.example.com',
  :server => '192.168.222.222',
}.to_yaml

substitution_list = {
  /:client:/ => "# hostname or IP address of client\n:client:",
  /:server:/ => "# hostname or IP address of server\n:server:"
}

substitution_list.each do |pattern, replacement|
  source.gsub!(pattern, replacement)
end

puts source

output:

--- 
# hostname or IP address of client
:client: host4.example.com
# hostname or IP address of server
:server: 192.168.222.222



回答2:


Something like this:

my_hash = {a: 444}
y=YAML::Stream.new()
y.add(my_hash)
y.emit("# this is a comment")

Of course, you will need to walk the input hash yourself and either add() or emit() as needed. You could look at the source of the to_yaml method for a quick start.




回答3:


This isn't perfect (no mid-Array support, for example), but it works for my needs.

  def commentify_yaml(db)
    ret = []
    db.to_yaml(line_width: -1).each_line do |l|
      if l.match(/^\s*:c\d+:/)
        l = l.sub(/:c(\d+)?:/, '#').
            sub(/(^\s*# )["']/, '\1').
            sub(/["']\s*$/, '').
            gsub(/''(\S+?)''/, "'\\1'").
            gsub(/(\S)''/, "\\1'")
      end
      ret << l.chomp
    end
    ret * "\n"
  end

Example usage.

commentify_yaml(
  {
    c1: 'Comment line 1',
    c2: 'Comment line 2',
    'hash_1' => {
      c1: 'Foo',
      c2: 'Bar',
      'key_1' => "Hello!",
    },
    'baz' => qux,
    c3: 'Keep up-numbering the comments in the same hash',
    'array_1' => [
       1,
       2,
       3
     ]
  }
)

==>

# Comment line 1
# Comment line 2
hash_1:
  # Foo
  # Bar
  key_1: "Hello!"
baz: "Value of qux"
# Keep up-numbering the comments in the same hash
array_1:
- 1
- 2
- 3

(Note: Syck does not indent arrays they way it arguably should.)



来源:https://stackoverflow.com/questions/14149570/can-rubys-yaml-module-be-used-to-embed-comments

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!