zenspider/enhanced-ruby-mode — pull request #55 by vzvu3k6k (2014-05-17 15:44:56+00:00)
Title: Human-friendly highlight and indentation notation for debugging and testing

This is a proposal of non-nested XML-like notation which expresses how Ruby code is parsed by `ErmBuffer::Parser#parse`. It is intented to be used in debug prints and test assertions.

You can try it by `git clone https://github.com/vzvu3k6k/enhanced-ruby-mode.git -b xml-like-notation`.

`tools/markup.rb` marks up Ruby code with this notation.

## Syntax Highlight

```
$ echo 'puts "Hello, world."' | ruby tools/markup.rb
((21 1 22 )(0 1 6 21 22)(1 7 20)(7 6 7 20 21))
---
<0>puts <7>"<1>Hello, world.<7>"<0>
```

`ErmBuffer::Parser#parse` parses `puts "Hello, world."` as `((21 1 21 )(0 1 6)(1 7 20)(7 6 7 20 21))`. In the new notation, this is represented as `<0>puts <7>"<1>Hello, world.<7>"`, which means `puts ` is highlighted with 0 font lock, `"` is 7, `Hello, world.` is 1, and `"` is 7.

## Indentation

```
$ cats blocks.rb
if foo
bar do |i|
puts 1
end
else
case baz
when quux
foobar {
nil
}
end
end
$ ruby tools/markup.rb blocks.rb --no-highlight
((103 1 104 b 1 d 14 l 17 r 19 e 34 s 38 b 45 s 56 d 77 e 93 e 97 e 101)(0 3 14 16 17 18 19 20 34 37 38 42 45 49 56 60 77 78 85 88 93 94 97 100 101)(3 17 18 19 20)(10 1 3 14 16 34 37 38 42 45 49 56 60 77 78 85 88 93 94 97 100 101 104))
---
<@b>if foo
bar <@d>do <@l>|i<@r>|
puts 1
<@e>end
<@s>else
<@b>case baz
<@s>when quux
foobar <@d>{
nil
<@e>}
<@e>end
<@e>end
```

In this notation, `<@b>` means `indent :b` in `ruby/erm_buffer.rb`, `<@d>` means `indent :d` and so on.

## Assertion

In `test/test_erm_buffer.rb`, assertions are written like

```rb
def test_reset_mode
assert_equal "((32 1 32 d 10 e 22)(0 1 2 8 9 11 14 16 17 19 22)(1 23 24)(3 9 11 22 23)(5 14 16)(11 3 8 24 28)(12 2 3 17 19))",
parse_text(%q{a=<a<12>=<11><
<3>#<@d>{<0>
<5>:x<0> <12>==<0> d
<@e><3>}<1>
<11>END
})
end
```

It is not so beautiful, but it is easier to read and write than raw sexp.

When assertion failed, it prints diffs of the notation and the return value of `ErmBuffer::Parser#parse`.

```
1) Failure:
TestErmBuffer#test_wrong [test/test_erm_buffer.rb:71]:
--- expected
+++ actual
@@ -1,3 +1,3 @@
-<1>puts <11><
+<0>puts <11><
<1>Hello, world.
<11>HERE

--- expected
+++ actual
@@ -1 +1 @@
-"((30 1 31 )(0 12 13)(1 1 6 13 27)(11 6 12 27 31))"
+"((30 1 31 )(0 1 6 12 13)(1 13 27)(11 6 12 27 31))"
```

Implementation of `assert_parse` is in `test/helper.rb`.

## Concerns

### Escaping of characters used in this notation

Currently tags of this notation are represented in the patterns of `/<@(.)>/`, `/<(\w+)>/` or `%r||` (the last one is an optional close tag, which can be removed). They rarely conflict with Ruby syntax, so I don't implement escaping.

But if this notation is expanded (aside from whether it is a good idea), escaping would be needed.