From babee30dd697033e25c3dd64677cf3b52a998afd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Krzy=C5=BCanowski?= Date: Wed, 12 Oct 2022 14:34:20 +0700 Subject: [PATCH] Vertical table update (#9) Properly handle very long values, improve readability by setting minimum length for columns --- README.md | 5 +-- lib/nazar.rb | 5 +++ lib/nazar/base_table.rb | 2 +- lib/nazar/horizontal_table.rb | 8 ++++- lib/nazar/version.rb | 2 +- lib/nazar/vertical_table.rb | 49 ++++++++++++++++++++++++++++- spec/nazar/horizontal_table_spec.rb | 2 +- spec/nazar/vertical_table_spec.rb | 14 ++++----- 8 files changed, 73 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 2c86a3a..4ff1b5e 100644 --- a/README.md +++ b/README.md @@ -240,9 +240,10 @@ You can also configure behaviour of Nazar: | `Nazar.config.formatter.layout` | `:auto` | Determines which layout should be used. See Layouts for more details | | `Nazar.config.formatter.paginate` | `true` | Determines if results too long/wide should be printed directly, or paginated with `less`. Horizontal layout is always paginated. | `Nazar.config.formatter.boolean` | ['✓', '✗'] | First item in array is a character for `true`, second for `false` | -| `Nazar.config.formatter.resize` | `true` | Determines if the table should always be resized to take full width | | `Nazar.config.enable_shorthand_method` | true | Determines if shorthand method should be defined. See Opt-in setup for more details | - +| `Nazar.config.table.resize` | `true` | Determines if the table should always be resized to take full width | +| `Nazar.config.table.min_width` | `nil` | Sets minimum width. By default uses the longest header length | +| `Nazar.config.table.max_width` | `nil` | Determines maximum table width. If `resize` is set to true, uses terminal width by default, otherwise uses content length | ## Contributing Bug reports and pull requests are welcome on GitHub at https://github.com/krzyzak/nazar. diff --git a/lib/nazar.rb b/lib/nazar.rb index f3e6901..a4b01a2 100644 --- a/lib/nazar.rb +++ b/lib/nazar.rb @@ -24,7 +24,12 @@ module Nazar # rubocop:disable Metrics/ModuleLength setting :boolean, default: ['✓', '✗'] setting :layout, default: :auto setting :paginate, default: true + end + + setting :table do setting :resize, default: true + setting :min_width, default: nil + setting :max_width, default: nil end setting :colors do diff --git a/lib/nazar/base_table.rb b/lib/nazar/base_table.rb index 77ba0b7..fdd1512 100644 --- a/lib/nazar/base_table.rb +++ b/lib/nazar/base_table.rb @@ -25,7 +25,7 @@ def table end def resize - Nazar.config.formatter.resize + Nazar.config.table.resize end def summary_row(value) diff --git a/lib/nazar/horizontal_table.rb b/lib/nazar/horizontal_table.rb index ecb2d52..da7a913 100644 --- a/lib/nazar/horizontal_table.rb +++ b/lib/nazar/horizontal_table.rb @@ -3,7 +3,7 @@ module Nazar class HorizontalTable < BaseTable def render - table.render(:unicode, border: { separator: :each_row }, multiline: true, resize: resize) + table.render(:unicode, options) end private @@ -11,5 +11,11 @@ def render def summary_row(value) super.fill(nil, 3, table.columns_size - 3) end + + def options + { border: { separator: :each_row }, multiline: true, resize: resize }.tap do |hash| + hash[:width] = Nazar.config.table.max_width if Nazar.config.table.max_width + end + end end end diff --git a/lib/nazar/version.rb b/lib/nazar/version.rb index 1fcb118..623c65d 100644 --- a/lib/nazar/version.rb +++ b/lib/nazar/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module Nazar - VERSION = '1.1.0' + VERSION = '1.2.0' end diff --git a/lib/nazar/vertical_table.rb b/lib/nazar/vertical_table.rb index 6eb34a1..709a24a 100644 --- a/lib/nazar/vertical_table.rb +++ b/lib/nazar/vertical_table.rb @@ -23,7 +23,7 @@ class VerticalBorder < TTY::Table::Border end def render - table.render_with(VerticalBorder, multiline: true, resize: resize) do |renderer| + table.render_with(VerticalBorder, options) do |renderer| renderer.border.style = :green if Nazar.config.colors.enabled renderer.border.separator = separators_around_each_item end @@ -37,6 +37,15 @@ def table @table ||= TTY::Table.new(rows: cells) end + def options + { + multiline: true, + resize: resize, + column_widths: column_widths, + width: max_width + } + end + def cells @cells.flat_map do |cell| cell.map.with_index do |item, index| @@ -50,5 +59,43 @@ def separators_around_each_item (i % headers.size).zero? || ((i + 1) % headers.size).zero? end end + + def column_widths + [headers_width, values_width] + end + + def max_width + Nazar.config.table.max_width || default_width + end + + def default_width + Nazar.config.table.resize ? TTY::Screen.width : natural_width + padding + end + + def natural_width + content_size = headers_width + content_width + + [content_size, TTY::Screen.width].min + end + + def content_width + cells.flatten.map(&:size).max + end + + def headers_width + [headers.map(&:size).max + 1, Nazar.config.table.min_width].compact.min + end + + def values_width + if Nazar.config.table.resize + TTY::Screen.width - headers_width + else + [content_width, TTY::Screen.width - headers_width].min + end + end + + def padding + 3 + end end end diff --git a/spec/nazar/horizontal_table_spec.rb b/spec/nazar/horizontal_table_spec.rb index 72a91ad..05188bd 100644 --- a/spec/nazar/horizontal_table_spec.rb +++ b/spec/nazar/horizontal_table_spec.rb @@ -4,7 +4,7 @@ RSpec.describe Nazar::HorizontalTable do before do - Nazar.config.formatter.resize = false + Nazar.config.table.resize = false end subject { described_class.new(headers, cells) } diff --git a/spec/nazar/vertical_table_spec.rb b/spec/nazar/vertical_table_spec.rb index 34dfbf7..4357fac 100644 --- a/spec/nazar/vertical_table_spec.rb +++ b/spec/nazar/vertical_table_spec.rb @@ -4,9 +4,9 @@ RSpec.describe Nazar::VerticalTable do before do - Nazar.config.formatter.resize = false @colors_before = Nazar.config.colors.enabled Nazar.config.colors.enabled = false + Nazar.config.table.resize = false end after do @@ -16,23 +16,23 @@ subject { described_class.new(headers, cells) } let(:headers) { ['Id', 'Name', 'Age'] } let(:cells) { [[1, 'John', 27], [2, 'Jane', 35]] } - let(:line) { "────────────\n" } describe '#render' do it 'renders data vertically' do table = subject.render.gsub(/[ \t]+$/, '') # Remove trailing whitespaces + expect(table).to eq(<<~TABLE.chomp) - ──────────── + ──────────────── Id 1 - ──────────── + ──────────────── Name John Age 27 - ──────────── + ──────────────── Id 2 - ──────────── + ──────────────── Name Jane Age 35 - ──────────── + ──────────────── TABLE end end