Module: Xolo::Core::Output
- Defined in:
- lib/xolo/core/output.rb
Overview
Methods for formattng and sending output to stdout Should be included in classes as needed
NOTE: Help output is auto-generated by ‘optimist’ The methods here are mostly for presenting info like columnizd lists and reports and the like.
Constant Summary collapse
- DEFAULT_LINE_WIDTH =
This is used when we are not outputting to a terminal usually we’re being piped or not running in a terminal so the lines should be as long as they want
2000
Class Method Summary collapse
-
.extended(extender) ⇒ Object
when this module is extended.
-
.included(includer) ⇒ Object
when this module is included.
Instance Method Summary collapse
-
#col_widths(data, header_row = []) ⇒ Array<Integer>
Given an Array of Arrays representing rows and columns of data figure out the widest width of each column and return an array of integers representing those widths.
-
#format_multiline_indent(value, indent:) ⇒ String
format a multi-line value by prepending the desired indentation to all but the first line, which is expected to be indented in-place where its being used.
-
#generate_report(lines, type: :fixed, header_row: [], title: nil) ⇒ String
Generate a report of rowed/columned data, either fixed-width or tab-delimited.
-
#list_in_cols(header, list) ⇒ void
TODO: Move this out of Xolo::Core Display a list of items in as many columns as possible based on terminal width, e.g.
-
#show_text(text, show_help = true) ⇒ Object
Send a string to the terminal, possibly piping it through ‘less’ if the number of lines is greater than the number of terminal lines.
-
#terminal_height ⇒ Integer
How many rows high is our terminal?.
-
#terminal_width ⇒ Integer
How many columns wide is our terminal?.
-
#terminal_word_wrap ⇒ Integer
How wide is our word wrap? terminal-width minus 5.
-
#use_less?(text) ⇒ Boolean
Should a given string be displayed via /usr/bin/less? true if stdout is a tty AND the string is > (terminal height - 2) The - 2 accounts for the final newline and an extra line at the bottom of the terminal, for better visual results.
-
#width_and_format(lines, header_row = []) ⇒ Array<Integer, String>
Given an Array of Arrays representing rows and columns of data, figure out the appropriate line-width for the longest line and the printf format string to create the columns.
Class Method Details
.extended(extender) ⇒ Object
when this module is extended
47 48 49 |
# File 'lib/xolo/core/output.rb', line 47 def self.extended(extender) Xolo.verbose_extend extender, self end |
.included(includer) ⇒ Object
when this module is included
42 43 44 |
# File 'lib/xolo/core/output.rb', line 42 def self.included(includer) Xolo.verbose_include includer, self end |
Instance Method Details
#col_widths(data, header_row = []) ⇒ Array<Integer>
Given an Array of Arrays representing rows and columns of data figure out the widest width of each column and return an array of integers representing those widths
231 232 233 234 235 236 237 238 239 240 |
# File 'lib/xolo/core/output.rb', line 231 def col_widths(data, header_row = []) widths = header_row.map { |c| c.to_s.length } data.each do |row| row.each_index do |col| this_width = row[col].to_s.length widths[col] = this_width if this_width > widths[col].to_i end # do field end # do line widths end |
#format_multiline_indent(value, indent:) ⇒ String
format a multi-line value by prepending the desired indentation to all but the first line, which is expected to be indented in-place where its being used.
84 85 86 87 88 89 90 91 |
# File 'lib/xolo/core/output.rb', line 84 def format_multiline_indent(value, indent:) value = value.to_s return value unless value.include? "\n" lines = value.split("\n") lines[1..-1].each { |line| line.prepend ' ' * indent } lines.join("\n") end |
#generate_report(lines, type: :fixed, header_row: [], title: nil) ⇒ String
Generate a report of rowed/columned data, either fixed-width or tab-delimited.
Title and header lines are pre-pended with ‘# ’ for easier exclusion when using the report as input for some other program. If the :type is :fixed, so will the column header line. (however, for parsing this data, try using the –json option)
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
# File 'lib/xolo/core/output.rb', line 146 def generate_report(lines, type: :fixed, header_row: [], title: nil) return Xolo::BLANK if lines.pix_empty? raise ArgumentError, 'The first argument must be an Array' unless lines.is_a?(Array) raise ArgumentError, 'The header_row must be an Array' unless header_row.is_a? Array # tab delim is easy if type == :tab report_tab = header_row.join("\t") lines.each { |line| report_tab += "\n#{line.join("\t")}" } return report_tab.strip end # if :tab # below here, fixed width line_width, format_str = width_and_format(lines, header_row) # title if given report = title ? +"# #{title}\n" : +'' unless header_row.empty? unless header_row.size == lines[0].size raise ArgumentError, "Header row must have #{lines[0].count} items" end # then the header line if given report += format_str % header_row # add a separator report += '#' + ('-' * (line_width - 1)) + "\n" end # add the rows lines.each { |line| report += format_str % line } report end |
#list_in_cols(header, list) ⇒ void
This method returns an undefined value.
TODO: Move this out of Xolo::Core Display a list of items in as many columns as possible based on terminal width, e.g. with 3 cols:
a thing another thing third thing
thing2 line2 thing third line 2
line3 thing another one and yet a 3rd
oh my line4 4 line ok? yes, this is it
and if the list is longer than terminal height, pipe it through ‘less’
112 113 114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/xolo/core/output.rb', line 112 def list_in_cols(header, list) longest_list_item = list.map(&:size).max use_columns = (longest_list_item + 5) < terminal_width list_to_display = use_columns ? highline_cli.list(list, :columns_down) : list.join("\n") output = +"# #{header}\n" output << '#' * (terminal_width - 5) output << "\n" output << list_to_display show_text output end |
#show_text(text, show_help = true) ⇒ Object
Send a string to the terminal, possibly piping it through ‘less’ if the number of lines is greater than the number of terminal lines
262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 |
# File 'lib/xolo/core/output.rb', line 262 def show_text(text, show_help = true) unless use_less?(text) puts text return end if show_help help = "# -- Using /usr/bin/less: ' ' next, 'b' prev, 'q' exit, 'h' help --" text = "#{help}\n#{text}" end # point stdout through less, print, then restore stdout less = IO.popen('/usr/bin/less', 'w') begin less.puts text # this catches the quitting of 'less' before all the output # is displayed rescue Errno::EPIPE true ensure less&.close end end |
#terminal_height ⇒ Integer
Returns how many rows high is our terminal?.
60 61 62 |
# File 'lib/xolo/core/output.rb', line 60 def terminal_height IO.console.winsize.first end |
#terminal_width ⇒ Integer
Returns how many columns wide is our terminal?.
66 67 68 |
# File 'lib/xolo/core/output.rb', line 66 def terminal_width IO.console.winsize.last end |
#terminal_word_wrap ⇒ Integer
Returns how wide is our word wrap? terminal-width minus 5.
72 73 74 |
# File 'lib/xolo/core/output.rb', line 72 def terminal_word_wrap @terminal_word_wrap ||= terminal_width - 5 end |
#use_less?(text) ⇒ Boolean
Should a given string be displayed via /usr/bin/less? true if stdout is a tty AND the string is > (terminal height - 2) The - 2 accounts for the final newline and an extra line at the bottom of the terminal, for better visual results
247 248 249 |
# File 'lib/xolo/core/output.rb', line 247 def use_less?(text) $stdout.tty? && text.lines.size > (terminal_height - 2) end |
#width_and_format(lines, header_row = []) ⇒ Array<Integer, String>
Given an Array of Arrays representing rows and columns of data, figure out the appropriate line-width for the longest line and the printf format string to create the columns
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 |
# File 'lib/xolo/core/output.rb', line 196 def width_and_format(lines, header_row = []) # below here, fixed width format_str = +'' line_width = 0 header_row[0] = "# #{header_row[0]}" col_widths(lines, header_row).each do |w| # make sure there's a space between columns col_width = w + 1 # add the column to the printf format format_str += "%-#{col_width}s" line_width += col_width end format_str += "\n" # if needed, limit the total line width for the header the width of the terminal max_width = $stdout.tty? ? terminal_word_wrap : DEFAULT_LINE_WIDTH line_width = max_width if line_width > max_width [line_width, format_str] end |