lib/toys/standard_middleware/handle_usage_errors.rb
# frozen_string_literal: true module Toys module StandardMiddleware ## # This middleware handles the case of a usage error. If a usage error, such # as an unrecognized flag or an unfulfilled required argument, is detected, # this middleware intercepts execution and displays the error along with # the short help string, and terminates execution with an error code. # class HandleUsageErrors ## # Exit code for usage error. (2 by convention) # @return [Integer] # USAGE_ERROR_EXIT_CODE = 2 ## # Create a HandleUsageErrors middleware. # # @param exit_code [Integer] The exit code to return if a usage error # occurs. Default is {USAGE_ERROR_EXIT_CODE}. # @param stream [IO] Output stream to write to. Default is stderr. # @param styled_output [Boolean,nil] Cause the tool to display help text # with ansi styles. If `nil`, display styles if the output stream is # a tty. Default is `nil`. # def initialize(exit_code: nil, stream: $stderr, styled_output: nil) @exit_code = exit_code || USAGE_ERROR_EXIT_CODE @stream = stream @styled_output = styled_output end ## # Intercept and handle usage errors during execution. # @private # def run(context) yield rescue ArgParsingError => e require "toys/utils/terminal" require "toys/utils/help_text" help_text = Utils::HelpText.from_context(context) terminal = Utils::Terminal.new(output: @stream, styled: @styled_output) terminal.puts(e.usage_errors.join("\n"), :bright_red, :bold) terminal.puts("") terminal.puts(help_text.usage_string(wrap_width: terminal.width)) Context.exit(@exit_code) end end end end