Make hint foundries configurable

Resolves #173

and the milestone from, originally, 1 Apr 2025

Change-Id: Iaa062ae4831187c96f99f339b29cc4374cc31afd
diff --git a/lib/Kalamar.pm b/lib/Kalamar.pm
index 9944e1b..d300aca 100644
--- a/lib/Kalamar.pm
+++ b/lib/Kalamar.pm
@@ -338,6 +338,42 @@
     };
   };
 
+  # Configure hint foundries for annotation layer helper hints
+  # Can be overridden via KALAMAR_HINT_FOUNDRIES environment variable (comma-separated)
+  # or via hint_foundries config option (array)
+  # Items starting with '-' exclude that foundry from defaults (e.g., '-spacy')
+  # If only exclusions are specified, they're removed from defaults
+  # If any positive items exist, they replace the defaults entirely
+  my @default_foundries = qw(base corenlp dereko malt marmot opennlp spacy treetagger);
+  my $hint_foundries;
+  my $config_foundries;
+  
+  if ($ENV{'KALAMAR_HINT_FOUNDRIES'}) {
+    $config_foundries = [split(/\s*,\s*/, $ENV{'KALAMAR_HINT_FOUNDRIES'})];
+  } elsif (exists $conf->{hint_foundries}) {
+    $config_foundries = $conf->{hint_foundries};
+  };
+
+  if ($config_foundries) {
+    # Separate exclusions (starting with '-') from inclusions
+    my @exclusions = map { substr($_, 1) } grep { /^-/ } @$config_foundries;
+    my @inclusions = grep { !/^-/ } @$config_foundries;
+
+    if (@inclusions) {
+      # If there are any positive items, use them as the full list
+      $hint_foundries = \@inclusions;
+    } elsif (@exclusions) {
+      # If only exclusions, remove them from defaults
+      my %exclude = map { lc($_) => 1 } @exclusions;
+      $hint_foundries = [grep { !$exclude{lc($_)} } @default_foundries];
+    } else {
+      $hint_foundries = \@default_foundries;
+    };
+  } else {
+    $hint_foundries = \@default_foundries;
+  };
+  $self->defaults(hint_foundries => $hint_foundries);
+
   # Configure documentation navigation
   my $doc_navi = Mojo::File->new($self->home->child('templates','doc','navigation.json'))->slurp;
   $doc_navi = $doc_navi ? decode_json($doc_navi) : [];