Module: SplttyCLI::Table

Defined in:
lib/spltty_cli/table.rb

Overview

Parse a markdown ledger table and format/append a single aligned row.

Parsing (shared with the Totals reader): only lines starting with "|" are considered, the separator row is detected by its character set, the first table row is the header, and columns are addressed by header name. Writing only appends the new row — existing rows are never rewritten.

Class Method Summary collapse

Class Method Details

.alignments(header, sep_cells) ⇒ Object



63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/spltty_cli/table.rb', line 63

def alignments(header, sep_cells)
  header.each_index.map do |j|
    sc = sep_cells && sep_cells[j] ? sep_cells[j].strip : nil
    if sc && sc.end_with?(":") && !sc.start_with?(":")
      :right
    elsif ["Value (R$)", "Orig. Value"].include?(header[j])
      :right # fallback when no separator (e.g. freshly scaffolded file)
    else
      :left
    end
  end
end

.format_row(parsed, values) ⇒ Object

Build the markdown row string for values (Hash: header name => string), padded to the existing column widths so it lines up with prior rows.



78
79
80
81
82
83
84
85
86
# File 'lib/spltty_cli/table.rb', line 78

def format_row(parsed, values)
  cells = parsed[:header].each_index.map do |j|
    name = parsed[:header][j]
    content = values.fetch(name, values[name.to_sym]).to_s
    width = [parsed[:widths][j], content.length].max
    parsed[:align][j] == :right ? content.rjust(width) : content.ljust(width)
  end
  "| #{cells.join(' | ')} |"
end

.insert_row(text, parsed, row) ⇒ Object

Insert row right after the last table line, preserving trailing newlines.



89
90
91
92
93
# File 'lib/spltty_cli/table.rb', line 89

def insert_row(text, parsed, row)
  lines = text.split("\n", -1)
  lines.insert(parsed[:anchor_idx] + 1, row)
  lines.join("\n")
end

.parse(text) ⇒ Object

Returns a hash describing the table:

:header      => array of column names
:align       => array of :left/:right per column
:widths      => array of existing max content width per column
:anchor_idx  => index (in text.split("\n", -1)) of the last "|" line

Raises:

  • (ArgumentError)


28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/spltty_cli/table.rb', line 28

def parse(text)
  lines = text.split("\n", -1)
  header = nil
  sep_cells = nil
  widths = nil
  anchor_idx = nil

  lines.each_with_index do |line, i|
    next unless line.strip.start_with?("|")

    anchor_idx = i
    cells = row_cells(line)

    if separator?(cells)
      sep_cells ||= cells if header
      next
    end

    if header.nil?
      header = cells
      widths = cells.map(&:length)
    else
      cells.each_with_index do |c, j|
        next if j >= widths.length

        widths[j] = [widths[j], c.length].max
      end
    end
  end

  raise ArgumentError, "no markdown table found" if header.nil?

  { header: header, align: alignments(header, sep_cells), widths: widths, anchor_idx: anchor_idx }
end

.row_cells(line) ⇒ Object

"| a | b |" -> ["a", "b"]



14
15
16
# File 'lib/spltty_cli/table.rb', line 14

def row_cells(line)
  line.strip.sub(/\A\|/, "").sub(/\|\z/, "").split("|", -1).map(&:strip)
end

.separator?(cells) ⇒ Boolean

A separator row is made up solely of -, :, and spaces (e.g. "|---|--:|").

Returns:

  • (Boolean)


19
20
21
# File 'lib/spltty_cli/table.rb', line 19

def separator?(cells)
  !cells.empty? && cells.all? { |c| c.gsub(/[:\-\s]/, "").empty? }
end