Skip to content

spec: file tree search (#10320)#10460

Open
lonexreb wants to merge 5 commits into
warpdotdev:masterfrom
lonexreb:spec/10320-file-tree-search
Open

spec: file tree search (#10320)#10460
lonexreb wants to merge 5 commits into
warpdotdev:masterfrom
lonexreb:spec/10320-file-tree-search

Conversation

@lonexreb
Copy link
Copy Markdown
Contributor

@lonexreb lonexreb commented May 8, 2026

Summary

Spec for #10320 — adds in-tree search to the File Tree / Project Explorer, openable via Cmd+F (Ctrl+F on Windows/Linux) when the tree has focus and via a discoverable magnifier button in the tree header.

This is a spec-only PR. No implementation in this change.

Highlights

  • Cmd+F is scoped to a new KeyContext::FileTreeFocus so it does not collide with editor / terminal Cmd+F.
  • Live filter on every keystroke; auto-expands folders containing matches.
  • Substring match against filename and path components, case-insensitive, NFC-normalized.
  • Next / previous match navigation via F3 / Shift+F3 (and Enter / Shift+Enter).
  • Dim-non-matches by default; file_tree.search.show_all_on_filter toggles to hide instead.
  • Esc and clear restore prior selection and tree expand state.

Scope

  • V1: filename + path-component substring search.
  • V1.5 (deferred): regex / glob, and an optional git-status filter row ("show only modified files").

Telemetry

Extends the existing file_tree.opened event with an optional search_used boolean per session.

Tag: ready-to-spec

Closes part of #10320 (spec only — implementation will follow once the spec is approved).

@cla-bot cla-bot Bot added the cla-signed label May 8, 2026
@github-actions github-actions Bot added the external-contributor Indicates that a PR has been opened by someone outside the Warp team. label May 8, 2026
@oz-for-oss
Copy link
Copy Markdown
Contributor

oz-for-oss Bot commented May 8, 2026

@lonexreb

I'm starting a first review of this spec-only pull request.

You can view the conversation on Warp.

I completed the review and no human review was requested for this pull request.

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

Copy link
Copy Markdown
Contributor

@oz-for-oss oz-for-oss Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overview

Reviewed the spec-only addition for File Tree / Project Explorer search. The behavior contract covers activation, matching, filtering, navigation, restoration, tests, and telemetry, and the supplemental security pass did not identify a design-level security concern.

Concerns

  • The show-all setting is internally inverted between the behavior contract and Settings/API surface.
  • Several implementation pointers do not match the current Warp file tree, keybinding, or telemetry surfaces, which would send implementation work down stale paths.

Verdict

Found: 0 critical, 4 important, 0 suggestions

Request changes

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

Comment thread specs/GH10320/SPEC.md Outdated

## Settings / API surface

- `file_tree.search.show_all_on_filter` — `bool`, default `false`. When
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ [IMPORTANT] The setting name and B3/B6 behavior imply true means showing all/dimming and false means hiding, but this says the inverse with default false; choose one semantic/default so implementation and users do not invert the toggle.

Comment thread specs/GH10320/SPEC.md Outdated
Comment on lines +110 to +112
- Keybinding registration for `Cmd+F` (mac) / `Ctrl+F` (win/linux), scoped
to the new `KeyContext::FileTreeFocus` so it does not collide with editor
or terminal `Cmd+F`.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ [IMPORTANT] KeyContext::FileTreeFocus does not exist in the current keybinding system; file tree bindings are registered with FixedBinding scoped to id!(FileTreeView::ui_name()), so the spec should either propose the new context architecture or use the existing scoped binding mechanism.

Comment thread specs/GH10320/SPEC.md Outdated
Comment on lines +130 to +134
- New module `app/src/file_tree/search.rs` for the matching pipeline and
match-list state.
- Update `app/src/file_tree/header.rs` to add the magnifier button.
- Update `app/src/file_tree/tree_view.rs` for the filter + highlight render
pipeline and auto-expand on match.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ [IMPORTANT] These implementation paths do not exist in the current tree (app/src/code/file_tree/view.rs and view/render.rs are the relevant files); update the pointers or describe the intended module moves so implementers do not build against stale paths.

Comment thread specs/GH10320/SPEC.md Outdated
Comment on lines +166 to +168
Extend the existing `file_tree.opened` event with an optional `search_used`
boolean per tree-panel session (set `true` if the user opened the search box
at any point during that session). No new event types are introduced.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ [IMPORTANT] The current telemetry surface is TelemetryEvent::FileTreeToggled / "File Tree Toggled", not file_tree.opened, and it is emitted when opening; specify the actual event/payload timing needed to attach search_used after a session has observed search usage.

@lonexreb
Copy link
Copy Markdown
Contributor Author

lonexreb commented May 8, 2026

Round-1 fixes for oz-for-oss review: (1) renamed setting to file_tree.search.dim_non_matches (bool, default true) — all references in B3, B6, Settings/API surface, Acceptance (A5), and Tests (T6) now use this single name with dimmed-by-default semantics (no more inverted variants); (2) Implementation Pointers audited against the codebase at commit 86940541 — corrected file tree path to app/src/code/file_tree/ (not app/src/file_tree/), removed references to non-existent header.rs/tree_view.rs/editor_page.rs, pointed magnifier-button work at view.rs (where the header row is inlined), settings to code_page.rs, and keymap context registration to the existing context.set.insert("FileTreeFocused") pattern (mirrors "EditorFocused" at app/src/terminal/view.rs:26640); (3) telemetry uses the real existing event TelemetryEvent::FileTreeToggled (label "File Tree Toggled", events.rs:5658) — extended with search_used: bool, with a fallback option to add a net-new FileTreeSearchUsed event if extending is awkward.

@lonexreb
Copy link
Copy Markdown
Contributor Author

lonexreb commented May 8, 2026

/oz-review

@oz-for-oss
Copy link
Copy Markdown
Contributor

oz-for-oss Bot commented May 8, 2026

@lonexreb

I'm re-reviewing this spec-only pull request in response to a review request.

You can view the conversation on Warp.

I completed the review and no human review was requested for this pull request.

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

Copy link
Copy Markdown
Contributor

@oz-for-oss oz-for-oss Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overview

Reviewed the file-tree search spec for completeness, clarity, feasibility, issue alignment, internal consistency, and high-level security concerns. The spec covers the main behavior, settings, tests, and telemetry shape, but two core matching semantics need to be pinned down before implementation.

Concerns

  • Folder matches are underspecified: the spec says children become in-context matches, but later hidden-mode and navigation/count behavior do not define whether those descendants are visible, counted, highlighted, or navigable.
  • Unicode matching is underspecified for a case-insensitive search: NFC normalization is defined, but non-ASCII case folding is not.

Verdict

Found: 0 critical, 2 important, 0 suggestions

Request changes

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

Comment thread specs/GH10320/SPEC.md Outdated
- Case-insensitive substring match.
- Match is checked against each path component (folder names and the file
basename) and against the full relative path string.
- A folder match reveals all of the folder's children as in-context matches
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ [IMPORTANT] Folder-as-context behavior needs exact semantics: specify whether descendants of a matching folder are visible in hide mode, included in the match count, highlighted, and reachable via next/previous navigation.

Comment thread specs/GH10320/SPEC.md Outdated
basename) and against the full relative path string.
- A folder match reveals all of the folder's children as in-context matches
(folder-as-context).
- Matching is locale-insensitive for ASCII; Unicode normalized using NFC
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ [IMPORTANT] The case-insensitive Unicode behavior is underspecified: define whether non-ASCII uses Unicode case folding after NFC normalization, or explicitly limit case-insensitive matching to ASCII.

@lonexreb
Copy link
Copy Markdown
Contributor Author

lonexreb commented May 8, 2026

Round-2 fixes: (1) folder-match descendant semantics now explicit — descendants visible (dim mode) or visible (hidden mode), counted via union (no double-count), only the folder name itself highlighted, navigation cycles depth-first/lex through file matches and folder-match descendants; acceptance + tests added; (2) Unicode case folding now explicitly Unicode Default Case Folding per TR#21 (full folding, status C+F), applied AFTER NFC normalization; locale-independent (no Turkish-specific I/i); test coverage for ß/SS, Greek final-sigma, and Turkish default-folding.

@lonexreb
Copy link
Copy Markdown
Contributor Author

lonexreb commented May 8, 2026

/oz-review

@oz-for-oss
Copy link
Copy Markdown
Contributor

oz-for-oss Bot commented May 8, 2026

@lonexreb

I'm re-reviewing this spec-only pull request in response to a review request.

You can view the conversation on Warp.

I completed the review and no human review was requested for this pull request.

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

Copy link
Copy Markdown
Contributor

@oz-for-oss oz-for-oss Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overview

This spec defines in-tree file search behavior for activation, matching, visibility modes, restoration, tests, and telemetry. The supplemental security pass did not identify design-level security findings.

Concerns

  • The Unicode matching contract is internally contradictory: it requires full case folding, but also permits Rust str::to_lowercase(), which does not satisfy the listed ß and sigma cases.
  • Hide-mode visibility is inconsistent with the folder-match descendant semantics; one section says all descendants of a matched folder remain visible, while the live-filter rule says only matching files plus ancestors render.

Verdict

Found: 1 critical, 1 important, 0 suggestions

Request changes

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

Comment thread specs/GH10320/SPEC.md Outdated
Comment on lines +129 to +131
- In Rust, the equivalent is `str::to_lowercase()` on a valid UTF-8
string, which performs full Unicode lowercasing per
`SpecialCasing.txt`. Implementations MAY use this directly.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚨 [CRITICAL] str::to_lowercase() is lowercasing, not Unicode default case folding; allowing it contradicts the required ß → ss and sigma equivalence tests, so specify an actual full case-folding implementation or relax those requirements.

Comment thread specs/GH10320/SPEC.md Outdated
Comment on lines +162 to +164
- When `false`: non-matching siblings are **hidden** entirely; only
matching files plus their ancestor folders (auto-expanded) are
rendered.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ [IMPORTANT] This hide-mode rule contradicts B2a.1/A_folder_match_visibility_hide, which require all descendants of a matched folder to remain visible even when their names do not match; align this rule with the folder-as-context semantics.

@lonexreb
Copy link
Copy Markdown
Contributor Author

lonexreb commented May 8, 2026

Addressed round-N review:

Critical — Unicode case-folding contradiction. The previous wording said the spec required full Unicode Default Case Folding (TR#21 C+F) but ALSO that str::to_lowercase() was an acceptable equivalent. Those two statements are not consistent: to_lowercase() applies SpecialCasing.txt lowercasing (which preserves ß as ß and does not collapse final-form sigma ς and middle sigma σ to a single form), while case folding applies CaseFolding.txt C+F (which folds ßss and collapses sigma forms).

Resolved by deleting the to_lowercase() permission entirely. The spec now requires a Unicode case-folding crate that implements C+F default folding (e.g. caseless::default_caseless_match_str / caseless::Caseless::default_case_fold) on the NFC-normalized strings, and explicitly forbids substituting str::to_lowercase() even as a fallback. Added a test gate: implementations MUST pass T_unicode_german_ss and T_unicode_greek_sigma — passing those is the authoritative check that the right folding is being applied.

Important — Hide-mode descendant visibility inconsistency. B2a.1 says all descendants of a matched folder are visible; B3's hide-mode rule said 'only matching files plus their ancestor folders are rendered'. Reconciled in B3 by stating that the rendered set in hide mode is (1) every node in the union match set (direct matches + folder-match descendants per B2a) plus (2) ancestor folders of those nodes. Folder-match descendants qualify as 'matching' for the hide rule because the match set is the union per B2a, so a matched folder DOES keep all descendants visible in hide mode. Wording in B3 explicitly supersedes the earlier 'filename matches plus ancestors' phrasing.

Commit: 713003d

@lonexreb
Copy link
Copy Markdown
Contributor Author

lonexreb commented May 8, 2026

/oz-review

@oz-for-oss
Copy link
Copy Markdown
Contributor

oz-for-oss Bot commented May 8, 2026

@lonexreb

I'm re-reviewing this spec-only pull request in response to a review request.

You can view the conversation on Warp.

I completed the review and no human review was requested for this pull request.

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

Copy link
Copy Markdown
Contributor

@oz-for-oss oz-for-oss Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overview

Reviewed the spec-only PR for File Tree search. The spec covers activation, filtering, restore behavior, settings, tests, and telemetry, and the supplemental security pass did not identify a design-level security finding.

Concerns

  • The match semantics are internally inconsistent: matching against each row's full relative path makes descendants of a matched folder direct matches, while later sections and tests treat them as context-only unless their own names match.
  • The settings summary should use the same union match-set wording as the behavior contract so implementers do not read hide mode as filename-only filtering.

Verdict

Found: 0 critical, 1 important, 1 suggestions

Request changes

Comment /oz-review on this pull request to retrigger a review (up to 3 times on the same pull request).

Powered by Oz

Comment thread specs/GH10320/SPEC.md Outdated
Comment on lines +57 to +60
- Case-insensitive substring match.
- Match is checked against each path component (folder names and the file
basename) and against the full relative path string.
- A folder match reveals all of the folder's descendants as in-context
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ [IMPORTANT] Matching each row's full relative path makes every descendant of a matching folder a direct match (for example, query src matches src/a.rs), which contradicts B2a.3 and T_folder_match_highlight where descendants are context-only unless their own name matches. Specify whether ancestor-component hits are context matches, or remove full-relative-path matching from descendant rows.

Comment thread specs/GH10320/SPEC.md Outdated
Comment on lines +232 to +233
When `false`, non-matching siblings are hidden entirely (only matching
files and their ancestor folders are rendered).
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 [SUGGESTION] This setting summary still says only matching files plus ancestors render, which conflicts with B2a's folder-descendant rule; align it with the union match set wording.

Suggested change
When `false`, non-matching siblings are hidden entirely (only matching
files and their ancestor folders are rendered).
When `false`, non-matching siblings are hidden entirely; rendered nodes are
the union match set (including folder-match descendants per B2a) plus the
ancestor folders needed to reveal those nodes.

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

Labels

cla-signed external-contributor Indicates that a PR has been opened by someone outside the Warp team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant