wp2txt 2.1.2 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/wp2txt/cli.rb CHANGED
@@ -118,6 +118,30 @@ module Wp2txt
118
118
  opt :show_matched_sections, "Include matched_sections field in JSON output (shows actual headings)",
119
119
  default: false
120
120
 
121
+ # Metadata index options (offline exhaustive queries)
122
+ opt :build_index, "Build local metadata index (categories, sections) from a multistream dump",
123
+ default: false, short: :none
124
+ opt :find_articles, "List article titles matching index filters (requires built index)",
125
+ default: false, short: :none
126
+ opt :in_category, "Filter by category for --find-articles (recursion depth via --depth)",
127
+ type: String, short: :none
128
+ opt :has_section, "Filter by section heading for --find-articles (alias-aware)",
129
+ type: String, short: :none
130
+ opt :title_match, "Filter by title substring for --find-articles",
131
+ type: String, short: :none
132
+ opt :limit, "Maximum number of titles to output with --find-articles (0 = no limit)",
133
+ default: 0, type: Integer, short: :none
134
+ opt :fulltext, "Also build the full-text (FTS5) index with --build-index",
135
+ default: false, short: :none
136
+ opt :fts_tokenizer, "FTS tokenizer: unicode61, trigram, or porter (default: auto by language)",
137
+ type: String, short: :none
138
+ opt :search, "Full-text search query (requires --build-index --fulltext beforehand)",
139
+ type: String, short: :none
140
+ opt :skip_fts_optimize, "Skip the final optimize step of the full-text build (much faster build; queries slightly slower until --fts-optimize is run)",
141
+ default: false, short: :none
142
+ opt :fts_optimize, "Optimize an existing full-text index (merge segments; idempotent)",
143
+ default: false, short: :none
144
+
121
145
  opt :file_size, "Approximate size (in MB) of each output file (0 for single file)",
122
146
  default: 10, short: "-f"
123
147
  opt :num_procs, "Number of parallel processes (auto-detected based on CPU/memory)",
@@ -294,6 +318,49 @@ module Wp2txt
294
318
  if opts[:show_matched_sections] && opts[:format].to_s.downcase != "json"
295
319
  Optimist.die "--show-matched-sections requires --format json"
296
320
  end
321
+
322
+ # Metadata index options
323
+ if opts[:build_index] && opts[:find_articles]
324
+ Optimist.die "--build-index and --find-articles cannot be combined (build first, then query)"
325
+ end
326
+
327
+ %i[in_category has_section title_match].each do |key|
328
+ if opts[key] && !opts[:find_articles] && !opts[:search]
329
+ Optimist.die "--#{key.to_s.tr('_', '-')} requires --find-articles or --search"
330
+ end
331
+ end
332
+
333
+ Optimist.die :limit, "must be 0 or greater" if opts[:limit].negative?
334
+
335
+ if opts[:fulltext] && !opts[:build_index]
336
+ Optimist.die "--fulltext requires --build-index"
337
+ end
338
+
339
+ if opts[:fts_tokenizer] && !%w[unicode61 trigram porter].include?(opts[:fts_tokenizer])
340
+ Optimist.die :fts_tokenizer, "must be unicode61, trigram, or porter"
341
+ end
342
+
343
+ if opts[:skip_fts_optimize] && !opts[:fulltext]
344
+ Optimist.die "--skip-fts-optimize requires --build-index --fulltext"
345
+ end
346
+
347
+ if opts[:fts_optimize] && (opts[:build_index] || opts[:find_articles] || opts[:search])
348
+ Optimist.die "--fts-optimize is a standalone mode (cannot combine with --build-index/--find-articles/--search)"
349
+ end
350
+
351
+ if opts[:search] && (opts[:build_index] || opts[:find_articles])
352
+ Optimist.die "--search cannot be combined with --build-index/--find-articles"
353
+ end
354
+
355
+ if opts[:build_index] || opts[:find_articles] || opts[:search] || opts[:fts_optimize]
356
+ conflicts = []
357
+ conflicts << "--articles" if opts[:articles]
358
+ conflicts << "--from-category" if opts[:from_category]
359
+ conflicts << "--section-stats" if opts[:section_stats]
360
+ unless conflicts.empty?
361
+ Optimist.die "--build-index/--find-articles/--search cannot be combined with #{conflicts.join(', ')}"
362
+ end
363
+ end
297
364
  end
298
365
 
299
366
  # Parse article list from comma-separated string