Skip to content

git add <tab> truncates filenames containing spaces #271

@nickeddy

Description

@nickeddy

Summary

In the Warp client, git add <tab> returns broken suggestions for any working-tree file whose name contains a space. The completion popup shows the filename truncated at the first space (often with a stray leading " from git's C-style quoting), and selecting the suggestion inserts the truncated string into the buffer. The user cannot stage files with spaces in their names via tab completion.

Reproduction

mkdir /tmp/repro && cd /tmp/repro
git init -q
touch "new file test.csv"

In Warp, type git add in /tmp/repro and press Tab.

Actual behavior

The popup shows a single suggestion that displays as "new (leading double-quote, content up to the first space, trailing space). Pressing Enter inserts that broken string into the buffer.

Expected behavior

The popup shows new file test.csv as a suggestion. Pressing Enter inserts a properly escaped form (new\ file\ test.csv for POSIX shells, or any equivalent that the shell will parse as the single token new file test.csv).

Environment

  • Warp version: v0.2026.05.13.09.15.stable_01
  • OS: Linux Mint 22.2 x86_64
  • Shell: zsh

Root cause

command-signatures/src/generators/git.rs:437-453 (in warpdotdev/command-signatures, pinned in warp's Cargo.toml at rev 00a032b8):

fn post_process_tracked_files(output: &str) -> GeneratorResults {
    let output = filter_messages(output);
    if output.starts_with("fatal:") {
        return GeneratorResults::default();
    }

    output
        .lines()
        // The first non-whitespace string is just a character indicating the type of indexed file.
        .filter_map(|file| file.split_whitespace().nth(1))   // <-- bug
        .map(|file| {
            Suggestion::with_description(file, "Changed file")
                .with_priority(Priority::Global(Importance::More(Order(100))))
                .with_icon(IconType::File)
        })
        .collect_unordered_results()
}

This post-processor consumes the output of git --no-optional-locks status --short (registered as the files_for_staging generator at line 770-775 and referenced from command-signatures/json/git.json for the git add argument).

git status --short formats lines as XY <pathname>. By default (core.quotepath=true) git C-style-quotes pathnames with special characters, so an untracked file new file test.csv produces ?? "new file test.csv". file.split_whitespace().nth(1) returns only the second whitespace-delimited token ("new), discarding the rest of the path. That truncated string flows through unchanged as both the suggestion's display value and its insertion replacement.

The existing test test_post_process_tracked_files (same file, line 968) only covers paths without spaces, which is why the regression slipped through.

Suggested fix

Switch the command to -z mode and rewrite the parser to handle the binary-safe NUL-separated format:

  • Change the command to git --no-optional-locks status --short -z. NUL terminators replace newlines and disable C-style quoting entirely.
  • In the post-processor, split the output on '\0', take everything from byte 3 of each record (skipping the fixed-width XY prefix), and skip the source-path record that follows any rename or copy entry (status starting with R or C).

NUL bytes survive the warp runtime end-to-end:

  • Local subprocess executor: raw Vec<u8> from child.output().await.
  • In-band executor: hex-encoded by the bootstrap shell wrapper (od -An -v -tx1) and hex::decoded on the warp side, so each 0x00 byte round-trips cleanly.
  • TMUX executor: same event.output: Vec<u8> pipeline as in-band.

Notes

  • The fix lives in warpdotdev/command-signatures, not warpdotdev/warp. After the command-signatures PR merges, warp's Cargo.toml pin needs to be bumped in a follow-up PR.
  • A latent gap exists at crates/warp_completer/src/completer/engine/argument/v2.rs:685-751 (warp side): script-output suggestions go through From<signatures::Suggestion> for Suggestion with no shell-escaping of the replacement. Once the generator is fixed, plain filenames with spaces will still need escaping at insertion time. That's a separate fix in warp and probably warrants its own issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions