### Create an Executable for Thor Commands Source: https://github.com/rails/thor/wiki/Groups Set up an executable file to run Thor commands. Ensure the Thor command class is required and its `start` method is called. ```ruby #!/usr/bin/env ruby require File.expand_path('lib/command', Dir.pwd) MyAwesomeGem::MyCommand.start ``` -------------------------------- ### Thor CLI Binary Setup Source: https://github.com/rails/thor/wiki/Integrating-with-Aruba-In-Process-Runs This script is the entry point for your Thor CLI application. It requires the runner class and initializes it with command-line arguments. ```ruby #!/usr/bin/env ruby require 'mycli/runner' MyCli::Runner.new(ARGV.dup).execute! ``` -------------------------------- ### Command-line Examples for Inter-Class Invocation Source: https://github.com/rails/thor/wiki/Invocations Illustrates the execution of tasks from different Thor classes, including passing options via the command line. ```bash thor a:list --line foo ``` ```bash thor a:list ``` ```bash thor b:dig --name bar ``` -------------------------------- ### Example of Repeatable Option Usage Source: https://github.com/rails/thor/wiki/Method-Options Illustrates how multiple instances of a repeatable option are collected into an array in the resulting options hash. ```ruby { format: ["html", "xml", "text"] } ``` -------------------------------- ### Interactive CLI Setup Wizard Source: https://context7.com/rails/thor/llms.txt Use Thor's shell methods like `say`, `ask`, `yes?`, and `no?` for interactive user input and output. Supports colored output, default values, limited choices, hidden input, and tab completion. ```ruby class InteractiveCLI < Thor include Thor::Actions desc "setup", "Interactive setup wizard" def setup # Simple output say "Welcome to the setup wizard!", :green say_status :info, "Starting configuration...", :blue # Ask for input name = ask("What is your name?") # Ask with default value email = ask("What is your email?", default: "user@example.com") # Ask with limited choices color = ask("Favorite color?", limited_to: ["red", "green", "blue"]) # Ask for password (hidden input) password = ask("Enter password:", echo: false) # Ask for file path (with tab completion) config_path = ask("Config file path:", path: true) # Yes/no questions if yes?("Enable feature X?", :yellow) say_status :enable, "Feature X", :green end unless no?("Skip optional step?") say_status :skip, "Optional step", :yellow end # Print formatted table data = [ ["Name", name], ["Email", email], ["Color", color] ] print_table(data) # Print with status indicators say_status :create, "config/settings.yml", :green say_status :update, "database.yml", :yellow say_status :remove, "old_config.yml", :red say_status :identical, "unchanged.yml", :blue end desc "confirm ACTION", "Confirm before performing action" def confirm(action) if yes?("Are you sure you want to #{action}? This cannot be undone.", :red) say "Performing #{action}...", :green else say "Cancelled.", :yellow end end end ``` -------------------------------- ### Subcommands with Custom Help Formatting Source: https://github.com/rails/thor/wiki/Subcommands This example demonstrates how to create subcommands that integrate correctly with Thor's help system by defining a custom `banner` and `subcommand_prefix`. This is useful for organizing complex CLIs. ```ruby #!/usr/bin/env ruby require 'thor' class SubCommandBase < Thor def self.banner(command, namespace = nil, subcommand = false) "#{basename} #{subcommand_prefix} #{command.usage}" end def self.subcommand_prefix self.name.gsub(%r{.*::}, '').gsub(%r{^[A-Z]}) { |match| match[0].downcase }.gsub(%r{[A-Z]}) { |match| "-#{match[0].downcase}" } end end module App class Docs < SubCommandBase desc "create", "create docs" def create # create end desc "publish", "publish docs" def publish # publish end end class CLI < Thor desc "docs", "create and publish docs" subcommand "docs", Docs end end App::CLI.start ``` -------------------------------- ### Direct Method Calls for Repeated Operations Source: https://github.com/rails/thor/wiki/Invocations Demonstrates using direct method calls (e.g., `setup()`) instead of `invoke` when a task needs to be executed multiple times within a single parent task. This is suitable for setup/teardown operations. ```ruby class Tests < Thor desc('all', 'run all tests') def all setup() invoke :some_test_suite teardown() setup() invoke :some_other_test_suite teardown() # etc. end desc('setup', 'set up the test database') def setup # some setup tasks here end desc('teardown', 'tear down the test database') def teardown # some teardown tasks here end end ``` -------------------------------- ### Thor Command Invocation Example Source: https://github.com/rails/thor/wiki/Home Illustrates how a Thor command with arguments and options is invoked from the bash shell and how it translates to a Ruby method call. ```bash thor app:install myname --force ``` -------------------------------- ### Run Specs Locally Source: https://github.com/rails/thor/blob/main/CONTRIBUTING.md Execute all test specifications locally to ensure code quality before submitting a pull request. This command requires Bundler to be installed. ```bash bundle exec rspec ``` -------------------------------- ### Download Remote File Source: https://context7.com/rails/thor/llms.txt The `get` method downloads a file from a given URL and saves it to a local path. ```ruby get "https://raw.githubusercontent.com/github/gitignore/main/Ruby.gitignore", "#{name}/.gitignore" ``` -------------------------------- ### Run Linting Checks Locally Source: https://github.com/rails/thor/blob/main/CONTRIBUTING.md Perform code linting using RuboCop to enforce coding style and identify potential issues. This command requires RuboCop to be installed. ```bash bundle exec rubocop ``` -------------------------------- ### Define Rake Tasks and Thor Task to Invoke Them Source: https://github.com/rails/thor/wiki/Calling-Rake-tasks-with-Thor This example defines custom Rake tasks ('cool', 'hiper_mega:super') using Rake::TaskLib and then creates a Thor task ('cool') that invokes the 'cool' Rake task and prints its description. ```ruby require 'thor/rake_compat' require "rake/tasklib" class RakeTask < Rake::TaskLib def initialize define end def define instance_eval do desc "Say it's cool" task :cool do puts "COOL" end namespace :hiper_mega do task :super do puts "HIPER MEGA SUPER" end end end end end class ThorTask < Thor include Thor::RakeCompat RakeTask.new desc 'cool', 'say cool' def cool Rake::Task['cool'].invoke puts ThorTask.tasks['cool'].description end end ``` -------------------------------- ### Create Executable File and Set Permissions Source: https://context7.com/rails/thor/llms.txt Demonstrates creating an executable file using `create_file` and then setting its permissions to 0755 using `chmod`. ```ruby create_file "#{name}/bin/run", "#!/usr/bin/env ruby\nputs 'Running!'" chmod "#{name}/bin/run", 0755 ``` -------------------------------- ### Create a Basic Thor Executable Script Source: https://github.com/rails/thor/wiki/Making-An-Executable Include the ruby shebang, require Thor, define your Thor class, and call `YourThorClassname.start` at the bottom. This script will execute Thor commands. ```ruby #!/usr/bin/env ruby require "rubygems" # ruby1.9 doesn't "require" it though require "thor" class MyThorCommand < Thor desc "foo", "Prints foo" def foo puts "foo" end end MyThorCommand.start ``` -------------------------------- ### Custom Help and Package Name Source: https://context7.com/rails/thor/llms.txt Customize the help output by setting a package name using `package_name`. Commands can be hidden from help using the `hide: true` option in their description. Long descriptions can be provided using `long_desc`. ```ruby class MyApp < Thor package_name "MyApp" # Shown in help output desc "visible", "A visible command" def visible puts "You can see this!" end desc "hidden", "A hidden command", hide: true def hidden puts "Secret command!" end desc "documented", "Well documented command" long_desc <<-LONGDESC This command does many things: 1. First it does X 2. Then it does Y 3. Finally it does Z Example: $ myapp documented --option value This will produce the following output: Result of the operation LONGDESC method_option :option, type: :string def documented puts "Documented!" end # Disable required option check for help disable_required_check! :help desc "requires_input", "Needs required option" method_option :input, type: :string, required: true def requires_input puts "Input: #{options[:input]}" end end ``` -------------------------------- ### Create New File with Content Source: https://context7.com/rails/thor/llms.txt Use `create_file` to generate a new file with specified content. The content can be a simple string or a heredoc. ```ruby create_file "#{name}/README.md", <<~MD # #{name.capitalize} A new application. MD ``` -------------------------------- ### Prepend to File Source: https://context7.com/rails/thor/llms.txt Use `prepend_to_file` to add content to the beginning of a file. This is useful for adding headers or initial configurations. ```ruby prepend_to_file "app/models/user.rb", "# frozen_string_literal: true\n\n" ``` -------------------------------- ### Copy File from Source Root Source: https://context7.com/rails/thor/llms.txt Utilize `copy_file` to duplicate a file from the `source_root` directory to a destination path. ```ruby copy_file "MIT-LICENSE", "#{name}/LICENSE" ``` -------------------------------- ### Copy Directory Structure Source: https://context7.com/rails/thor/llms.txt Use `directory` to copy an entire directory and its contents from the `source_root` to a specified destination. ```ruby directory "assets", "#{name}/public/assets" ``` -------------------------------- ### Basic Thor CLI Class Source: https://context7.com/rails/thor/llms.txt Define a basic Thor CLI application by inheriting from Thor and defining commands as methods. Use `desc` for usage and description. Ensure `exit_on_failure?` is set to true for error handling. ```ruby #!/usr/bin/env ruby require "thor" class MyCLI < Thor def self.exit_on_failure? true end desc "hello NAME", "Say hello to NAME" def hello(name) puts "Hello, #{name}!" end desc "goodbye NAME", "Say goodbye to NAME" long_desc <<-LONGDESC `goodbye` will print a farewell message to the specified person. You can optionally specify the --formal flag to use a more formal greeting. LONGDESC method_option :formal, type: :boolean, default: false def goodbye(name) if options[:formal] puts "Farewell, #{name}. It was a pleasure." else puts "Bye, #{name}!" end end end MyCLI.start(ARGV) # Usage: # $ ./cli.rb hello World # Hello, World! # # $ ./cli.rb goodbye John --formal # Farewell, John. It was a pleasure. # # $ ./cli.rb help # Commands: # cli.rb goodbye NAME # Say goodbye to NAME # cli.rb hello NAME # Say hello to NAME # cli.rb help [COMMAND] # Describe available commands or one specific command ``` -------------------------------- ### Define Thor Class with Options and Tasks Source: https://github.com/rails/thor/wiki/Home Inherit from Thor to create a command-line application. Use `package_name` for identification, `map` to alias commands, `desc` to document tasks, and `method_options` to define task-specific options. ```ruby class App < Thor package_name "App" map "-L" => :list desc "install APP_NAME", "install one of the available apps" method_options :force => :boolean, :alias => :string def install(name) user_alias = options[:alias] if options.force? # do something end # other code end desc "list [SEARCH]", "list all of the available apps, limited by SEARCH" def list(search="") # list everything end end ``` -------------------------------- ### Make Script Executable Source: https://github.com/rails/thor/wiki/Making-An-Executable Use the `chmod` command to make the script executable by all users. ```sh chmod a+x mythorcommand.rb ``` -------------------------------- ### Define Option with Alias Source: https://github.com/rails/thor/wiki/Method-Options Creates an option and assigns it a short alias for convenience. Aliases allow users to use shorter flags on the command line. ```ruby method_option :aliases => "bar" ``` -------------------------------- ### Invoking Tasks from Different Classes with Options Source: https://github.com/rails/thor/wiki/Invocations Shows how class B can invoke a task from class A, passing options to it. This highlights the ability to pass arguments and options during task invocation. ```ruby class A < Thor desc "list LINE", "Does A stuff" method_option :line, :type => :string, :required => false def list unless options[:line].nil? puts "Line option is #{options[:line]}" else puts "Line option wasn't passed" end end end class B < Thor desc "dig NAME", "Does B stuff" method_option :name, :type => :string def dig invoke 'a:list', [], :line => options[:name] end end ``` -------------------------------- ### Define String Option with Default Value Source: https://github.com/rails/thor/wiki/Method-Options Creates a string option with a default value. This is useful when an option is optional but has a sensible fallback. ```ruby method_option :value, :default => "some value" ``` -------------------------------- ### Runtime Options for Generators Source: https://context7.com/rails/thor/llms.txt Utilize `add_runtime_options!` to include standard options like `--force`, `--pretend`, `--quiet`, and `--skip` in your Thor groups. File operations automatically respect these options. ```ruby class SafeGenerator < Thor::Group include Thor::Actions # Add standard runtime options: --force, --pretend, --quiet, --skip add_runtime_options! argument :name def self.source_root File.dirname(__FILE__) end def create_structure # All file operations respect --pretend (dry run) empty_directory "#{name}/lib" create_file "#{name}/lib/#{name}.rb", "# #{name}" end def work_inside_directory # Execute block inside a directory inside(name) do create_file "config.yml", "app: #{name}" # Run shell command run "bundle init" unless options[:pretend] end end def conditional_overwrite # With --force: overwrite without asking # With --skip: skip if exists # Default: ask user create_file "#{name}/README.md", "# #{name}", force: options[:force] end end class CLI < Thor register(SafeGenerator, "generate", "generate NAME", "Generate project structure") end ``` -------------------------------- ### Define a Basic Thor Task Source: https://github.com/rails/thor/wiki/Getting-Started Create a simple Thor task within a .thor file. The class name defines the namespace and the method name becomes the task. ```ruby class Test < Thor desc "example", "an example task" def example puts "I'm a thor task!" end end ``` -------------------------------- ### Define Multiple Options with Aliases Source: https://github.com/rails/thor/wiki/Method-Options Defines multiple options, specifying their types and aliases in a hash format. This is a concise way to declare several options at once. ```ruby method_options %w( force -f ) => :boolean ``` -------------------------------- ### Stop on Unknown Options Source: https://context7.com/rails/thor/llms.txt Configure commands to stop parsing options when encountering unknown flags. Use `stop_on_unknown_option!` to specify commands that should behave this way, and `check_unknown_options!` to control checking for unknown options globally or with exceptions. ```ruby class PassthroughCLI < Thor class_option :verbose, type: :boolean, aliases: "-v" # Stop parsing at unknown options for exec command stop_on_unknown_option! :exec check_unknown_options! except: :exec desc "exec COMMAND", "Execute a shell command" def exec(*args) puts "Verbose: #{options[:verbose]}" if options[:verbose] command = args.join(" ") puts "Executing: #{command}" system(command) end desc "run_tests", "Run tests with coverage" method_option :coverage, type: :boolean def run_tests puts "Running tests..." end end ``` -------------------------------- ### MyCli Runner Class for In-Process Execution Source: https://github.com/rails/thor/wiki/Integrating-with-Aruba-In-Process-Runs This class enables in-process testing by allowing dependencies like STDIN, STDOUT, and STDERR to be injected. It handles Thor's execution and exception management, proxying the exit code. ```ruby require 'mycli/app' module MyCli class Runner # Allow everything fun to be injected from the outside while defaulting to normal implementations. def initialize(argv, stdin = STDIN, stdout = STDOUT, stderr = STDERR, kernel = Kernel) @argv, @stdin, @stdout, @stderr, @kernel = argv, stdin, stdout, stderr, kernel end def execute! exit_code = begin # Thor accesses these streams directly rather than letting them be injected, so we replace them... $stderr = @stderr $stdin = @stdin $stdout = @stdout # Run our normal Thor app the way we know and love. MyCli::App.start(@argv) # Thor::Base#start does not have a return value, assume success if no exception is raised. 0 rescue StandardError => e # The ruby interpreter would pipe this to STDERR and exit 1 in the case of an unhandled exception b = e.backtrace @stderr.puts("#{b.shift}: #{e.message} (#{e.class})") @stderr.puts(b.map{|s| "\tfrom #{s}"}.join("\n")) 1 rescue SystemExit => e e.status ensure # TODO: reset your app here, free up resources, etc. # Examples: # MyApp.logger.flush # MyApp.logger.close # MyApp.logger = nil # # MyApp.reset_singleton_instance_variables # ...then we put the streams back. $stderr = STDERR $stdin = STDIN $stdout = STDOUT end # Proxy our exit code back to the injected kernel. @kernel.exit(exit_code) end end end ``` -------------------------------- ### Aruba Configuration for In-Process Thor Testing Source: https://github.com/rails/thor/wiki/Integrating-with-Aruba-In-Process-Runs This configuration file sets up Aruba to use the `MyCli::Runner` for in-process execution of Thor applications. It integrates the runner with Aruba's in-process capabilities. ```ruby # ... require 'aruba/cucumber' require 'aruba/in_process' require 'mycli/runner' Aruba::Processes::InProcess.main_class = MyCli::Runner Aruba.process = Aruba::Processes::InProcess # ... ``` -------------------------------- ### Executing a Thor Task Source: https://github.com/rails/thor/wiki/Invocations Command-line execution of the 'one' task from the Counter class. ```bash thor counter:one ``` -------------------------------- ### Include Thor::Actions in a Thor Class Source: https://github.com/rails/thor/wiki/Actions Include `Thor::Actions` to gain access to Thor's built-in scripting and generator actions within your Thor class. ```ruby class App < Thor include Thor::Actions # tasks end ``` -------------------------------- ### Execute Thor Command Source: https://github.com/rails/thor/wiki/Making-An-Executable Run the executable script with a command name as an argument. ```sh ./mythorcommand.rb foo ``` -------------------------------- ### Internal Thor Command Conversion Source: https://github.com/rails/thor/wiki/Home Shows the internal Ruby representation of a Thor command invocation, demonstrating how options and arguments are passed to the corresponding class method. ```ruby App.new.install("myname") # with {'force' => true} as options hash ``` -------------------------------- ### Generate Projects with Thor::Group Source: https://context7.com/rails/thor/llms.txt Thor::Group executes defined methods sequentially, making it suitable for generators and multi-step tasks where order is important. It includes argument and option handling. ```ruby require "thor/group" class ProjectGenerator < Thor::Group include Thor::Actions argument :name, type: :string, desc: "Project name" class_option :test_framework, type: :string, default: "minitest", enum: ["minitest", "rspec"], desc: "Test framework" def self.source_root File.dirname(__FILE__) end def create_root_directory empty_directory(name) end def create_lib_directory empty_directory("#{name}/lib") create_file("#{name}/lib/#{name}.rb", <<~RUBY) module #{name.capitalize} VERSION = "0.1.0" end RUBY end def create_test_directory test_dir = options[:test_framework] == "rspec" ? "spec" : "test" empty_directory("#{name}/#{test_dir}") end def create_gemfile create_file("#{name}/Gemfile", <<~RUBY) source "https://rubygems.org" gem "rake" gem "#{options[:test_framework]}" RUBY end def print_success say("Project '#{name}' created successfully!", :green) end end # Register with a parent Thor class class Generator < Thor register(ProjectGenerator, "project", "project NAME", "Generate a new project") end Generator.start(ARGV) ``` -------------------------------- ### Create Nested Commands with Subcommands Source: https://context7.com/rails/thor/llms.txt Use `subcommand` to create nested command structures, similar to `git remote add`. Each subcommand is defined as a separate Thor class. ```ruby class Remote < Thor desc "add NAME URL", "Add a new remote" def add(name, url) puts "Adding remote '#{name}' with URL: #{url}" end desc "remove NAME", "Remove a remote" def remove(name) puts "Removing remote '#{name}'" end desc "list", "List all remotes" def list puts "origin https://github.com/user/repo.git" puts "upstream https://github.com/org/repo.git" end end class Branch < Thor desc "create NAME", "Create a new branch" method_option :from, type: :string, default: "main", desc: "Base branch" def create(name) puts "Creating branch '#{name}' from '#{options[:from]}'" end desc "delete NAME", "Delete a branch" method_option :force, type: :boolean, aliases: "-f", desc: "Force delete" def delete(name) force = options[:force] ? " (forced)" : "" puts "Deleting branch '#{name}'#{force}" end end class Git < Thor desc "remote SUBCOMMAND", "Manage remotes" subcommand "remote", Remote desc "branch SUBCOMMAND", "Manage branches" subcommand "branch", Branch desc "status", "Show working tree status" def status puts "On branch main\nNothing to commit" end end Git.start(ARGV) ``` -------------------------------- ### Define source_root for File Actions Source: https://github.com/rails/thor/wiki/Actions Define the `source_root` class method to specify the directory where template files are located for actions like `copy_file`. This method should return the absolute path to the root directory. ```ruby class App < Thor include Thor::Actions def self.source_root File.dirname(__FILE__) end end ``` -------------------------------- ### Define a Basic Thor Command Class Source: https://github.com/rails/thor/wiki/Groups A standard Thor class with a single command. This serves as a base for integrating Thor::Group subclasses. ```ruby require "thor" module MyAwesomeGem class MyCommand < Thor desc "foo", "Prints foo" def foo puts "foo" end end end ``` -------------------------------- ### Map Command Aliases with Thor Source: https://context7.com/rails/thor/llms.txt Use `map` to define alternative command names, shortcuts, and aliases for your Thor commands. This is useful for creating short flags and alternative invocations. ```ruby class GitLike < Thor map "-v" => :version map "--version" => :version map "st" => :status map ["-l", "--list"] => :list desc "version", "Show version" def version puts "GitLike v1.0.0" end desc "status", "Show current status" def status puts "All systems operational" end desc "list", "List all items" def list puts "Items: a, b, c" end default_command :status # Run status when no command given end ``` -------------------------------- ### Insert Route Before End of Block Source: https://context7.com/rails/thor/llms.txt Use `insert_into_file` with the `before` option to insert content before a specific pattern, such as the `end` keyword in `config/routes.rb`. ```ruby insert_into_file "config/routes.rb", " #{route}\n", before: /^end/ ``` -------------------------------- ### Define Numeric Option with Default Value Source: https://github.com/rails/thor/wiki/Method-Options Creates a numeric option with a default value. This is suitable for options expecting numerical input. ```ruby method_option :threshold => 3.0 ``` -------------------------------- ### Define a Simple Subcommand in Thor Source: https://github.com/rails/thor/wiki/Subcommands Use the `subcommand` method to map a string name to a Thor subclass, creating a nested command structure. Ensure the subcommand class is required. ```ruby require 'thor' require "sub" class MyApp < Thor desc "parentcommand SUBCOMMAND", "Some Parent Command" subcommand "sub", Sub end MyApp.start ``` ```ruby class Sub < Thor desc "command", "an example task" def command puts "I'm a thor task!" end end ``` -------------------------------- ### Define a Thor Task with Named Options Source: https://github.com/rails/thor/wiki/Getting-Started Implement named options for a Thor task using `method_option`. Options can have aliases and descriptions, and are accessed via the `options` hash. ```ruby class Test < Thor desc "example FILE", "an example task" method_option :delete, :aliases => "-d", :desc => "Delete the file after parsing it" def example(file) puts "You supplied the file: #{file}" delete_file = options[:delete] if delete_file puts "You specified that you would like to delete #{file}" else puts "You do not want to delete #{file}" end end end ``` -------------------------------- ### Define Repeatable String Option Source: https://github.com/rails/thor/wiki/Method-Options Defines a string option that can be used multiple times. Values are collected into an array, even if the option is used only once. ```ruby method_options :format, type: :string, repeatable: true ``` -------------------------------- ### Append to File Source: https://context7.com/rails/thor/llms.txt Use `append_to_file` to add content to the end of a file. This is suitable for adding new configurations or data. ```ruby append_to_file "config/application.rb", <<~RUBY # Custom configuration config.time_zone = "UTC" RUBY ``` -------------------------------- ### Thor Executable Script with Correct Exit on Failure Source: https://github.com/rails/thor/wiki/Making-An-Executable Modify the script to include `self.exit_on_failure?` and set it to `true`. This ensures the script reports failure to the operating system when commands are not found or arguments are invalid. ```ruby #!/usr/bin/env ruby require "rubygems" # ruby1.9 doesn't "require" it though require "thor" class MyThorCommand < Thor def self.exit_on_failure? true end desc "foo", "Prints foo" def foo puts "foo" end end MyThorCommand.start ``` -------------------------------- ### Comment Lines Matching Pattern Source: https://context7.com/rails/thor/llms.txt Use `comment_lines` to add a '#' character to the beginning of lines in a file that match a given regular expression. ```ruby comment_lines "config/environments/production.rb", /config\.assets\.debug/ ``` -------------------------------- ### Thor Task Invocation with Dependency Source: https://github.com/rails/thor/wiki/Invocations Demonstrates how Thor's `invoke` method ensures a task is called only once within an invocation chain. Each `invoke` creates a new Thor object, allowing options to be re-parsed. ```ruby class Counter < Thor desc "one", "Prints 1 2 3" def one puts 1 invoke :two invoke :three end desc "two", "Prints 2 3" def two puts 2 invoke :three end desc "three", "Prints 3" def three puts 3 end end ``` -------------------------------- ### Register a Thor::Group as a Subcommand Source: https://github.com/rails/thor/wiki/Groups Register a Thor::Group class with a Thor command class using the `register` method. This makes the group available as a subcommand. ```ruby require "thor" require File.expand_path("lib/mycounter_file", Dir.pwd) module MyAwesomeGem class MyCommand < Thor desc "foo", "Prints foo" def foo puts "foo" end # register(class_name, subcommand_alias, usage_list_string, description_string) register(MyAwesomeGem::MyCounter, "counter", "counter", "Prints some numbers in sequence") end end ``` -------------------------------- ### Output of Invoked Tasks Source: https://github.com/rails/thor/wiki/Invocations The resulting output when the 'counter:one' task is executed, showing that 'three' was invoked only once. ```bash 1 2 3 ``` -------------------------------- ### Insert Gem into Gemfile Source: https://context7.com/rails/thor/llms.txt Adds a gem line to the `Gemfile`. Use `insert_into_file` with the `after` option to place it after a specific pattern, like the `source` line. ```ruby insert_into_file "Gemfile", gem_line, after: "source \"https://rubygems.org\"\n\n" ``` -------------------------------- ### Define a Custom Generator with Thor Source: https://github.com/rails/thor/wiki/Generators This Ruby code defines a custom Thor generator named 'Newgem'. It includes arguments, options, and actions for creating project files. ```ruby class Newgem < Thor::Group include Thor::Actions # Define arguments and options argument :name class_option :test_framework, :default => :test_unit def self.source_root File.dirname(__FILE__) end def create_lib_file template('templates/newgem.tt', "#{name}/lib/#{name}.rb") end def create_test_file test = options[:test_framework] == "rspec" ? :spec : :test create_file "#{name}/#{test}/#{name}_#{test}.rb" end def copy_licence if yes?("Use MIT license?") # Make a copy of the MITLICENSE file at the source root copy_file "MITLICENSE", "#{name}/MITLICENSE" else say "Shame on you…", :red end end end ``` -------------------------------- ### Inject into Class Source: https://context7.com/rails/thor/llms.txt Use `inject_into_class` to insert code into a specific class definition within a file. It requires the file path, class name, and the code to inject. ```ruby inject_into_class "app/models/user.rb", "User", <<~RUBY validates :email, presence: true has_many :posts RUBY ``` -------------------------------- ### Process ERB Template Source: https://context7.com/rails/thor/llms.txt The `template` method processes ERB files from the `source_root`, allowing dynamic content generation based on instance variables. ```ruby template "config.yml.tt", "#{name}/config/config.yml" ``` -------------------------------- ### Define a Thor Task with a File Parameter Source: https://github.com/rails/thor/wiki/Getting-Started Add a parameter to a Thor task by including it in the method definition and updating the description. This parameter is required when running the task. ```ruby class Test < Thor desc "example FILE", "an example task that does something with a file" def example(file) puts "You supplied the file: #{file}" end end ``` -------------------------------- ### Defining Method Options in Thor Source: https://context7.com/rails/thor/llms.txt Use `method_option` to define command-specific options with types, aliases, defaults, and validation. Supported types include string, boolean, numeric, array, and hash. Options can be repeatable. ```ruby class FileManager < Thor desc "process FILE", "Process a file with various options" method_option :format, type: :string, aliases: "-f", default: "json", enum: ["json", "xml", "csv"], desc: "Output format" method_option :verbose, type: :boolean, aliases: "-v", desc: "Enable verbose output" method_option :count, type: :numeric, aliases: "-n", default: 10, desc: "Number of items" method_option :tags, type: :array, aliases: "-t", desc: "Tags to apply" method_option :metadata, type: :hash, aliases: "-m", desc: "Key-value metadata" method_option :output, type: :string, required: true, aliases: "-o", desc: "Output path" def process(file) puts "Processing: #{file}" puts "Format: #{options[:format]}" puts "Verbose: #{options[:verbose]}" puts "Count: #{options[:count]}" puts "Tags: #{options[:tags].inspect}" if options[:tags] puts "Metadata: #{options[:metadata].inspect}" if options[:metadata] puts "Output: #{options[:output]}" end desc "upload FILES", "Upload multiple files" method_option :format, type: :string, repeatable: true, desc: "Output formats (can be used multiple times)" def upload(*files) puts "Uploading: #{files.join(', ')}" puts "Formats: #{options[:format].inspect}" # ["json", "xml"] when --format json --format xml end end # Usage: # $ ./file_manager.rb process data.txt -o /tmp/out -f xml -v -n 5 -t tag1 tag2 -m key1:value1 key2:value2 # Processing: data.txt # Format: xml # Verbose: true # Count: 5 # Tags: ["tag1", "tag2"] # Metadata: {"key1"=>"value1", "key2"=>"value2"} # Output: /tmp/out ``` -------------------------------- ### Define Thor::Group with Class Options Source: https://github.com/rails/thor/wiki/Groups Use `class_option` to define options for a Thor::Group. These are similar to `method_option` but apply to the group level. ```ruby class Counter < Thor::Group argument :number, :type => :numeric, :desc => "The number to start counting" class_option :verbose, :type => :boolean, :aliases => "-v", :desc => "Enable verbose output" desc "Prints the 'number' given upto 'number+2'" def one puts number + 0 end def two puts number + 1 end def three puts number + 2 end end ``` -------------------------------- ### Define Thor::Group with Arguments Source: https://github.com/rails/thor/wiki/Groups Thor::Group can parse arguments. Use the `argument` method to define them, which become available as attributes. ```ruby class Counter < Thor::Group # number will be available as attr_accessor argument :number, :type => :numeric, :desc => "The number to start counting" desc "Prints the 'number' given upto 'number+2'" def one puts number + 0 end def two puts number + 1 end def three puts number + 2 end end ``` -------------------------------- ### Search and Replace in File Source: https://context7.com/rails/thor/llms.txt The `gsub_file` method performs a global search and replace operation within a file, similar to `sed`. ```ruby gsub_file "config/database.yml", /adapter: sqlite3/, "adapter: postgresql" ``` -------------------------------- ### Define a Thor::Group Class Source: https://github.com/rails/thor/wiki/Groups Use Thor::Group to define a sequence of tasks. The `desc` method provides a description for the entire group. ```ruby require 'thor/group' module MyAwesomeGem class MyCounter < Thor::Group desc "Prints 1 2 3" def one puts 1 end def two puts 2 end def three puts 3 end end end ``` -------------------------------- ### Define Boolean Option with Alias Source: https://github.com/rails/thor/wiki/Method-Options Creates a boolean option and assigns it a short alias. This allows the option to be specified using either the full name or the short flag. ```ruby method_option :force, :type => :boolean, :aliases => "-f" ``` -------------------------------- ### Defining Class Options in Thor Source: https://context7.com/rails/thor/llms.txt Use `class_option` to define options that apply to all commands within a Thor class. Options can be constrained using `exclusive` or `at_least_one` blocks for validation. ```ruby class DeployTool < Thor class_option :environment, type: :string, aliases: "-e", default: "development", desc: "Deployment environment" class_option :dry_run, type: :boolean, aliases: "-n", desc: "Perform a dry run" desc "deploy APP", "Deploy an application" exclusive do method_option :force, type: :boolean, desc: "Force deployment" method_option :safe, type: :boolean, desc: "Safe deployment mode" end at_least_one do method_option :server, type: :string, desc: "Target server" method_option :cluster, type: :string, desc: "Target cluster" end def deploy(app) puts "Environment: #{options[:environment]}" puts "Dry run: #{options[:dry_run]}" puts "Deploying #{app} to #{options[:server] || options[:cluster]}" end desc "status", "Check deployment status" def status puts "Checking status in #{options[:environment]} environment..." end end # Usage: # $ ./deploy.rb deploy myapp -e production --server web1 # Environment: production # Dry run: # Deploying myapp to web1 # # Error cases: ``` -------------------------------- ### Namespacing Thor Tasks with Ruby Modules Source: https://github.com/rails/thor/wiki/Namespaces Nest your Thor class within a Ruby module to create a hierarchical namespace for your tasks. This is useful for organizing related tasks under a common prefix. ```ruby module Sinatra class App < Thor desc 'install', 'Install something' def install # task code end # other tasks end end ``` ```bash thor sinatra:app:install ``` -------------------------------- ### Define Boolean Option with Default Value Source: https://github.com/rails/thor/wiki/Method-Options Creates a boolean option with a default value of false. This is commonly used for flags that enable or disable features. ```ruby method_option :force => false ``` -------------------------------- ### Define Required Hash Option with Default Value Source: https://github.com/rails/thor/wiki/Method-Options Defines a required hash option with an empty hash as its default value. This ensures the option is provided and is of the hash type. ```ruby method_option :attributes, :type => :hash, :default => {}, :required => true ``` -------------------------------- ### Customizing Thor Namespace with `namespace` Method Source: https://github.com/rails/thor/wiki/Namespaces Use the `namespace` method within your Thor class to define a custom namespace, overriding the default module-based naming. This allows for more flexible task invocation. ```ruby module Sinatra class App < Thor namespace :myapp def install # task code end # other tasks end end ``` ```bash thor myapp:install ``` -------------------------------- ### Invoking Other Thor Tasks Source: https://context7.com/rails/thor/llms.txt Use the `invoke` method to call other Thor tasks, ensuring they are executed only once by default. This is useful for managing dependencies between tasks. ```ruby class BuildSystem < Thor desc "clean", "Clean build artifacts" def clean puts "Cleaning..." end desc "compile", "Compile source files" def compile invoke :clean # Invokes clean first puts "Compiling..." end desc "test", "Run tests" method_option :coverage, type: :boolean def test invoke :compile # Invokes compile (and transitively clean) puts "Running tests..." puts "With coverage" if options[:coverage] end desc "deploy", "Deploy application" def deploy invoke :test # Clean and compile run only once invoke :compile # Won't run again - already invoked puts "Deploying..." end end class OtherTasks < Thor desc "notify", "Send notification" method_option :message, type: :string, required: true def notify puts "Notification: #{options[:message]}" end end class MainCLI < Thor desc "release VERSION", "Create a release" def release(version) # Invoke task from another class invoke "build_system:deploy" # Invoke with options invoke "other_tasks:notify", [], message: "Released version #{version}" puts "Released #{version}!" end end ``` -------------------------------- ### Remove File Source: https://context7.com/rails/thor/llms.txt The `remove_file` method deletes a specified file. It's often used with a conditional check to ensure the file exists before attempting deletion. ```ruby remove_file "tmp/cache/.keep" if File.exist?("tmp/cache/.keep") ``` -------------------------------- ### Default Thor Task Invocation Source: https://github.com/rails/thor/wiki/Namespaces Tasks in a Thor class without an explicit namespace are invoked using the class name as the namespace. ```ruby class App < Thor desc 'install', 'Install something' def install # task code end # other tasks end ``` ```bash thor app:install ``` -------------------------------- ### Uncomment Lines Matching Pattern Source: https://context7.com/rails/thor/llms.txt Use `uncomment_lines` to remove '#' characters from the beginning of lines in a file that match a given regular expression. ```ruby uncomment_lines "config/environments/production.rb", /config\.force_ssl/ ``` -------------------------------- ### ERB Template for Generator Source: https://github.com/rails/thor/wiki/Generators This ERB template is used by the Thor generator to create a Ruby class file. It utilizes the 'name' argument passed to the generator. ```erb class <%= name.capitalize %> end ``` -------------------------------- ### Define Thor Task to Invoke Rake Spec Task Source: https://github.com/rails/thor/wiki/Calling-Rake-tasks-with-Thor This Thor class defines a 'spec' task that invokes a Rake task named 'spec'. It requires Thor::RakeCompat and RSpec::Core::RakeTask. ```ruby require 'thor/rake_compat' require 'rspec/core/rake_task' class Default < Thor include Thor::RakeCompat RSpec::Core::RakeTask.new(:spec) do |t| t.rspec_opts = ['--options', './.rspec'] end desc 'spec', 'Run RSpec tests' def spec Rake::Task['spec'].invoke end end ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.