diff options
| author | Benjamin Sanders <ben@Benjamins-MacBook-Pro.local> | 2025-10-11 10:34:24 -0400 |
|---|---|---|
| committer | Benjamin Sanders <ben@Benjamins-MacBook-Pro.local> | 2025-10-11 10:34:24 -0400 |
| commit | 5571dc766e2143e39762ff0b47c41d1c2e154f4c (patch) | |
| tree | f4f124d314a7e76c04484515aa0fd1f2e271a601 /vendor/bundle/ruby/3.4.0/gems/terminal-table-3.0.2/lib | |
| parent | 359f3309c97fc894b63e0a295c76ab298504d635 (diff) | |
Vendor bundled gems for deployment
Diffstat (limited to 'vendor/bundle/ruby/3.4.0/gems/terminal-table-3.0.2/lib')
10 files changed, 938 insertions, 0 deletions
diff --git a/vendor/bundle/ruby/3.4.0/gems/terminal-table-3.0.2/lib/terminal-table.rb b/vendor/bundle/ruby/3.4.0/gems/terminal-table-3.0.2/lib/terminal-table.rb new file mode 100644 index 0000000..ebea259 --- /dev/null +++ b/vendor/bundle/ruby/3.4.0/gems/terminal-table-3.0.2/lib/terminal-table.rb @@ -0,0 +1,26 @@ +#-- +# Copyright (c) 2008-2009 TJ Holowaychuk <tj@vision-media.ca> +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +#++ + +%w(cell row separator style table table_helper util version).each do |file| + require_relative "./terminal-table/#{file}" +end diff --git a/vendor/bundle/ruby/3.4.0/gems/terminal-table-3.0.2/lib/terminal-table/cell.rb b/vendor/bundle/ruby/3.4.0/gems/terminal-table-3.0.2/lib/terminal-table/cell.rb new file mode 100644 index 0000000..0ec261d --- /dev/null +++ b/vendor/bundle/ruby/3.4.0/gems/terminal-table-3.0.2/lib/terminal-table/cell.rb @@ -0,0 +1,94 @@ +require 'unicode/display_width' + +module Terminal + class Table + class Cell + ## + # Cell value. + + attr_reader :value + + ## + # Column span. + + attr_reader :colspan + + ## + # Initialize with _options_. + + def initialize options = nil + @value, options = options, {} unless Hash === options + @value = options.fetch :value, value + @alignment = options.fetch :alignment, nil + @colspan = options.fetch :colspan, 1 + @width = options.fetch :width, @value.to_s.size + @index = options.fetch :index + @table = options.fetch :table + end + + def alignment? + !@alignment.nil? + end + + def alignment + @alignment || @table.style.alignment || :left + end + + def alignment=(val) + supported = %w(left center right) + if supported.include?(val.to_s) + @alignment = val + else + raise "Aligment must be one of: #{supported.join(' ')}" + end + end + + def align(val, position, length) + positions = { :left => :ljust, :right => :rjust, :center => :center } + val.public_send(positions[position], length) + end + def lines + @value.to_s.split(/\n/) + end + + ## + # Render the cell. + + def render(line = 0) + left = " " * @table.style.padding_left + right = " " * @table.style.padding_right + display_width = Unicode::DisplayWidth.of(Util::ansi_escape(lines[line])) + render_width = lines[line].to_s.size - display_width + width + align("#{left}#{lines[line]}#{right}", alignment, render_width + @table.cell_padding) + end + alias :to_s :render + + ## + # Returns the longest line in the cell and + # removes all ANSI escape sequences (e.g. color) + + def value_for_column_width_recalc + lines.map{ |s| Util::ansi_escape(s) }.max_by{ |s| Unicode::DisplayWidth.of(s) } + end + + ## + # Returns the width of this cell + + def width + padding = (colspan - 1) * @table.cell_spacing + inner_width = (1..@colspan).to_a.inject(0) do |w, counter| + w + @table.column_width(@index + counter - 1) + end + inner_width + padding + end + + def inspect + fields = %i[alignment colspan index value width].map do |name| + val = self.instance_variable_get('@'+name.to_s) + "@#{name}=#{val.inspect}" + end.join(', ') + return "#<#{self.class} #{fields}>" + end + end + end +end diff --git a/vendor/bundle/ruby/3.4.0/gems/terminal-table-3.0.2/lib/terminal-table/import.rb b/vendor/bundle/ruby/3.4.0/gems/terminal-table-3.0.2/lib/terminal-table/import.rb new file mode 100644 index 0000000..33b2791 --- /dev/null +++ b/vendor/bundle/ruby/3.4.0/gems/terminal-table-3.0.2/lib/terminal-table/import.rb @@ -0,0 +1,3 @@ +require 'terminal-table' #required as some people require this file directly from their Gemfiles + +include Terminal::Table::TableHelper diff --git a/vendor/bundle/ruby/3.4.0/gems/terminal-table-3.0.2/lib/terminal-table/row.rb b/vendor/bundle/ruby/3.4.0/gems/terminal-table-3.0.2/lib/terminal-table/row.rb new file mode 100644 index 0000000..a549008 --- /dev/null +++ b/vendor/bundle/ruby/3.4.0/gems/terminal-table-3.0.2/lib/terminal-table/row.rb @@ -0,0 +1,66 @@ +module Terminal + class Table + class Row + + ## + # Row cells + + attr_reader :cells + + attr_reader :table + + ## + # Initialize with _width_ and _options_. + + def initialize table, array = [], **_kwargs + @cell_index = 0 + @table = table + @cells = [] + array.each { |item| self << item } + end + + def add_cell item + options = item.is_a?(Hash) ? item : {:value => item} + cell = Cell.new(options.merge(:index => @cell_index, :table => @table)) + @cell_index += cell.colspan + @cells << cell + end + alias << add_cell + + def [] index + cells[index] + end + + def height + cells.map { |c| c.lines.count }.max || 0 + end + + def render + vleft, vcenter, vright = @table.style.vertical + (0...height).to_a.map do |line| + vleft + cells.map do |cell| + cell.render(line) + end.join(vcenter) + vright + end.join("\n") + end + + def number_of_columns + @cells.collect(&:colspan).inject(0, &:+) + end + + # used to find indices where we have table '+' crossings. + # in cases where the colspan > 1, then we will skip over some numbers + # if colspan is always 1, then the list should be incrementing by 1. + # + # skip 0 entry, because it's the left side. + # skip last entry, because it's the right side. + # we only care about "+/T" style crossings. + def crossings + idx = 0 + @cells[0...-1].map { |c| idx += c.colspan } + end + + end + + end +end diff --git a/vendor/bundle/ruby/3.4.0/gems/terminal-table-3.0.2/lib/terminal-table/separator.rb b/vendor/bundle/ruby/3.4.0/gems/terminal-table-3.0.2/lib/terminal-table/separator.rb new file mode 100644 index 0000000..0413925 --- /dev/null +++ b/vendor/bundle/ruby/3.4.0/gems/terminal-table-3.0.2/lib/terminal-table/separator.rb @@ -0,0 +1,66 @@ +module Terminal + class Table + class Separator < Row + + ## + # `prevrow`, `nextrow` contain references to adjacent rows. + # + # `border_type` is a symbol used to control which type of border is used + # on the separator (:top for top-edge, :bot for bottom-edge, + # :div for interior, and :strong for emphasized-interior) + # + # `implicit` is false for user-added separators, and true for + # implicit/auto-generated separators. + + def initialize(*args, border_type: :div, implicit: false) + super + @prevrow, @nextrow = nil, nil + @border_type = border_type + @implicit = implicit + end + + attr_accessor :border_type + attr_reader :implicit + + def render + left_edge, ctrflat, ctrud, right_edge, ctrdn, ctrup = @table.style.horizontal(border_type) + + prev_crossings = @prevrow.respond_to?(:crossings) ? @prevrow.crossings : [] + next_crossings = @nextrow.respond_to?(:crossings) ? @nextrow.crossings : [] + rval = [left_edge] + numcols = @table.number_of_columns + (0...numcols).each do |idx| + rval << ctrflat * (@table.column_width(idx) + @table.cell_padding) + pcinc = prev_crossings.include?(idx+1) + ncinc = next_crossings.include?(idx+1) + border_center = if pcinc && ncinc + ctrud + elsif pcinc + ctrup + elsif ncinc + ctrdn + elsif !ctrud.empty? + # special case if the center-up-down intersection is empty + # which happens when verticals/intersections are removed. in that case + # we do not want to replace with a flat element so return empty-string in else block + ctrflat + else + '' + end + rval << border_center if idx < numcols-1 + end + + rval << right_edge + rval.join + end + + # Save off neighboring rows, so that we can use them later in determining + # which types of table edges to use. + def save_adjacent_rows(prevrow, nextrow) + @prevrow = prevrow + @nextrow = nextrow + end + + end + end +end diff --git a/vendor/bundle/ruby/3.4.0/gems/terminal-table-3.0.2/lib/terminal-table/style.rb b/vendor/bundle/ruby/3.4.0/gems/terminal-table-3.0.2/lib/terminal-table/style.rb new file mode 100644 index 0000000..dc89737 --- /dev/null +++ b/vendor/bundle/ruby/3.4.0/gems/terminal-table-3.0.2/lib/terminal-table/style.rb @@ -0,0 +1,284 @@ +# coding: utf-8 +require 'forwardable' + +module Terminal + class Table + + class Border + + attr_accessor :data, :top, :bottom, :left, :right + def initialize + @top, @bottom, @left, @right = true, true, true, true + end + def []=(key, val) + @data[key] = val + end + def [](key) + @data[key] + end + def initialize_dup(other) + super + @data = other.data.dup + end + def remove_verticals + self.class.const_get("VERTICALS").each { |key| @data[key] = "" } + self.class.const_get("INTERSECTIONS").each { |key| @data[key] = "" } + end + def remove_horizontals + self.class.const_get("HORIZONTALS").each { |key| @data[key] = "" } + end + + # If @left, return the edge else empty-string. + def maybeleft(key) ; @left ? @data[key] : '' ; end + + # If @right, return the edge else empty-string. + def mayberight(key) ; @right ? @data[key] : '' ; end + + end + + class AsciiBorder < Border + HORIZONTALS = %i[x] + VERTICALS = %i[y] + INTERSECTIONS = %i[i] + + def initialize + super + @data = { x: "-", y: "|", i: "+" } + end + + # Get vertical border elements + # @return [Array] 3-element list of [left, center, right] + def vertical + [maybeleft(:y), @data[:y], mayberight(:y)] # left, center, right + end + + # Get horizontal border elements + # @return [Array] a 6 element list of: [i-left, horizontal-bar, i-up/down, i-right, i-down, i-up] + def horizontal(_type) + x, i = @data[:x], @data[:i] + [maybeleft(:i), x, i, mayberight(:i), i, i] + end + end + + class MarkdownBorder < AsciiBorder + def initialize + super + @top, @bottom = false, false + @data = { x: "-", y: "|", i: "|" } + end + end + + class UnicodeBorder < Border + + ALLOWED_SEPARATOR_BORDER_STYLES = %i[ + top bot + div dash dot3 dot4 + thick thick_dash thick_dot3 thick_dot4 + heavy heavy_dash heavy_dot3 heavy_dot4 + bold bold_dash bold_dot3 bold_dot4 + double + ] + + HORIZONTALS = %i[x sx ax bx nx bx_dot3 bx_dot4 bx_dash x_dot3 x_dot4 x_dash] + VERTICALS = %i[y yw ye] + INTERSECTIONS = %i[nw n ne nd + aw ai ae ad au + bw bi be bd bu + w i e dn up + sw s se su] + def initialize + super + @data = { + nil => nil, + nw: "┌", nx: "─", n: "┬", ne: "┐", + yw: "│", y: "│", ye: "│", + aw: "╞", ax: "═", ai: "╪", ae: "╡", ad: '╤', au: "╧", # double + bw: "┝", bx: "━", bi: "┿", be: "┥", bd: '┯', bu: "┷", # heavy/bold/thick + w: "├", x: "─", i: "┼", e: "┤", dn: "┬", up: "┴", # normal div + sw: "└", sx: "─", s: "┴", se: "┘", + # alternative dots/dashes + x_dot4: '┈', x_dot3: '┄', x_dash: '╌', + bx_dot4: '┉', bx_dot3: '┅', bx_dash: '╍', + } + end + # Get vertical border elements + # @return [Array] 3-element list of [left, center, right] + def vertical + [maybeleft(:yw), @data[:y], mayberight(:ye)] + end + + # Get horizontal border elements + # @return [Array] a 6 element list of: [i-left, horizontal-bar, i-up/down, i-right, i-down, i-up] + def horizontal(type) + raise ArgumentError, "Border type is #{type.inspect}, must be one of #{ALLOWED_SEPARATOR_BORDER_STYLES.inspect}" unless ALLOWED_SEPARATOR_BORDER_STYLES.include?(type) + lookup = case type + when :top + [:nw, :nx, :n, :ne, :n, nil] + when :bot + [:sw, :sx, :s, :se, nil, :s] + when :double + # typically used for the separator below the heading row or above a footer row) + [:aw, :ax, :ai, :ae, :ad, :au] + when :thick, :thick_dash, :thick_dot3, :thick_dot4, + :heavy, :heavy_dash, :heavy_dot3, :heavy_dot4, + :bold, :bold_dash, :bold_dot3, :bold_dot4 + # alternate thick/bold border + xref = type.to_s.sub(/^(thick|heavy|bold)/,'bx').to_sym + [:bw, xref, :bi, :be, :bd, :bu] + when :dash, :dot3, :dot4 + # alternate thin dividers + xref = "x_#{type}".to_sym + [:w, xref, :i, :e, :dn, :up] + else # :div (center, non-emphasized) + [:w, :x, :i, :e, :dn, :up] + end + rval = lookup.map { |key| @data.fetch(key) } + rval[0] = '' unless @left + rval[3] = '' unless @right + rval + end + end + + # Unicode Border With rounded edges + class UnicodeRoundBorder < UnicodeBorder + def initialize + super + @data.merge!({nw: '╭', ne: '╮', sw: '╰', se: '╯'}) + end + end + + # Unicode Border with thick outer edges + class UnicodeThickEdgeBorder < UnicodeBorder + def initialize + super + @data = { + nil => nil, + nw: "┏", nx: "━", n: "┯", ne: "┓", nd: nil, + yw: "┃", y: "│", ye: "┃", + aw: "┣", ax: "═", ai: "╪", ae: "┫", ad: '╤', au: "╧", # double + bw: "┣", bx: "━", bi: "┿", be: "┫", bd: '┯', bu: "┷", # heavy/bold/thick + w: "┠", x: "─", i: "┼", e: "┨", dn: "┬", up: "┴", # normal div + sw: "┗", sx: "━", s: "┷", se: "┛", su: nil, + # alternative dots/dashes + x_dot4: '┈', x_dot3: '┄', x_dash: '╌', + bx_dot4: '┉', bx_dot3: '┅', bx_dash: '╍', + } + end + end + + # A Style object holds all the formatting information for a Table object + # + # To create a table with a certain style, use either the constructor + # option <tt>:style</tt>, the Table#style object or the Table#style= method + # + # All these examples have the same effect: + # + # # by constructor + # @table = Table.new(:style => {:padding_left => 2, :width => 40}) + # + # # by object + # @table.style.padding_left = 2 + # @table.style.width = 40 + # + # # by method + # @table.style = {:padding_left => 2, :width => 40} + # + # To set a default style for all tables created afterwards use Style.defaults= + # + # Terminal::Table::Style.defaults = {:width => 80} + # + class Style + extend Forwardable + def_delegators :@border, :vertical, :horizontal, :remove_verticals, :remove_horizontals + + @@defaults = { + :border => AsciiBorder.new, + :padding_left => 1, :padding_right => 1, + :margin_left => '', + :width => nil, :alignment => nil, + :all_separators => false, + } + + ## settors/gettor for legacy ascii borders + def border_x=(val) ; @border[:x] = val ; end + def border_y=(val) ; @border[:y] = val ; end + def border_i=(val) ; @border[:i] = val ; end + def border_y ; @border[:y] ; end + def border_y_width ; Util::ansi_escape(@border[:y]).length ; end + + # Accessor for instance of Border + attr_reader :border + def border=(val) + if val.is_a? Symbol + # convert symbol name like :foo_bar to get class FooBarBorder + klass_str = val.to_s.split('_').collect(&:capitalize).join + "Border" + begin + klass = Terminal::Table::const_get(klass_str) + @border = klass.new + rescue NameError + raise "Cannot lookup class Terminal::Table::#{klass_str} from symbol #{val.inspect}" + end + else + @border = val + end + end + + def border_top=(val) ; @border.top = val ; end + def border_bottom=(val) ; @border.bottom = val ; end + def border_left=(val) ; @border.left = val ; end + def border_right=(val) ; @border.right = val ; end + + def border_top ; @border.top ; end + def border_bottom ; @border.bottom ; end + def border_left ; @border.left ; end + def border_right ; @border.right ; end + + + attr_accessor :padding_left + attr_accessor :padding_right + + attr_accessor :margin_left + + attr_accessor :width + attr_accessor :alignment + + attr_accessor :all_separators + + + def initialize options = {} + apply self.class.defaults.merge(options) + end + + def apply options + options.each do |m, v| + __send__ "#{m}=", v + end + end + + class << self + def defaults + klass_defaults = @@defaults.dup + # border is an object that needs to be duplicated on instantiation, + # otherwise everything will be referencing the same object-id. + klass_defaults[:border] = klass_defaults[:border].dup + klass_defaults + end + + def defaults= options + @@defaults = defaults.merge(options) + end + + end + + def on_change attr + method_name = :"#{attr}=" + old_method = method method_name + define_singleton_method(method_name) do |value| + old_method.call value + yield attr.to_sym, value + end + end + + end + end +end diff --git a/vendor/bundle/ruby/3.4.0/gems/terminal-table-3.0.2/lib/terminal-table/table.rb b/vendor/bundle/ruby/3.4.0/gems/terminal-table-3.0.2/lib/terminal-table/table.rb new file mode 100644 index 0000000..f483e31 --- /dev/null +++ b/vendor/bundle/ruby/3.4.0/gems/terminal-table-3.0.2/lib/terminal-table/table.rb @@ -0,0 +1,372 @@ +require 'unicode/display_width' + +module Terminal + class Table + + attr_reader :title + attr_reader :headings + + ## + # Generates a ASCII/Unicode table with the given _options_. + + def initialize options = {}, &block + @elaborated = false + @headings = [] + @rows = [] + @column_widths = [] + self.style = options.fetch :style, {} + self.headings = options.fetch :headings, [] + self.rows = options.fetch :rows, [] + self.title = options.fetch :title, nil + yield_or_eval(&block) if block + + style.on_change(:width) { require_column_widths_recalc } + end + + ## + # Align column _n_ to the given _alignment_ of :center, :left, or :right. + + def align_column n, alignment + # nil forces the column method to return the cell itself + column(n, nil).each do |cell| + cell.alignment = alignment unless cell.alignment? + end + end + + ## + # Add a row. + + def add_row array + row = array == :separator ? Separator.new(self) : Row.new(self, array) + @rows << row + require_column_widths_recalc unless row.is_a?(Separator) + end + alias :<< :add_row + + ## + # Add a separator. + + def add_separator(border_type: :div) + @rows << Separator.new(self, border_type: border_type) + end + + def cell_spacing + cell_padding + style.border_y_width + end + + def cell_padding + style.padding_left + style.padding_right + end + + ## + # Return column _n_. + + def column n, method = :value, array = rows + array.map { |row| + # for each cells in a row, find the column with index + # just greater than the required one, and go back one. + index = col = 0 + row.cells.each do |cell| + break if index > n + index += cell.colspan + col += 1 + end + cell = row[col - 1] + cell && method ? cell.__send__(method) : cell + }.compact + end + + ## + # Return _n_ column including headings. + + def column_with_headings n, method = :value + column n, method, headings_with_rows + end + + ## + # Return columns. + + def columns + (0...number_of_columns).map { |n| column n } + end + + ## + # Return length of column _n_. + + def column_width n + column_widths[n] || 0 + end + alias length_of_column column_width # for legacy support + + ## + # Return total number of columns available. + + def number_of_columns + headings_with_rows.map { |r| r.number_of_columns }.max || 0 + end + + ## + # Set the headings + + def headings= arrays + arrays = [arrays] unless arrays.first.is_a?(Array) + @headings = arrays.map do |array| + row = Row.new(self, array) + require_column_widths_recalc + row + end + end + + ## + # Elaborate rows to form an Array of Rows and Separators with adjacency properties added. + # + # This is separated from the String rendering so that certain features may be tweaked + # before the String is built. + + def elaborate_rows + + buffer = style.border_top ? [Separator.new(self, border_type: :top, implicit: true)] : [] + unless @title.nil? + buffer << Row.new(self, [title_cell_options]) + buffer << Separator.new(self, implicit: true) + end + @headings.each do |row| + unless row.cells.empty? + buffer << row + buffer << Separator.new(self, border_type: :double, implicit: true) + end + end + if style.all_separators + @rows.each_with_index do |row, idx| + # last separator is bottom, others are :div + border_type = (idx == @rows.size - 1) ? :bot : :div + buffer << row + buffer << Separator.new(self, border_type: border_type, implicit: true) + end + else + buffer += @rows + buffer << Separator.new(self, border_type: :bot, implicit: true) if style.border_bottom + end + + # After all implicit Separators are inserted we need to save off the + # adjacent rows so that we can decide what type of intersections to use + # based on column spans in the adjacent row(s). + buffer.each_with_index do |r, idx| + if r.is_a?(Separator) + prev_row = idx > 0 ? buffer[idx - 1] : nil + next_row = buffer.fetch(idx + 1, nil) + r.save_adjacent_rows(prev_row, next_row) + end + end + + @elaborated = true + @rows = buffer + end + + ## + # Render the table. + + def render + elaborate_rows unless @elaborated + @rows.map { |r| style.margin_left + r.render.rstrip }.join("\n") + end + alias :to_s :render + + ## + # Return rows without separator rows. + + def rows + @rows.reject { |row| row.is_a? Separator } + end + + def rows= array + @rows = [] + array.each { |arr| self << arr } + end + + def style=(options) + style.apply options + end + + def style + @style ||= Style.new + end + + def title=(title) + @title = title + require_column_widths_recalc + end + + ## + # Check if _other_ is equal to self. _other_ is considered equal + # if it contains the same headings and rows. + + def == other + if other.respond_to? :render and other.respond_to? :rows + self.headings == other.headings and self.rows == other.rows + end + end + + private + + def columns_width + column_widths.inject(0) { |s, i| s + i + cell_spacing } + style.border_y_width + end + + def recalc_column_widths + @require_column_widths_recalc = false + n_cols = number_of_columns + space_width = cell_spacing + return if n_cols == 0 + + # prepare rows + all_rows = headings_with_rows + all_rows << Row.new(self, [title_cell_options]) unless @title.nil? + + # DP states, dp[colspan][index][split_offset] => column_width. + dp = [] + + # prepare initial value for DP. + all_rows.each do |row| + index = 0 + row.cells.each do |cell| + cell_value = cell.value_for_column_width_recalc + cell_width = Unicode::DisplayWidth.of(cell_value.to_s) + colspan = cell.colspan + + # find column width from each single cell. + dp[colspan] ||= [] + dp[colspan][index] ||= [0] # add a fake cell with length 0. + dp[colspan][index][colspan] ||= 0 # initialize column length to 0. + + # the last index `colspan` means width of the single column (split + # at end of each column), not a width made up of multiple columns. + single_column_length = [cell_width, dp[colspan][index][colspan]].max + dp[colspan][index][colspan] = single_column_length + + index += colspan + end + end + + # run DP. + (1..n_cols).each do |colspan| + dp[colspan] ||= [] + (0..n_cols-colspan).each do |index| + dp[colspan][index] ||= [1] + (1...colspan).each do |offset| + # processed level became reverse map from width => [offset, ...]. + left_colspan = offset + left_index = index + left_width = dp[left_colspan][left_index].keys.first + + right_colspan = colspan - left_colspan + right_index = index + offset + right_width = dp[right_colspan][right_index].keys.first + + dp[colspan][index][offset] = left_width + right_width + space_width + end + + # reverse map it for resolution (max width and short offset first). + rmap = {} + dp[colspan][index].each_with_index do |width, offset| + rmap[width] ||= [] + rmap[width] << offset + end + + # sort reversely and store it back. + dp[colspan][index] = Hash[rmap.sort.reverse] + end + end + + resolve = lambda do |colspan, full_width, index = 0| + # stop if reaches the bottom level. + return @column_widths[index] = full_width if colspan == 1 + + # choose best split offset for partition, or second best result + # if first one is not dividable. + candidate_offsets = dp[colspan][index].collect(&:last).flatten + offset = candidate_offsets[0] + offset = candidate_offsets[1] if offset == colspan + + # prepare for next round. + left_colspan = offset + left_index = index + left_width = dp[left_colspan][left_index].keys.first + + right_colspan = colspan - left_colspan + right_index = index + offset + right_width = dp[right_colspan][right_index].keys.first + + # calculate reference column width, give remaining spaces to left. + total_non_space_width = full_width - (colspan - 1) * space_width + ref_column_width = total_non_space_width / colspan + remainder = total_non_space_width % colspan + rem_left_width = [remainder, left_colspan].min + rem_right_width = remainder - rem_left_width + ref_left_width = ref_column_width * left_colspan + + (left_colspan - 1) * space_width + rem_left_width + ref_right_width = ref_column_width * right_colspan + + (right_colspan - 1) * space_width + rem_right_width + + # at most one width can be greater than the reference width. + if left_width <= ref_left_width and right_width <= ref_right_width + # use refernce width (evenly partition). + left_width = ref_left_width + right_width = ref_right_width + else + # the wider one takes its value, shorter one takes the rest. + if left_width > ref_left_width + right_width = full_width - left_width - space_width + else + left_width = full_width - right_width - space_width + end + end + + # run next round. + resolve.call(left_colspan, left_width, left_index) + resolve.call(right_colspan, right_width, right_index) + end + + full_width = dp[n_cols][0].keys.first + unless style.width.nil? + new_width = style.width - space_width - style.border_y_width + if new_width < full_width + raise "Table width exceeds wanted width " + + "of #{style.width} characters." + end + full_width = new_width + end + + resolve.call(n_cols, full_width) + end + + ## + # Return headings combined with rows. + + def headings_with_rows + @headings + rows + end + + def yield_or_eval &block + return unless block + if block.arity > 0 + yield self + else + self.instance_eval(&block) + end + end + + def title_cell_options + {:value => @title, :alignment => :center, :colspan => number_of_columns} + end + + def require_column_widths_recalc + @require_column_widths_recalc = true + end + + def column_widths + recalc_column_widths if @require_column_widths_recalc + @column_widths + end + end +end diff --git a/vendor/bundle/ruby/3.4.0/gems/terminal-table-3.0.2/lib/terminal-table/table_helper.rb b/vendor/bundle/ruby/3.4.0/gems/terminal-table-3.0.2/lib/terminal-table/table_helper.rb new file mode 100644 index 0000000..5a85325 --- /dev/null +++ b/vendor/bundle/ruby/3.4.0/gems/terminal-table-3.0.2/lib/terminal-table/table_helper.rb @@ -0,0 +1,9 @@ +module Terminal + class Table + module TableHelper + def table headings = [], *rows, &block + Terminal::Table.new :headings => headings.to_a, :rows => rows, &block + end + end + end +end diff --git a/vendor/bundle/ruby/3.4.0/gems/terminal-table-3.0.2/lib/terminal-table/util.rb b/vendor/bundle/ruby/3.4.0/gems/terminal-table-3.0.2/lib/terminal-table/util.rb new file mode 100644 index 0000000..a584c3d --- /dev/null +++ b/vendor/bundle/ruby/3.4.0/gems/terminal-table-3.0.2/lib/terminal-table/util.rb @@ -0,0 +1,13 @@ +module Terminal + class Table + module Util + # removes all ANSI escape sequences (e.g. color) + def ansi_escape(line) + line.to_s.gsub(/\x1b(\[|\(|\))[;?0-9]*[0-9A-Za-z]/, ''). + gsub(/\x1b(\[|\(|\))[;?0-9]*[0-9A-Za-z]/, ''). + gsub(/(\x03|\x1a)/, '') + end + module_function :ansi_escape + end + end +end diff --git a/vendor/bundle/ruby/3.4.0/gems/terminal-table-3.0.2/lib/terminal-table/version.rb b/vendor/bundle/ruby/3.4.0/gems/terminal-table-3.0.2/lib/terminal-table/version.rb new file mode 100644 index 0000000..42c0c18 --- /dev/null +++ b/vendor/bundle/ruby/3.4.0/gems/terminal-table-3.0.2/lib/terminal-table/version.rb @@ -0,0 +1,5 @@ +module Terminal + class Table + VERSION = '3.0.2' + end +end |
