Skip to content

Commit

Permalink
Finalizing the CLI commands architecture
Browse files Browse the repository at this point in the history
  • Loading branch information
Yacine Petitprez committed Apr 3, 2018
1 parent 3fb53ba commit e4e6619
Show file tree
Hide file tree
Showing 11 changed files with 161 additions and 148 deletions.
54 changes: 27 additions & 27 deletions sample/cli/cli.cr
Original file line number Diff line number Diff line change
@@ -1,37 +1,37 @@
require "../src/clear"
require "../../src/clear"

def initdb
Clear.logger.level = ::Logger::INFO
Clear::SQL.init("postgres://postgres@localhost/clear_spec")
end
# def initdb
# Clear.logger.level = ::Logger::INFO
# Clear::SQL.init("postgres://postgres@localhost/clear_spec")
# end

initdb
# initdb

class UpdatePasswordField3
include Clear::Migration
# class UpdatePasswordField3
# include Clear::Migration

def change(dir)
dir.up { puts "3:up" }
dir.down { puts "3:down" }
end
end
# def change(dir)
# dir.up { puts "3:up" }
# dir.down { puts "3:down" }
# end
# end

class CreateDatabase1
include Clear::Migration
# class CreateDatabase1
# include Clear::Migration

def change(dir)
dir.up { puts "1:up" }
dir.down { puts "1:down" }
end
end
# def change(dir)
# dir.up { puts "1:up" }
# dir.down { puts "1:down" }
# end
# end

class ApplyChange2
include Clear::Migration
# class ApplyChange2
# include Clear::Migration

def change(dir)
dir.up { puts "2:up" }
dir.down { puts "2:down" }
end
end
# def change(dir)
# dir.up { puts "2:up" }
# dir.down { puts "2:down" }
# end
# end

Clear::CLI.run
14 changes: 0 additions & 14 deletions spec/cli/generator_spec.cr

This file was deleted.

29 changes: 22 additions & 7 deletions src/clear/cli.cr
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,26 @@ require "option_parser"

module Clear::CLI
def self.display_help_and_exit
puts <<-HELP
clear-cli [options] <command>
help = <<-HELP
clear-cli [options] <command> [...]
Commands:
Commands:
Migration:
migration status # Show the current status of the database.
migration up XXX # Turn up a specific migration.
migration down XXX # Turn down a specific migration.
migration set # Go to a specific step. Down all migration after, up all migration before.
migration set # Go to a specific step.
# Down all migration after,
# up all migration before.
migrate # Migrate to the newest version.
rollback # Revert the last migration.
from_models # Generate a migration from all the models discovered. Good for projects bootstrapping !
from_models # Generate a migration from all the
# models discovered.
# Good for projects bootstrapping !
Generator:
generate XXX # Generate some files
Helpers:
table2model # Output a model based on a pg table.
Expand All @@ -23,13 +30,19 @@ module Clear::CLI
Use --help on each command to get more informations
HELP

puts help

exit
end

# Do not use the clear-cli binary but instead use the appctl
# to compile the source of the custom project
def self.delegate_run(args : Array(String))
system("./bin/appctl", "clear_cli", *args)
def self.delegate_run(args = nil)
if args
system("./bin/appctl", ["clear_cli"] + args)
else
system("./bin/appctl", ["clear_cli"])
end
end

def self.ensure_in_custom_project
Expand Down Expand Up @@ -62,6 +75,8 @@ module Clear::CLI
when "--verbose"
Clear.logger.level = ::Logger::DEBUG
next
when "g", "generate"
Clear::CLI::Generate.run(args)
when "db"
Clear::CLI::DB.run(args)
when "migration"
Expand Down
19 changes: 7 additions & 12 deletions src/clear/cli/db.cr
Original file line number Diff line number Diff line change
@@ -1,25 +1,20 @@
# The `db` command
#
# # Commands
#
module Clear::CLI::DB
def self.display_help_and_exit(opts)
puts <<-HELP
clear-cli [cli-options] db [db-command]
class Clear::CLI::DBCommand < Clear::CLI::Command
def get_help_string
<<-HELP
clear-cli [cli-options] db [db-command]
Commands:
Commands:
create # Create the database
HELP

exit
end

def self.run(args)
def run_impl(args)
OptionParser.parse(args) do |opts|
opts.unknown_args do |args, options|
arg = args.shift
case arg
when "create"
puts "TODO"
exit
end
end
Expand Down
5 changes: 0 additions & 5 deletions src/clear/cli/from_model.cr

This file was deleted.

71 changes: 43 additions & 28 deletions src/clear/cli/generator.cr
Original file line number Diff line number Diff line change
@@ -1,40 +1,55 @@
require "ecr"
record Clear::CLI::Generator, name : String, desc : String, callback : Array(String) -> Void

module Clear::CLI
module Generate
record Generator, name : String, desc : String, callback : Hash(Symbol, String) -> Void
class Clear::CLI::GeneratorCommand < Clear::CLI::Command
def get_help_string
<<-HELP
clear-cli [cli-options] generate [list | generator_name] (options)
@@generators : Hash(String, Generator) = {} of String => Generator
Options:
--list # List the generators
def self.add_generator(name, desc, &block : Hash(Symbol, String) -> Void)
add_generator Generator.new(name, desc, block)
end
Available generators:
#{generator_list_string}
HELP
end

def self.add_generator(generator : Generator)
@@generators[generator.name] = generator
end
@@generators = {} of String => Clear::CLI::Generator

def self.run_generator(name, options, directory : String? = nil)
opts = {} of Symbol => String
def self.add(name, desc, &block : Array(String) -> Void)
@@generators[name] = Generator.new(name, desc, block)
end

opts[:email] = `git config user.email`.chomp || "[email protected]"
opts[:user_name] = `git config user.name`.chomp || "Your Name"
opts[:app_name] = "MyApp"
opts[:app_name_underscore] = opts[:app_name].underscore
opts[:directory] = directory || opts[:app_name_underscore]
def self.[]?(generator)
@@generators[name]?
end

@@generators[name].callback.call(opts)
end
def self.[](generator)
@@generators[name]
end

macro ecr_to_s(file, opts)
io = IO::Memory.new
ECR.embed {{file}}, io
io.to_s
end
def generator_list_string
@generators.values.map { |v| " #{v.name}\t#{v.desc}" }.join("\n")
end

def self.run(args)
def run_impl(args)
while args.size > 0
arg = args.shift
case arg
when "--list", "-l"
puts print_generator_list
exit 0
else
generator = Clear::CLI::GeneratorCommand[arg]?
if generator
generator.callback.call(args)
exit 0
else
puts "I don't know how to generate `#{generator}`"
exit 1
end
end
end

display_help_and_exit 1
end
end

require "./generators/**"
20 changes: 15 additions & 5 deletions src/clear/cli/generators/migration.cr
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
Clear::CLI::Generate.add_generator("migration",
Clear::CLI::GeneratorCommand.add("migration",
"Create a new migration") do |opts|
g = Generate::Generator.new
g.target_directory = "."

timestamp = Time.now.epoch.to_s.rjust(10, '0')

file_name = "#{timestamp}_#{opts[:name].underscore}.cr"
opts[:class_name] = "#{opts[:name].camelcase}#{timestamp}"
name = opts.shift?

g.in_directory "src/db/migrations" do
g.file(file_name, "./templates/migration.ecr")
if name
name_underscore = name.underscore
class_name = name.camelcase

file_name = "#{timestamp}_#{name_underscore}.cr"
g["class_name"] = "#{class_name}#{timestamp}"

g.in_directory "src/db/migrations" do
g.file(file_name, "./templates/migration.ecr")
end
else
puts "Please provide a name for the migration"
exit(1)
end
end
60 changes: 36 additions & 24 deletions src/clear/cli/generators/new/kemal.cr
Original file line number Diff line number Diff line change
@@ -1,61 +1,73 @@
require "generate"

Clear::CLI::Generate.add_generator("new/kemal",
"Setup a minimal application with kemal and clear") do |opts|
Clear::CLI::GeneratorCommand.add("new/kemal",
"Setup a minimal application with kemal and clear") do |args|
g = Generate::Generator.new
g.target_directory = opts[:directory] || "."

g["app_name"] = opts[:app_name]
g["app_name_underscore"] = opts[:app_name].underscore
g["git_username"] = opts[:user_name]
g["git_email"] = opts[:email]
g.target_directory = "."

OptionParser.parse(args) do |opts|
opts.on("-d", "--directory DIRECTORY", "Set directory") do |dir|
g.target_directory = dir
end

opts.on("-n", "--name NAME", "Set application name") do |name|
g["app_name"] = name
end
end

g["app_name"] ||= Dir.basename(`pwd #{g.target_directory}`.chomp)
g["app_name_underscore"] = g["app_name"].underscore

g["git_username"] = `git config user.email`.chomp || "[email protected]"
g["git_email"] = `git config user.name`.chomp || "Your Name"

g.in_directory "bin" do
g.file "appctl", Clear::CLI.ecr_to_s("./templates/kemal/bin/appctl.ecr", opts)
g.file "clear_cli.cr", Clear::CLI.ecr_to_s("./templates/kemal/bin/clear_cli.cr.ecr", opts)
g.file "server.cr", Clear::CLI.ecr_to_s("./templates/kemal/bin/server.cr.ecr", opts)
g.file "appctl", Clear::CLI::Generate.ecr_to_s("./templates/kemal/bin/appctl.ecr", opts)
g.file "clear_cli.cr", Clear::CLI::Generate.ecr_to_s("./templates/kemal/bin/clear_cli.cr.ecr", opts)
g.file "server.cr", Clear::CLI::Generate.ecr_to_s("./templates/kemal/bin/server.cr.ecr", opts)
end

g.in_directory "config" do
g.file "database.yml", Clear::CLI.ecr_to_s("./templates/kemal/config/database.yml.ecr", opts)
g.file "database.yml", Clear::CLI::Generate.ecr_to_s("./templates/kemal/config/database.yml.ecr", opts)
end

g.in_directory "src" do
g.in_directory "controllers" do
g.file "application_controller.cr", Clear::CLI.ecr_to_s("./templates/kemal/src/controllers/application_controller.ecr", opts)
g.file "welcome_controller.cr", Clear::CLI.ecr_to_s("./templates/kemal/src/controllers/welcome_controller.ecr", opts)
g.file "application_controller.cr", Clear::CLI::Generate.ecr_to_s("./templates/kemal/src/controllers/application_controller.ecr", opts)
g.file "welcome_controller.cr", Clear::CLI::Generate.ecr_to_s("./templates/kemal/src/controllers/welcome_controller.ecr", opts)
end

g.in_directory "db" do
g.file "init.cr", Clear::CLI.ecr_to_s("./templates/kemal/src/db/init.ecr", opts)
g.file "init.cr", Clear::CLI::Generate.ecr_to_s("./templates/kemal/src/db/init.ecr", opts)
end

g.in_directory "models" do
g.file "init.cr", Clear::CLI.ecr_to_s("./templates/kemal/src/models/application_model.ecr", opts)
g.file "init.cr", Clear::CLI::Generate.ecr_to_s("./templates/kemal/src/models/application_model.ecr", opts)
end

g.in_directory "views" do
g.in_directory "components" do
g.file "footer.cr", Clear::CLI.ecr_to_s("./templates/kemal/src/views/components/footer.ecr", opts)
g.file "footer.cr", Clear::CLI::Generate.ecr_to_s("./templates/kemal/src/views/components/footer.ecr", opts)
end

g.in_directory "layouts" do
g.file "application.cr", Clear::CLI.ecr_to_s("./templates/kemal/src/views/layouts/application.ecr", opts)
g.file "application.cr", Clear::CLI::Generate.ecr_to_s("./templates/kemal/src/views/layouts/application.ecr", opts)
end

g.in_directory "welcome" do
g.file "index.cr", Clear::CLI.ecr_to_s("./templates/kemal/src/views/welcome/index.ecr", opts)
g.file "index.cr", Clear::CLI::Generate.ecr_to_s("./templates/kemal/src/views/welcome/index.ecr", opts)
end
end

g.file "app.cr", Clear::CLI.ecr_to_s("./templates/kemal/src/app.ecr", opts)
g.file "app.cr", Clear::CLI::Generate.ecr_to_s("./templates/kemal/src/app.ecr", opts)
end

g.file ".gitignore", Clear::CLI.ecr_to_s("./templates/kemal/_gitignore.ecr", opts)
g.file "shard.yml", Clear::CLI.ecr_to_s("./templates/kemal/shard.yml.ecr", opts)
g.file ".gitignore", Clear::CLI::Generate.ecr_to_s("./templates/kemal/_gitignore.ecr", opts)
g.file "shard.yml", Clear::CLI::Generate.ecr_to_s("./templates/kemal/shard.yml.ecr", opts)

system("chmod +x #{opts[:directory]}/bin/appctl")
system("cd #{opts[:directory]} && shards")
system("chmod +x #{g.target_directory}/bin/appctl")
system("cd #{g.target_directory} && shards")

puts "Clear + Kemal template is now generated. `cd #{opts[:directory]} && clear-cli server` to play ! :-)"
puts "Clear + Kemal template is now generated. `cd #{g.target_directory} && clear-cli server` to play ! :-)"
end
Loading

0 comments on commit e4e6619

Please sign in to comment.