Skip to content

feat(input): auto-wrap drag-and-dropped file paths with @[] syntax#2808

Merged
tusharmath merged 15 commits intotailcallhq:mainfrom
tapizquent-gail:feat/auto-wrap-dropped-file-paths
Apr 12, 2026
Merged

feat(input): auto-wrap drag-and-dropped file paths with @[] syntax#2808
tusharmath merged 15 commits intotailcallhq:mainfrom
tapizquent-gail:feat/auto-wrap-dropped-file-paths

Conversation

@tapizquent-gail
Copy link
Copy Markdown
Contributor

When a user drags and drops a file onto the terminal, the terminal pastes the raw file path as text. Forge requires @[path] syntax to recognise file references, so dropped files were silently ignored.

This commit detects bare file paths and wraps them at paste time so the @[...] reference appears immediately in the input buffer:

  • Reedline editor (editor.rs): a custom ForgeEditMode wraps the default Emacs mode and intercepts crossterm Paste events. The pasted text is transformed before it reaches the reedline buffer, giving the user instant visual feedback.
  • Zsh shell plugin (bindings.zsh): the forge-bracketed-paste widget intercepts pasted text and wraps it when it points to an existing file.
Screen.Recording.2026-04-02.at.17.47.39.mov

@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Apr 2, 2026

CLA assistant check
All committers have signed the CLA.

@github-actions github-actions bot added the type: feature Brand new functionality, features, pages, workflows, endpoints, etc. label Apr 2, 2026
tapizquent-gail and others added 3 commits April 2, 2026 21:10
When a user drags and drops a file onto the terminal, the terminal
pastes the raw file path as text. Forge requires @[path] syntax to
recognise file references, so dropped files were silently ignored.

This commit detects bare file paths and wraps them at paste time so
the @[...] reference appears immediately in the input buffer:

- Reedline editor (editor.rs): a custom ForgeEditMode wraps the
  default Emacs mode and intercepts crossterm Paste events. The
  pasted text is transformed before it reaches the reedline buffer,
  giving the user instant visual feedback.
- Zsh shell plugin (bindings.zsh): the forge-bracketed-paste widget
  intercepts pasted text and wraps it when it points to an existing
  file.

Co-Authored-By: ForgeCode <noreply@forgecode.dev>
strip_surrounding_quotes would panic on a single quote character
because slicing s[1..0] is an invalid range. Add an early return
for strings shorter than 2 characters.

Co-Authored-By: ForgeCode <noreply@forgecode.dev>
- Remove fast path in wrap_pasted_text that discarded surrounding
  whitespace from the original paste content.
- Add double-quote stripping in the zsh bracketed-paste widget to
  match the Rust implementation which already handled both quote
  styles.

Co-Authored-By: ForgeCode <noreply@forgecode.dev>
@tapizquent-gail tapizquent-gail force-pushed the feat/auto-wrap-dropped-file-paths branch from 9715d7f to 3f4b3e8 Compare April 3, 2026 01:10
@tapizquent-gail
Copy link
Copy Markdown
Contributor Author

This also pretty much addresses #2811 , as you can copy an image anywhere and just paste it with the proper syntax now

@ssddOnTop
Copy link
Copy Markdown
Collaborator

@tapizquent-gail Does this work with zsh plugin as well?

@tapizquent-gail
Copy link
Copy Markdown
Contributor Author

@tapizquent-gail Does this work with zsh plugin as well?

Yes.

Screen.Recording.2026-04-02.at.21.42.40.mov

tapizquent-gail and others added 2 commits April 2, 2026 23:10
- Fix Rust wrap_pasted_text to try entire paste as a single path before
  token splitting, handling bare paths with spaces
- Add backslash-escape awareness: strip '\ ' to ' ' before is_file()
  checks so terminal drag-and-drop (Ghostty, iTerm2) works correctly
- Update tokenizer to treat backslash-space as non-boundary so escaped
  paths stay as a single token
- Fix zsh forge-bracketed-paste to handle backslash-escaped and quoted
  paths with spaces
- Add forge-accept-line fallback (_forge_wrap_file_paths) for terminals
  that don't emit bracketed-paste on drag-and-drop (e.g. JetBrains)
- Only trigger @[] wrapping when zsh buffer starts with ':' (sentinel)
- Add zsh test script (scripts/test-zsh-utils.sh) with 21 correctness
  and performance tests

Co-Authored-By: ForgeCode <noreply@forgecode.dev>
Move all file path detection and @[...] wrapping logic from the zsh
plugin into Rust, exposed as a new `forge zsh format --buffer <text>`
CLI subcommand.  This addresses the PR review comment requesting a
single well-tested implementation.

Changes:
- Add ZshCommandGroup::Format variant with --buffer arg to CLI
- Make wrap_pasted_text() public so it can be called from the dispatch
- Simplify forge-bracketed-paste widget to delegate to forge zsh format
- Simplify forge-accept-line dispatcher to delegate to forge zsh format
- Remove _forge_wrap_file_paths and _forge_unescape_backslashes from
  zsh helpers (139 lines of zsh replaced by a one-line CLI call)
- Update test script to exercise forge zsh format end-to-end
- Add CLI parsing test for the new subcommand

Net: -156 lines (79 added, 235 removed)

Co-Authored-By: ForgeCode <noreply@forgecode.dev>
@tapizquent-gail
Copy link
Copy Markdown
Contributor Author

Improved, now works with paths or files containing spaces and uses rust syntax for format. For RustRover's terminal (which doesn't emit bracketed-paste on drag-and-drop), we added a fallback in forge-accept-line -- when you press Enter, it runs forge zsh format on the input text before dispatching, so paths still get wrapped even if the paste handler never fired.

@tusharmath tusharmath self-assigned this Apr 9, 2026
@tusharmath tusharmath enabled auto-merge (squash) April 12, 2026 07:30
@tusharmath
Copy link
Copy Markdown
Collaborator

@tapizquent-gail I think we need a better way to make it work with RustRover and VSCode. We need to insert in the terminal with proper syntax highlighting to suggest that that a file has been attached.

@tusharmath tusharmath merged commit 72516c2 into tailcallhq:main Apr 12, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type: feature Brand new functionality, features, pages, workflows, endpoints, etc.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants