Skip to content

feat(autocomplete): sample multiple array elements for richer suggestions#147

Merged
bellicose100xp merged 12 commits intomainfrom
mixed-array
Feb 20, 2026
Merged

feat(autocomplete): sample multiple array elements for richer suggestions#147
bellicose100xp merged 12 commits intomainfrom
mixed-array

Conversation

@bellicose100xp
Copy link
Owner

Summary

  • Multi-element array sampling: Autocomplete now samples up to N elements (default 10) from arrays and merges their keys, so fields present in any element appear as suggestions — not just fields from the first element.
  • Destructured stream merging: When jq produces streamed objects ({...}\n{...}) or streamed arrays ([{...}]\n[{...}]), keys/elements from subsequent values are merged into the first for autocomplete.
  • Null/scalar-first reclassification: When streamed output starts with null or a scalar but subsequent values are objects, the result type is reclassified so autocomplete can still extract field suggestions.
  • Configurable sample size: The array sample size is exposed via array_sample_size in the config file.

Test plan

  • 2882 unit/integration tests pass (cargo test)
  • cargo clippy --all-targets --all-features — zero warnings
  • cargo fmt --all --check — zero formatting issues
  • cargo build --release — zero build warnings
  • Manual TUI test: load tests/fixtures/mixed-type-array.json, type .services[].deployments[]?.tasks[]?.payload.data appears in autocomplete

Update collect_fields_recursive() to iterate the first 10 array
elements instead of only the first, unioning their keys into the
all_field_names fallback cache. This ensures fields present only
in non-first elements of heterogeneous arrays appear in suggestions.

Add ARRAY_SAMPLE_SIZE constant (10) in json_navigator.rs as the
single source of truth for the sample limit across the codebase.
… analyzer

Add extract_union_fields_from_array() to sample first N array elements
and deduplicate keys using a shared HashSet. Add analyze_multi_values()
as the core implementation, and make analyze_value() delegate to it.

Update extract_suggestions_for_type() for ArrayOfObjects to use the
new union extraction instead of only examining the first element.

Fields from non-first elements now appear in suggestions. Type detection
uses first-occurrence-wins semantics for overlapping keys.
Add navigate_multi() that fans out at ArrayIterator segments, returning
up to sample_size values per array level. Total results are capped at
MAX_NAVIGATED_VALUES (100) to prevent combinatorial explosion at deeply
nested levels.

This is the foundation for Phase 4 where non-executing context
(map, select, builders) will use navigate_multi to surface keys from
multiple array elements.
Replace single-value navigate() with navigate_multi() in
get_nested_field_suggestions(), enabling multi-element array traversal
for non-executing contexts (map, select, array/object builders).

Combined with analyze_multi_values(), this surfaces keys from multiple
array elements when autocompleting inside map(.field), select(.field),
and similar constructs.
… results

When jq output is destructured objects (e.g., .services[] produces
streaming objects), merge keys from the first N streamed objects into
a synthetic combined object. This ensures autocomplete sees all fields
across heterogeneous streamed results, not just the first object.

Uses entry().or_insert() for first-occurrence-wins semantics, matching
the type detection behavior in other phases.
…mpling

Add issue #145 integration tests verifying:
- .services[]. includes extra_service_key from second element
- select(. with services also shows non-first-element keys
- Nested array paths surface keys across elements
- Invalid paths fall back cleanly

Update README autocomplete limitation to document N=10 sampling
behavior instead of first-element-only.
When jq streams multiple arrays (e.g., .services[].tasks produces
[{...}]\n[{...}]), merge elements from the first N arrays into a
single combined array. This ensures autocomplete sees fields from all
streamed arrays, not just the first.

Previously only destructured objects were merged (Phase 5). This
handles the parallel case where the streamed values are arrays of
objects rather than bare objects.
…ling

Fill test gaps identified by coverage audit:

navigate_multi: Field on non-object values, negative index underflow,
  ArrayIterator on non-arrays, intermediate empty results
analyze_multi_values: empty slice, scalar-only values, multiple arrays
  with single .[] suggestion, suppress brackets, scalar-only arrays
collect_fields_recursive: array exceeding ARRAY_SAMPLE_SIZE limit
parse_and_detect_type: mixed-type streams for both destructured objects
  and arrays, sample limit enforcement for both merge paths
Expose the array sample size (previously hardcoded to 10) as a
user-configurable option under [autocomplete] in config.toml. Also
raise MAX_NAVIGATED_VALUES from 100 to 1000 for better coverage of
heterogeneous arrays on modern hardware.
…calar

When streaming output starts with null or a scalar but subsequent values
are objects, reclassify to DestructuredObjects (or ArrayOfObjects) so
autocomplete can extract field suggestions from the object values.
Verify that array_sample_size is correctly forwarded and respected at
both the preprocessing layer (destructured stream merging) and the
result analyzer layer (array field suggestion extraction). Also trim
redundant phrasing from the autocomplete known limitation in README.
@bellicose100xp bellicose100xp merged commit 159c03d into main Feb 20, 2026
9 checks passed
@bellicose100xp bellicose100xp deleted the mixed-array branch February 20, 2026 19:45
@codecov
Copy link

codecov bot commented Feb 20, 2026

Codecov Report

❌ Patch coverage is 95.30201% with 7 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/autocomplete/json_navigator.rs 87.87% 4 Missing ⚠️
src/config.rs 0.00% 3 Missing ⚠️

📢 Thoughts on this report? Let us know!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant