Compare commits
No commits in common. "e418f58f447c09185d03c28e607cd1d29a47811c" and "d296c9d159e97c48bbaa5f14b79224cca09bd61f" have entirely different histories.
e418f58f44
...
d296c9d159
4 changed files with 77 additions and 253 deletions
1
.gitattributes
vendored
1
.gitattributes
vendored
|
@ -1 +0,0 @@
|
||||||
*.svg filter=lfs diff=lfs merge=lfs -text
|
|
|
@ -1,15 +0,0 @@
|
||||||
@@REQUEST
|
|
||||||
|
|
||||||
I would like to change CLI parameters structure add add two subcommands:
|
|
||||||
* init : which will create an example .code_preloader.yml file (with comments)
|
|
||||||
* pack : which will create the packed version of the current directory for LLM prompting
|
|
||||||
|
|
||||||
Most of current options (except --version and --help) must become options of the pack subcommand.
|
|
||||||
|
|
||||||
I already started some changes to achieve this goal, but it is not finished, and I need your help and expert advises.
|
|
||||||
|
|
||||||
Can you please tell me :
|
|
||||||
* where the changes should occur (which File? which Class? and which method?)
|
|
||||||
* what kind of changes must be made there?
|
|
||||||
|
|
||||||
Please do not write code yet, simply explain.
|
|
63
src/cli.cr
63
src/cli.cr
|
@ -18,52 +18,20 @@ module CodePreloader
|
||||||
def initialize(args)
|
def initialize(args)
|
||||||
@output_file_path = ""
|
@output_file_path = ""
|
||||||
@config = Config.new()
|
@config = Config.new()
|
||||||
@config.detect_config()
|
|
||||||
@config.parse_arguments(args)
|
@config.parse_arguments(args)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Executes the main functionality of the CLI application.
|
# Executes the main functionality of the CLI application.
|
||||||
def exec
|
def exec
|
||||||
case @config.subcommand
|
# get local values for typing
|
||||||
when Config::Subcommand::Init then exec_init(@config.init_options)
|
output_file_path = @output_file_path
|
||||||
when Config::Subcommand::Pack then exec_pack(@config.pack_options)
|
repository_path_list = @config.repository_path_list
|
||||||
when Config::Subcommand::Version then exec_version
|
header_prompt_file_path = @config.header_prompt_file_path
|
||||||
when Config::Subcommand::Help then exec_help
|
footer_prompt_file_path = @config.footer_prompt_file_path
|
||||||
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?
|
|
||||||
abort("FIXME: Not implemented!")
|
|
||||||
end
|
|
||||||
|
|
||||||
def exec_version
|
|
||||||
abort("FIXME: Not implemented!")
|
|
||||||
end
|
|
||||||
|
|
||||||
def exec_none
|
|
||||||
abort("No command specified!")
|
|
||||||
end
|
|
||||||
|
|
||||||
def exec_help
|
|
||||||
abort("FIXME: Not implemented!")
|
|
||||||
end
|
|
||||||
|
|
||||||
def exec_pack(pack_options)
|
|
||||||
abort("Unexpected nil value for pack_options!") if pack_options.nil?
|
|
||||||
|
|
||||||
output_file_path = pack_options.output_file_path
|
|
||||||
repository_path_list = pack_options.repository_path_list
|
|
||||||
header_prompt_file_path = pack_options.header_prompt_file_path
|
|
||||||
footer_prompt_file_path = pack_options.footer_prompt_file_path
|
|
||||||
regular_output_file = false
|
|
||||||
|
|
||||||
filelist = FileList.new()
|
filelist = FileList.new()
|
||||||
filelist.add(repository_path_list)
|
filelist.add(repository_path_list)
|
||||||
pack_options.ignore_list.each do |ignore_pattern|
|
@config.ignore_list.each do |ignore_pattern|
|
||||||
filelist.reject { |path| !!(path =~ Regex.new(ignore_pattern)) }
|
filelist.reject { |path| !!(path =~ Regex.new(ignore_pattern)) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -77,28 +45,27 @@ module CodePreloader
|
||||||
footer_prompt = File.read(footer_prompt_file_path)
|
footer_prompt = File.read(footer_prompt_file_path)
|
||||||
end
|
end
|
||||||
|
|
||||||
output_file_path.try do |path|
|
unless output_file_path.nil? || output_file_path.try(&.empty?) || (output_file_path != "-")
|
||||||
break if path.empty?
|
output_file = File.open(output_file_path, "w")
|
||||||
break if path == "-"
|
invalid_output_file = false
|
||||||
regular_output_file = true
|
|
||||||
output_file = File.open(path, "w")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
invalid_output_file = true
|
||||||
output_file = STDOUT
|
output_file = STDOUT
|
||||||
header_prompt = ""
|
header_prompt = ""
|
||||||
footer_prompt = ""
|
footer_prompt = ""
|
||||||
|
|
||||||
output_file.puts header_prompt if header_prompt_file_path
|
output_file.puts header_prompt if @config.header_prompt_file_path
|
||||||
|
|
||||||
STDERR.puts "Processing repository: #{repository_path_list}"
|
STDERR.puts "Processing repository: #{@config.repository_path_list}"
|
||||||
filelist.each do |file_path|
|
filelist.each do |file_path|
|
||||||
process_file(file_path, output_file)
|
process_file(file_path, output_file)
|
||||||
end
|
end
|
||||||
|
|
||||||
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 regular_output_file
|
output_file.close if !invalid_output_file
|
||||||
STDERR.puts "Processing completed. Output written to: #{regular_output_file ? output_file_path : "stdout" }"
|
STDERR.puts "Processing completed. Output written to: #{invalid_output_file ? "stdout" : output_file_path}"
|
||||||
|
|
||||||
rescue e : Exception
|
rescue e : Exception
|
||||||
STDERR.puts "An error occurred during execution: #{e.message}"
|
STDERR.puts "An error occurred during execution: #{e.message}"
|
||||||
|
|
247
src/config.cr
247
src/config.cr
|
@ -6,151 +6,63 @@ require "./version"
|
||||||
|
|
||||||
module CodePreloader
|
module CodePreloader
|
||||||
class Config
|
class Config
|
||||||
|
property repository_path_list : Array(String) = [] of String
|
||||||
enum Subcommand
|
property ignore_list : Array(String) = [] of String
|
||||||
None
|
property output_file_path : String?
|
||||||
Init
|
property header_prompt_file_path : String?
|
||||||
Pack
|
property footer_prompt_file_path : String?
|
||||||
Help
|
|
||||||
Version
|
|
||||||
end
|
|
||||||
|
|
||||||
class InitOptions
|
|
||||||
property config_file_path : String? = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
class PackOptions
|
|
||||||
property config_file_path : String? = nil
|
|
||||||
property repository_path_list : Array(String) = [] of 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?
|
|
||||||
end
|
|
||||||
|
|
||||||
getter parser : OptionParser?
|
|
||||||
property subcommand : Subcommand = Subcommand::None
|
|
||||||
property pack_options : PackOptions?
|
|
||||||
property init_options : InitOptions?
|
|
||||||
|
|
||||||
def initialize()
|
def initialize()
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse_init_options(parser)
|
|
||||||
@init_options = InitOptions.new
|
|
||||||
|
|
||||||
parser.banner = [
|
|
||||||
"#{PROGRAM_NAME} v#{VERSION}",
|
|
||||||
"Usage: code-preloader init [options]\n",
|
|
||||||
"Global options:"
|
|
||||||
].join("\n")
|
|
||||||
|
|
||||||
parser.separator "\nInit options:"
|
|
||||||
parser.unknown_args do |remaining_args, _|
|
|
||||||
# FIXME: detect and make error if there are more or less than one
|
|
||||||
remaining_args.each do |arg|
|
|
||||||
@init_options.try &.config_file_path = arg
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
parser.on(
|
|
||||||
"-c FILE",
|
|
||||||
"--config=FILE",
|
|
||||||
"Load parameters from FILE"
|
|
||||||
) do |config_file|
|
|
||||||
@init_options.try { |opt| opt.config_file_path = config_file }
|
|
||||||
end
|
|
||||||
|
|
||||||
parser.separator ""
|
|
||||||
|
|
||||||
parser.missing_option do |opt|
|
|
||||||
puts parser
|
|
||||||
abort("ERROR: Missing parameter for option #{opt}!")
|
|
||||||
end
|
|
||||||
|
|
||||||
parser.invalid_option do |opt|
|
|
||||||
puts parser
|
|
||||||
abort("ERROR: Invalid option #{opt}!")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def parse_pack_options(parser)
|
|
||||||
@pack_options = PackOptions.new
|
|
||||||
|
|
||||||
parser.banner = [
|
|
||||||
"#{PROGRAM_NAME} v#{VERSION}",
|
|
||||||
"Usage: code-preloader pack [options] DIR ...\n",
|
|
||||||
"Global options:"
|
|
||||||
].join("\n")
|
|
||||||
|
|
||||||
parser.separator "\nPack options:"
|
|
||||||
parser.on(
|
|
||||||
"-i REGEXP",
|
|
||||||
"--ignore=REGEXP",
|
|
||||||
"Ignore file or directory"
|
|
||||||
) do |ignore_file|
|
|
||||||
@pack_options.try { |opt| opt.ignore_list << ignore_file }
|
|
||||||
end
|
|
||||||
|
|
||||||
parser.on(
|
|
||||||
"-o FILE",
|
|
||||||
"--output=FILE",
|
|
||||||
"Write output to FILE"
|
|
||||||
) do |output_file|
|
|
||||||
@pack_options.try { |opt| opt.output_file_path = output_file }
|
|
||||||
end
|
|
||||||
|
|
||||||
parser.on(
|
|
||||||
"-H FILE",
|
|
||||||
"--header-prompt=FILE",
|
|
||||||
"Load header prompt from FILE"
|
|
||||||
) do |header_prompt_file|
|
|
||||||
@pack_options.try { |opt| opt.header_prompt_file_path = header_prompt_file }
|
|
||||||
end
|
|
||||||
|
|
||||||
parser.on(
|
|
||||||
"-F FILE",
|
|
||||||
"--footer-prompt=FILE",
|
|
||||||
"Load footer prompt from FILE"
|
|
||||||
) do |footer_prompt_file|
|
|
||||||
@pack_options.try { |opt| opt.footer_prompt_file_path = footer_prompt_file }
|
|
||||||
end
|
|
||||||
|
|
||||||
parser.on(
|
|
||||||
"-c FILE",
|
|
||||||
"--config=FILE",
|
|
||||||
"Load parameters from FILE"
|
|
||||||
) do |config_file|
|
|
||||||
@pack_options.try { |opt| load_pack_config(config_file) }
|
|
||||||
end
|
|
||||||
|
|
||||||
parser.separator ""
|
|
||||||
|
|
||||||
parser.unknown_args do |remaining_args, _|
|
|
||||||
remaining_args.each do |arg|
|
|
||||||
@pack_options.try { |opt| opt.repository_path_list << arg }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
parser.missing_option do |opt|
|
|
||||||
puts parser
|
|
||||||
abort("ERROR: Missing parameter for option #{opt}!")
|
|
||||||
end
|
|
||||||
|
|
||||||
parser.invalid_option do |ex|
|
|
||||||
puts parser
|
|
||||||
abort("ERROR: Invalid option #{ex}")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def parse_arguments(args : Array(String))
|
def parse_arguments(args : Array(String))
|
||||||
@parser = OptionParser.new do |parser|
|
OptionParser.parse(args) do |parser|
|
||||||
parser.banner = [
|
parser.banner = [
|
||||||
"#{PROGRAM_NAME} v#{VERSION}",
|
"#{PROGRAM_NAME} v#{VERSION}",
|
||||||
"Usage: code-preloader <subcommand> [options] [DIR] [...]\n",
|
"Usage: code-preloader [options] DIR ...\n",
|
||||||
"Global options:"
|
"Options:"
|
||||||
].join("\n")
|
].join("\n")
|
||||||
|
|
||||||
|
parser.on(
|
||||||
|
"-c FILE",
|
||||||
|
"--config=FILE",
|
||||||
|
"Load parameters from FILE"
|
||||||
|
) do |config_file|
|
||||||
|
load_config(config_file)
|
||||||
|
end
|
||||||
|
|
||||||
|
parser.on(
|
||||||
|
"-i REGEXP",
|
||||||
|
"--ignore=REGEXP",
|
||||||
|
"Ignore file or directory"
|
||||||
|
) do |ignore_file|
|
||||||
|
@ignore_list << ignore_file
|
||||||
|
end
|
||||||
|
|
||||||
|
parser.on(
|
||||||
|
"-o FILE",
|
||||||
|
"--output=FILE",
|
||||||
|
"Write output to FILE"
|
||||||
|
) do |output_file|
|
||||||
|
@output_file_path = output_file
|
||||||
|
end
|
||||||
|
|
||||||
|
parser.on(
|
||||||
|
"-H FILE",
|
||||||
|
"--header-prompt=FILE",
|
||||||
|
"Load header prompt from FILE"
|
||||||
|
) do |header_prompt_file|
|
||||||
|
@header_prompt_file_path = header_prompt_file
|
||||||
|
end
|
||||||
|
|
||||||
|
parser.on(
|
||||||
|
"-F FILE",
|
||||||
|
"--footer-prompt=FILE",
|
||||||
|
"Load footer prompt from FILE"
|
||||||
|
) do |footer_prompt_file|
|
||||||
|
@footer_prompt_file_path = footer_prompt_file
|
||||||
|
end
|
||||||
|
|
||||||
parser.on("--version", "Show version") do
|
parser.on("--version", "Show version") do
|
||||||
STDOUT.puts "#{PROGRAM_NAME} #{VERSION}"
|
STDOUT.puts "#{PROGRAM_NAME} #{VERSION}"
|
||||||
exit(0)
|
exit(0)
|
||||||
|
@ -161,56 +73,20 @@ module CodePreloader
|
||||||
exit
|
exit
|
||||||
end
|
end
|
||||||
|
|
||||||
parser.separator "\nSubcommands:"
|
parser.unknown_args do |remaining_args, _|
|
||||||
|
remaining_args.each do |arg|
|
||||||
parser.on("init", "Create an example .code_preloader.yml file") do
|
@repository_path_list << arg
|
||||||
@subcommand = Subcommand::Init
|
end
|
||||||
parse_init_options(parser)
|
|
||||||
end
|
|
||||||
|
|
||||||
parser.on("pack", "Create the packed version of a directory for LLM prompting") do
|
|
||||||
@subcommand = Subcommand::Pack
|
|
||||||
parse_pack_options(parser)
|
|
||||||
end
|
|
||||||
|
|
||||||
parser.separator ""
|
|
||||||
|
|
||||||
parser.invalid_option do |ex|
|
|
||||||
puts parser
|
|
||||||
abort("ERROR: Invalid option #{ex}")
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@parser.try &.parse(args)
|
|
||||||
validate
|
validate
|
||||||
end
|
end
|
||||||
|
|
||||||
def detect_config
|
|
||||||
# FIXME: detect config name, if any
|
|
||||||
end
|
|
||||||
|
|
||||||
private def validate
|
private def validate
|
||||||
case @subcommand
|
abort("Missing repository path.") if @repository_path_list.empty?
|
||||||
when Subcommand::Init then validate_init
|
|
||||||
when Subcommand::Pack then validate_pack
|
|
||||||
else
|
|
||||||
abort("Unknown subcommand #{@subcommand}")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private def validate_init
|
STDERR.puts("Output file path not specified (using STDOUT)") if @output_file_path.nil? || @output_file_path.try(&.empty?)
|
||||||
abort("No init options defined!") if @init_options.nil?
|
|
||||||
end
|
|
||||||
|
|
||||||
private def validate_pack
|
|
||||||
abort("No pack options defined!") if @pack_options.nil?
|
|
||||||
@pack_options.try do |opts|
|
|
||||||
abort("Missing repository path.") if opts.repository_path_list.empty?
|
|
||||||
|
|
||||||
if opts.output_file_path.nil? || opts.output_file_path.try(&.empty?)
|
|
||||||
STDERR.puts("Output file path not specified (using STDOUT)")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Reads and returns a list of paths to ignore from the given file.
|
# Reads and returns a list of paths to ignore from the given file.
|
||||||
|
@ -221,19 +97,16 @@ module CodePreloader
|
||||||
exit(1)
|
exit(1)
|
||||||
end
|
end
|
||||||
|
|
||||||
private def load_pack_config(config_file_path : String)
|
private def load_config(config_file_path : String)
|
||||||
config_str = File.read(config_file_path)
|
config_str = File.read(config_file_path)
|
||||||
|
|
||||||
root = Models::RootConfig.from_yaml(config_str)
|
root = Models::RootConfig.from_yaml(config_str)
|
||||||
|
|
||||||
@pack_options.try do |opts|
|
@repository_path = root.repository_path_list || @repository_path_list
|
||||||
opts.config_file_path = config_file_path
|
@ignore_list = root.ignore_list || @ignore_list
|
||||||
opts.repository_path_list = root.repository_path_list || opts.repository_path_list
|
@output_file_path = root.output_file_path || @output_file_path
|
||||||
opts.ignore_list = root.ignore_list || opts.ignore_list
|
@header_prompt_file_path = root.header_prompt_file_path || @header_prompt_file_path
|
||||||
opts.output_file_path = root.output_file_path || opts.output_file_path
|
@footer_prompt_file_path = root.footer_prompt_file_path || @footer_prompt_file_path
|
||||||
opts.header_prompt_file_path = root.header_prompt_file_path || opts.header_prompt_file_path
|
|
||||||
opts.footer_prompt_file_path = root.footer_prompt_file_path || opts.footer_prompt_file_path
|
|
||||||
end
|
|
||||||
|
|
||||||
rescue ex : Exception
|
rescue ex : Exception
|
||||||
STDERR.puts "Failed to load config file: #{ex.message}"
|
STDERR.puts "Failed to load config file: #{ex.message}"
|
||||||
|
|
Loading…
Reference in a new issue