From aea7979e4090e2ec7fa4f9edfbbe236089098254 Mon Sep 17 00:00:00 2001 From: Glenn Date: Mon, 16 Jun 2025 16:14:09 +0200 Subject: [PATCH] refactor(cli): enhance file inclusion/exclusion logic Improves the flexibility and clarity of file processing by introducing separate include and exclude lists. - Replace `ignore_list` with `exclude_list` and add `include_list` in `.code_preloader.yml`. - Update `cli.cr` to handle both `include_list` and `exclude_list` for file selection. - Add support for tracing exceptions with a new `trace` configuration option. - Modify `PackOptions` class to include `exclude_list` and `include_list` properties. - Adjust option parsing in `config.cr` to reflect new configuration options. Signed-off-by: Glenn --- .code_preloader.yml | 5 ++- src/cli.cr | 20 ++++++++---- src/config.cr | 67 ++++++++++++++++++++++++--------------- src/filelist.cr | 20 ++++++------ src/models/root_config.cr | 7 ++-- static/default_config.yml | 9 ++++-- 6 files changed, 81 insertions(+), 47 deletions(-) diff --git a/.code_preloader.yml b/.code_preloader.yml index cd65b58..fdc251a 100644 --- a/.code_preloader.yml +++ b/.code_preloader.yml @@ -1,6 +1,9 @@ --- -ignore_list: +include_list: + - .*cr$ + +exclude_list: - ^\.git/.* - ^\.vagrant/.* - ^misc/.* diff --git a/src/cli.cr b/src/cli.cr index 2e8eedd..458ec58 100644 --- a/src/cli.cr +++ b/src/cli.cr @@ -92,12 +92,15 @@ module CodePreloader filelist = FileList.new() filelist.add(source_list) - pack_options.ignore_list.each do |ignore_pattern| - filelist.reject { |path| !!(path =~ Regex.new(ignore_pattern)) } - end + pack_options.exclude_list + .map { |exclude_pattern| Regex.new(exclude_pattern) } + .each { |exclude_regexp| filelist.reject { |path| !!(path =~ exclude_regexp) } } + pack_options.include_list + .map { |include_pattern| Regex.new(include_pattern) } + .each { |include_regexp| filelist.select { |path| !!(path =~ include_regexp) } } STDERR.puts "Loading template file from: #{prompt_template_path ? prompt_template_path : "" }".colorize(:yellow) - if prompt_template_path + if prompt_template_path prompt_template_content = File.read(prompt_template_path) else prompt_template_content = FileStorage.get("default_template.j2").gets_to_end @@ -136,19 +139,22 @@ module CodePreloader # FIXME: prompt_footer_path.try { output_file.puts prompt_footer_content } output_file.puts Crinja.render( - prompt_template_content, - { + prompt_template_content, + { "prompt_header": prompt_header_content, "prompt_files": processed_files, "prompt_footer": prompt_footer_content } - ) + ) output_file.close if regular_output_file STDERR.puts "Processing completed.".colorize(:yellow) rescue e : Exception STDERR.puts "ERROR: #{e.message}" + if @config.trace? + STDERR.puts e.backtrace.map(&.gsub(/^/, " ")).join("\n") + end exit(1) end diff --git a/src/config.cr b/src/config.cr index 2c98917..d6e64d3 100644 --- a/src/config.cr +++ b/src/config.cr @@ -27,14 +27,16 @@ module CodePreloader class PackOptions property config_path : String? = nil property source_list : Array(String) = [] of String - property ignore_list : Array(String) = [] of String + property exclude_list : Array(String) = [] of String + property include_list : Array(String) = [] of String property output_path : String? property prompt_template_path : String? property prompt_header_path : String? property prompt_footer_path : String? end - getter verbose : Bool = false + getter? verbose : Bool = false + getter? trace : Bool = false getter parser : OptionParser? getter subcommand : Subcommand = Subcommand::None getter pack_options : PackOptions? @@ -60,9 +62,10 @@ module CodePreloader end end + parser.on( - "-c FILE", - "--config=FILE", + "-c FILE", + "--config=FILE", "Load parameters from FILE" ) do |config_file| @init_options.try { |opt| opt.config_path = config_file } @@ -83,11 +86,11 @@ module CodePreloader # complete_with "code-preloader init", parser end - def parse_pack_options(parser) + def parse_pack_options(parser) @pack_options = PackOptions.new unless ENV["CODE_PRELOADER_DETECT"]? =~ /(no|false|0)/i - config_file = detect_config_file + config_file = detect_config_file config_file.try { |path| load_pack_config(path) } end @@ -99,48 +102,56 @@ module CodePreloader parser.separator "\nPack options:" parser.on( - "-c FILE", - "--config=FILE", + "-c FILE", + "--config=FILE", "Load parameters from FILE\n(default: autodetect)" ) do |config_file| @pack_options.try { |opt| load_pack_config(config_file) } end parser.on( - "-F FILE", - "--prompt-footer=FILE", + "-F FILE", + "--prompt-footer=FILE", "Load prompt footer from FILE (default: none)" ) do |prompt_footer_path| @pack_options.try { |opt| opt.prompt_footer_path = prompt_footer_path } end parser.on( - "-H FILE", - "--prompt-header=FILE", + "-H FILE", + "--prompt-header=FILE", "Load prompt header from FILE (default: none)" ) do |prompt_header_path| @pack_options.try { |opt| opt.prompt_header_path = prompt_header_path } end parser.on( - "-i REGEXP", - "--ignore=REGEXP", - "Ignore file or directory. Can be used\nmultiple times (default: none)" - ) do |ignore_file| - @pack_options.try { |opt| opt.ignore_list << ignore_file } + "-i REGEXP", + "--include=REGEXP", + "Include file or directory. Can be used\nmultiple times (default: none)" + ) do |include_regexp| + @pack_options.try { |opt| opt.include_list << include_regexp } end parser.on( - "-o FILE", - "--output=FILE", + "-e REGEXP", + "--exclude=REGEXP", + "Exclude file or directory. Can be used\nmultiple times (default: none)" + ) do |exclude_regexp| + @pack_options.try { |opt| opt.exclude_list << exclude_regexp } + end + + parser.on( + "-o FILE", + "--output=FILE", "Write output to FILE (default: \"-\", STDOUT)" ) do |output_file| @pack_options.try { |opt| opt.output_path = output_file } end parser.on( - "-t FILE", - "--template=FILE", + "-t FILE", + "--template=FILE", "Load template from FILE (default: internal)" ) do |prompt_template_path| @pack_options.try { |opt| opt.prompt_template_path = prompt_template_path } @@ -186,11 +197,14 @@ module CodePreloader @verbose = true end + parser.on("-t", "--trace", "Show detailed traces for exceptions") do + @trace = true + end + parser.on("--version", "Show version") do @subcommand = Subcommand::Version end - parser.separator "\nSubcommands:" parser.on("init", "Create an example .code_preloader.yml file") do @@ -277,11 +291,14 @@ module CodePreloader if opts.source_list.nil? || opts.source_list.try &.empty? root.source_list.try { |value| opts.source_list = value } end - if opts.ignore_list.nil? || opts.ignore_list.try &.empty? - root.ignore_list.try { |value| opts.ignore_list = value } + if opts.exclude_list.nil? || opts.exclude_list.try &.empty? + root.exclude_list.try { |value| opts.exclude_list = value } + end + if opts.include_list.nil? || opts.include_list.try &.empty? + root.include_list.try { |value| opts.include_list = value } end if opts.output_path.nil? - opts.output_path = root.output_path + opts.output_path = root.output_path end if opts.prompt_header_path.nil? root.prompt.try &.header_path.try { |value| opts.prompt_header_path = value } diff --git a/src/filelist.cr b/src/filelist.cr index 2ccb99d..dd794e4 100644 --- a/src/filelist.cr +++ b/src/filelist.cr @@ -13,13 +13,13 @@ module CodePreloader end @sources : Array(String) - @filters_in : Array(Filter) - @filters_out : Array(Filter) + @include_filters : Array(Filter) + @exclude_filters : Array(Filter) def initialize(dirs = [] of String) @sources = [] of String - @filters_in = [] of Filter - @filters_out = [] of Filter + @include_filters = [] of Filter + @exclude_filters = [] of Filter dirs.each { |dir| self.add(dir) } end @@ -34,11 +34,11 @@ module CodePreloader end def select(&filter : Filter) - @filters_in << filter + @include_filters << filter end def reject(&filter : Filter) - @filters_out << filter + @exclude_filters << filter end def each(&block) @@ -56,16 +56,16 @@ module CodePreloader must_reject = false clean_path = path.to_s.gsub(/^\.\//,"") - @filters_in.each do |filter_in| + @include_filters.each do |filter_in| must_select = must_select || filter_in.call(clean_path) end - keep = keep && must_select if @filters_in.any? + keep = keep && must_select if @include_filters.any? keep = keep || is_dir - @filters_out.each do |filter_out| + @exclude_filters.each do |filter_out| must_reject = must_reject || filter_out.call(clean_path) end - keep = keep && !must_reject if @filters_out.any? + keep = keep && !must_reject if @exclude_filters.any? keep end diff --git a/src/models/root_config.cr b/src/models/root_config.cr index a5e3737..58f4377 100644 --- a/src/models/root_config.cr +++ b/src/models/root_config.cr @@ -16,7 +16,10 @@ module CodePreloader::Models @[YAML::Field(key: "prompt")] getter prompt : PromptConfig? - @[YAML::Field(key: "ignore_list")] - getter ignore_list : Array(String)? + @[YAML::Field(key: "exclude_list")] + getter exclude_list : Array(String)? + + @[YAML::Field(key: "include_list")] + getter include_list : Array(String)? end end diff --git a/static/default_config.yml b/static/default_config.yml index 82822ee..eaea9aa 100644 --- a/static/default_config.yml +++ b/static/default_config.yml @@ -6,9 +6,14 @@ # - "path/to/repo1" # - "path/to/repo2" -# List of patterns to ignore during preloading -ignore_list: +# List of patterns to exclude (= ignore) during preloading +exclude_list: - ^\.git/.* + - ".*\\.(png|jpeg|jpg|webp|pdf|mp4|mp3)$" + +# List of patterns to include (= limit) during preloading +include_list: + - ".*\\.(md|txt|markdown)$" # Path to the output file (if null, output to STDOUT) output_path: null