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)


632
633
634
635
636
637
638
# File 'lib/wadler/print.rb', line 632

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)


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

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)


650
651
652
# File 'lib/wadler/print.rb', line 650

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)


742
743
744
# File 'lib/wadler/print.rb', line 742

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)


660
661
662
663
664
665
666
# File 'lib/wadler/print.rb', line 660

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)


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

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)


678
679
680
# File 'lib/wadler/print.rb', line 678

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)


688
689
690
691
692
693
694
# File 'lib/wadler/print.rb', line 688

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)


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

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)


706
707
708
# File 'lib/wadler/print.rb', line 706

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)


375
376
377
378
379
380
381
# File 'lib/wadler/print.rb', line 375

def break(line_continuation: '')
  if line_continuation && config.trim_trailing_whitespaces?
    line_continuation = line_continuation.sub(/(?:#{Regexp.escape(whitespace)})+\z/, '')
  end
  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
351
352
353
# File 'lib/wadler/print.rb', line 347

def breakable(str = ' ', line_continuation: '', width: str.length)
  if config.trim_trailing_whitespaces? && line_continuation
    line_continuation = line_continuation.sub(/(?:#{Regexp.escape(whitespace)})+\z/, '')
  end
  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]


616
617
618
# File 'lib/wadler/print.rb', line 616

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)


396
397
398
399
# File 'lib/wadler/print.rb', line 396

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)


785
786
787
788
# File 'lib/wadler/print.rb', line 785

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:



773
774
775
776
777
778
779
780
# File 'lib/wadler/print.rb', line 773

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)


807
808
809
810
# File 'lib/wadler/print.rb', line 807

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)


796
797
798
799
# File 'lib/wadler/print.rb', line 796

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]


607
608
609
# File 'lib/wadler/print.rb', line 607

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)


829
830
831
832
# File 'lib/wadler/print.rb', line 829

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)


818
819
820
821
# File 'lib/wadler/print.rb', line 818

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)


716
717
718
719
720
721
722
# File 'lib/wadler/print.rb', line 716

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)


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

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)


734
735
736
# File 'lib/wadler/print.rb', line 734

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)


750
751
752
# File 'lib/wadler/print.rb', line 750

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)


758
759
760
# File 'lib/wadler/print.rb', line 758

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)


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
512
513
514
515
516
517
# File 'lib/wadler/print.rb', line 475

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)


522
523
524
# File 'lib/wadler/print.rb', line 522

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)


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
593
594
595
596
597
598
# File 'lib/wadler/print.rb', line 555

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:



432
433
434
# File 'lib/wadler/print.rb', line 432

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