Class: RailroadDiagrams::TextDiagram
- Inherits:
-
Object
- Object
- RailroadDiagrams::TextDiagram
- Defined in:
- lib/railroad_diagrams/text_diagram.rb
Constant Summary collapse
- PARTS_UNICODE =
{ 'cross_diag' => '╳', 'corner_bot_left' => '└', 'corner_bot_right' => '┘', 'corner_top_left' => '┌', 'corner_top_right' => '┐', 'cross' => '┼', 'left' => '│', 'line' => '─', 'line_vertical' => '│', 'multi_repeat' => '↺', 'rect_bot' => '─', 'rect_bot_dashed' => '┄', 'rect_bot_left' => '└', 'rect_bot_right' => '┘', 'rect_left' => '│', 'rect_left_dashed' => '┆', 'rect_right' => '│', 'rect_right_dashed' => '┆', 'rect_top' => '─', 'rect_top_dashed' => '┄', 'rect_top_left' => '┌', 'rect_top_right' => '┐', 'repeat_bot_left' => '╰', 'repeat_bot_right' => '╯', 'repeat_left' => '│', 'repeat_right' => '│', 'repeat_top_left' => '╭', 'repeat_top_right' => '╮', 'right' => '│', 'roundcorner_bot_left' => '╰', 'roundcorner_bot_right' => '╯', 'roundcorner_top_left' => '╭', 'roundcorner_top_right' => '╮', 'roundrect_bot' => '─', 'roundrect_bot_dashed' => '┄', 'roundrect_bot_left' => '╰', 'roundrect_bot_right' => '╯', 'roundrect_left' => '│', 'roundrect_left_dashed' => '┆', 'roundrect_right' => '│', 'roundrect_right_dashed' => '┆', 'roundrect_top' => '─', 'roundrect_top_dashed' => '┄', 'roundrect_top_left' => '╭', 'roundrect_top_right' => '╮', 'separator' => '─', 'tee_left' => '┤', 'tee_right' => '├' }.freeze
- PARTS_ASCII =
{ 'cross_diag' => 'X', 'corner_bot_left' => '\\', 'corner_bot_right' => '/', 'corner_top_left' => '/', 'corner_top_right' => '\\', 'cross' => '+', 'left' => '|', 'line' => '-', 'line_vertical' => '|', 'multi_repeat' => '&', 'rect_bot' => '-', 'rect_bot_dashed' => '-', 'rect_bot_left' => '+', 'rect_bot_right' => '+', 'rect_left' => '|', 'rect_left_dashed' => '|', 'rect_right' => '|', 'rect_right_dashed' => '|', 'rect_top' => '-', 'rect_top_dashed' => '-', 'rect_top_left' => '+', 'rect_top_right' => '+', 'repeat_bot_left' => '\\', 'repeat_bot_right' => '/', 'repeat_left' => '|', 'repeat_right' => '|', 'repeat_top_left' => '/', 'repeat_top_right' => '\\', 'right' => '|', 'roundcorner_bot_left' => '\\', 'roundcorner_bot_right' => '/', 'roundcorner_top_left' => '/', 'roundcorner_top_right' => '\\', 'roundrect_bot' => '-', 'roundrect_bot_dashed' => '-', 'roundrect_bot_left' => '\\', 'roundrect_bot_right' => '/', 'roundrect_left' => '|', 'roundrect_left_dashed' => '|', 'roundrect_right' => '|', 'roundrect_right_dashed' => '|', 'roundrect_top' => '-', 'roundrect_top_dashed' => '-', 'roundrect_top_left' => '/', 'roundrect_top_right' => '\\', 'separator' => '-', 'tee_left' => '|', 'tee_right' => '|' }.freeze
Class Attribute Summary collapse
-
.parts ⇒ Object
Returns the value of attribute parts.
Instance Attribute Summary collapse
-
#entry ⇒ Object
readonly
Returns the value of attribute entry.
-
#exit ⇒ Object
readonly
Returns the value of attribute exit.
-
#height ⇒ Object
readonly
Returns the value of attribute height.
-
#lines ⇒ Object
readonly
Returns the value of attribute lines.
-
#width ⇒ Object
readonly
Returns the value of attribute width.
Class Method Summary collapse
- .enclose_lines(lines, lefts, rights) ⇒ Object
- .gaps(outer_width, inner_width) ⇒ Object
- .get_parts(part_names) ⇒ Object
- .max_width(*args) ⇒ Object
- .pad_l(string, width, pad) ⇒ Object
- .pad_r(string, width, pad) ⇒ Object
- .rect(item, dashed: false) ⇒ Object
- .round_rect(item, dashed: false) ⇒ Object
- .set_formatting(characters = nil, defaults = nil) ⇒ Object
Instance Method Summary collapse
- #alter(new_entry: nil, new_exit: nil, new_lines: nil) ⇒ Object
- #append_below(item, lines_between, move_entry: false, move_exit: false) ⇒ Object
- #append_right(item, chars_between) ⇒ Object
- #center(new_width, pad = ' ') ⇒ Object
- #copy ⇒ Object
- #dump(show = true) ⇒ Object
- #expand(left, right, top, bottom) ⇒ Object
-
#initialize(entry, exit, lines) ⇒ TextDiagram
constructor
A new instance of TextDiagram.
Constructor Details
#initialize(entry, exit, lines) ⇒ TextDiagram
Returns a new instance of TextDiagram.
247 248 249 250 251 252 253 254 255 256 257 258 259 260 |
# File 'lib/railroad_diagrams/text_diagram.rb', line 247 def initialize(entry, exit, lines) @entry = entry @exit = exit @lines = lines.dup @height = lines.size @width = lines.any? ? lines[0].length : 0 raise "Entry is not within diagram vertically:\n#{dump(false)}" unless entry <= lines.length raise "Exit is not within diagram vertically:\n#{dump(false)}" unless exit <= lines.length lines.each do |line| raise "Diagram data is not rectangular:\n#{dump(false)}" unless lines[0].length == line.length end end |
Class Attribute Details
.parts ⇒ Object
Returns the value of attribute parts.
108 109 110 |
# File 'lib/railroad_diagrams/text_diagram.rb', line 108 def parts @parts end |
Instance Attribute Details
#entry ⇒ Object (readonly)
Returns the value of attribute entry.
245 246 247 |
# File 'lib/railroad_diagrams/text_diagram.rb', line 245 def entry @entry end |
#exit ⇒ Object (readonly)
Returns the value of attribute exit.
245 246 247 |
# File 'lib/railroad_diagrams/text_diagram.rb', line 245 def exit @exit end |
#height ⇒ Object (readonly)
Returns the value of attribute height.
245 246 247 |
# File 'lib/railroad_diagrams/text_diagram.rb', line 245 def height @height end |
#lines ⇒ Object (readonly)
Returns the value of attribute lines.
245 246 247 |
# File 'lib/railroad_diagrams/text_diagram.rb', line 245 def lines @lines end |
#width ⇒ Object (readonly)
Returns the value of attribute width.
245 246 247 |
# File 'lib/railroad_diagrams/text_diagram.rb', line 245 def width @width end |
Class Method Details
.enclose_lines(lines, lefts, rights) ⇒ Object
165 166 167 168 169 170 171 |
# File 'lib/railroad_diagrams/text_diagram.rb', line 165 def enclose_lines(lines, lefts, rights) unless lines.length == lefts.length && lines.length == rights.length raise 'All arguments must be the same length' end lines.each_with_index.map { |line, i| lefts[i] + line + rights[i] } end |
.gaps(outer_width, inner_width) ⇒ Object
173 174 175 176 177 178 179 180 181 182 183 184 185 |
# File 'lib/railroad_diagrams/text_diagram.rb', line 173 def gaps(outer_width, inner_width) diff = outer_width - inner_width case INTERNAL_ALIGNMENT when 'left' [0, diff] when 'right' [diff, 0] else left = diff / 2 right = diff - left [left, right] end end |
.get_parts(part_names) ⇒ Object
161 162 163 |
# File 'lib/railroad_diagrams/text_diagram.rb', line 161 def get_parts(part_names) part_names.map { |name| @parts[name] } end |
.max_width(*args) ⇒ Object
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/railroad_diagrams/text_diagram.rb', line 128 def max_width(*args) max_width = 0 args.each do |arg| width = case arg when TextDiagram arg.width when Array arg.map(&:length).max when Numeric arg.to_s.length else arg.length end max_width = width if width > max_width end max_width end |
.pad_l(string, width, pad) ⇒ Object
147 148 149 150 151 152 |
# File 'lib/railroad_diagrams/text_diagram.rb', line 147 def pad_l(string, width, pad) gap = width - string.length raise "Gap #{gap} must be a multiple of pad string '#{pad}'" unless (gap % pad.length).zero? (pad * (gap / pad.length)) + string end |
.pad_r(string, width, pad) ⇒ Object
154 155 156 157 158 159 |
# File 'lib/railroad_diagrams/text_diagram.rb', line 154 def pad_r(string, width, pad) gap = width - string.length raise "Gap #{gap} must be a multiple of pad string '#{pad}'" unless (gap % pad.length).zero? string + (pad * (gap / pad.length)) end |
.rect(item, dashed: false) ⇒ Object
120 121 122 |
# File 'lib/railroad_diagrams/text_diagram.rb', line 120 def rect(item, dashed: false) rectish('rect', item, dashed) end |
.round_rect(item, dashed: false) ⇒ Object
124 125 126 |
# File 'lib/railroad_diagrams/text_diagram.rb', line 124 def round_rect(item, dashed: false) rectish('roundrect', item, dashed) end |
.set_formatting(characters = nil, defaults = nil) ⇒ Object
110 111 112 113 114 115 116 117 118 |
# File 'lib/railroad_diagrams/text_diagram.rb', line 110 def set_formatting(characters = nil, defaults = nil) return unless characters @parts = defaults ? defaults.dup : {} @parts.merge!(characters) @parts.each do |name, value| raise ArgumentError, "Text part #{name} is more than 1 character: #{value}" if value.size != 1 end end |
Instance Method Details
#alter(new_entry: nil, new_exit: nil, new_lines: nil) ⇒ Object
262 263 264 265 266 267 268 |
# File 'lib/railroad_diagrams/text_diagram.rb', line 262 def alter(new_entry: nil, new_exit: nil, new_lines: nil) self.class.new( new_entry || @entry, new_exit || @exit, new_lines || @lines.dup ) end |
#append_below(item, lines_between, move_entry: false, move_exit: false) ⇒ Object
270 271 272 273 274 275 276 277 278 279 280 |
# File 'lib/railroad_diagrams/text_diagram.rb', line 270 def append_below(item, lines_between, move_entry: false, move_exit: false) new_width = [@width, item.width].max new_lines = center(new_width).lines lines_between.each { |line| new_lines << TextDiagram.pad_r(line, new_width, ' ') } new_lines += item.center(new_width).lines new_entry = move_entry ? @height + lines_between.size + item.entry : @entry new_exit = move_exit ? @height + lines_between.size + item.exit : @exit self.class.new(new_entry, new_exit, new_lines) end |
#append_right(item, chars_between) ⇒ Object
282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 |
# File 'lib/railroad_diagrams/text_diagram.rb', line 282 def append_right(item, chars_between) join_line = [@exit, item.entry].max new_height = [@height - @exit, item.height - item.entry].max + join_line left = (0, 0, join_line - @exit, new_height - @height - (join_line - @exit)) right = item.(0, 0, join_line - item.entry, new_height - item.height - (join_line - item.entry)) new_lines = (0...new_height).map do |i| sep = i == join_line ? chars_between : ' ' * chars_between.size left_line = i < left.lines.size ? left.lines[i] : ' ' * left.width right_line = i < right.lines.size ? right.lines[i] : ' ' * right.width "#{left_line}#{sep}#{right_line}" end self.class.new( @entry + (join_line - @exit), item.exit + (join_line - item.entry), new_lines ) end |
#center(new_width, pad = ' ') ⇒ Object
303 304 305 306 307 308 309 310 311 312 313 |
# File 'lib/railroad_diagrams/text_diagram.rb', line 303 def center(new_width, pad = ' ') raise 'Cannot center into smaller width' if width < @width return copy if new_width == @width total_padding = new_width - @width left_width = total_padding / 2 left = [pad * left_width] * @height right = [pad * (total_padding - left_width)] * @height self.class.new(@entry, @exit, self.class.enclose_lines(@lines, left, right)) end |
#copy ⇒ Object
315 316 317 |
# File 'lib/railroad_diagrams/text_diagram.rb', line 315 def copy self.class.new(@entry, @exit, @lines.dup) end |
#dump(show = true) ⇒ Object
340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 |
# File 'lib/railroad_diagrams/text_diagram.rb', line 340 def dump(show = true) result = "height=#{@height}; len(lines)=#{@lines.length}" result += "; entry outside diagram: entry=#{@ntry}" if @entry > @lines.length result += "; exit outside diagram: exit=#{@exit}" if @exit > @lines.length (0...[@lines.length, @entry + 1, @exit + 1].max).each do |y| result += "\n[#{format('%03d', y)}]" result += " '#{@lines[y]}' len=#{@lines[y].length}" if y < @lines.length if y == @entry && y == @exit result += ' <- entry, exit' elsif y == @entry result += ' <- entry' elsif y == @exit result += ' <- exit' end end if show puts result else result end end |
#expand(left, right, top, bottom) ⇒ Object
319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 |
# File 'lib/railroad_diagrams/text_diagram.rb', line 319 def (left, right, top, bottom) return copy if [left, right, top, bottom].all?(&:zero?) new_lines = [] top.times { new_lines << (' ' * (@width + left + right)) } @lines.each do |line| left_part = (line == @lines[@entry] ? self.class.parts['line'] : ' ') * left right_part = (line == @lines[@exit] ? self.class.parts['line'] : ' ') * right new_lines << "#{left_part}#{line}#{right_part}" end bottom.times { new_lines << (' ' * (@width + left + right)) } self.class.new( @entry + top, @exit + top, new_lines ) end |