Class: Reckon::Options

Inherits:
Object
  • Object
show all
Defined in:
lib/reckon/options.rb

Overview

Singleton class for parsing command line flags

Class Method Summary collapse

Class Method Details

.parse_command_line_options(args = ARGV, stdin = $stdin) ⇒ Object



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
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
182
183
184
185
186
187
188
# File 'lib/reckon/options.rb', line 6

def self.parse_command_line_options(args = ARGV, stdin = $stdin)
  options = { output_file: $stdout }
  OptionParser.new do |opts|
    opts.banner = "Usage: Reckon.rb [options]"
    opts.separator ""

    opts.on("-f", "--file FILE", "The CSV file to parse") do |file|
      options[:file] = file
    end

    opts.on("-a", "--account NAME", "The Ledger Account this file is for") do |a|
      options[:bank_account] = a
    end

    options[:verbose] = Logger::WARN
    opts.on("-v", "--v", "Run verbosely (show info log messages)") do
      options[:verbose] = Logger::INFO
    end

    opts.on("", "--verbose", "Run verbosely (show info log messages)") do
      options[:verbose] = Logger::INFO
    end

    opts.on("", "--vv", "Run very verbosely (show debug log messages)") do
      options[:verbose] = Logger::DEBUG
    end

    opts.on("-i", "--inverse", "Use the negative of each amount") do |v|
      options[:inverse] = v
    end

    opts.on("-p", "--print-table", "Print out the parsed CSV in table form") do |p|
      options[:print_table] = p
    end

    opts.on("-o", "--output-file FILE", "The ledger file to append to") do |o|
      options[:output_file] = File.open(o, 'a')
    end

    opts.on("-l", "--learn-from FILE",
            "An existing ledger file to learn accounts from") do |l|
      options[:existing_ledger_file] = l
    end

    opts.on("", "--ignore-columns 1,2,5",
            "Columns to ignore, starts from 1") do |ignore|
      options[:ignore_columns] = ignore.split(",").map(&:to_i)
    end

    opts.on("", "--money-column 2", Integer,
            "Column number of the money column, starts from 1") do |col|
      options[:money_column] = col
    end

    opts.on("", "--money-columns 2,3",
            "Column number of the money columns, starts from 1 (1 or 2 columns)") do |ignore|
      options[:money_columns] = ignore.split(",").map(&:to_i)
    end

    opts.on("", "--raw-money", "Don't format money column (for stocks)") do |n|
      options[:raw] = n
    end

    options[:sort] = :date
    opts.on("", "--sort DATE|DESC|AMT", "Sort file by date, description, or amount") do |s|
      if s == 'DESC'
        options[:sort] = :description
      elsif s == 'AMT'
        options[:sort] = :money
      elsif s == 'DATE'
        options[:sort] = :date
      else
        raise "'#{s}' is not valid. valid sort options are DATE, DESC, AMT"
      end
    end

    opts.on("", "--date-column 3", Integer,
            "Column number of the date column, starts from 1") do |col|
      options[:date_column] = col
    end

    opts.on("", "--contains-header [N]", Integer,
            "Skip N header rows - default 1") do |hdr|
      options[:contains_header] = 1
      options[:contains_header] = hdr.to_i
    end

    opts.on("", "--contains-footer [N]", Integer,
            "Skip N footer rows - default 0") do |hdr|
      options[:contains_footer] = hdr.to_i || 0
    end

    opts.on("", "--csv-separator ','", "CSV separator (default ',')") do |sep|
      options[:csv_separator] = sep
    end

    opts.on("", "--comma-separates-cents",
            "Use comma to separate cents ($100,50 vs. $100.50)") do |c|
      options[:comma_separates_cents] = c
    end

    opts.on("", "--encoding 'UTF-8'", "Specify an encoding for the CSV file") do |e|
      options[:encoding] = e
    end

    opts.on("-c", "--currency '$'",
            "Currency symbol to use - default $ (ex £, EUR)") do |e|
      options[:currency] = e || '$'
    end

    opts.on("", "--date-format FORMAT",
            "CSV file date format (see `date` for format)") do |d|
      options[:date_format] = d
    end

    opts.on("", "--ledger-date-format FORMAT",
            "Ledger date format (see `date` for format)") do |d|
      options[:ledger_date_format] = d
    end

    opts.on("-u", "--unattended",
            "Don't ask questions and guess all the accounts automatically. Use with --learn-from or --account-tokens options.") do |n|
      options[:unattended] = n
    end

    opts.on("-t", "--account-tokens FILE",
            "YAML file with manually-assigned tokens for each account (see README)") do |a|
      options[:account_tokens_file] = a
    end

    opts.on("", "--table-output-file FILE") do |n|
      options[:table_output_file] = n
    end

    options[:default_into_account] = 'Expenses:Unknown'
    opts.on("", "--default-into-account NAME", "Default into account") do |a|
      options[:default_into_account] = a
    end

    options[:default_outof_account] = 'Income:Unknown'
    opts.on("", "--default-outof-account NAME", "Default 'out of' account") do |a|
      options[:default_outof_account] = a
    end

    opts.on("", "--fail-on-unknown-account",
            "Fail on unmatched transactions.") do |n|
      options[:fail_on_unknown_account] = n
    end

    opts.on("", "--suffixed", "Append currency symbol as a suffix.") do |e|
      options[:suffixed] = e
    end

    opts.on("", "--ledger-format FORMAT",
            "Output/Learn format: BEANCOUNT or LEDGER. Default: LEDGER") do |n|
      options[:format] = n
    end

    opts.on_tail("-h", "--help", "Show this message") do
      puts opts
      exit
    end

    opts.on_tail("--version", "Show version") do
      puts VERSION
      exit
    end

    opts.parse!(args)
  end

  if options[:file] == '-'
    unless options[:unattended]
      raise "--unattended is required to use STDIN as CSV source."
    end

    options[:string] = stdin.read
  end

  validate_options(options)

  return options
end

.validate_options(options) ⇒ Object



190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
# File 'lib/reckon/options.rb', line 190

def self.validate_options(options)
  cli = HighLine.new
  unless options[:file]
    options[:file] = cli.ask("What CSV file should I parse? ")
    if options[:file].empty?
      puts "\nERROR: You must provide a CSV file to parse.\n"
      exit
    end
  end

  unless options[:bank_account]
    if options[:unattended]
      puts "ERROR: Must specify --account in unattended mode"
      exit
    end

    options[:bank_account] = cli.ask("What is the Ledger account name?\n") do |q|
      q.readline = true
      q.validate = /^.{2,}$/
      q.default = "Assets:Bank:Checking"
    end
  end

  return true
end