2021-03-31 19:36:03 +00:00
|
|
|
|
2021-04-04 12:47:31 +00:00
|
|
|
require "./models"
|
|
|
|
require "./actions"
|
|
|
|
require "./models"
|
|
|
|
|
2021-03-31 19:36:03 +00:00
|
|
|
module Hodler
|
|
|
|
class Cli
|
|
|
|
alias Options = {
|
2021-04-04 12:47:31 +00:00
|
|
|
action: Action::Type,
|
|
|
|
verbose_enable: Bool,
|
|
|
|
config_file: String
|
2021-03-31 19:36:03 +00:00
|
|
|
}
|
|
|
|
|
2021-04-04 12:47:31 +00:00
|
|
|
property config : ConfigModel?
|
|
|
|
property options : Options?
|
2021-03-31 19:36:03 +00:00
|
|
|
|
|
|
|
def initialize
|
2021-04-04 12:47:31 +00:00
|
|
|
@config = nil
|
2021-03-31 19:36:03 +00:00
|
|
|
@options = nil
|
|
|
|
end
|
|
|
|
|
2021-04-04 12:47:31 +00:00
|
|
|
def self.parse_options(args) : Options
|
2021-03-31 19:36:03 +00:00
|
|
|
# default values
|
2021-04-04 12:47:31 +00:00
|
|
|
action = Action::Type::Report
|
|
|
|
config_file = XDGBasedir.full_path("hodler/wallet.yml", :config, :read).as(String)
|
|
|
|
verbose_enable = true
|
2021-03-31 19:36:03 +00:00
|
|
|
|
|
|
|
# parse
|
|
|
|
OptionParser.parse(args) do |parser|
|
2021-04-04 12:47:31 +00:00
|
|
|
parser.banner = "Usage: #{Version::PROGRAM} [options] [commands] [arguments]"
|
|
|
|
|
|
|
|
parser.separator
|
|
|
|
parser.separator "Options"
|
2021-03-31 19:36:03 +00:00
|
|
|
|
2021-04-04 12:47:31 +00:00
|
|
|
parser.on "-c CONFIG_FILE", "--config=CONFIG_FILE", "Use the following config file" do |file|
|
|
|
|
config_file = file
|
2021-03-31 19:36:03 +00:00
|
|
|
end
|
|
|
|
|
2021-04-04 12:47:31 +00:00
|
|
|
parser.on "-v", "--verbose", "Be verbose" do
|
|
|
|
verbose_enable = !verbose_enable
|
|
|
|
end
|
2021-03-31 19:36:03 +00:00
|
|
|
|
2021-04-04 12:47:31 +00:00
|
|
|
parser.on "--version", "Show version" do
|
2021-03-31 19:36:03 +00:00
|
|
|
puts "version #{Version::VERSION}"
|
|
|
|
exit 0
|
|
|
|
end
|
2021-04-04 12:47:31 +00:00
|
|
|
|
|
|
|
parser.on "-h", "--help", "Show this help" do
|
2021-03-31 19:36:03 +00:00
|
|
|
puts parser
|
|
|
|
exit 0
|
|
|
|
end
|
|
|
|
|
2021-04-04 12:47:31 +00:00
|
|
|
parser.on "--completion", "Provide autocompletion for bash" do
|
|
|
|
# nothing here
|
|
|
|
end
|
|
|
|
complete_with Version::PROGRAM, parser
|
|
|
|
|
|
|
|
parser.separator
|
|
|
|
parser.separator "Commands"
|
|
|
|
|
|
|
|
parser.on("report", "Compute report") do
|
|
|
|
parser.banner = "Usage: #{Version::PROGRAM} list [arguments]"
|
|
|
|
action = Action::Type::Report
|
|
|
|
end
|
|
|
|
|
|
|
|
parser.on("tui", "Run ncurses interactive UI") do
|
|
|
|
parser.banner = "Usage: #{Version::PROGRAM} tui [arguments]"
|
|
|
|
action = Action::Type::TextUi
|
|
|
|
end
|
|
|
|
|
|
|
|
parser.on("web", "Run web interactive UI") do
|
|
|
|
parser.banner = "Usage: #{Version::PROGRAM} web [arguments]"
|
|
|
|
action = Action::Type::WebUi
|
|
|
|
end
|
|
|
|
|
|
|
|
parser.separator
|
|
|
|
|
|
|
|
parser.missing_option do |flag|
|
|
|
|
STDERR.puts parser
|
|
|
|
STDERR.puts "ERROR: #{flag} requires an argument.".colorize(:red)
|
|
|
|
exit(1)
|
|
|
|
end
|
|
|
|
|
|
|
|
parser.invalid_option do |flag|
|
|
|
|
STDERR.puts parser
|
|
|
|
STDERR.puts "ERROR: #{flag} is not a valid option.".colorize(:red)
|
|
|
|
exit(1)
|
|
|
|
end
|
|
|
|
|
|
|
|
parser.unknown_args do |unknown_args|
|
|
|
|
unknown_args = unknown_args - %w(report web tui)
|
|
|
|
next if unknown_args.empty?
|
|
|
|
|
|
|
|
STDERR.puts parser
|
|
|
|
STDERR.puts "ERROR: \"#{unknown_args[0]}\" is not a valid command.".colorize(:red)
|
|
|
|
exit(1)
|
|
|
|
end
|
|
|
|
|
2021-03-31 19:36:03 +00:00
|
|
|
end
|
|
|
|
|
2021-04-04 12:47:31 +00:00
|
|
|
return {
|
|
|
|
verbose_enable: verbose_enable,
|
|
|
|
config_file: config_file,
|
|
|
|
action: action
|
|
|
|
}.as(Options)
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.parse_config(options)
|
|
|
|
puts "Loading configuration...".colorize(:yellow) if options[:verbose_enable]
|
|
|
|
config_file = options[:config_file]
|
2021-03-31 19:36:03 +00:00
|
|
|
|
2021-04-04 12:47:31 +00:00
|
|
|
if ! File.exists? config_file
|
|
|
|
STDERR.puts "ERROR: Unable to read configuration file '#{config_file}'".colorize(:red)
|
|
|
|
exit 1
|
|
|
|
end
|
|
|
|
|
|
|
|
yaml_str = File.read(config_file)
|
|
|
|
config = ConfigModel.from_yaml(yaml_str)
|
|
|
|
|
|
|
|
if config.nil?
|
|
|
|
STDERR.puts "ERROR: Invalid YAML content in '#{config_file}'"
|
|
|
|
exit 1
|
|
|
|
end
|
|
|
|
|
|
|
|
return config
|
2021-03-31 19:36:03 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def self.run(args)
|
|
|
|
app = Cli.new
|
2021-04-04 12:47:31 +00:00
|
|
|
options = Cli.parse_options(args)
|
|
|
|
config = Cli.parse_config(options)
|
|
|
|
app.options = options
|
|
|
|
app.config = config
|
|
|
|
|
|
|
|
portfolio = PortfolioFactory.build(options, config)
|
|
|
|
|
|
|
|
action = ActionFactory.build(options, config)
|
|
|
|
action.perform
|
|
|
|
|
|
|
|
rescue ex : YAML::ParseException
|
|
|
|
STDERR.puts "ERROR: #{ex.message}".colorize(:red)
|
2021-03-31 19:36:03 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|