mirror of
https://github.com/ruby/ruby.git
synced 2025-08-15 21:49:06 +02:00

Previously, trying to round-trip label-list and name-lists with the
ToRdoc converter was not possible:
```ruby
doc = <<~RDOC
foo ::
bar ::
hi
RDOC
markup = RDoc::Markup.parse(doc)
markup # => [doc: [list: NOTE [item: ["foo ", "bar"]; [para: "hi"]]]]
rt = RDoc::Markup::ToRdoc.new.convert(markup)
rt # => "foo\nbar:\n hi\n\n"
rt_markup = RDoc::Markup.parse(rt)
rt_markup # => [doc: [para: "foo ", "bar:"], [verb: "hi\n"]]
```
This commit addresses the issue by fixing ToRdoc to generate output that
can be properly reparsed by RDoc. ToRdoc tests additionally needed to be
updated for the new output.
The old implementation of `accept_list_item_start` was copied to ToBs
because those tests did not pass with the new changes and I am
unfamiliar with the `backspace` format.
After:
```ruby
doc = <<~RDOC
foo ::
bar ::
hi
RDOC
markup = RDoc::Markup.parse(doc)
markup # => [doc: [list: NOTE [item: ["foo ", "bar"]; [para: "hi"]]]]
rt = RDoc::Markup::ToRdoc.new.convert(markup)
rt # => "foo::\nbar::\n hi\n\n"
rt_markup = RDoc::Markup.parse(rt)
rt_markup # => [doc: [list: NOTE [item: ["foo", "bar"]; [para: "hi"], blankline]]]
```
c6c51aa900
102 lines
2.3 KiB
Ruby
102 lines
2.3 KiB
Ruby
# frozen_string_literal: true
|
|
##
|
|
# Outputs RDoc markup with hot backspace action! You will probably need a
|
|
# pager to use this output format.
|
|
#
|
|
# This formatter won't work on 1.8.6 because it lacks String#chars.
|
|
|
|
class RDoc::Markup::ToBs < RDoc::Markup::ToRdoc
|
|
|
|
##
|
|
# Returns a new ToBs that is ready for hot backspace action!
|
|
|
|
def initialize markup = nil
|
|
super
|
|
|
|
@in_b = false
|
|
@in_em = false
|
|
end
|
|
|
|
##
|
|
# Sets a flag that is picked up by #annotate to do the right thing in
|
|
# #convert_string
|
|
|
|
def init_tags
|
|
add_tag :BOLD, '+b', '-b'
|
|
add_tag :EM, '+_', '-_'
|
|
add_tag :TT, '' , '' # we need in_tt information maintained
|
|
end
|
|
|
|
##
|
|
# Makes heading text bold.
|
|
|
|
def accept_heading heading
|
|
use_prefix or @res << ' ' * @indent
|
|
@res << @headings[heading.level][0]
|
|
@in_b = true
|
|
@res << attributes(heading.text)
|
|
@in_b = false
|
|
@res << @headings[heading.level][1]
|
|
@res << "\n"
|
|
end
|
|
|
|
##
|
|
# Prepares the visitor for consuming +list_item+
|
|
|
|
def accept_list_item_start list_item
|
|
type = @list_type.last
|
|
|
|
case type
|
|
when :NOTE, :LABEL then
|
|
bullets = Array(list_item.label).map do |label|
|
|
attributes(label).strip
|
|
end.join "\n"
|
|
|
|
bullets << ":\n" unless bullets.empty?
|
|
|
|
@prefix = ' ' * @indent
|
|
@indent += 2
|
|
@prefix << bullets + (' ' * @indent)
|
|
else
|
|
bullet = type == :BULLET ? '*' : @list_index.last.to_s + '.'
|
|
@prefix = (' ' * @indent) + bullet.ljust(bullet.length + 1)
|
|
width = bullet.length + 1
|
|
@indent += width
|
|
end
|
|
end
|
|
|
|
##
|
|
# Turns on or off regexp handling for +convert_string+
|
|
|
|
def annotate tag
|
|
case tag
|
|
when '+b' then @in_b = true
|
|
when '-b' then @in_b = false
|
|
when '+_' then @in_em = true
|
|
when '-_' then @in_em = false
|
|
end
|
|
''
|
|
end
|
|
|
|
##
|
|
# Calls convert_string on the result of convert_regexp_handling
|
|
|
|
def convert_regexp_handling target
|
|
convert_string super
|
|
end
|
|
|
|
##
|
|
# Adds bold or underline mixed with backspaces
|
|
|
|
def convert_string string
|
|
return string unless @in_b or @in_em
|
|
chars = if @in_b then
|
|
string.chars.map do |char| "#{char}\b#{char}" end
|
|
elsif @in_em then
|
|
string.chars.map do |char| "_\b#{char}" end
|
|
end
|
|
|
|
chars.join
|
|
end
|
|
|
|
end
|