typed_print 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 85e9b5563417e0d0cb32b45b946ec26f3697a220802c6e012595faecc3d74275
4
- data.tar.gz: b40e48244c2020e69b5f25c3049468f7431df3b7eb6a60d6a35080ace995cc63
3
+ metadata.gz: 4ded9b786c7fc0596377055e783a299fe9eab5558d0d375d978f8186ab72c840
4
+ data.tar.gz: d6433125b154f6b2deaaf7764b2b02919d72d4e25e53edc1a2af379265289c96
5
5
  SHA512:
6
- metadata.gz: f4d9957cd9d3647ee46761fca7ecfc70093958719730d56f39dd10442392dc29d70a6779bed68ff60a45eb1890780d28c4162defec8b2107e90a758b6d224350
7
- data.tar.gz: c18f2fa2dcebc25b150a914afa7795ce07434aa3b43dd3ad3d0abad64c3ce9e3574ed08a3667e214b33bff7cd1977d0eacdd98f4674de2e4265ddef2e4c2efc0
6
+ metadata.gz: 8d7b5bd554c0e68e5d8846103e2020db279a96f3ce7d075281492a42570f7d055dd58c38a15bfe8d3be8b6af67a1f30c6c3d81d476c5d080d533049ad62a8561
7
+ data.tar.gz: 27cdf2be6875f4a47f666c5716db1b50b1ffa3136d3ba548a8d8d6f8a123be07ae3f73d8a92c1a6031f75b3fd03011490aea81508bb5140678fbb09faba9b820
data/CHANGELOG.md CHANGED
@@ -1,13 +1,31 @@
1
+ # Changelog
2
+
3
+ ## [0.3.0] - 2026-04-27
4
+
5
+ ### Added
6
+ - Optional color support via `pastel` gem (runtime optional, dev dependency)
7
+ - `color: true` for automatic type-based coloring (headers cyan, numbers green, booleans green/red, nil gray)
8
+ - `colors: { col: :color }` for manual per-column color mapping
9
+ - Color support for both `:plain` and `:markdown` formats
10
+
11
+ ## [0.2.0] - 2026-04-22
12
+
13
+ ### Added
14
+ - Markdown table output with `format: :markdown` option
15
+ - New `TypedPrint.table` method returns string without printing
16
+ - Support for both plain and markdown formats
17
+
18
+ ### Changed
19
+ - Internal refactoring to support multiple output formats
20
+
1
21
  ## [0.1.0] - 2026-04-21
2
22
 
3
23
  ### Added
4
24
  - Initial release
5
25
  - Basic table formatting for Ruby hashes
6
26
  - Column alignment options (left, right, center)
7
- - Column filtering with `:only` option
8
- - Custom headers with `:headers` option
27
+ - Column filtering with `only:` option
28
+ - Custom headers with `headers:` option
9
29
  - Smart type formatting (booleans, nil, strings)
10
30
  - Preserves original column order
11
- - `TypedPrint.print` method for printing to stdout
12
- - `TypedPrint.table` method for returning formatted string
13
31
  - Zero dependencies
data/README.md CHANGED
@@ -8,29 +8,29 @@ Beautiful, aligned table output for Ruby hashes and objects with zero dependenci
8
8
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
9
9
  [![Gem Downloads](https://img.shields.io/gem/dt/typed_print)](https://rubygems.org/gems/typed_print)
10
10
 
11
+ ![TypedPrint Demo](assets/demo.gif)
12
+
11
13
  ## Features
12
14
 
13
- - 🚀 Zero dependencies
15
+ - 🚀 Zero runtime dependencies
14
16
  - 📊 Automatic column width calculation
15
17
  - 🎯 Smart type formatting (booleans, nil, strings)
16
18
  - 📐 Column alignment (left, right, center)
17
19
  - 🎨 Custom column headers
18
20
  - 🔍 Column filtering
19
21
  - 📝 Preserves original column order
22
+ - 📄 Markdown table output (v0.2.0+)
23
+ - 🌈 Optional color output via `pastel` gem (v0.3.0+)
20
24
 
21
25
  ## Installation
22
26
 
23
27
  Add this line to your application's Gemfile:
24
28
 
25
- ```ruby
26
- gem 'typed_print'
27
- ```
29
+ `gem 'typed_print'`
28
30
 
29
31
  Or install it yourself:
30
32
 
31
- ```bash
32
- gem install typed_print
33
- ```
33
+ `gem install typed_print`
34
34
 
35
35
  ## Usage
36
36
 
@@ -48,72 +48,78 @@ TypedPrint.print(data)
48
48
  ```
49
49
 
50
50
  Output:
51
+
51
52
  ```
52
- Name Score Active
53
+ Name Score Active
53
54
  ------+------+-------
54
55
  Alice 100 true
55
56
  Bob 42 false
56
57
  ```
57
58
 
58
- ### Column Alignment
59
+ ### Markdown Format (NEW in v0.2.0)
60
+ ```ruby
61
+ TypedPrint.print(data, format: :markdown)
62
+ ```
59
63
 
60
- Right-align specific columns:
64
+ Output:
65
+ ```
66
+ | Name | Score | Active |
67
+ |-------|-------|--------|
68
+ | Alice | 100 | true |
69
+ | Bob | 42 | false |
70
+ ```
61
71
 
72
+ ### Column Alignment
62
73
  ```ruby
63
74
  TypedPrint.print(data, align: { score: :right })
64
75
  ```
65
76
 
66
77
  Output:
67
78
  ```
68
- Name Score Active
79
+ Name Score Active
69
80
  ------+------+-------
70
81
  Alice 100 true
71
- Bob 42 false
82
+ Bob 42 false
72
83
  ```
73
84
 
74
85
  ### Filter Columns
75
86
 
76
- Show only specific columns:
77
-
78
87
  ```ruby
79
88
  TypedPrint.print(data, only: [:name, :score])
80
89
  ```
81
90
 
82
91
  Output:
83
92
  ```
84
- Name Score
93
+ Name Score
85
94
  ------+------
86
95
  Alice 100
87
96
  Bob 42
88
97
  ```
89
98
 
90
99
  ### Custom Headers
91
-
92
- Rename columns for display:
93
-
94
100
  ```ruby
95
101
  TypedPrint.print(data, headers: { name: "Username", score: "Points", active: "Status" })
96
102
  ```
97
103
 
98
104
  Output:
99
105
  ```
100
- Username Points Status
106
+ Username Points Status
101
107
  ---------+------+-------
102
108
  Alice 100 true
103
109
  Bob 42 false
104
110
  ```
105
111
 
106
112
  ### Return String Instead of Printing
107
-
108
- Use `table` method to get the formatted string:
109
-
110
113
  ```ruby
111
114
  table_string = TypedPrint.table(data)
112
115
  puts table_string.upcase
113
- ```
114
116
 
115
- ### Working with Different Data Types
117
+ # Markdown format
118
+ markdown_string = TypedPrint.table(data, format: :markdown)
119
+ File.write("table.md", markdown_string)
120
+ ````
116
121
 
122
+ ### Working with Different Data Types
117
123
  ```ruby
118
124
  mixed_data = [
119
125
  { name: "Product A", price: 29.99, in_stock: true, notes: nil },
@@ -125,25 +131,49 @@ TypedPrint.print(mixed_data)
125
131
 
126
132
  Output:
127
133
  ```
128
- Name Price In_stock Notes
134
+ Name Price In_stock Notes
129
135
  ----------+-------+---------+-------------
130
136
  Product A 29.99 true
131
137
  Product B 49.99 false Limited edition
132
138
  ```
133
139
 
134
140
  ## API Reference
135
-
136
141
  `TypedPrint.print(data, options)` Prints the formatted table to stdout and returns `nil`.
137
142
 
143
+
138
144
  **Options:**
139
145
  - `align: Hash` - Column alignment (`:left`, `:right`, `:center`), defaults to `:left`
140
146
  - `only: Array` - Array of column symbols to display
141
147
  - `headers: Hash` - Custom headers for columns
148
+ - `format: Symbol` - Output format (`:plain` or `:markdown`), defaults to `:plain`
149
+ - `color: Boolean` - Auto color by type (headers cyan, numbers/true green, false red, nil gray), requires `pastel` gem
150
+ - `colors: Hash` - Manual per-column color map (e.g. `{ name: :cyan, score: :green }`), requires `pastel` gem
142
151
 
143
152
  `TypedPrint.table(data, options)` returns the formatted table as a string.
144
153
 
145
154
  Same options as `print`.
146
155
 
156
+ ### Color Output (v0.3.0+)
157
+
158
+ Color support is optional and requires the `pastel` gem. Add it to your Gemfile:
159
+
160
+ ```ruby
161
+ gem 'pastel'
162
+ ```
163
+
164
+ **Automatic coloring by type:**
165
+ ```ruby
166
+ TypedPrint.print(data, color: true)
167
+ # Headers → cyan, Integer/Float/true → green, false → red, nil → gray
168
+ ```
169
+
170
+ **Manual per-column colors:**
171
+ ```ruby
172
+ TypedPrint.print(data, colors: { name: :cyan, score: :green, active: :yellow })
173
+ ```
174
+
175
+ Both `:plain` and `:markdown` formats support color. If `pastel` is not installed, color options are silently ignored and output is plain text.
176
+
147
177
  ## Development
148
178
 
149
179
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests.
data/assets/demo.gif ADDED
Binary file
data/assets/demo.rb ADDED
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ $LOAD_PATH.unshift File.expand_path("../lib", __dir__)
4
+ require "typed_print"
5
+
6
+ data = [
7
+ { name: "Alice", score: 98, active: true },
8
+ { name: "Bob", score: 74, active: false },
9
+ { name: "Charlie", score: 61, active: true },
10
+ { name: "Diana", score: 42, active: false }
11
+ ]
12
+
13
+ puts "# Basic table"
14
+ TypedPrint.print(data)
15
+ sleep 2
16
+
17
+ puts "\n# Right-align score column"
18
+ TypedPrint.print(data, align: { score: :right })
19
+ sleep 2
20
+
21
+ puts "\n# Filter columns"
22
+ TypedPrint.print(data, only: [:name, :score])
23
+ sleep 2
24
+
25
+ puts "\n# Custom headers"
26
+ TypedPrint.print(data, headers: { name: "Player", score: "Points", active: "Status" })
27
+ sleep 2
28
+
29
+ puts "\n# Markdown format"
30
+ TypedPrint.print(data, format: :markdown)
31
+ sleep 2
32
+
33
+ puts "\n# Automatic colors"
34
+ TypedPrint.print(data, color: true)
35
+ sleep 2
36
+
37
+ puts "\n# Manual colors"
38
+ TypedPrint.print(data, colors: { name: :cyan, score: :green, active: :yellow })
data/assets/demo.tape ADDED
@@ -0,0 +1,14 @@
1
+ Output assets/demo.gif
2
+
3
+ Set FontSize 14
4
+ Set Width 800
5
+ Set Height 600
6
+ Set Theme "Dracula"
7
+ Set Shell "bash"
8
+ Set TypingSpeed 40ms
9
+
10
+ Sleep 1s
11
+ Type "bundle exec ruby assets/demo.rb"
12
+ Sleep 800ms
13
+ Enter
14
+ Sleep 18s
@@ -1,12 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ begin
4
+ require "pastel"
5
+ rescue LoadError
6
+ # Pastel not installed; color output silently disabled
7
+ end
8
+
3
9
  module TypedPrint
4
10
  class Table
5
- def initialize(data, alignments = {}, only_columns = nil, custom_headers = {})
11
+ def initialize(data, alignments = {}, only_columns = nil, custom_headers = {}, color: false, colors: nil)
6
12
  @data = data
7
13
  @alignments = alignments
8
14
  @only_columns = only_columns&.map(&:to_sym)
9
15
  @custom_headers = custom_headers.transform_keys(&:to_sym)
16
+ @color_auto = color
17
+ @colors = colors&.transform_keys(&:to_sym)
10
18
 
11
19
  @headers = determine_headers
12
20
  end
@@ -22,32 +30,30 @@ module TypedPrint
22
30
  def render_plain
23
31
  return "" if @data.empty?
24
32
 
25
- # Build rows
26
- rows = @data.map { |row| @headers.map { |h| format_value(row[h]) } }
33
+ rows_plain = @data.map { |row| @headers.map { |h| format_value(row[h]) } }
34
+ header_strings_plain = @headers.map { |h| header_label(h) }
27
35
 
28
- # Build header strings (with custom headers or capitalized defaults)
29
- header_strings = @headers.map do |h|
30
- if @custom_headers[h]
31
- @custom_headers[h]
32
- else
33
- h.to_s.split('_').map(&:capitalize).join(' ')
34
- end
35
- end
36
-
37
- # Calculate column widths
38
- column_widths = header_strings.map(&:length)
39
- rows.each do |row|
36
+ column_widths = header_strings_plain.map(&:length)
37
+ rows_plain.each do |row|
40
38
  row.each_with_index do |cell, i|
41
39
  column_widths[i] = [column_widths[i], cell.length].max
42
40
  end
43
41
  end
44
42
 
45
- # Build output
43
+ if color_mode?
44
+ header_color = @color_auto ? :cyan : nil
45
+ header_strings_display = header_strings_plain.map { |h| colorize(h, header_color) }
46
+ rows_display = @data.map { |row| @headers.map { |h| colorize_cell(h, row[h]) } }
47
+ else
48
+ header_strings_display = header_strings_plain
49
+ rows_display = rows_plain
50
+ end
51
+
46
52
  output = []
47
- output << format_row(header_strings, column_widths, :center)
53
+ output << format_row(header_strings_display, column_widths, :center, header_strings_plain)
48
54
  output << separator(column_widths)
49
- rows.each do |row|
50
- output << format_row(row, column_widths)
55
+ rows_plain.each_with_index do |plain_row, ri|
56
+ output << format_row(rows_display[ri], column_widths, nil, plain_row)
51
57
  end
52
58
 
53
59
  output.join("\n")
@@ -56,35 +62,34 @@ module TypedPrint
56
62
  def render_markdown
57
63
  return "" if @data.empty?
58
64
 
59
- # Build rows
60
- rows = @data.map { |row| @headers.map { |h| format_value(row[h]) } }
65
+ rows_plain = @data.map { |row| @headers.map { |h| format_value(row[h]) } }
66
+ header_strings_plain = @headers.map { |h| header_label(h) }
61
67
 
62
- # Build header strings
63
- header_strings = @headers.map do |h|
64
- if @custom_headers[h]
65
- @custom_headers[h]
66
- else
67
- h.to_s.split('_').map(&:capitalize).join(' ')
68
- end
69
- end
70
-
71
- # Calculate column widths for consistent spacing
72
- column_widths = header_strings.map(&:length)
73
- rows.each do |row|
68
+ column_widths = header_strings_plain.map(&:length)
69
+ rows_plain.each do |row|
74
70
  row.each_with_index do |cell, i|
75
71
  column_widths[i] = [column_widths[i], cell.length].max
76
72
  end
77
73
  end
78
74
 
79
- # Build markdown table
75
+ if color_mode?
76
+ header_color = @color_auto ? :cyan : nil
77
+ header_strings_display = header_strings_plain.map { |h| colorize(h, header_color) }
78
+ rows_display = @data.map { |row| @headers.map { |h| colorize_cell(h, row[h]) } }
79
+ else
80
+ header_strings_display = header_strings_plain
81
+ rows_display = rows_plain
82
+ end
83
+
80
84
  output = []
81
- # Header row
82
- output << "| " + header_strings.each_with_index.map { |h, i| h.ljust(column_widths[i]) }.join(" | ") + " |"
83
- # Separator row
85
+ output << "| " + header_strings_display.each_with_index.map { |h, i|
86
+ pad_right(h, header_strings_plain[i], column_widths[i])
87
+ }.join(" | ") + " |"
84
88
  output << "|" + column_widths.map { |w| "-" * (w + 2) }.join("|") + "|"
85
- # Data rows
86
- rows.each do |row|
87
- output << "| " + row.each_with_index.map { |cell, i| cell.ljust(column_widths[i]) }.join(" | ") + " |"
89
+ rows_plain.each_with_index do |plain_row, ri|
90
+ output << "| " + rows_display[ri].each_with_index.map { |cell, i|
91
+ pad_right(cell, plain_row[i], column_widths[i])
92
+ }.join(" | ") + " |"
88
93
  end
89
94
 
90
95
  output.join("\n")
@@ -101,6 +106,49 @@ module TypedPrint
101
106
  end
102
107
  end
103
108
 
109
+ def header_label(h)
110
+ if @custom_headers[h]
111
+ @custom_headers[h]
112
+ else
113
+ h.to_s.split("_").map(&:capitalize).join(" ")
114
+ end
115
+ end
116
+
117
+ def color_mode?
118
+ @color_auto || (@colors && !@colors.empty?)
119
+ end
120
+
121
+ def colorize(text, color)
122
+ return text unless color && defined?(Pastel)
123
+ @pastel ||= Pastel.new
124
+ @pastel.send(color, text)
125
+ rescue
126
+ text
127
+ end
128
+
129
+ def colorize_cell(header_key, original_value)
130
+ plain = format_value(original_value)
131
+ color = cell_color(header_key, original_value)
132
+ colorize(plain, color)
133
+ end
134
+
135
+ def cell_color(header_key, value)
136
+ if @colors
137
+ @colors[header_key]
138
+ elsif @color_auto
139
+ auto_color(value)
140
+ end
141
+ end
142
+
143
+ def auto_color(value)
144
+ case value
145
+ when Integer, Float then :green
146
+ when true then :green
147
+ when false then :red
148
+ when nil then :bright_black
149
+ end
150
+ end
151
+
104
152
  def determine_headers
105
153
  all_keys = @data.flat_map(&:keys).uniq
106
154
 
@@ -112,8 +160,9 @@ module TypedPrint
112
160
  end
113
161
  end
114
162
 
115
- def format_row(cells, widths, alignment_override = nil)
163
+ def format_row(cells, widths, alignment_override = nil, plain_cells = nil)
116
164
  cells.each_with_index.map do |cell, i|
165
+ plain_cell = plain_cells ? plain_cells[i] : cell
117
166
  width = widths[i]
118
167
  header_key = @headers[i]
119
168
 
@@ -125,17 +174,25 @@ module TypedPrint
125
174
  :left
126
175
  end
127
176
 
177
+ padding = width - plain_cell.length
178
+
128
179
  case align
129
180
  when :right
130
- cell.rjust(width)
181
+ " " * padding + cell
131
182
  when :center
132
- cell.center(width)
183
+ left_pad = padding / 2
184
+ right_pad = padding - left_pad
185
+ " " * left_pad + cell + " " * right_pad
133
186
  else
134
- cell.ljust(width)
187
+ cell + " " * padding
135
188
  end
136
189
  end.join(" ")
137
190
  end
138
191
 
192
+ def pad_right(colored_text, plain_text, width)
193
+ colored_text + " " * (width - plain_text.length)
194
+ end
195
+
139
196
  def separator(widths)
140
197
  widths.map { |w| "-" * w }.join("-+-")
141
198
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TypedPrint
4
- VERSION = "0.2.0"
4
+ VERSION = "0.3.0"
5
5
  end
data/lib/typed_print.rb CHANGED
@@ -4,13 +4,13 @@ require "typed_print/version"
4
4
  require "typed_print/table"
5
5
 
6
6
  module TypedPrint
7
- def self.print(data, align: {}, only: nil, headers: {}, format: :plain)
8
- puts table(data, align: align, only: only, headers: headers, format: format)
7
+ def self.print(data, align: {}, only: nil, headers: {}, format: :plain, color: false, colors: nil)
8
+ puts table(data, align: align, only: only, headers: headers, format: format, color: color, colors: colors)
9
9
  nil
10
10
  end
11
11
 
12
- def self.table(data, align: {}, only: nil, headers: {}, format: :plain)
13
- table_obj = TypedPrint::Table.new(data, align, only, headers)
12
+ def self.table(data, align: {}, only: nil, headers: {}, format: :plain, color: false, colors: nil)
13
+ table_obj = TypedPrint::Table.new(data, align, only, headers, color: color, colors: colors)
14
14
  table_obj.render(format)
15
15
  end
16
16
  end
metadata CHANGED
@@ -1,14 +1,28 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: typed_print
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ender Ahmet Yurt
8
8
  bindir: exe
9
9
  cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
- dependencies: []
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: pastel
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '0'
19
+ type: :development
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '0'
12
26
  description: TypedPrint provides zero-dependency, beautifully formatted table output
13
27
  for Ruby data structures with automatic column sizing, alignment options, custom
14
28
  headers, and column filtering.
@@ -23,6 +37,9 @@ files:
23
37
  - LICENSE.txt
24
38
  - README.md
25
39
  - Rakefile
40
+ - assets/demo.gif
41
+ - assets/demo.rb
42
+ - assets/demo.tape
26
43
  - lib/typed_print.rb
27
44
  - lib/typed_print/table.rb
28
45
  - lib/typed_print/version.rb