code-preloader/src/cli.cr

191 lines
5.9 KiB
Crystal
Raw Normal View History

2024-01-04 16:35:39 +01:00
require "colorize"
2023-12-29 14:13:20 +01:00
require "file"
require "option_parser"
2023-12-31 13:47:16 +01:00
require "magic"
2024-01-04 22:51:04 +01:00
require "crinja"
2023-12-29 14:13:20 +01:00
2023-12-29 15:53:54 +01:00
require "./config"
2024-01-02 12:32:00 +01:00
require "./filelist"
2023-12-29 15:53:54 +01:00
2023-12-29 14:13:20 +01:00
# 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.
2024-01-04 22:51:04 +01:00
2023-12-29 14:13:20 +01:00
class Cli
2024-01-04 22:51:04 +01:00
alias ProcessedFile = NamedTuple(path: String, content: String, mime_type: String)
2023-12-29 15:53:54 +01:00
@config : Config
2023-12-29 14:13:20 +01:00
# Initializes the Cli class with default values.
2023-12-29 15:53:54 +01:00
def initialize(args)
2024-01-04 22:51:04 +01:00
@output_path = ""
2023-12-29 15:53:54 +01:00
@config = Config.new()
@config.parse_arguments(args)
2023-12-29 14:13:20 +01:00
end
# Executes the main functionality of the CLI application.
def exec
case @config.subcommand
when Config::Subcommand::Init then exec_init(@config.init_options)
when Config::Subcommand::Pack then exec_pack(@config.pack_options)
when Config::Subcommand::Version then exec_version
when Config::Subcommand::Help then exec_help
when Config::Subcommand::None then exec_none
else
abort("Unknown subcommand #{@config.subcommand}!")
end
end
def exec_init(init_options)
abort("Unexpected nil value for init_options!") if init_options.nil?
2024-01-04 12:57:05 +01:00
# Default path for the .code_preloader.yml file
default_config_path = "example.code_preloader.yml"
# Use the specified path if provided, otherwise use the default
2024-01-04 22:51:04 +01:00
config_path = init_options.config_path || default_config_path
2024-01-04 12:57:05 +01:00
# Content of the .code_preloader.yml file
config_content = [
"---",
"# Example configuration for Code-Preloader",
"",
"# List of repository paths to preload",
2024-01-04 22:51:04 +01:00
"# source_list:",
2024-01-04 12:57:05 +01:00
"# - \"path/to/repo1\"",
"# - \"path/to/repo2\"",
"",
"# List of patterns to ignore during preloading",
"ignore_list:",
2024-01-04 16:35:39 +01:00
" - ^\\.git/.*",
2024-01-04 12:57:05 +01:00
"",
"# Path to the output file (if null, output to STDOUT)",
2024-01-04 22:51:04 +01:00
"output_path: null",
2024-01-04 12:57:05 +01:00
"",
"# Optional: Path to a file containing the header prompt",
2024-01-04 22:51:04 +01:00
"header_path: null",
2024-01-04 12:57:05 +01:00
"",
"# Optional: Path to a file containing the footer prompt",
2024-01-04 22:51:04 +01:00
"footer_path: null",
2024-01-04 13:00:08 +01:00
""
2024-01-04 12:57:05 +01:00
].join("\n")
# Writing the configuration content to the file
2024-01-04 22:51:04 +01:00
File.write(config_path, config_content)
puts "Configuration file created at: #{config_path}"
2024-01-04 12:57:05 +01:00
rescue e : Exception
abort("ERROR: Unable to create the configuration file: #{e.message}")
end
def exec_version
puts "#{PROGRAM_NAME} v#{VERSION}"
exit(0)
end
def exec_none
STDERR.puts @config.parser
abort("ERROR: No command specified!")
end
def exec_help
2024-01-04 22:51:04 +01:00
@config.help_options.try do |opts|
puts opts.parser_snapshot
end
exit(0)
end
def exec_pack(pack_options)
abort("Unexpected nil value for pack_options!") if pack_options.nil?
preloaded_content = {} of String => NamedTuple(mime: String, content: String)
2024-01-04 22:51:04 +01:00
config_path = pack_options.config_path
output_path = pack_options.output_path
source_list = pack_options.source_list
prompt_header_path = pack_options.prompt_header_path
prompt_footer_path = pack_options.prompt_footer_path
prompt_template_path = pack_options.prompt_template_path
regular_output_file = false
2024-01-04 22:51:04 +01:00
prompt_header_content = nil
prompt_footer_content = nil
prompt_template_content = ""
STDERR.puts "Loading config file from: #{config_path}".colorize(:yellow)
2024-01-02 12:32:00 +01:00
filelist = FileList.new()
2024-01-04 22:51:04 +01:00
filelist.add(source_list)
pack_options.ignore_list.each do |ignore_pattern|
2024-01-02 12:32:00 +01:00
filelist.reject { |path| !!(path =~ Regex.new(ignore_pattern)) }
2023-12-29 14:13:20 +01:00
end
2024-01-04 22:51:04 +01:00
abort("No prompt file defined!") if prompt_template_path.nil?
prompt_template_content = File.read(prompt_template_path)
if !prompt_header_path.nil?
STDERR.puts "Loading header prompt from: #{prompt_header_path}".colorize(:yellow)
prompt_header_content = File.read(prompt_header_path)
2023-12-29 14:13:20 +01:00
end
2024-01-04 22:51:04 +01:00
if !prompt_footer_path.nil?
STDERR.puts "Loading footer prompt from: #{prompt_footer_path}".colorize(:yellow)
prompt_footer_content = File.read(prompt_footer_path)
2024-01-02 12:32:00 +01:00
end
2023-12-29 14:57:11 +01:00
2024-01-04 16:35:39 +01:00
output_file = STDOUT
2024-01-04 22:51:04 +01:00
output_path.try do |path|
break if path.empty?
break if path == "-"
regular_output_file = true
output_file = File.open(path, "w")
end
2024-01-04 22:51:04 +01:00
STDERR.puts "Writing output to: #{regular_output_file ? output_path : "stdout" }".colorize(:yellow)
2023-12-29 14:13:20 +01:00
2024-01-04 22:51:04 +01:00
# FIXME: prompt_header_path.try { output_file.puts prompt_header_content }
2023-12-29 14:57:11 +01:00
2024-01-04 22:51:04 +01:00
STDERR.puts "Processing source directories: #{source_list}".colorize(:yellow)
processed_files = [] of ProcessedFile
2024-01-02 12:32:00 +01:00
filelist.each do |file_path|
2024-01-04 16:35:39 +01:00
STDERR.puts "Processing file: #{file_path}".colorize(:yellow)
file_result = process_file(file_path, output_file)
2024-01-04 22:51:04 +01:00
processed_files << file_result
end
2023-12-29 14:57:11 +01:00
2024-01-04 22:51:04 +01:00
# FIXME: prompt_footer_path.try { output_file.puts prompt_footer_content }
output_file.puts Crinja.render(
prompt_template_content,
{
"prompt_header": prompt_header_content,
"prompt_files": processed_files,
"prompt_footer": prompt_footer_content
}
)
2023-12-29 14:57:11 +01:00
output_file.close if regular_output_file
2024-01-04 16:35:39 +01:00
STDERR.puts "Processing completed.".colorize(:yellow)
2023-12-29 14:13:20 +01:00
rescue e : Exception
2024-01-04 22:51:04 +01:00
STDERR.puts "ERROR: #{e.message}"
2023-12-29 14:13:20 +01:00
exit(1)
end
2024-01-02 12:32:00 +01:00
private def process_file(file_path : String, output_file : IO::FileDescriptor)
2024-01-04 16:35:39 +01:00
mime = ""
clean_content = ""
File.open(file_path) do |fh|
mime = Magic.mime_type.of(fh)
clean_content = (
fh.gets_to_end
.strip
.gsub(/\n\s*\n\s*\n/,"\n\n")
)
end
return {
2024-01-04 22:51:04 +01:00
path: file_path,
content: clean_content,
mime_type: mime
}
2023-12-29 14:13:20 +01:00
end
end
end