serpent icon indicating copy to clipboard operation
serpent copied to clipboard

[feature request] multi-line on more than one level of depth

Open fab13n opened this issue 12 years ago • 2 comments

It seems that the line option only causes carriage returns between elements of the outermost table. For deeper structures such as ASTs, it seriously impedes readability.

I know it's hard to find heuristics which produce readable results without making the whole algorithm much more complex, but since @agladysh mentioned the issue in #10 and it's also a need of mine, I'm tracing it as a separate issue.

For my use case, having a predicate in the options deciding whether to put a table's content in line on in column would probably be good enough. The kind of predicate I'd use would probably be something like "if the table has no tag field, more than one array-part child and at least one of these children as a depth of at least 3, put children in columns". I'm not concerned with rendering speed.

Here's an example of what I get with Metalua's pretty-printer vs. what Serpent produces:

mlc=require 'metalua.compiler'.new()

ast=mlc:src_to_ast[[
        local who = "world"
        print(string.format("Hello %s", who))
        if who then
            print "foo"
            print "bar"
            print "foo"
            print "bar"
            print "foo"
            print "bar"
        end
]]

print "metalua.pprint:"
pp=require 'metalua.pprint'
pp.print(ast,{ line_max=1, hide_hash=true, metalua_tag=true })

print "\nserpent.block:"
s=require 'serpent'
print(s.block(ast, {rawstring=true, custom=custom, comment=false}))

Result:

metalua.pprint:
{ `Local{ { `Id "who" }, 
          { `String "world" } }, 
  `Call{ `Id "print", 
         `Call{ `Index{ `Id "string", 
                        `String "format" }, 
                `String "Hello %s", 
                `Id "who" } }, 
  `If{ `Id "who", 
       { `Call{ `Id "print", 
                `String "foo" }, 
         `Call{ `Id "print", 
                `String "bar" }, 
         `Call{ `Id "print", 
                `String "foo" }, 
         `Call{ `Id "print", 
                `String "bar" }, 
         `Call{ `Id "print", 
                `String "foo" }, 
         `Call{ `Id "print", 
                `String "bar" } } } }

serpent.block:
{
  `Local{{`Id "who"},{`String "world"}},
  `Call{`Id "print",`Call{`Index{`Id "string",`String "format"},`String "Hello %s",`Id "who"}},
  `If{`Id "who",{`Call{`Id "print",`String "foo"},`Call{`Id "print",`String "bar"},`Call{`Id "print",`String "foo"},`Call{`Id "print",`String "bar"},`Call{`Id "print",`String "foo"},`Call{`Id "print",`String "bar"}}},
}

fab13n avatar Dec 31 '13 12:12 fab13n

Fabien, the block call should already do what you expect to do. For some reason, I get a different output from the same script:

metalua.pprint:
{ `Local{ { `Id "who" }, 
          { `String "world" } }, 
  `Call{ `Id "print", 
         `Call{ `Index{ `Id "string", 
                        `String "format" }, 
                `String "Hello %s", 
                `Id "who" } }, 
  `If{ `Id "who", 
       { `Call{ `Id "print", 
                `String "foo" }, 
         `Call{ `Id "print", 
                `String "bar" }, 
         `Call{ `Id "print", 
                `String "foo" }, 
         `Call{ `Id "print", 
                `String "bar" }, 
         `Call{ `Id "print", 
                `String "foo" }, 
         `Call{ `Id "print", 
                `String "bar" } } } }

serpent.block:
{
  {
    {
      `Id "who",
      lineinfo = <?|L1|C15-17|K15-17>
    },
    {
      `String "world",
      lineinfo = <?|L1|C21-27|K21-27>
    },
    lineinfo = <?|L1|C9-27|K9-27>,
    tag = "Local"
  },
  {
    `Id "print",
    {
      {
        `Id "string",
        `String "format",
        lineinfo = <?|L2|C15-27|K43-55>,
        tag = "Index"
      },
      `String "Hello %s",
      `Id "who",
      lineinfo = <?|L2|C15-44|K43-72>,
      tag = "Call"
    },
    lineinfo = <?|L2|C9-45|K37-73>,
    tag = "Call"
  },
  {
    `Id "who",
    {
      {
        `Id "print",
        `String "foo",
        lineinfo = <?|L4|C13-23|K107-117>,
        tag = "Call"
      },
      {
        `Id "print",
        `String "bar",
        lineinfo = <?|L5|C13-23|K131-141>,
        tag = "Call"
      },
      {
        `Id "print",
        `String "foo",
        lineinfo = <?|L6|C13-23|K155-165>,
        tag = "Call"
      },
      {
        `Id "print",
        `String "bar",
        lineinfo = <?|L7|C13-23|K179-189>,
        tag = "Call"
      },
      {
        `Id "print",
        `String "foo",
        lineinfo = <?|L8|C13-23|K203-213>,
        tag = "Call"
      },
      {
        `Id "print",
        `String "bar",
        lineinfo = <?|L9|C13-23|K227-237>,
        tag = "Call"
      },
      lineinfo = <?|L4-9|C13-23|K107-237>
    },
    lineinfo = <?|L3-10|C9-11|K83-249>,
    tag = "If"
  },
  lineinfo = <?|L1-10|C9-11|K9-249>
}

I just used the code from metalua-parser module from github. Maybe your version has some additional __tostring processing I'm missing?

pkulchenko avatar Jan 09 '14 21:01 pkulchenko

@fab13n, any update on this? I'd like to make sure I'm running the correct code so that I can test on the same fragment you are testing.

pkulchenko avatar Jan 20 '14 05:01 pkulchenko