Skip to content

tui: @ file search drops filename text after # even without a line suffix #60304

Closed

Description

@HeZ2z

Description

TUI @ file autocomplete treats the last # as the start of a line-number suffix even when what follows is not a line number. For a valid filename such as report#2026.md, it searches only for report; for #notes.md, it searches for an empty base. The suffix of the filename cannot narrow the results, and with the 20-result cap the intended file may be absent.

Reproduction

On dev commit 82666b6612cdb2ba13a7a26e150b21e897a80373, run from packages/tui:

bun -e 'import {parseFileLineRange} from "./src/prompt/parse.ts"; for (const q of ["report#2026.md", "#notes.md", "report#2026.md#3"]) console.log(q,JSON.stringify(parseFileLineRange(q)))'

Actual:

report#2026.md {"base":"report"}
#notes.md {"base":""}
report#2026.md#3 {"base":"report#2026.md","lineRange":{"startLine":3}}

Expected: the first two inputs keep the full filename as the search base; a valid #3 line suffix is still recognized. The autocomplete implementation passes this base to file search. To confirm the user-visible consequence, I used the actual ripgrep-backed FileSystemSearch with 40 reportNN.txt files plus report#2026.md and a limit of 20: searching report returned 20 other files, while searching report#2026.md returned the target. Ranking may vary by filesystem. This verifies the parser and real search separately, not a full interactive TUI run. The parser blob matches current upstream dev.

Activity

  1. opencodejr commented on Oct 29, 2026

    @opencodejr
    Contributor

    Thanks for the clear report. I reproduced this on v2.2.1 and on the latest dev (ccd406b).

    Steps: a project with 40 reportNN.txt files plus report#2026.md, then type @report#2026.md in the prompt. The autocomplete shows report00.txt, report01.txt and so on, and report#2026.md is not among the visible entries. As you found, parseFileLineRange in packages/tui/src/prompt/parse.ts returns the text before the last # even when what follows isn't a line range, so the search runs on report only.

    The recording and screenshots below show it, and the script below reproduces it.

    Related: #58033 is a different bug in the same #N line-range handling.

    recording.mp4

    Screenshot

    Screenshot

    Reproduction script (drive.ts)
    // Repro for #60304: `@` file autocomplete drops the text after '#' even when it is not a line suffix.
    import { Effect } from "effect"
    import { OpenCodeDriver } from "opencode-drive"
    
    const files: Record<string, string> = { "report#2026.md": "# target\n" }
    for (let i = 0; i < 40; i++) files[`report${String(i).padStart(2, "0")}.txt`] = `filler ${i}\n`
    
    export default OpenCodeDriver.use(
      {
        ...(process.env.OC_DEV ? { opencode: { dev: process.env.OC_DEV } } : {}),
        project: { git: true, files },
        tui: { recording: true, keypressOverlay: true },
      },
      ({ ui }) =>
        Effect.gen(function* () {
          yield* Effect.sleep("2 seconds")
          // Type the full, valid filename after '@'
          yield* ui.type("@report#2026.md")
          yield* Effect.sleep("2 seconds")
          yield* ui.screenshot("full-filename-query")
          // Bug: the list shows report00.txt, report01.txt, ... (search base "report") instead of report#2026.md
          yield* Effect.sleep("1 second")
        }),
    )

    Run it with opencode-drive: opencode-drive run ./drive.ts. It drives opencode from your PATH; set OC_DEV to the path of an OpenCode checkout to run that from source instead.

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions