Spec-Zone.ru › Ruby 2.3

class PrettyPrint

Parent:
Object

frozen_string_literal: true

Этот класс реализует алгоритм красивой печати. Он находит разрывы строк и красивые отступы для структурированных данных.

По умолчанию класс предполагает, что примитивные элементы — это строки, и каждый байт в строках имеет ширину в одну колонку. Но его можно использовать для других ситуаций, передав соответствующие аргументы для некоторых методов:

  • объект новой строки и блок генерации пробелов для ::new

  • необязательный аргумент ширины для #text

  • #breakable

Существует несколько потенциальных применений:

  • форматирование текста с использованием пропорциональных шрифтов

  • многобайтовые символы, ширина которых отличается от количества байтов

  • форматирование, не связанное со строками

Ошибки

  • Форматирование на основе ячеек?

  • Другая (лучшая) модель/алгоритм?

Сообщите об ошибках на bugs.ruby-lang.org

Ссылки

Christian Lindig, Strictly Pretty, Март 2000, www.st.cs.uni-sb.de/~lindig/papers/#pretty

Philip Wadler, A prettier printer, Март 1998, homepages.inf.ed.ac.uk/wadler/topics/language-design.html#prettier

Автор

Tanaka Akira <akr@fsij.org>

Атрибуты

genspace[R]

Lambda или Proc, принимающий один аргумент типа Fixnum и возвращающий соответствующее число пробелов.

По умолчанию это:

lambda {|n| ' ' * n}
group_queue[R]

PrettyPrint::GroupQueue групп в стеке, которые нужно отформатировать.

indent[R]

Количество пробелов для отступа.

maxwidth[R]

Максимальная ширина строки перед её разделением на новую строку.

По умолчанию 79, и должно быть типа Fixnum.

newline[R]

Значение, которое добавляется к output для добавления новой строки.

По умолчанию «n», и должно быть типа String.

output[R]

Объект вывода.

По умолчанию '', и должен принимать метод <<

Методы класса Public

format(output=''.dup, maxwidth=79, newline="\n", genspace=lambda {|n| ' ' * n}) { |q| ... } Показать исходный код
# File lib/prettyprint.rb, line 45
def PrettyPrint.format(output=''.dup, maxwidth=79, newline="\n", genspace=lambda {|n| ' ' * n})
  q = PrettyPrint.new(output, maxwidth, newline, &genspace)
  yield q
  q.flush
  output
end

Это метод удобства, который эквивалентен следующему:

begin
  q = PrettyPrint.new(output, maxwidth, newline, &genspace)
  ...
  q.flush
  output
end
new(output=''.dup, maxwidth=79, newline="\n", &genspace) Показать исходный код
# File lib/prettyprint.rb, line 82
def initialize(output=''.dup, maxwidth=79, newline="\n", &genspace)
  @output = output
  @maxwidth = maxwidth
  @newline = newline
  @genspace = genspace || lambda {|n| ' ' * n}

  @output_width = 0
  @buffer_width = 0
  @buffer = []

  root_group = Group.new(0)
  @group_stack = [root_group]
  @group_queue = GroupQueue.new(root_group)
  @indent = 0
end

Создаёт буфер для красивой печати.

output — целевой объект вывода. Если он не указан, используется ''. Он должен иметь метод <<, принимающий первый аргумент obj метода #text, первый аргумент sep метода #breakable, первый аргумент newline метода ::new и результат блока для ::new.

maxwidth задаёт максимальную длину строки. Если он не указан, используется 79. Однако фактические выводы могут превысить maxwidth, если предоставлен длинный неразрывный текст.

newline используется для переносов строк. Если он не указан, используется «n».

Блок используется для генерации пробелов. {|width| ' ' * width} используется, если он не задан.

singleline_format(output=''.dup, maxwidth=nil, newline=nil, genspace=nil) { |q| ... } Показать исходный код
# File lib/prettyprint.rb, line 59
def PrettyPrint.singleline_format(output=''.dup, maxwidth=nil, newline=nil, genspace=nil)
  q = SingleLine.new(output)
  yield q
  output
end

Аналогично ::format, но результат без переносов строк.

maxwidth, newline и genspace игнорируются.

Вызов breakable в блоке не переносит строку и обрабатывается как просто вызов text.

Методы экземпляра Public

break_outmost_groups() Показать исходный код
# File lib/prettyprint.rb, line 160
def break_outmost_groups
  while @maxwidth < @output_width + @buffer_width
    return unless group = @group_queue.deq
    until group.breakables.empty?
      data = @buffer.shift
      @output_width = data.output(@output, @output_width)
      @buffer_width -= data.width
    end
    while !@buffer.empty? && Text === @buffer.first
      text = @buffer.shift
      @output_width = text.output(@output, @output_width)
      @buffer_width -= text.width
    end
  end
end

Разбивает буфер на строки, которые короче maxwidth.

breakable(sep=' ', width=sep.length) Показать исходный код
# File lib/prettyprint.rb, line 224
def breakable(sep=' ', width=sep.length)
  group = @group_stack.last
  if group.break?
    flush
    @output << @newline
    @output << @genspace.call(@indent)
    @output_width = @indent
    @buffer_width = 0
  else
    @buffer << Breakable.new(sep, width, self)
    @buffer_width += width
    break_outmost_groups
  end
end

Указывает, что здесь можно переносить строку при необходимости, и текст шириной width столбцов sep вставляется, если строка не разрывается в этом месте.

Если sep не указан, используется « ».

Если width не указан, используется sep.length. Вам нужно будет указать это, если sep является многобайтовым символом, например.

current_group() Показать исходный код
# File lib/prettyprint.rb, line 155
def current_group
  @group_stack.last
end

Возвращает группу, добавленную в стек последней.

Пример:

out = ""
=> ""
q = PrettyPrint.new(out)
=> #<PrettyPrint:0x82f85c0 @output="", @maxwidth=79, @newline="\n", @genspace=#<Proc:0x82f8368@/home/vbatts/.rvm/rubies/ruby-head/lib/ruby/2.0.0/prettyprint.rb:82 (lambda)>, @output_width=0, @buffer_width=0, @buffer=[], @group_stack=[#<PrettyPrint::Group:0x82f8138 @depth=0, @breakables=[], @break=false>], @group_queue=#<PrettyPrint::GroupQueue:0x82fb7c0 @queue=[[#<PrettyPrint::Group:0x82f8138 @depth=0, @breakables=[], @break=false>]]>, @indent=0>
q.group {
  q.text q.current_group.inspect
  q.text q.newline
  q.group(q.current_group.depth + 1) {
    q.text q.current_group.inspect
    q.text q.newline
    q.group(q.current_group.depth + 1) {
      q.text q.current_group.inspect
      q.text q.newline
      q.group(q.current_group.depth + 1) {
        q.text q.current_group.inspect
        q.text q.newline
      }
    }
  }
}
=> 284
 puts out
#<PrettyPrint::Group:0x8354758 @depth=1, @breakables=[], @break=false>
#<PrettyPrint::Group:0x8354550 @depth=2, @breakables=[], @break=false>
#<PrettyPrint::Group:0x83541cc @depth=3, @breakables=[], @break=false>
#<PrettyPrint::Group:0x8347e54 @depth=4, @breakables=[], @break=false>
fill_breakable(sep=' ', width=sep.length) Показать исходный код
# File lib/prettyprint.rb, line 212
def fill_breakable(sep=' ', width=sep.length)
  group { breakable sep, width }
end

Аналогично breakable, но решение о переносе строки определяется индивидуально.

Два fill_breakable внутри группы могут привести к 4 результатам: (перенос,перенос), (перенос,не перенос), (не перенос,перенос), (не перенос,не перенос). Это отличается от breakable, так как два breakable внутри группы могут привести к 2 результатам: (перенос,перенос), (не перенос,не перенос).

Текст sep вставляется, если строка не разрывается в этом месте.

Если sep не указан, используется « ».

Если width не указан, используется sep.length. Вам нужно будет указать это, если sep является многобайтовым символом, например.

Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API