Class: Oppen::Wadler

Inherits:
Object
  • Object
show all
Defined in:
lib/wadler/print.rb

Overview

Wadler.

Defined Under Namespace

Classes: Wrap

Instance Attribute Summary collapse

Convenience Methods Built On {separate} collapse

Convenience Methods Built On {surround} collapse

Instance Method Summary collapse

Constructor Details

#initialize(base_indent: 0, config: Config.wadler, indent: 0, new_line: "\n", out: StringIO.new, space_gen: ' ', whitespace: ' ', width: 80) ⇒ Wadler

Returns a new instance of Wadler.

Parameters:

  • base_indent (Integer) (defaults to: 0)

    the starting indentation level for the whole printer.

  • config (Config) (defaults to: Config.wadler)

    to customize the printer's behavior.

  • indent (Integer) (defaults to: 0)

    the default indentation amount for #group and #nest.

  • new_line (String) (defaults to: "\n")

    the new line String.

  • out (Object) (defaults to: StringIO.new)

    the output string buffer. It should have a write and string methods.

  • space_gen (String, Proc) (defaults to: ' ')

    indentation string or a string generator.

    • If a String, spaces will be generated with the the lambda ->(n){ space * n }, where n is the number of columns to indent.
    • If a Proc, it will receive n and it needs to return a String.
  • whitespace (String) (defaults to: ' ')

    the whitespace character. Used to trim trailing whitespaces.

  • width (Integer) (defaults to: 80)

    maximum line width desired.

See Also:



51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/wadler/print.rb', line 51

def initialize(base_indent: 0, config: Config.wadler, indent: 0, new_line: "\n",
               out: StringIO.new, space_gen: ' ',
               whitespace: ' ', width: 80)
  @config = config
  @current_indent = base_indent
  @indent = indent
  @new_line = new_line
  @out = out
  @space_gen = space_gen
  @tokens = []
  @whitespace = whitespace
  @width = width
end

Instance Attribute Details

#configConfig (readonly)

Returns The printer's configuration, altering its behavior.

Returns:

  • (Config)

    The printer's configuration, altering its behavior.



9
10
11
# File 'lib/wadler/print.rb', line 9

def config
  @config
end

#current_indentInteger (readonly)

Returns the current indentation amount.

Returns:

  • (Integer)

    the current indentation amount.



12
13
14
# File 'lib/wadler/print.rb', line 12

def current_indent
  @current_indent
end

#new_lineString (readonly)

Returns the new line string, e.g. \n.

Returns:

  • (String)

    the new line string, e.g. \n.



15
16
17
# File 'lib/wadler/print.rb', line 15

def new_line
  @new_line
end

#outObject (readonly)

Returns the output string buffer. It should have a write and string methods.

Returns:

  • (Object)

    the output string buffer. It should have a write and string methods.



18
19
20
# File 'lib/wadler/print.rb', line 18

def out
  @out
end

#space_genProc (readonly)

Returns space generator, a callable.

Returns:

  • (Proc)

    space generator, a callable.



21
22
23
# File 'lib/wadler/print.rb', line 21

def space_gen
  @space_gen
end

#tokensArray<Token> (readonly)

Returns the tokens list that is being built.

Returns:

  • (Array<Token>)

    the tokens list that is being built.



24
25
26
# File 'lib/wadler/print.rb', line 24

def tokens
  @tokens
end

#whitespaceString (readonly)

Returns the whitespace character. Used to trim trailing whitespaces.

Returns:

  • (String)

    the whitespace character. Used to trim trailing whitespaces.



27
28
29
# File 'lib/wadler/print.rb', line 27

def whitespace
  @whitespace
end

#widthInteger (readonly)

Returns maximum line width.

Returns:

  • (Integer)

    maximum line width.



30
31
32
# File 'lib/wadler/print.rb', line 30

def width
  @width
end

Instance Method Details

#add_missing_begin_and_endNil

Returns:

  • (Nil)


68
69
70
71
72
# File 'lib/wadler/print.rb', line 68

def add_missing_begin_and_end
  tokens.unshift Oppen.begin_consistent(offset: 0)
  tokens << Oppen.end
  tokens << Oppen.eof if !tokens.last.is_a?(Oppen::Token::EOF)
end

#angles(padding: '', **kwargs, &block) ⇒ self

#surround with < >. New lines can appear after and before the delimiters.

Parameters:

  • padding (String) (defaults to: '')

    ('') Passed to lft_breakable and rgt_breakable.

Returns:

  • (self)


626
627
628
629
630
631
632
# File 'lib/wadler/print.rb', line 626

def angles(padding: '', **kwargs, &block)
  surround(
    '<', '>',
    **kwargs.merge(lft_breakable: padding, rgt_breakable: padding),
    &block
  )
end

#angles_break_both(**kwargs) ⇒ self

#surround with < >. New lines cannot appear after and before the delimiters.

Returns:

  • (self)


637
638
639
# File 'lib/wadler/print.rb', line 637

def angles_break_both(**kwargs, &)
  angles(**kwargs.merge(lft_force_break: true, rgt_force_break: true), &)
end

#angles_break_none(**kwargs) ⇒ self

#surround with < >. New lines will appear after and before the delimiters.

Returns:

  • (self)


644
645
646
# File 'lib/wadler/print.rb', line 644

def angles_break_none(**kwargs, &)
  angles(**kwargs.merge(lft_can_break: false, rgt_can_break: false), &)
end

#backticks(**kwargs) ⇒ self

#surround with ` `. New lines cannot appear after and before the delimiters unless you specify it with rgt_can_break and lft_can_break.

Returns:

  • (self)


736
737
738
# File 'lib/wadler/print.rb', line 736

def backticks(**kwargs, &)
  surround('`', '`', lft_can_break: false, rgt_can_break: false, **kwargs, &)
end

#braces(padding: '', **kwargs, &block) ⇒ self

#surround with { }. New lines can appear after and before the delimiters.

Parameters:

  • padding (String) (defaults to: '')

    ('') Passed to lft_breakable and rgt_breakable.

Returns:

  • (self)


654
655
656
657
658
659
660
# File 'lib/wadler/print.rb', line 654

def braces(padding: '', **kwargs, &block)
  surround(
    '{', '}',
    **kwargs.merge(lft_breakable: padding, rgt_breakable: padding),
    &block
  )
end

#braces_break_both(**kwargs) ⇒ self

#surround with { }. New lines cannot appear after and before the delimiters.

Returns:

  • (self)


665
666
667
# File 'lib/wadler/print.rb', line 665

def braces_break_both(**kwargs, &)
  braces(**kwargs.merge(lft_force_break: true, rgt_force_break: true), &)
end

#braces_break_none(**kwargs) ⇒ self

#surround with { }. New lines will appear after and before the delimiters.

Returns:

  • (self)


672
673
674
# File 'lib/wadler/print.rb', line 672

def braces_break_none(**kwargs, &)
  braces(**kwargs.merge(lft_can_break: false, rgt_can_break: false), &)
end

#brackets(padding: '', **kwargs, &block) ⇒ self

#surround with [ ]. New lines can appear after and before the delimiters.

Parameters:

  • padding (String) (defaults to: '')

    ('') Passed to lft_breakable and rgt_breakable.

Returns:

  • (self)


682
683
684
685
686
687
688
# File 'lib/wadler/print.rb', line 682

def brackets(padding: '', **kwargs, &block)
  surround(
    '[', ']',
    **kwargs.merge(lft_breakable: padding, rgt_breakable: padding),
    &block
  )
end

#brackets_break_both(**kwargs) ⇒ self

#surround with [ ]. New lines cannot appear after and before the delimiters.

Returns:

  • (self)


693
694
695
# File 'lib/wadler/print.rb', line 693

def brackets_break_both(**kwargs, &)
  brackets(**kwargs.merge(lft_force_break: true, rgt_force_break: true), &)
end

#brackets_break_none(**kwargs) ⇒ self

#surround with [ ]. New lines will appear after and before the delimiters.

Returns:

  • (self)


700
701
702
# File 'lib/wadler/print.rb', line 700

def brackets_break_none(**kwargs, &)
  brackets(**kwargs.merge(lft_can_break: false, rgt_can_break: false), &)
end

#break(line_continuation: '') ⇒ self

Create a new break element.

Examples:

out = Oppen::Wadler.new
out.text 'a'
out.break
out.text 'b'
out.break line_continuation: '#'
out.text 'c'
puts out.output

# =>
# a
# b#
# c

Parameters:

  • line_continuation (String) (defaults to: '')

    printed before the line break.

Returns:

  • (self)


372
373
374
375
# File 'lib/wadler/print.rb', line 372

def break(line_continuation: '')
  tokens << Oppen.line_break(line_continuation:, offset: current_indent)
  self
end

#breakable(str = ' ', line_continuation: '', width: str.length) ⇒ self

Create a new breakable element.

Parameters:

  • str (String) (defaults to: ' ')

    the value of the token that will be displayed if no new line is needed.

  • line_continuation (String) (defaults to: '')

    printed before the line break.

  • width (Integer) (defaults to: str.length)

    the width of the token.

Returns:

  • (self)

See Also:



347
348
349
350
# File 'lib/wadler/print.rb', line 347

def breakable(str = ' ', line_continuation: '', width: str.length)
  tokens << Oppen.break(str, width:, line_continuation:, offset: current_indent)
  self
end

#concat(*args, **kwargs) ⇒ Object

Concatenates args.

This is a wrapper around #separate where breakable: false.

See Also:

  • [separate]


610
611
612
# File 'lib/wadler/print.rb', line 610

def concat(*args, **kwargs, &)
  separate(*args, **kwargs.merge(breakable: false), &)
end

#consistentObject

An alias for group(:consistent, ...)



237
238
239
# File 'lib/wadler/print.rb', line 237

def consistent(...)
  group(:consistent, ...)
end

#do { ... } ⇒ self

A convenient way to avoid breaking chains of calls.

Examples:

out
  .do { fn_call(fn_arg) }
  .breakable
  .text('=')
  .breakable
  .do { fn_call(fn_arg) }

Yields:

  • to execute the passed block

Returns:

  • (self)


390
391
392
393
# File 'lib/wadler/print.rb', line 390

def do
  yield
  self
end

#group(break_type = :consistent, delim: nil, indent: @indent) { ... } ⇒ self

Create a new group.

Examples:

1 String Delimiter

out = Oppen::Wadler.new
out
  .text('a')
  .group(indent: 2, delim: '|') {
    out.break.text 'b'
  }
puts out.output

# =>
# a
#   |
#   b
#   |

1 Delimiter in Array

out = Oppen::Wadler.new
out
  .text('a')
  .group(indent: 2, delim: ['|']) {
    out.break.text 'b'
  }
puts out.output

# =>
# a
#   |
#   b

2 Delimiters

out = Oppen::Wadler.new
out
  .text('a')
  .group(indent: 2, delim: %i[{ }]) {
    out.break.text 'b'
  }
puts out.output

# =>
# a
#   {
#   b
#   }

Consistent Breaking

out = Oppen::Wadler.new
out.group(:consistent) {
  out.text('a').break.text('b').breakable.text('c')
}
puts out.output

# =>
# a
# b
# c

Inconsistent Breaking

out = Oppen::Wadler.new
out.group(:inconsistent) {
  out.text('a').break.text('b').breakable.text('c')
}
puts out.output

# =>
# a
# b c

Parameters:

  • indent (Integer) (defaults to: @indent)

    indentation.

  • delim (Nil|String|Symbol|Array<Nil, String, Symbol>) (defaults to: nil)

    delimiters, to be printed at the start and the end of the group:

    • If it's nil, nothing will be printed
    • If it's a Strings or a Symbol, it will be printed at both positions.
    • If it's an Array of many items, the first two elements will be used for the start and end of the group.
  • break_type (Token::BreakType) (defaults to: :consistent)

    break type.

Yields:

  • the block of text in a group.

Returns:

  • (self)

See Also:



203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
# File 'lib/wadler/print.rb', line 203

def group(break_type = :consistent, delim: nil, indent: @indent)
  lft, rgt =
    case delim
    in nil then ['', '']
    in String | Symbol then [delim, delim]
    in Array then delim.values_at(0, 1).map(&:to_s)
    end

  tokens <<
    case break_type
    in :consistent
      Oppen.begin_consistent(offset: indent)
    in :inconsistent
      Oppen.begin_inconsistent(offset: indent)
    end

  if !lft.empty?
    self.break
    text lft
  end

  yield

  if !rgt.empty?
    self.break
    text rgt
  end

  tokens << Oppen.end

  self
end

#group_closeself

Close a group.

Returns:

  • (self)


779
780
781
782
# File 'lib/wadler/print.rb', line 779

def group_close
  tokens << Oppen.end
  self
end

#group_open(break_type: :consistent, indent: 0) ⇒ self

Open a consistent group.

Parameters:

  • break_type (Symbol) (defaults to: :consistent)

    :consistent or :inconsistent

  • indent (Integer) (defaults to: 0)

    the amount of indentation of the group.

Returns:

  • (self)

See Also:



767
768
769
770
771
772
773
774
# File 'lib/wadler/print.rb', line 767

def group_open(break_type: :consistent, indent: 0)
  if %i[consistent inconsistent].none?(break_type)
    raise ArgumentError, '%s is not a valid type. Choose one: :consistent or :inconsistent'
  end

  tokens << Oppen.send(:"begin_#{break_type}", offset: indent)
  self
end

#inconsistentObject

An alias for group(:inconsistent, ...)



242
243
244
# File 'lib/wadler/print.rb', line 242

def inconsistent(...)
  group(:inconsistent, ...)
end

#indent_close(indent: @indent) ⇒ self

Close a group and subtract indent.

Parameters:

  • indent (Integer) (defaults to: @indent)

    the amount of indentation of the group.

Returns:

  • (self)


801
802
803
804
# File 'lib/wadler/print.rb', line 801

def indent_close(indent: @indent)
  @current_indent -= indent
  group_close
end

#indent_open(indent: @indent) ⇒ self

Open a consistent group and add indent amount.

Parameters:

  • indent (Integer) (defaults to: @indent)

    the amount of indentation of the group.

Returns:

  • (self)


790
791
792
793
# File 'lib/wadler/print.rb', line 790

def indent_open(indent: @indent)
  @current_indent += indent
  group_open
end

#lines(*args, **kwargs) ⇒ Object

Separate args into lines.

This is a wrapper around #separate where breakable: true.

See Also:

  • [separate]


601
602
603
# File 'lib/wadler/print.rb', line 601

def lines(*args, **kwargs, &)
  separate(*args, **kwargs.merge(force_break: true), &)
end

#nest(delim: nil, indent: @indent) { ... } ⇒ self

Note:

indentation cannot happen if there are no breaks in the #nest.

Note:

a #nest will not forcibly indent its content if the break type of

Create a new non-strict #group.

#groups isolate breaking decisions, and in that sense they're considered strict; e.g. when a breakable is transformed into an actual break, its parent #group might not get broken if the result could fit on the line.

This is not the case with #nest: if the same breakable was in a #nest, the #group containing the #nest will also be broken.

the enclosing #group is :inconsistent.

Examples:

out = Oppen::Wadler.new
out.nest(delim: %i[{ }], indent: 2) {
  out.text('a').break.text('b')
}
puts out.output

# =>
# {
#   a
#   b
# }

Parameters:

  • delim (Nil|String|Symbol|Array<Nil, String, Symbol>) (defaults to: nil)

    delimiters, to be printed at the start and the end of the group:

    • nil is always the empty string.
    • If it's a Strings or a Symbol, it will be printed at both positions.
    • If it's an Array of many items, the first two elements will be used for the start and end of the group.
  • indent (Integer) (defaults to: @indent)

    indentation.

Yields:

  • the block of text in a nest.

Returns:

  • (self)


286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
# File 'lib/wadler/print.rb', line 286

def nest(delim: nil, indent: @indent)
  lft, rgt =
    case delim
    in nil then ['', '']
    in String | Symbol then [delim, delim]
    in Array then delim.values_at(0, 1).map(&:to_s)
    end

  @current_indent += indent

  if !lft.empty?
    text lft
    self.break
  end

  begin
    yield
  ensure
    @current_indent -= indent
  end

  if !rgt.empty?
    self.break
    text rgt
  end

  self
end

#nest_close(indent: @indent) ⇒ self

Close a nest by subtracting indent.

Parameters:

  • indent (Integer) (defaults to: @indent)

    the amount of indentation of the nest.

Returns:

  • (self)


823
824
825
826
# File 'lib/wadler/print.rb', line 823

def nest_close(indent: @indent)
  @current_indent -= indent
  self
end

#nest_open(indent: @indent) ⇒ self

Open a nest by adding indent.

Parameters:

  • indent (Integer) (defaults to: @indent)

    the amount of indentation of the nest.

Returns:

  • (self)


812
813
814
815
# File 'lib/wadler/print.rb', line 812

def nest_open(indent: @indent)
  @current_indent += indent
  self
end

#outputString

Call this to extract the final pretty-printed output.

Returns:

  • (String)


77
78
79
80
81
82
83
84
85
86
87
# File 'lib/wadler/print.rb', line 77

def output
  add_missing_begin_and_end
  Oppen.print(
    tokens:,
    new_line:,
    config:,
    space: space_gen,
    out:,
    width:,
  )
end

#parens(padding: '', **kwargs, &block) ⇒ self

#surround with ( ). New lines can appear after and before the delimiters.

Parameters:

  • padding (String) (defaults to: '')

    ('') Passed to lft_breakable and rgt_breakable.

Returns:

  • (self)


710
711
712
713
714
715
716
# File 'lib/wadler/print.rb', line 710

def parens(padding: '', **kwargs, &block)
  surround(
    '(', ')',
    **kwargs.merge(lft_breakable: padding, rgt_breakable: padding),
    &block
  )
end

#parens_break_both(**kwargs) ⇒ self

#surround with ( ). New lines cannot appear after and before the delimiters.

Returns:

  • (self)


721
722
723
# File 'lib/wadler/print.rb', line 721

def parens_break_both(**kwargs, &)
  parens(**kwargs.merge(lft_force_break: true, rgt_force_break: true), &)
end

#parens_break_none(**kwargs) ⇒ self

#surround with ( ). New lines will appear after and before the delimiters.

Returns:

  • (self)


728
729
730
# File 'lib/wadler/print.rb', line 728

def parens_break_none(**kwargs, &)
  parens(**kwargs.merge(lft_can_break: false, rgt_can_break: false), &)
end

#quote_double(**kwargs) ⇒ self

#surround with " ". New lines cannot appear after and before the delimiters unless you specify it with rgt_can_break and lft_can_break.

Returns:

  • (self)


744
745
746
# File 'lib/wadler/print.rb', line 744

def quote_double(**kwargs, &)
  surround('"', '"', lft_can_break: false, rgt_can_break: false, **kwargs, &)
end

#quote_single(**kwargs) ⇒ self

#surround with ' '. New lines cannot appear after and before the delimiters unless you specify it with rgt_can_break and lft_can_break.

Returns:

  • (self)


752
753
754
# File 'lib/wadler/print.rb', line 752

def quote_single(**kwargs, &)
  surround("'", "'", lft_can_break: false, rgt_can_break: false, **kwargs, &)
end

#separate(args, sep, breakable: ' ', break_pos: :after, break_type: nil, indent: false, force_break: false, line_continuation: '') { ... } ⇒ self

Produce a separated list.

Examples:

Consistent Breaking

puts out.separate((1..3).map(&:to_s), ',') { |i| out.text i}

# =>
# 1,
# 2,
# 3

Inconsistent Breaking

puts out.separate((1..3).map(&:to_s), ',', break_type: :inconsistent) { |i| out.text i}

# =>
# 1, 2,
# 3

Parameters:

  • args (String)

    a list of values.

  • sep (String)

    a separator.

  • breakable (String|Nil) (defaults to: ' ')

    adds a breakable after the separator.

  • break_pos (Symbol) (defaults to: :after)

    whether to break :before or :after the seraparator.

  • break_type (Symbol|Nil) (defaults to: nil)

    whether the break is :consistent or :inconsistent. If nil is given, the tokens will not be surrounded by a group.

  • indent (Boolean|Integer) (defaults to: false)
    • If true, indent by @indent.
    • If an 'Integer', indent by its value.
  • force_break (Boolean) (defaults to: false)

    adds a break after the separator.

  • line_continuation (String) (defaults to: '')

    string to display before new line.

Yields:

  • to execute the passed block.

Returns:

  • (self)


469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
# File 'lib/wadler/print.rb', line 469

def separate(args, sep, breakable: ' ', break_pos: :after,
             break_type: nil, indent: false,
             force_break: false, line_continuation: '')
  if args.is_a?(Enumerator) ? args.count == 1 : args.length == 1
    yield(*args[0])
    return self
  end

  first = true
  wrap {
    wrap {
      args&.each do |*as|
        if first
          breakable '' if !line_continuation.empty? && break_pos == :after
          first = false
        elsif break_pos == :after
          text sep
          breakable(breakable, line_continuation:) if breakable && !force_break
          self.break(line_continuation:) if force_break
        else
          breakable(breakable, line_continuation:) if breakable && !force_break
          self.break(line_continuation:) if force_break
          text sep
        end
        yield(*as)
      end
    }
      .when(break_type) { |body|
        group(break_type, indent: 0) {
          body.()
        }
      }
      .end
  }
    .when(indent) { |body|
      nest(indent: indent.is_a?(Integer) ? indent : @indent) {
        body.()
      }
    }.end
  breakable('', line_continuation:) if !line_continuation.empty? && !break_type

  self
end

#show_print_commands(**kwargs) ⇒ String

Convert a list of tokens to its wadler representation.

This method reverse engineers a tokens list to transform it into Wadler printing commands. It can be particularly useful when debugging a black box program.

Examples:

out = Oppen::Wadler.new
out.text('Hello World!')
out.show_print_commands(out_name: 'out')

# =>
# out.group(:consistent, indent: 0) {
#   out.text("Hello World!", width: 12)
# }

Parameters:

  • kwargs (Hash)

    a customizable set of options

Options Hash (**kwargs):

  • :base_indent (Integer)

    the base indentation amount of the output.

  • :printer_name (String)

    the name of the Wadler instance in the output.

Returns:

  • (String)


111
112
113
114
# File 'lib/wadler/print.rb', line 111

def show_print_commands(**kwargs)
  add_missing_begin_and_end
  Oppen.tokens_to_wadler(tokens, **kwargs)
end

#spaceself

A shorhand for text ' '.

Returns:

  • (self)


516
517
518
# File 'lib/wadler/print.rb', line 516

def space
  text ' '
end

#surround(lft, rgt, **opts) { ... } ⇒ self

Surround a block with +lft+ and +rgt+

Parameters:

  • lft (String)

    lft left surrounding string.

  • rgt (String)

    rgt right surrounding string.

  • opts (Hash)

    a customizable set of options

Options Hash (**opts):

  • :group (Boolean) — default: true

    whether to create a group enclosing lft, rgt, and the passed block.

  • :indent (Boolean) — default: @indent

    whether to indent the passed block.

  • :lft_breakable (String) — default: ''

    left breakable string.

  • :lft_can_break (Boolean) — default: true

    injects break or breakable only if true; i.e. lft_breakable will be ignored if false.

  • :lft_force_break (Boolean) — default: false

    force break instead of using lft_breakable.

  • :rgt_breakable (String) — default: ''

    right breakable string.

  • :rgt_can_break (Boolean) — default: true

    injects break or breakable only if true. i.e. rgt_breakable will be ignored if false.

  • :rgt_force_break (Boolean) — default: false

    force break instead of using rgt_breakable.

Yields:

  • the passed block to be surrounded with lft and rgt.

Returns:

  • (self)


549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
# File 'lib/wadler/print.rb', line 549

def surround(lft, rgt, **opts)
  group = opts.fetch(:group, true)
  group_open(break_type: :inconsistent) if group

  text lft if lft

  indent = opts.fetch(:indent, @indent)
  nest_open(indent:)

  lft_breakable = opts.fetch(:lft_breakable, '')
  lft_can_break = opts.fetch(:lft_can_break, true)
  lft_force_break = opts.fetch(:lft_force_break, false)
  if lft && lft_can_break
    if lft_force_break
      self.break
    else
      breakable lft_breakable
    end
  end

  if block_given?
    yield
  end

  nest_close

  rgt_breakable = opts.fetch(:rgt_breakable, '')
  rgt_can_break = opts.fetch(:rgt_can_break, true)
  rgt_force_break = opts.fetch(:rgt_force_break, false)
  if rgt
    if rgt_can_break
      if rgt_force_break
        self.break
      else
        breakable rgt_breakable
      end
    end
    text rgt
  end

  group_close if group

  self
end

#text(value, width: value.length) ⇒ self

Create a new text element.

Parameters:

  • value (String)

    the value of the token.

Returns:

  • (self)


321
322
323
324
325
326
327
328
329
330
331
332
333
# File 'lib/wadler/print.rb', line 321

def text(value, width: value.length)
  if config.trim_trailing_whitespaces? && value.match(/((?:#{Regexp.escape(whitespace)})+)\z/)
    match = Regexp.last_match(1)
    matched_length = match.length
    if value.length != matched_length
      tokens << Oppen.string(value[0...-matched_length], width: width - matched_length)
    end
    tokens << Oppen.whitespace(match)
  else
    tokens << Oppen.string(value, width:)
  end
  self
end

#wrap(&blk) ⇒ Wrap

A means to wrap a piece of code in several ways.

Examples:

out
  .wrap {
    # all printing instructions here will be deferred.
    # they will be executed in `when` blocks by calling the `wrapped`.
    out.text(...)
    # ...
  } # This is "wrapped".
  .when(cond1){ |wrapped|
    # when cond1 is true you execute this block.
    out.text("before wrapped")
    # call the wrapped
    wrapped.call
    # and continue printing
    out.text("after wrapped)
  }
  .when(cond2){ |wrapped|
    # and you cand define many conditions.
  }
  .end

Calling end is not needed if there's another call after the last when:

out
  .wrap{...} # This is "wrapped".
  .when(cond1){ |wrapped| ... }
  .when(cond2){ |wrapped| ... }
  .text('foo')

Returns:



426
427
428
# File 'lib/wadler/print.rb', line 426

def wrap(&blk)
  Wrap.new(blk)
end