class Asciidoctor::IncludeExt::LinenoLinesSelector

Lines selector that selects lines of the content to be included based on the specified ranges of line numbers.

@note Instance of this class can be used only once, as a predicate to

filter a single include directive.

@example

include::some-file.adoc[lines=1;3..4;6..-1]

@example

selector = LinenoLinesSelector.new("some-file.adoc", {"lines" => "1;3..4;6..-1"})
IO.foreach(filename).select.with_index(1, &selector)

@see asciidoctor.org/docs/user-manual#by-line-ranges

Attributes

first_included_lineno[R]

@return [Integer, nil] 1-based line number of the first included line,

or `nil` if none.

Public Class Methods

handles?(_, attributes) click to toggle source

@param attributes [Hash<String, String>] the attributes parsed from the

`include::[]`s attributes slot.

@return [Boolean] `true` if the attributes hash contains a key `“lines”`.

# File lib/asciidoctor/include_ext/lineno_lines_selector.rb, line 28
def self.handles?(_, attributes)
  attributes.key? 'lines'
end
new(_, attributes, **) click to toggle source

@param attributes [Hash<String, String>] the attributes parsed from the

`include::[]`s attributes slot. It must contain a key `"lines"`.
# File lib/asciidoctor/include_ext/lineno_lines_selector.rb, line 34
def initialize(_, attributes, **)
  @ranges = parse_attribute(attributes['lines'])
  @first_included_lineno = @ranges.last.first unless @ranges.empty?
end

Public Instance Methods

include?(_, line_num) click to toggle source

Returns `true` if the given line should be included, `false` otherwise.

@note This method modifies state of this object. It's supposed to be

called successively with each line of the content being included.
See {LinenoLinesSelector example}.

@param line_num [Integer] 1-based line number. @return [Boolean] `true` to select the line, or `false` to reject.

# File lib/asciidoctor/include_ext/lineno_lines_selector.rb, line 47
def include?(_, line_num)
  return false if @ranges.empty?

  ranges = @ranges
  ranges.pop while !ranges.empty? && ranges.last.last < line_num
  ranges.last.cover?(line_num) if !ranges.empty?
end
to_proc() click to toggle source

@return [Proc] {#include?} method as a Proc.

# File lib/asciidoctor/include_ext/lineno_lines_selector.rb, line 56
def to_proc
  method(:include?).to_proc
end

Protected Instance Methods

parse_attribute(lines_def) click to toggle source

@param lines_def [String] a comma or semicolon separated numbers and

and ranges (e.g. `1..2`) specifying lines to be selected, or rejected
if prefixed with "!".

@return [Array<Range>] an array of ranges sorted by the range begin in

_descending_ order.
# File lib/asciidoctor/include_ext/lineno_lines_selector.rb, line 67
def parse_attribute(lines_def)
  lines_def
    .split(/[,;]/)
    .map! { |line_def|
      from, to = line_def.split('..', 2).map(&:to_i)
      to ||= from
      to = ::Float::INFINITY if to == -1
      (from..to)
    }.sort! do |a, b|
      b.first <=> a.first
    end
end