diff --git a/bin/sublayer b/bin/sublayer index 20c0f49..34a313c 100755 --- a/bin/sublayer +++ b/bin/sublayer @@ -1,5 +1,5 @@ #!/usr/bin/env ruby -require "sublayer/cli" +require_relative "../lib/sublayer/cli" Sublayer::CLI.start(ARGV) diff --git a/lib/sublayer/cli.rb b/lib/sublayer/cli.rb index 00019ce..bb58e20 100644 --- a/lib/sublayer/cli.rb +++ b/lib/sublayer/cli.rb @@ -1,191 +1,19 @@ -require "tty-prompt" -require "tty-progressbar" -require "tty-command" -require "tty-file" -require "fileutils" -require "yaml" +require "thor" require "sublayer/version" +require "yaml" +require "fileutils" +require "active_support/inflector" -module Sublayer - class CLI - PLACEHOLDERS = { - "PROJECT_NAME" => { gsub: true, camelcase: false }, - "ProjectName" => { gsub: true, camelcase: true }, - "project_name" => { gsub: true, camelcase: false, underscore: true } - } - - def self.start(args) - new.run(args) - end - - def run(args) - command = args.shift - - case command - when "new" - create_new_project(args.first) - when "help", nil - display_help - else - puts "Unknown command: #{command}" - display_help - end - end - - private - - def create_new_project(project_name) - prompt = TTY::Prompt.new - - project_name ||= prompt.ask("What is the name of your project?") - - project_type = prompt.select("Select a project template: ", ["CLI", "Quick Script"]) - ai_provider = prompt.select("Select an AI provider:", ["OpenAI", "Claude", "Gemini"]) - - ai_model = if ai_provider == "OpenAI" - prompt.select("Which OpenAI model would you like to use?", ["gpt-4o", "gpt-4o-mini", "gpt-4-turbo", "gpt-4", "gpt-3.5-turbo"]) - elsif ai_provider == "Claude" - prompt.select("Which Anthropic model would you like to use?", ["claude-3-5-sonnet-20240620", "claude-3-opus-20240229", "claude-3-haiku-20240307"]) - elsif ai_provider == "Gemini" - prompt.select("Which Gemini model would you like to use?", ["gemini-1.5-pro-latest", "gemini-1.5-flash-latest"]) - end - - create_project(project_name, project_type, ai_provider, ai_model) - end - - def create_project(project_name, project_type, ai_provider, ai_model) - project_path = File.join(Dir.pwd, project_name) - - progress_bar = TTY::ProgressBar.new("Creating project [:bar] :percent", total: 8) - - progress_bar.advance(1, log: "Creating project directory") - FileUtils.mkdir_p(project_path) - - progress_bar.advance(1, log: "Copying template files") - copy_template_files(project_path, project_type) - - progress_bar.advance(1, log: "Replacing placeholders") - replace_placeholders(project_path, project_name) - - progress_bar.advance(1, log: "Generating configuration") - generate_config_file(project_path, project_name, project_type, ai_provider, ai_model) - - progress_bar.advance(1, log: "Finalizing project") - finalize_project(project_path, project_type) - - puts "\nSublayer project '#{project_name}' created successfully!" - end - - def copy_template_files(project_path, project_type) - template_dir = project_type == "CLI" ? "cli" : "quick_script" - source_path = File.join(File.dirname(__FILE__), "templates", template_dir) - FileUtils.cp_r("#{source_path}/.", project_path) - - FileUtils.mkdir_p(File.join(project_path, "log")) if should_add_log_folder(project_type) - end - - def should_add_log_folder(project_type) - project_type == "CLI" - end - - def generate_config_file(project_path, project_name, project_type, ai_provider, ai_model) - config = { - project_name: project_name, - project_type: project_type, - ai_provider: ai_provider, - ai_model: ai_model - } - - TTY::File.create_file(File.join(project_path, "lib", project_name, "config", "sublayer.yml"), YAML.dump(config)) if project_type == "CLI" - - if project_type == "Quick Script" - config_lines = <<~CONFIG - Sublayer.configuration.ai_provider = Sublayer::Providers::#{config[:ai_provider]} - Sublayer.configuration.ai_model = "#{config[:ai_model]}" - CONFIG - project_file = File.join(project_path, "#{project_name}.rb") - File.write(project_file, File.read(project_file) + config_lines) - end - end - - def project_type_instructions(project_type) - if project_type == "CLI" - "Run your CLI application:\n ```\n ruby bin/#{File.basename(project_path)}\n ```" - else - "Start your web server:\n ```\n ruby app.rb\n ```\n Then visit http://localhost:4567 in your browser." - end - end - - def replace_placeholders(project_path, project_name) - # First rename the lib/PROJECT_NAME directory to lib/project_name - FileUtils.mv(File.join(project_path, "lib", "PROJECT_NAME"), File.join(project_path, "lib", project_name.gsub("-", "_").downcase)) if File.directory?(File.join(project_path, "lib", "PROJECT_NAME")) - - # Then walk through each file in the project and replace the placeholder content and filenames - Dir.glob("#{project_path}/**/*", File::FNM_DOTMATCH).each do |file_path| - next if File.directory?(file_path) - next if file_path.include?(".git/") - - content = File.read(file_path) - PLACEHOLDERS.each do |placeholder, options| - replacement = if options[:camelcase] - project_name.split(/[_-]/).map(&:capitalize).join - elsif options[:underscore] - project_name.gsub("-", "_").downcase - else - project_name - end - content.gsub!(placeholder, replacement) if options[:gsub] - end - - File.write(file_path, content) - - - if file_path.include?('PROJECT_NAME') - new_path = file_path.gsub("PROJECT_NAME", project_name.gsub("-", "_").downcase) - - FileUtils.mkdir_p(File.dirname(new_path)) - FileUtils.mv(file_path, new_path) - end - - if file_path.include?('project_name') - new_path = file_path.gsub("project_name", project_name.gsub("-", "_").downcase) - - FileUtils.mkdir_p(File.dirname(new_path)) - FileUtils.mv(file_path, new_path) - end - end - - # replace the sublayer version in the gemspec file with Sublayer::VERSION - if File.exist?(File.join(project_path, "#{project_name}.gemspec")) - gemspec_path = File.join(project_path, "#{project_name}.gemspec") - gemspec_content = File.read(gemspec_path) - gemspec_content.gsub!("SUBLAYER_VERSION", Sublayer::VERSION) - File.write(gemspec_path, gemspec_content) - end - end - - def finalize_project(project_path, project_type) - cmd = TTY::Command.new(printer: :null) - - if TTY::Prompt.new.yes?("Initialize a git repository?") - cmd.run("git init", chdir: project_path) - end +require_relative "cli/commands/new_project" - if TTY::Prompt.new.yes?("Install dependencies now?") - cmd.run("bundle install", chdir: project_path) - end +module Sublayer + class CLI < Thor - puts "To get started, run:" - puts " cd #{File.basename(project_path)}" - puts " ./bin/#{File.basename(project_path)}" if project_type == "CLI" - puts " ruby #{File.basename(project_path)}.rb" if project_type == "Quick Script" - end + register(Sublayer::Commands::NewProject, "new", "new PROJECT_NAME", "Creates a new Sublayer project") - def display_help - puts "Usage: sublayer [command] [arguments]" - puts "Commands:" - puts " new PROJECT_NAME Create a new Sublayer project" - puts " help Display this help message" + desc "version", "Prints the Sublayer version" + def version + puts Sublayer::VERSION end end end diff --git a/lib/sublayer/cli/commands/new_project.rb b/lib/sublayer/cli/commands/new_project.rb new file mode 100644 index 0000000..84b1d70 --- /dev/null +++ b/lib/sublayer/cli/commands/new_project.rb @@ -0,0 +1,116 @@ +module Sublayer + module Commands + class NewProject < Thor::Group + include Thor::Actions + + argument :project_name, type: :string, desc: "The name of your project" + + class_option :template, type: :string, desc: "Type of project (CLI or QuickScript)", aliases: :t + class_option :provider, type: :string, desc: "AI provider (OpenAI, Claude, or Gemini)", aliases: :p + class_option :model, type: :string, desc: "AI model name to use (e.g. gpt-4o, claude-3-haiku-20240307, gemini-1.5-flash-latest)", aliases: :m + + def sublayer_version + Sublayer::VERSION + end + + def self.source_root + File.dirname(__FILE__) + end + + def ask_for_project_details + puts options[:template] + @project_template = options[:template] || ask("Select a project template:", default: "CLI", limited_to: %w[CLI QuickScript]) + @ai_provider = options[:provider] || ask("Select an AI provider:", default: "OpenAI", limited_to: %w[OpenAI Claude Gemini]) + @ai_model = options[:model] || select_ai_model + end + + def create_project_directory + say "Creating project directory", :green + empty_directory project_name + end + + def copy_template_files + say "Copying template files", :green + template_dir = @project_template == "CLI" ? "cli" : "quick_script" + directory "../templates/#{template_dir}", project_name + empty_directory File.join(project_name, "log") if @project_template =="CLI" + end + + def generate_config_file + say "Generating configuration", :green + + config = { + project_name: project_name, + project_template: @project_template, + ai_provider: @ai_provider, + ai_model: @ai_model + } + + if @project_template == "CLI" + create_file File.join(project_name, "lib", project_name, "config", "sublayer.yml"), YAML.dump(config) + else + append_to_file File.join(project_name, "#{project_name}.rb") do + <<~CONFIG + Sublayer.configuration.ai_provider = Sublayer::Providers::#{config[:ai_provider]} + Sublayer.configuration.ai_model = "#{config[:ai_model]}" + CONFIG + end + end + end + + def finalize_project + say "Finalizing project", :green + inside(project_name) do + if @project_template == "CLI" + chmod("bin/#{project_name}", "+x") + run("bundle install") if yes?("Install gems?") + else + append_to_file "#{project_name}.rb" do + <<~INSTRUCTIONS + puts "Welcome to your quick Sublayer script!" + puts "To get started, create some generators, actions, or agents in their respective directories and call them here" + puts "For more information, visit https://docs.sublayer.com" + INSTRUCTIONS + end + end + + run("git init") if yes?("Initialize a git repository?") + end + end + + def print_next_steps + say "\nSublayer project '#{project_name}' created successfully!", :green + say "To get started, run:" + say " cd #{project_name}" + if @project_template == "CLI" + say " ./bin/#{project_name}" + else + say " ruby #{project_name}.rb" + end + end + + private + + def select_ai_model + case @ai_provider + when "OpenAI" + ask("Which OpenAI model would you like to use?", default: "gpt-4o", limited_to: %w[gpt-4o gpt-4o-mini gpt-4-turbo gpt-3.5-turbo]) + when "Claude" + ask("Which Anthropic model would you like to use?", default: "claude-3-5-sonnet-20240620", limited_to: %w[claude-3-5-sonnet-20240620 claude-3-opus-20240620 claude-3-haiku-20240307]) + when "Gemini" + ask("Which Google model would you like to use?", default: "gemini-1.5-flash-latest", limited_to: %w[gemini-1.5-flash-latest gemini-1.5-pro-latest]) + end + end + + def rename_project_name_directory + old_path = File.join(project_name, "lib", "PROJECT_NAME") + new_path = File.join(project_name, "lib", project_name.gsub("-", "_").downcase) + + if File.directory?(old_path) + say "Renaming project directory", :green + FileUtils.mv(old_path, new_path) + end + end + end + end +end diff --git a/lib/sublayer/templates/cli/PROJECT_NAME.gemspec b/lib/sublayer/cli/templates/cli/%project_name%.gemspec.tt similarity index 75% rename from lib/sublayer/templates/cli/PROJECT_NAME.gemspec rename to lib/sublayer/cli/templates/cli/%project_name%.gemspec.tt index 85e3d23..5af2fcb 100644 --- a/lib/sublayer/templates/cli/PROJECT_NAME.gemspec +++ b/lib/sublayer/cli/templates/cli/%project_name%.gemspec.tt @@ -1,22 +1,22 @@ -require_relative "lib/PROJECT_NAME/version" +require_relative "lib/<%= project_name.gsub("-", "_") %>/version" Gem::Specification.new do |spec| - spec.name = "PROJECT_NAME" - spec.version = ProjectName::VERSION + spec.name = "<%= project_name %>" + spec.version = <%= project_name.camelize %>::VERSION spec.authors = ["Your Name"] spec.email = ["your.email@example.com"] spec.summary = "Summary of your project" spec.description = "Longer description of your project" - spec.homepage = "https://github.com/yourusername/PROJECT_NAME" + spec.homepage = "https://github.com/yourusername/<%= project_name %>" spec.license = "MIT" spec.required_ruby_version = ">= 2.6.0" spec.metadata["allowed_push_host"] = "TODO: Set to your gem server 'https://example.com'" spec.metadata["homepage_uri"] = spec.homepage - spec.metadata["source_code_uri"] = "https://github.com/yourusername/PROJECT_NAME" - spec.metadata["changelog_uri"] = "https://github.com/yourusername/PROJECT_NAME/blob/master/CHANGELOG.md" + spec.metadata["source_code_uri"] = "https://github.com/yourusername/<%= project_name %>" + spec.metadata["changelog_uri"] = "https://github.com/yourusername/<%= project_name %>/blob/master/CHANGELOG.md" # Specify which files should be added to the gem when it is released. # The `git ls-files -z` loads the files in the RubyGem that have been added into git. @@ -30,6 +30,6 @@ Gem::Specification.new do |spec| spec.require_paths = ["lib"] # Add dependencies here - spec.add_dependency "sublayer", "~> SUBLAYER_VERSION" + spec.add_dependency "sublayer", "~> <%= sublayer_version %>" spec.add_dependency "thor", "~> 1.2" end diff --git a/lib/sublayer/templates/cli/.gitignore b/lib/sublayer/cli/templates/cli/.gitignore similarity index 100% rename from lib/sublayer/templates/cli/.gitignore rename to lib/sublayer/cli/templates/cli/.gitignore diff --git a/lib/sublayer/templates/cli/Gemfile b/lib/sublayer/cli/templates/cli/Gemfile similarity index 100% rename from lib/sublayer/templates/cli/Gemfile rename to lib/sublayer/cli/templates/cli/Gemfile diff --git a/lib/sublayer/templates/cli/README.md b/lib/sublayer/cli/templates/cli/README.md.tt similarity index 83% rename from lib/sublayer/templates/cli/README.md rename to lib/sublayer/cli/templates/cli/README.md.tt index 77202b0..671bba1 100644 --- a/lib/sublayer/templates/cli/README.md +++ b/lib/sublayer/cli/templates/cli/README.md.tt @@ -1,4 +1,4 @@ -# ProjectName +# <%= project_name %> Welcome to your new Sublayer CLI project! @@ -13,7 +13,7 @@ Execute: To run your CLI application: ``` -$ bin/PROJECT_NAME +$ bin/<%= project_name %> ``` Available commands: diff --git a/lib/sublayer/cli/templates/cli/bin/%project_name%.tt b/lib/sublayer/cli/templates/cli/bin/%project_name%.tt new file mode 100755 index 0000000..1bd9351 --- /dev/null +++ b/lib/sublayer/cli/templates/cli/bin/%project_name%.tt @@ -0,0 +1,5 @@ +#!/usr/bin/env ruby + +require_relative "../lib/<%= project_name %>" + +<%= project_name.camelize %>::CLI.start(ARGV) diff --git a/lib/sublayer/cli/templates/cli/lib/%project_name%.rb.tt b/lib/sublayer/cli/templates/cli/lib/%project_name%.rb.tt new file mode 100644 index 0000000..5f89c52 --- /dev/null +++ b/lib/sublayer/cli/templates/cli/lib/%project_name%.rb.tt @@ -0,0 +1,21 @@ +require "yaml" +require "thor" +require "sublayer" +require_relative "<%= project_name.gsub("-", "_") %>/version" +require_relative "<%= project_name.gsub("-", "_") %>/config" + +Dir[File.join(__dir__, "<%= project_name.gsub("-", "_") %>", "commands", "*.rb")].each { |file| require file } +Dir[File.join(__dir__, "<%= project_name.gsub("-", "_") %>", "generators", "*.rb")].each { |file| require file } +Dir[File.join(__dir__, "<%= project_name.gsub("-", "_") %>", "actions", "*.rb")].each { |file| require file } +Dir[File.join(__dir__, "<%= project_name.gsub("-", "_") %>", "agents", "*.rb")].each { |file| require file } + +require_relative "<%= project_name.gsub("-", "_") %>/cli" + +module <%= project_name.camelize %> + class Error < StandardError; end + Config.load + + def self.root + File.dirname __dir__ + end +end diff --git a/lib/sublayer/templates/cli/lib/PROJECT_NAME/actions/example_action.rb b/lib/sublayer/cli/templates/cli/lib/%project_name%/actions/example_action.rb.tt similarity index 87% rename from lib/sublayer/templates/cli/lib/PROJECT_NAME/actions/example_action.rb rename to lib/sublayer/cli/templates/cli/lib/%project_name%/actions/example_action.rb.tt index 0e96b54..0ab7076 100644 --- a/lib/sublayer/templates/cli/lib/PROJECT_NAME/actions/example_action.rb +++ b/lib/sublayer/cli/templates/cli/lib/%project_name%/actions/example_action.rb.tt @@ -1,6 +1,6 @@ # frozen_string_literal: true -module ProjectName +module <%= project_name.camelize %> module Actions class ExampleAction < Sublayer::Actions::Base def initialize(input:) diff --git a/lib/sublayer/templates/cli/lib/PROJECT_NAME/agents/example_agent.rb b/lib/sublayer/cli/templates/cli/lib/%project_name%/agents/example_agent.rb.tt similarity index 91% rename from lib/sublayer/templates/cli/lib/PROJECT_NAME/agents/example_agent.rb rename to lib/sublayer/cli/templates/cli/lib/%project_name%/agents/example_agent.rb.tt index 54591dd..6c75c2e 100644 --- a/lib/sublayer/templates/cli/lib/PROJECT_NAME/agents/example_agent.rb +++ b/lib/sublayer/cli/templates/cli/lib/%project_name%/agents/example_agent.rb.tt @@ -1,6 +1,6 @@ # frozen_string_literal: true -module ProjectName +module <%= project_name.camelize %> module Agents class ExampleAgent < Sublayer::Agents::Base trigger_on_files_changed { ["example_file.txt"] } diff --git a/lib/sublayer/cli/templates/cli/lib/%project_name%/cli.rb.tt b/lib/sublayer/cli/templates/cli/lib/%project_name%/cli.rb.tt new file mode 100644 index 0000000..6cc19a6 --- /dev/null +++ b/lib/sublayer/cli/templates/cli/lib/%project_name%/cli.rb.tt @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +module <%= project_name.camelize %> + class CLI < Thor + <%= project_name.camelize %>::Commands.constants.reject{ |command_class| command_class == :BaseCommand }.each do |command_class| + command = <%= project_name.camelize %>::Commands.const_get(command_class) + desc command.command_name, command.description + define_method(command.command_name) do |*args| + command.new(options).execute(*args) + end + end + end +end diff --git a/lib/sublayer/templates/cli/lib/PROJECT_NAME/commands/base_command.rb b/lib/sublayer/cli/templates/cli/lib/%project_name%/commands/base_command.rb.tt similarity index 92% rename from lib/sublayer/templates/cli/lib/PROJECT_NAME/commands/base_command.rb rename to lib/sublayer/cli/templates/cli/lib/%project_name%/commands/base_command.rb.tt index 0626c31..9fb0fed 100644 --- a/lib/sublayer/templates/cli/lib/PROJECT_NAME/commands/base_command.rb +++ b/lib/sublayer/cli/templates/cli/lib/%project_name%/commands/base_command.rb.tt @@ -1,4 +1,4 @@ -module ProjectName +module <%= project_name.camelize %> module Commands class BaseCommand def self.command_name diff --git a/lib/sublayer/templates/cli/lib/PROJECT_NAME/commands/example_command.rb b/lib/sublayer/cli/templates/cli/lib/%project_name%/commands/example_command.rb.tt similarity index 62% rename from lib/sublayer/templates/cli/lib/PROJECT_NAME/commands/example_command.rb rename to lib/sublayer/cli/templates/cli/lib/%project_name%/commands/example_command.rb.tt index 29dcec6..0e615ad 100644 --- a/lib/sublayer/templates/cli/lib/PROJECT_NAME/commands/example_command.rb +++ b/lib/sublayer/cli/templates/cli/lib/%project_name%/commands/example_command.rb.tt @@ -1,4 +1,4 @@ -module ProjectName +module <%= project_name.camelize %> module Commands class ExampleCommand < BaseCommand def self.description @@ -6,7 +6,7 @@ def self.description end def execute(*args) - puts ProjectName::Generators::ExampleGenerator.new(input: args.join(" ")).generate + puts <%= project_name.camelize %>::Generators::ExampleGenerator.new(input: args.join(" ")).generate end end end diff --git a/lib/sublayer/templates/cli/lib/PROJECT_NAME/config.rb b/lib/sublayer/cli/templates/cli/lib/%project_name%/config.rb.tt similarity index 94% rename from lib/sublayer/templates/cli/lib/PROJECT_NAME/config.rb rename to lib/sublayer/cli/templates/cli/lib/%project_name%/config.rb.tt index b3bcc65..d34a87d 100644 --- a/lib/sublayer/templates/cli/lib/PROJECT_NAME/config.rb +++ b/lib/sublayer/cli/templates/cli/lib/%project_name%/config.rb.tt @@ -1,4 +1,4 @@ -module ProjectName +module <%= project_name.camelize %> module Config def self.load config_path = File.join(File.dirname(__FILE__), "config", "sublayer.yml") diff --git a/lib/sublayer/templates/cli/lib/PROJECT_NAME/config/.keep b/lib/sublayer/cli/templates/cli/lib/%project_name%/config/.keep similarity index 100% rename from lib/sublayer/templates/cli/lib/PROJECT_NAME/config/.keep rename to lib/sublayer/cli/templates/cli/lib/%project_name%/config/.keep diff --git a/lib/sublayer/templates/cli/lib/PROJECT_NAME/generators/example_generator.rb b/lib/sublayer/cli/templates/cli/lib/%project_name%/generators/example_generator.rb.tt similarity index 93% rename from lib/sublayer/templates/cli/lib/PROJECT_NAME/generators/example_generator.rb rename to lib/sublayer/cli/templates/cli/lib/%project_name%/generators/example_generator.rb.tt index 5071f1e..9696249 100644 --- a/lib/sublayer/templates/cli/lib/PROJECT_NAME/generators/example_generator.rb +++ b/lib/sublayer/cli/templates/cli/lib/%project_name%/generators/example_generator.rb.tt @@ -1,6 +1,6 @@ # frozen_string_literal: true -module ProjectName +module <%= project_name.camelize %> module Generators class ExampleGenerator < Sublayer::Generators::Base llm_output_adapter type: :single_string, diff --git a/lib/sublayer/templates/cli/lib/PROJECT_NAME/version.rb b/lib/sublayer/cli/templates/cli/lib/%project_name%/version.rb.tt similarity index 60% rename from lib/sublayer/templates/cli/lib/PROJECT_NAME/version.rb rename to lib/sublayer/cli/templates/cli/lib/%project_name%/version.rb.tt index 5369b58..0fa4c5e 100644 --- a/lib/sublayer/templates/cli/lib/PROJECT_NAME/version.rb +++ b/lib/sublayer/cli/templates/cli/lib/%project_name%/version.rb.tt @@ -1,5 +1,5 @@ # frozen_string_literal: true -module ProjectName +module <%= project_name.camelize %> VERSION = "0.0.1" end diff --git a/lib/sublayer/templates/cli/spec/.keep b/lib/sublayer/cli/templates/cli/spec/.keep similarity index 100% rename from lib/sublayer/templates/cli/spec/.keep rename to lib/sublayer/cli/templates/cli/spec/.keep diff --git a/lib/sublayer/templates/quick_script/project_name.rb b/lib/sublayer/cli/templates/quick_script/%project_name%.rb similarity index 85% rename from lib/sublayer/templates/quick_script/project_name.rb rename to lib/sublayer/cli/templates/quick_script/%project_name%.rb index e72608b..4b1464b 100644 --- a/lib/sublayer/templates/quick_script/project_name.rb +++ b/lib/sublayer/cli/templates/quick_script/%project_name%.rb @@ -1,7 +1,7 @@ require "yaml" require "sublayer" +# Load any Actions, Generators, and Agents Dir[File.join(__dir__, "actions", "*.rb")].each { |file| require file } -Dir[File.join(__dir__, "agents", "*.rb")].each { |file| require file } Dir[File.join(__dir__, "generators", "*.rb")].each { |file| require file } - +Dir[File.join(__dir__, "agents", "*.rb")].each { |file| require file } diff --git a/lib/sublayer/templates/quick_script/README.md b/lib/sublayer/cli/templates/quick_script/README.md.tt similarity index 73% rename from lib/sublayer/templates/quick_script/README.md rename to lib/sublayer/cli/templates/quick_script/README.md.tt index a894635..75280a1 100644 --- a/lib/sublayer/templates/quick_script/README.md +++ b/lib/sublayer/cli/templates/quick_script/README.md.tt @@ -1,4 +1,4 @@ -# ProjectName +# <%= project_name.camelize %> Welcome to your new Sublayer quick script project! @@ -7,10 +7,10 @@ There are example Agents, Generators, and Actions in the respective folders. ## Usage Create your own custom agents, generators, and actions and use them in -`project_name.rb` +`<%= project_name %>.rb` Run your script: ``` -$ ruby project_name.rb +$ ruby <%= project_name %>.rb ``` diff --git a/lib/sublayer/templates/quick_script/actions/example_action.rb b/lib/sublayer/cli/templates/quick_script/actions/example_action.rb similarity index 100% rename from lib/sublayer/templates/quick_script/actions/example_action.rb rename to lib/sublayer/cli/templates/quick_script/actions/example_action.rb diff --git a/lib/sublayer/templates/quick_script/agents/example_agent.rb b/lib/sublayer/cli/templates/quick_script/agents/example_agent.rb similarity index 100% rename from lib/sublayer/templates/quick_script/agents/example_agent.rb rename to lib/sublayer/cli/templates/quick_script/agents/example_agent.rb diff --git a/lib/sublayer/templates/quick_script/generators/example_generator.rb b/lib/sublayer/cli/templates/quick_script/generators/example_generator.rb similarity index 100% rename from lib/sublayer/templates/quick_script/generators/example_generator.rb rename to lib/sublayer/cli/templates/quick_script/generators/example_generator.rb diff --git a/lib/sublayer/templates/cli/bin/PROJECT_NAME b/lib/sublayer/templates/cli/bin/PROJECT_NAME deleted file mode 100755 index f503a8e..0000000 --- a/lib/sublayer/templates/cli/bin/PROJECT_NAME +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env ruby - -require_relative "../lib/project_name" - -ProjectName::CLI.start(ARGV) diff --git a/lib/sublayer/templates/cli/lib/PROJECT_NAME/cli.rb b/lib/sublayer/templates/cli/lib/PROJECT_NAME/cli.rb deleted file mode 100644 index e8b5b26..0000000 --- a/lib/sublayer/templates/cli/lib/PROJECT_NAME/cli.rb +++ /dev/null @@ -1,13 +0,0 @@ -# frozen_string_literal: true - -module ProjectName - class CLI < Thor - ProjectName::Commands.constants.reject{ |command_class| command_class == :BaseCommand }.each do |command_class| - command = ProjectName::Commands.const_get(command_class) - desc command.command_name, command.description - define_method(command.command_name) do |*args| - command.new(options).execute(*args) - end - end - end -end diff --git a/lib/sublayer/templates/cli/lib/project_name.rb b/lib/sublayer/templates/cli/lib/project_name.rb deleted file mode 100644 index df12bbc..0000000 --- a/lib/sublayer/templates/cli/lib/project_name.rb +++ /dev/null @@ -1,21 +0,0 @@ -require "yaml" -require "thor" -require "sublayer" -require_relative "PROJECT_NAME/version" -require_relative "PROJECT_NAME/config" - -Dir[File.join(__dir__, "PROJECT_NAME", "commands", "*.rb")].each { |file| require file } -Dir[File.join(__dir__, "PROJECT_NAME", "generators", "*.rb")].each { |file| require file } -Dir[File.join(__dir__, "PROJECT_NAME", "actions", "*.rb")].each { |file| require file } -Dir[File.join(__dir__, "PROJECT_NAME", "agents", "*.rb")].each { |file| require file } - -require_relative "PROJECT_NAME/cli" - -module ProjectName - class Error < StandardError; end - Config.load - - def self.root - File.dirname __dir__ - end -end diff --git a/spec/cli_spec.rb b/spec/cli_spec.rb deleted file mode 100644 index 7cb6b6b..0000000 --- a/spec/cli_spec.rb +++ /dev/null @@ -1,45 +0,0 @@ -require "spec_helper" -require "sublayer/cli" - -RSpec.describe Sublayer::CLI do - let(:cli) { described_class.new } - let(:prompt) { instance_double(TTY::Prompt) } - - before do - allow(TTY::Prompt).to receive(:new).and_return(prompt) - allow(prompt).to receive(:ask).and_return("test_project") - allow(prompt).to receive(:select).and_return("CLI", "OpenAI") - allow(prompt).to receive(:yes?).and_return(false) - end - - describe "#run" do - it "creates a new project when given the 'new' command" do - expect(cli).to receive(:create_new_project).with("test_project") - cli.run(["new", "test_project"]) - end - - it "displays help when given the 'help' command" do - expect { cli.run(["help"]) }.to output(/Usage: sublayer/).to_stdout - end - - it "displays help when given no command" do - expect { cli.run([]) }.to output(/Usage: sublayer/).to_stdout - end - - it "displays an error for unknown commands" do - expect { cli.run(["unknown"]) }.to output(/Unknown command: unknown/).to_stdout - end - - describe "#create_new_project" do - it "creates a new project with the given name" do - expect(FileUtils).to receive(:mkdir_p).twice - expect(FileUtils).to receive(:cp_r) - expect(TTY::File).to receive(:create_file) - expect(cli).to receive(:replace_placeholders) - expect(cli).to receive(:finalize_project) - - cli.send(:create_new_project, "test_project") - end - end - end -end diff --git a/spec/integration/quick_script_creation_spec.rb b/spec/integration/quick_script_creation_spec.rb index aa61b65..37b1181 100644 --- a/spec/integration/quick_script_creation_spec.rb +++ b/spec/integration/quick_script_creation_spec.rb @@ -22,8 +22,8 @@ end it "creates a new project with all the expected files and structures" do - command = "ruby -I lib #{File.dirname(__FILE__)}/../../bin/sublayer new #{project_name}" - input = "\e[B\n\n\nn\n\n" + command = "ruby -I lib #{File.dirname(__FILE__)}/../../bin/sublayer new #{project_name} --template quick_script" + input = "OpenAI\ngpt-4o\nn\n\n" output, status = Open3.capture2e(command, chdir: TMP_DIR, stdin_data: input) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index c7bf10f..7c1de4a 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -3,6 +3,7 @@ require "sublayer" require "pry" require "vcr" +require_relative "../lib/sublayer/cli" VCR.configure do |config| config.cassette_library_dir = "spec/vcr_cassettes"