require 'thor' require 'fileutils' require 'pg/url' require 'string/builder' require 'tty/prompt' require 'limeta/connection' require 'limeta/table' module Limeta class CLI < Thor using String::Builder default_task :convert class_option :adapter, type: :string, aliases: '-a', desc: 'Database adapter', enum: %w[psql sqlite3], required: true class_option :conn, type: :string, aliases: '-c', desc: 'Connection string', required: false class_option :table, type: :string, aliases: '-t', desc: 'Export table name', required: true disable_required_check! :help, :version desc "[FILES]", "Export PGN metadata to a database" def convert(*files) files = expand files raise ArgumentError.new("No PGN files provided") if files.empty? prompt = TTY::Prompt.new conn = case options[:adapter] when 'psql' options[:conn] || PG::URL.prompt when 'sqlite3' options[:conn] || String.build do |s| path = File.expand_path prompt.ask("Path to database file:") extensions = %w[.db .sql .sqlite .sqlite3] if File.file? path if extensions.include? File.extname(path) s << path else raise "Expected #{File.basename path} extension to be one of #{extensions.inspect}" end elsif File.directory? path puts if prompt.yes? "Create a database in \e[1m#{path}\e[0m?" db = nil pass = false until pass name = prompt.ask "Database name:" db = File.join path, "#{name.sub(/\.(sqlite3|sqlite|sql|db|)/, '')}.sqlite3" puts pass = prompt.yes? "Is \e[1m#{db}\e[0m correct?" end puts if File.exist? db puts "\e[31mWARNING\e[0m: Database \e[1m#{db}\e[0m already exists." return unless prompt.yes? "Continue anyway?" else FileUtils.touch db puts "Database #{db} created" end s << db else return end else if File.directory? File.dirname(path) if extensions.include? File.extname(path) if prompt.yes? "Create database \e[1m#{path}\e[0m?" FileUtils.touch path puts "Database \e[1m#{path}\e[0m created" else return end else raise "Expected #{File.basename path} extension to be one of #{extensions.inspect}" end else raise "Invalid path #{path}" end end end end conn = case options[:adapter] when 'psql' then conn.start_with?("postgres://") ? conn : "postgres://#{conn}" when 'sqlite3' then conn end db = Limeta::Connection.establish conn, adapter: options[:adapter] table = Limeta::Table.new options[:table], database: db table.populate! files end map %w[--version -v] => :version desc '--version, -v', 'Display installed Limeta version' def version() puts Limeta::VERSION end no_tasks do def expand(files) files.map{|f| File.file?(f) ? Dir[f] : Dir["#{f}/**/*.pgn"]}.flatten end end class << self def help(shell, subcommand = false) list = printable_commands(true, subcommand) Thor::Util.thor_classes_in(self).each do |klass| list += klass.printable_commands(false) end list.reject! {|l| l[0].split[1] == 'help'} if defined?(@package_name) && @package_name shell.say "#{@package_name} commands:" else shell.say "Commands:" end shell.print_table(list, indent: 2, truncate: true) shell.say class_options_help(shell) end end end end