Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ The return value is a native PG::Result object, which supports mapping or extrac
=> #<PG::Result:0x000000012ebf6a38 status=PGRES_TUPLES_OK ntuples=3 nfields=1 cmd_tuples=3>
```

## TODO

- [ ] `--list` / `--table` CLI flags to override auto-detection

## Development

After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
Expand Down
17 changes: 16 additions & 1 deletion lib/taql.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
require "io/console"
require_relative "taql/cli"
require_relative "taql/list"
require_relative "taql/table"
require_relative "taql/version"
require_relative "taql/railtie" if defined?(Rails)
Expand All @@ -10,13 +12,26 @@ class << self
def execute(query, options = {}, connection: nil)
(connection || default_connection).execute(query).tap do |result|
if (results = result.entries).any?
$stdout.puts Table.new(results, markdown: options[:markdown])
$stdout.puts formatter(results, markdown: options[:markdown])
end
end
end

private

def formatter(results, markdown: false)
table = Table.new(results, markdown: markdown)
if !markdown && table.table_width > terminal_width
List.new(results, terminal_width: terminal_width)
else
table
end
end

def terminal_width
IO.console&.winsize&.last || Float::INFINITY
end

def default_connection
@default_connection&.call || raise("Taql not properly initialized with Rails")
end
Expand Down
49 changes: 49 additions & 0 deletions lib/taql/list.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
module Taql
class List
DASH = "-".freeze
PIPE = " | ".freeze

def initialize(entries, terminal_width: nil)
@entries = entries.map { |entry| entry.transform_values(&:to_s) }
@terminal_width = terminal_width
end

def print
output if entries.any?
end

private

attr_reader :entries

def headers
@headers ||= entries.flat_map(&:keys).uniq
end

def max_header_width
@max_header_width ||= headers.map(&:length).max
end

def divider_width
@terminal_width&.finite? ? @terminal_width : 32
end

def output
records = entries.map { |entry| [separator, *rows(entry)].join("\n") }

[*records, separator].join("\n")
end

def separator
DASH * divider_width
end

def rows(entry)
headers.map do |header|
"#{header.upcase.rjust(max_header_width)}#{PIPE}#{entry[header]}"
end
end

alias_method :to_s, :print
end
end
4 changes: 4 additions & 0 deletions lib/taql/table.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ def initialize(entries, markdown: false)
@markdown = markdown
end

def table_width
column_widths.sum + (3 * columns.count) + 1
end

def body
entries.map(&:values)
end
Expand Down
74 changes: 74 additions & 0 deletions test/test_list.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
require "test_helper"

class TestList < Minitest::Test
def test_vertical_output
list = Taql::List.new([
{"name" => "Alice", "age" => 30},
{"name" => "Bob", "age" => 25}
], terminal_width: 40)

result = list.print

assert_includes result, "NAME | Alice"
assert_includes result, " AGE | 25"
end

def test_single_record
list = Taql::List.new([
{"name" => "Alice", "age" => 30}
], terminal_width: 40)

result = list.print

assert_includes result, "NAME | Alice"
assert_includes result, " AGE | 30"
end

def test_divider_fills_terminal_width
list = Taql::List.new([
{"name" => "Alice"}
], terminal_width: 40)

lines = list.print.lines.map(&:chomp)

assert_equal 40, lines.first.length
assert_equal 40, lines.last.length
end

def test_trailing_separator
list = Taql::List.new([
{"name" => "Alice"}
], terminal_width: 40)

last_line = list.print.lines.last.chomp

assert_match(/\A-+\z/, last_line)
end

def test_renders_nothing_when_empty
list = Taql::List.new([])

assert_nil list.print
end

def test_default_divider_without_terminal_width
list = Taql::List.new([
{"name" => "Alice"}
])

result = list.print

assert_match(/\A-+\n/, result)
end

def test_headers_are_right_padded
list = Taql::List.new([
{"name" => "Alice", "email" => "alice@example.com"}
], terminal_width: 40)

result = list.print

assert_includes result, " NAME | Alice"
assert_includes result, "EMAIL | alice@example.com"
end
end
8 changes: 8 additions & 0 deletions test/test_table.rb
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,12 @@ def test_headers_with_heterogeneous_entries

assert_equal ["name", "age", "email"], table.headers
end

def test_table_width_calculation
table = Taql::Table.new([
{"name" => "Alice", "age" => 30}
])

assert_equal 15, table.table_width
end
end
Loading