Skip to content

Commit

Permalink
new and improved methods for border separation including dash/dot3/do…
Browse files Browse the repository at this point in the history
…t4 support
  • Loading branch information
nanobowers committed Jan 26, 2021
1 parent 7b62f1c commit 404b89c
Show file tree
Hide file tree
Showing 5 changed files with 179 additions and 35 deletions.
40 changes: 38 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -324,16 +324,19 @@ Inside the `UnicodeBorder` class, there are definitions for a variety of corner/

```
@data = {
nil => nil,
nw: "┌", nx: "─", n: "┬", ne: "┐",
yw: "│", y: "│", ye: "│",
hw: "╞", hx: "═", hi: "╪", he: "╡", hd: '╤', hu: "╧",
aw: "╞", ax: "═", ai: "╪", ae: "╡", ad: '╤', au: "╧",
bw: "┝", bx: "━", bi: "┿", be: "┥", bd: '┯', bu: "┷",
w: "├", x: "─", i: "┼", e: "┤", dn: "┬", up: "┴",
sw: "└", sx: "─", s: "┴", se: "┘",
}
```

Note that many are defined as directional (:nw == north-west), others defined in terms of 'x' or 'y'.
The border that separates headings (below each heading) are defined with 'h*' entries.
The border that separates headings (below each heading) is of type `:double` and is defined with 'a*' entries.
Alternate `:heavy` types that can be applied to separators can be defined with 'b*' entries.

When defining a new set of borders, it's probably easiest to define a new class that inherits from UnicodeBorder and replaces the @data Hash.
However, these corners can be these can be overridden with:
Expand All @@ -343,6 +346,39 @@ table.style = {border: :unicode}
table.style.border[:nw] = '*' # override the north-west corner of the table
```

### Customizing row separators

Row-separators can now be customized in a variety of ways. The default separator's border_type is referred to as `:mid`. Additional `:strong` / `:strong_a` and `:strong_b` separator styles can be applied to separate sections (e.g. header/footer/title).

The separator border_type may be specified when a user-defined separator added. Alternatively, borders may be adjusted after the table's rows are elaborated, but before the table is rendered.

Separator `border_type`s can be adjusted to be heavy, use double-lines, and different dash/dot styles. The border type should be one of:

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


To manually set the separator border_type, the `add_separator` method may be called.
```ruby
add_separator(border_type: :heavy_dash)
```

Alternatively, if `style: :all_separators` is used, it may be necessary to elaborate the Rows prior to rendering.
```ruby
table = Terminal::Table.new do |t|
t.add_row [1, 'One']
t.add_row [2, 'Two']
t.add_row [3, 'Three']
t.style = {:all_separators => true}
end
rows = table.elaborate_rows
rows[2].border_type = :heavy # modify separator row: emphasize below title
puts table.render
```

## More examples

For more examples, please see the `examples` directory included in the
Expand Down
4 changes: 2 additions & 2 deletions lib/terminal-table/separator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ class Separator < Row
#
# `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,
# :mid for interior, and :strong for emphasized-interior)
# :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: :mid, implicit: false)
def initialize(*args, border_type: :div, implicit: false)
super
@prevrow, @nextrow = nil, nil
@border_type = border_type
Expand Down
66 changes: 48 additions & 18 deletions lib/terminal-table/style.rb
Original file line number Diff line number Diff line change
Expand Up @@ -70,22 +70,35 @@ def initialize

class UnicodeBorder < Border

ALLOWED_SEPARATOR_BORDER_STYLES = %i[top bot mid strong]
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 hx nx]
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
hw hi he hd hu
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: "│",
hw: "╞", hx: "═", hi: "╪", he: "╡", hd: '╤', hu: "╧",
w: "├", x: "─", i: "┼", e: "┤", dn: "┬", up: "┴",
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
Expand All @@ -97,17 +110,29 @@ def vertical
# 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 must be one of #{ALLOWED_SEPARATOR_BORDER_STYLES.inspect}, was #{type.inspect}" unless ALLOWED_SEPARATOR_BORDER_STYLES.include?(type)
rval = case type
when :strong # (typically used for the separator below the heading row or above a footer row)
[@data[:hw], @data[:hx], @data[:hi], @data[:he], @data[:hd], @data[:hu] ]
when :top
[@data[:nw], @data[:nx], @data[:n], @data[:ne], @data[:n], nil ]
when :bot
[@data[:sw], @data[:sx], @data[:s], @data[:se], nil, @data[:s] || @data[:up] ]
else # :mid (center, unbolded)
[@data[:w], @data[:x], @data[:i], @data[:e], @data[:dn], @data[:up] ]
end
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
Expand All @@ -127,11 +152,16 @@ class UnicodeThickEdgeBorder < UnicodeBorder
def initialize
super
@data = {
nil => nil,
nw: "┏", nx: "━", n: "┯", ne: "┓", nd: nil,
yw: "┃", y: "│", ye: "┃",
hw: "┣", hx: "═", hi: "╪", he: "┫", hd: '╤', hu: "╧",
w: "┠", x: "─", i: "┼", e: "┨", dn: "┬", up: "┴",
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
Expand Down
8 changes: 4 additions & 4 deletions lib/terminal-table/table.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def add_row array
##
# Add a separator.

def add_separator(border_type: :mid)
def add_separator(border_type: :div)
@rows << Separator.new(self, border_type: border_type)
end

Expand Down Expand Up @@ -135,13 +135,13 @@ def elaborate_rows
@headings.each do |row|
unless row.cells.empty?
buffer << row
buffer << Separator.new(self, border_type: :strong, implicit: true)
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 :mid
border_type = (idx == @rows.size - 1) ? :bot : :mid
# 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
Expand Down
96 changes: 87 additions & 9 deletions spec/unicode_table_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ module Terminal
@table.headings = ['Char', 'Num']
@table << ['a', 1]
separator = Terminal::Table::Separator.new(@table)
# For UnicodeBorder this now defaults to a :mid border_type
# For UnicodeBorder this now defaults to a :div border_type
separator.render.should eq '├────────────┤'
end

Expand Down Expand Up @@ -129,15 +129,15 @@ module Terminal
:padding_left => 0, :padding_right => 2,
:margin_left => 'y' * 2
}
@table.style.border[:hi] = "x"
@table.style.border[:ai] = "x"
@table.style.border[:y] = ":"
@table.style.border[:nw] = "1"
@table.style.border[:ne] = "2"
@table.style.border[:sw] = "3"
@table.style.border[:se] = "4"
@table.style.border[:s] = "^"
@table.style.border[:hw] = "5"
@table.style.border[:he] = "6"
@table.style.border[:aw] = "5"
@table.style.border[:ae] = "6"

@table << ['a', 1]
@table << ['b', 2]
Expand Down Expand Up @@ -685,7 +685,7 @@ module Terminal
it "should be able to make a footer row" do
@table.headings = ['name', 'value']
@table.rows = [['a', 1], ['b', 2], ['c', 3]]
@table.add_separator(border_type: :strong)
@table.add_separator(border_type: :double)
@table.add_row ['tot', 6]
@table.render.should eq <<-EOF.deindent
┌──────┬───────┐
Expand All @@ -709,13 +709,13 @@ module Terminal
# Elaborate here, and we will modify the border-types
# post elaboration.
rows = @table.elaborate_rows
rows[2].border_type = :strong # emphasize below title
rows[4].border_type = :mid # de-emphasize below header
rows[-3].border_type = :strong # emphasize above footer
rows[2].border_type = :heavy # emphasize below title
rows[4].border_type = :div # de-emphasize below header
rows[-3].border_type = :double # emphasize above footer
@table.render.should eq <<-EOF.deindent
┌──────────────┐
│ Animals │
╞══════╤═══════╡
┝━━━━━━┯━━━━━━━┥
│ name │ value │
├──────┼───────┤
│ rat │ 1 │
Expand All @@ -729,5 +729,83 @@ module Terminal
EOF
end

it "should be able manually specify separator borders" do
@table.style = { border: :unicode_round }
@table.title = 'Animals'
@table.headings = ['name', 'value']
@table.add_row ['rat', 1]
@table.add_separator
@table.add_row ['cat', 2]
@table.add_separator(border_type: :bold)
@table.add_row ['dog', 3]
@table.add_separator(border_type: :double)
@table.add_row ['totl', 6]
@table.render.should eq <<-EOF.deindent
╭──────────────╮
│ Animals │
├──────┬───────┤
│ name │ value │
╞══════╪═══════╡
│ rat │ 1 │
├──────┼───────┤
│ cat │ 2 │
┝━━━━━━┿━━━━━━━┥
│ dog │ 3 │
╞══════╪═══════╡
│ totl │ 6 │
╰──────┴───────╯
EOF
end

it "should test many separator borders" do
@table.style = { border: :unicode_thick_edge }
@table.title = 'Borders'
@table.headings = ['name', 'value']
@table.add_row ['1st', 1]
@table.add_separator(border_type: :heavy)
@table.add_separator(border_type: :heavy_dash)
@table.add_separator(border_type: :heavy_dot3)
@table.add_separator(border_type: :heavy_dot4)
@table.add_separator(border_type: :thick)
@table.add_separator(border_type: :thick_dash)
@table.add_separator(border_type: :thick_dot3)
@table.add_separator(border_type: :thick_dot4)
@table.add_separator(border_type: :bold)
@table.add_separator(border_type: :bold_dash)
@table.add_separator(border_type: :bold_dot3)
@table.add_separator(border_type: :bold_dot4)
@table.add_separator(border_type: :dash)
@table.add_separator(border_type: :dot3)
@table.add_separator(border_type: :dot4)
@table.add_separator(border_type: :double)
@table.add_row ['last', 'N']
@table.render.should eq <<-EOF.deindent
┏━━━━━━━━━━━━━━┓
┃ Borders ┃
┠──────┬───────┨
┃ name │ value ┃
┣══════╪═══════┫
┃ 1st │ 1 ┃
┣━━━━━━┿━━━━━━━┫
┣╍╍╍╍╍╍┿╍╍╍╍╍╍╍┫
┣┅┅┅┅┅┅┿┅┅┅┅┅┅┅┫
┣┉┉┉┉┉┉┿┉┉┉┉┉┉┉┫
┣━━━━━━┿━━━━━━━┫
┣╍╍╍╍╍╍┿╍╍╍╍╍╍╍┫
┣┅┅┅┅┅┅┿┅┅┅┅┅┅┅┫
┣┉┉┉┉┉┉┿┉┉┉┉┉┉┉┫
┣━━━━━━┿━━━━━━━┫
┣╍╍╍╍╍╍┿╍╍╍╍╍╍╍┫
┣┅┅┅┅┅┅┿┅┅┅┅┅┅┅┫
┣┉┉┉┉┉┉┿┉┉┉┉┉┉┉┫
┠╌╌╌╌╌╌┼╌╌╌╌╌╌╌┨
┠┄┄┄┄┄┄┼┄┄┄┄┄┄┄┨
┠┈┈┈┈┈┈┼┈┈┈┈┈┈┈┨
┣══════╪═══════┫
┃ last │ N ┃
┗━━━━━━┷━━━━━━━┛
EOF
end

end
end

0 comments on commit 404b89c

Please sign in to comment.