agent_ui: Auto-capture file context on paste (#42982)

Closes #42972


https://github.com/user-attachments/assets/98f2d3dc-5682-4670-b636-fa8ea2495c69

Release Notes:

- Added automatic file context detection when pasting code into the AI
agent panel. Pasted code now displays as collapsible badges showing the
file path and line numbers (e.g., "app/layout.tsx (18-25)").

---------

Co-authored-by: Bennet Bo Fenner <bennetbo@gmx.de>
This commit is contained in:
ozzy
2025-12-08 17:32:04 +01:00
committed by GitHub
co-authored by Bennet Bo Fenner
parent 18421845eb
commit f6a6630171
4 changed files with 268 additions and 18 deletions
+52 -10
View File
@@ -1592,6 +1592,45 @@ pub struct ClipboardSelection {
pub is_entire_line: bool,
/// The indentation of the first line when this content was originally copied.
pub first_line_indent: u32,
#[serde(default)]
pub file_path: Option<PathBuf>,
#[serde(default)]
pub line_range: Option<RangeInclusive<u32>>,
}
impl ClipboardSelection {
pub fn for_buffer(
len: usize,
is_entire_line: bool,
range: Range<Point>,
buffer: &MultiBufferSnapshot,
project: Option<&Entity<Project>>,
cx: &App,
) -> Self {
let first_line_indent = buffer
.indent_size_for_line(MultiBufferRow(range.start.row))
.len;
let file_path = util::maybe!({
let project = project?.read(cx);
let file = buffer.file_at(range.start)?;
let project_path = ProjectPath {
worktree_id: file.worktree_id(cx),
path: file.path().clone(),
};
project.absolute_path(&project_path, cx)
});
let line_range = file_path.as_ref().map(|_| range.start.row..=range.end.row);
Self {
len,
is_entire_line,
first_line_indent,
file_path,
line_range,
}
}
}
// selections, scroll behavior, was newest selection reversed
@@ -12812,13 +12851,15 @@ impl Editor {
text.push_str(chunk);
len += chunk.len();
}
clipboard_selections.push(ClipboardSelection {
clipboard_selections.push(ClipboardSelection::for_buffer(
len,
is_entire_line,
first_line_indent: buffer
.indent_size_for_line(MultiBufferRow(selection.start.row))
.len,
});
selection.range(),
&buffer,
self.project.as_ref(),
cx,
));
}
}
@@ -12961,13 +13002,14 @@ impl Editor {
text.push('\n');
len += 1;
}
clipboard_selections.push(ClipboardSelection {
clipboard_selections.push(ClipboardSelection::for_buffer(
len,
is_entire_line,
first_line_indent: buffer
.indent_size_for_line(MultiBufferRow(trimmed_range.start.row))
.len,
});
trimmed_range,
&buffer,
self.project.as_ref(),
cx,
));
}
}
}