diff --git a/src/cli.cr b/src/cli.cr index 8a63ed3..8add1a6 100644 --- a/src/cli.cr +++ b/src/cli.cr @@ -1,71 +1,31 @@ + # vim: set ts=2 sw=2 et ft=crystal: require "file" require "option_parser" +require "./config" + # The CodePreloader module organizes classes and methods related to preloading code files. module CodePreloader # The Cli class handles command-line interface operations for the CodePreloader. class Cli - getter repository_path : String? - getter ignore_list : Array(String) = [] of String - getter output_file_path : String? - getter header_prompt_file_path : String? # Add type annotation - getter footer_prompt_file_path : String? # Assuming you'll also need this + @config : Config # Initializes the Cli class with default values. - def initialize - @repository_path = "" + def initialize(args) @output_file_path = "" + @config = Config.new() + @config.parse_arguments(args) end - # Parses command-line arguments and initializes the necessary configurations. - def parse_arguments(args : Array(String)) - OptionParser.parse(args) do |parser| - parser.banner = "Usage: code-preloader [options] ROOT_DIR" - - parser.on("-c CONFIG_FILE", "--config=CONFIG_FILE", "Load parameters from CONFIG_FILE") do |config_file| - load_config(config_file) - end - - parser.on("-i IGNORE_PATH", "--ignore=IGNORE_PATH", "Ignore file or directory") do |ignore_file| - @ignore_list << ignore_file - end - - parser.on("-o OUTPUT_FILE", "--output=OUTPUT_FILE", "Write output to OUTPUT_FILE") do |output_file| - @output_file_path = output_file - end - - parser.on("--header-prompt=HEADER_PROMPT_FILE", "Load header prompt from HEADER_PROMPT_FILE") do |header_prompt_file| - @header_prompt_file_path = header_prompt_file - end - - parser.on("--footer-prompt=FOOTER_PROMPT_FILE", "Load footer prompt from FOOTER_PROMPT_FILE") do |footer_prompt_file| - @footer_prompt_file_path = footer_prompt_file - end - - parser.on("-h", "--help", "Show this help") do - STDERR.puts parser - exit - end - - parser.unknown_args do |remaining_args, _| - if remaining_args.size != 1 - abort("Invalid number of arguments. Expected exactly one argument for ROOT_DIR.") - end - @repository_path = remaining_args[0] - end - end - - validate_arguments - end # Executes the main functionality of the CLI application. def exec header_prompt = "" footer_prompt = "" - __header_prompt_file_path = @header_prompt_file_path - __footer_prompt_file_path = @footer_prompt_file_path + __header_prompt_file_path = @config.header_prompt_file_path + __footer_prompt_file_path = @config.footer_prompt_file_path if !__header_prompt_file_path.nil? STDERR.puts "Loading header prompt from: #{__header_prompt_file_path}" @@ -77,10 +37,10 @@ module CodePreloader footer_prompt = File.read(__footer_prompt_file_path) end - STDERR.puts "Processing repository: #{repository_path}" + STDERR.puts "Processing repository: #{@config.repository_path}" __output_file_path = @output_file_path - __repository_path = @repository_path + __repository_path = @config.repository_path abort("@output_file_path should be non-nil here") if __output_file_path.nil? abort("@repository_path should be non-nil here") if __repository_path.nil? @@ -93,11 +53,11 @@ module CodePreloader invalid_output_file = false end - output_file.puts header_prompt if header_prompt_file_path + output_file.puts header_prompt if @config.header_prompt_file_path process_repository(__repository_path, output_file) - output_file.puts footer_prompt if footer_prompt_file_path + output_file.puts footer_prompt if @config.footer_prompt_file_path output_file.close if !invalid_output_file STDERR.puts "Processing completed. Output written to: #{invalid_output_file ? "stdout" : __output_file_path}" @@ -109,7 +69,6 @@ module CodePreloader # Processes the specified repository and writes the output to a file. def process_repository(repository_path : String, output_file : IO::FileDescriptor) - process_directory(repository_path, output_file) rescue e : IO::Error @@ -118,11 +77,14 @@ module CodePreloader end private def process_directory(path : String, output_file : IO::FileDescriptor) + __repository_path = @config.repository_path + abort("@repository_path should be non-nil here") if __repository_path.nil? + Dir.each_child(path) do |child| child_path = File.join(path, child) ignores = ( - ignore_list + @config.ignore_list .map{ |prefix| [prefix, File.expand_path(child_path) =~ /^#{File.expand_path(prefix)}/] } .reject!{ |item| item[1].nil? } ) @@ -139,7 +101,7 @@ module CodePreloader end private def process_file(file_path : String, output_file : IO::FileDescriptor) - __repository_path = @repository_path + __repository_path = @config.repository_path abort("@repository_path should be non-nil here") if __repository_path.nil? relative_file_path = file_path.sub(/^#{Regex.escape(__repository_path)}/, ".").lstrip @@ -148,34 +110,5 @@ module CodePreloader output_file.puts(File.read(file_path)) output_file.puts "" end - - private def preamble_text : String - local_preamble_file_path = @preamble_file_path - return "" if local_preamble_file_path.nil? - - File.read(local_preamble_file_path) - rescue e : IO::Error - STDERR.puts "Error reading preamble file: #{e.message}" - exit(1) - end - - private def validate_arguments - abort("Missing repository path.") if @repository_path.nil? || @repository_path.try(&.empty?) - abort("Missing repository path.") if - STDERR.puts("Output file path not specified (using STDOUT)") if @output_file_path.nil? || @output_file_path.try(&.empty?) - end - - # Reads and returns a list of paths to ignore from the given file. - def self.get_ignore_list(ignore_file_path : String) : Array(String) - File.exists?(ignore_file_path) ? File.read_lines(ignore_file_path).map(&.strip) : [] of String - rescue e : IO::Error - STDERR.puts "Error reading ignore file: #{e.message}" - exit(1) - end - - # Loads configuration from a config file. - private def load_config(config_file_path : String) - # Implement configuration loading logic here - end end end diff --git a/src/config.cr b/src/config.cr new file mode 100644 index 0000000..101404a --- /dev/null +++ b/src/config.cr @@ -0,0 +1,88 @@ +require "option_parser" +require "yaml" + +module CodePreloader + class Config + property repository_path : String? + property ignore_list : Array(String) = [] of String + property output_file_path : String? + property header_prompt_file_path : String? + property footer_prompt_file_path : String? + + def initialize() + end + + def parse_arguments(args : Array(String)) + OptionParser.parse(args) do |parser| + parser.banner = "Usage: code-preloader [options] ROOT_DIR" + + parser.on("-c CONFIG_FILE", "--config=CONFIG_FILE", "Load parameters from CONFIG_FILE") do |config_file| + load_config(config_file) + end + + parser.on("-i IGNORE_PATH", "--ignore=IGNORE_PATH", "Ignore file or directory") do |ignore_file| + @ignore_list << ignore_file + end + + parser.on("-o OUTPUT_FILE", "--output=OUTPUT_FILE", "Write output to OUTPUT_FILE") do |output_file| + @output_file_path = output_file + end + + parser.on("--header-prompt=HEADER_PROMPT_FILE", "Load header prompt from HEADER_PROMPT_FILE") do |header_prompt_file| + @header_prompt_file_path = header_prompt_file + end + + parser.on("--footer-prompt=FOOTER_PROMPT_FILE", "Load footer prompt from FOOTER_PROMPT_FILE") do |footer_prompt_file| + @footer_prompt_file_path = footer_prompt_file + end + + parser.on("-h", "--help", "Show this help") do + STDERR.puts parser + exit + end + + parser.unknown_args do |remaining_args, _| + if remaining_args.size > 1 + abort("Invalid number of arguments. Expected exactly one argument for ROOT_DIR.") + end + @repository_path = remaining_args[0] + end + end + + validate_arguments + end + + private def validate_arguments + abort("Missing repository path.") if @repository_path.nil? || @repository_path.try(&.empty?) + abort("Missing repository path.") if + STDERR.puts("Output file path not specified (using STDOUT)") if @output_file_path.nil? || @output_file_path.try(&.empty?) + end + + # Reads and returns a list of paths to ignore from the given file. + def self.get_ignore_list(ignore_file_path : String) : Array(String) + File.exists?(ignore_file_path) ? File.read_lines(ignore_file_path).map(&.strip) : [] of String + rescue e : IO::Error + STDERR.puts "Error reading ignore file: #{e.message}" + exit(1) + end + + private def load_config(config_file_path : String) + config_data = YAML.parse(File.read(config_file_path)).as_h + + @repository_path = config_data["repository_path"]?.try &.as_s || @repository_path + + if ignore_list_yaml = config_data["ignore_list"]? + @ignore_list = ignore_list_yaml.as_a.map(&.as_s) + end + + @output_file_path = config_data["output_file_path"]?.try &.as_s || @output_file_path + @header_prompt_file_path = config_data["header_prompt_file_path"]?.try &.as_s || @header_prompt_file_path + @footer_prompt_file_path = config_data["footer_prompt_file_path"]?.try &.as_s || @footer_prompt_file_path + + rescue ex + STDERR.puts "Failed to load config file: #{ex.message}" + exit(1) + end + end +end + diff --git a/src/main.cr b/src/main.cr index 0706111..62e64f8 100644 --- a/src/main.cr +++ b/src/main.cr @@ -3,9 +3,9 @@ require "./cli" + # Now that we have checked for nil, it's safe to use not_nil! -app = CodePreloader::Cli.new -app.parse_arguments(ARGV) +app = CodePreloader::Cli.new(ARGV) app.exec()