YAML: Find line number of key?

Hi there,

I’ve been digging around in Psych’s lowlevel interface the last few
hours, but I couldn’t find what I was looking for. Given this YAML file:

···

------------------------------
foo:
  bar:
    baz: 3
  blubb:
    baz: 4
-------------------------------

How can I find the line number the key(chain) foo-bar-baz is in (that
is, 3 in this case)? I’ve found Psych supports a nice visitor pattern
for parsing, but it seems to not provide the line numbers of the
elements it encounters. So, is there any way (monkey-patching if
necessary) to get the line numbers out of Psych?

Background: I want to programmatically insert comments into an existing
YAML file and as I’ve already found out, inserting comments with Psych
is impossible. That is, I want to say "insert this comment before the
key foo-bar-baz".

Thanks in advance.
Marvin

Hi Marvin,

I don't have experience with psych but taking a look at the
documentation I've managed to do the code bellow.
(Perhaps there's a clever way to do it).
I tried to "craft" a Handler that have access to the Parser instance
so that it could call #mark on it.

Handler

#mark

require 'psych'

class ScalarHandler < Psych::Handler

  def parser=(parser)
    @parser=parser
  end

  def mark
    @parser.mark
  end

  def scalar value, anchor, tag, plain, quoted, style
    p [value, anchor, tag, plain, quoted, style]
    p mark
  end

end

scalar_handler = ScalarHandler.new
parser = Psych::Parser.new(scalar_handler)
scalar_handler.parser = parser

yaml_document = <<END
foo:
  bar:
    baz: 3
  blubb:
    baz: 4
END

parser.parse(yaml_document)

["foo", nil, nil, true, false, 1]
#<struct Psych::Parser::Mark index=4, line=0, column=4>
["bar", nil, nil, true, false, 1]
#<struct Psych::Parser::Mark index=11, line=1, column=6>
["baz", nil, nil, true, false, 1]
#<struct Psych::Parser::Mark index=20, line=2, column=8>
["3", nil, nil, true, false, 1]
#<struct Psych::Parser::Mark index=25, line=3, column=2>
["blubb", nil, nil, true, false, 1]
#<struct Psych::Parser::Mark index=31, line=3, column=8>
["baz", nil, nil, true, false, 1]
#<struct Psych::Parser::Mark index=40, line=4, column=8>
["4", nil, nil, true, false, 1]
#<struct Psych::Parser::Mark index=43, line=5, column=0>

Does this help you start things up?
(Sorry if this is not the point (if I didn't get it right)).

Abinoam Jr.

···

On Fri, Aug 9, 2013 at 12:49 PM, Quintus <quintus@quintilianus.eu> wrote:

Hi there,

I’ve been digging around in Psych’s lowlevel interface the last few
hours, but I couldn’t find what I was looking for. Given this YAML file:

------------------------------
foo:
  bar:
    baz: 3
  blubb:
    baz: 4
-------------------------------

How can I find the line number the key(chain) foo-bar-baz is in (that
is, 3 in this case)? I’ve found Psych supports a nice visitor pattern
for parsing, but it seems to not provide the line numbers of the
elements it encounters. So, is there any way (monkey-patching if
necessary) to get the line numbers out of Psych?

Background: I want to programmatically insert comments into an existing
YAML file and as I’ve already found out, inserting comments with Psych
is impossible. That is, I want to say "insert this comment before the
key foo-bar-baz".

Thanks in advance.
Marvin

This looks very good! Thank you for your help, I’ve even resorted to
writing a minimal YAML-parser for this because I came to the conclusion
the line numbering is hidden away in the C part of Psych (libyaml).

Thanks!
Marvin

···

Am Sun, 11 Aug 2013 00:20:24 -0300 schrieb "Abinoam Jr." <abinoam@gmail.com>:

Hi Marvin,

I don't have experience with psych but taking a look at the
documentation I've managed to do the code bellow.
(Perhaps there's a clever way to do it).
I tried to "craft" a Handler that have access to the Parser instance
so that it could call #mark on it.