context_editor: Allow copying entire line when selection is empty (#30612)
Closes #27879 Release Notes: - Allow copying entire line when selection is empty in text threads
This commit is contained in:
parent
71ea7aee3b
commit
2b74163a48
1 changed files with 96 additions and 4 deletions
|
@ -1590,7 +1590,7 @@ impl ContextEditor {
|
||||||
&mut self,
|
&mut self,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) -> (String, CopyMetadata, Vec<text::Selection<usize>>) {
|
) -> (String, CopyMetadata, Vec<text::Selection<usize>>) {
|
||||||
let (selection, creases) = self.editor.update(cx, |editor, cx| {
|
let (mut selection, creases) = self.editor.update(cx, |editor, cx| {
|
||||||
let mut selection = editor.selections.newest_adjusted(cx);
|
let mut selection = editor.selections.newest_adjusted(cx);
|
||||||
let snapshot = editor.buffer().read(cx).snapshot(cx);
|
let snapshot = editor.buffer().read(cx).snapshot(cx);
|
||||||
|
|
||||||
|
@ -1648,7 +1648,18 @@ impl ContextEditor {
|
||||||
} else if message.offset_range.end >= selection.range().start {
|
} else if message.offset_range.end >= selection.range().start {
|
||||||
let range = cmp::max(message.offset_range.start, selection.range().start)
|
let range = cmp::max(message.offset_range.start, selection.range().start)
|
||||||
..cmp::min(message.offset_range.end, selection.range().end);
|
..cmp::min(message.offset_range.end, selection.range().end);
|
||||||
if !range.is_empty() {
|
if range.is_empty() {
|
||||||
|
let snapshot = context.buffer().read(cx).snapshot();
|
||||||
|
let point = snapshot.offset_to_point(range.start);
|
||||||
|
selection.start = snapshot.point_to_offset(Point::new(point.row, 0));
|
||||||
|
selection.end = snapshot.point_to_offset(cmp::min(
|
||||||
|
Point::new(point.row + 1, 0),
|
||||||
|
snapshot.max_point(),
|
||||||
|
));
|
||||||
|
for chunk in context.buffer().read(cx).text_for_range(selection.range()) {
|
||||||
|
text.push_str(chunk);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
for chunk in context.buffer().read(cx).text_for_range(range) {
|
for chunk in context.buffer().read(cx).text_for_range(range) {
|
||||||
text.push_str(chunk);
|
text.push_str(chunk);
|
||||||
}
|
}
|
||||||
|
@ -3202,9 +3213,77 @@ pub fn make_lsp_adapter_delegate(
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use gpui::App;
|
use fs::FakeFs;
|
||||||
use language::Buffer;
|
use gpui::{App, TestAppContext, VisualTestContext};
|
||||||
|
use language::{Buffer, LanguageRegistry};
|
||||||
|
use prompt_store::PromptBuilder;
|
||||||
use unindent::Unindent;
|
use unindent::Unindent;
|
||||||
|
use util::path;
|
||||||
|
|
||||||
|
#[gpui::test]
|
||||||
|
async fn test_copy_paste_no_selection(cx: &mut TestAppContext) {
|
||||||
|
cx.update(init_test);
|
||||||
|
|
||||||
|
let fs = FakeFs::new(cx.executor());
|
||||||
|
let registry = Arc::new(LanguageRegistry::test(cx.executor()));
|
||||||
|
let prompt_builder = Arc::new(PromptBuilder::new(None).unwrap());
|
||||||
|
let context = cx.new(|cx| {
|
||||||
|
AssistantContext::local(
|
||||||
|
registry,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
prompt_builder.clone(),
|
||||||
|
Arc::new(SlashCommandWorkingSet::default()),
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
});
|
||||||
|
let project = Project::test(fs.clone(), [path!("/test").as_ref()], cx).await;
|
||||||
|
let window = cx.add_window(|window, cx| Workspace::test_new(project.clone(), window, cx));
|
||||||
|
let workspace = window.root(cx).unwrap();
|
||||||
|
let cx = &mut VisualTestContext::from_window(*window, cx);
|
||||||
|
|
||||||
|
let context_editor = window
|
||||||
|
.update(cx, |_, window, cx| {
|
||||||
|
cx.new(|cx| {
|
||||||
|
ContextEditor::for_context(
|
||||||
|
context,
|
||||||
|
fs,
|
||||||
|
workspace.downgrade(),
|
||||||
|
project,
|
||||||
|
None,
|
||||||
|
window,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
context_editor.update_in(cx, |context_editor, window, cx| {
|
||||||
|
context_editor.editor.update(cx, |editor, cx| {
|
||||||
|
editor.set_text("abc\ndef\nghi", window, cx);
|
||||||
|
editor.move_to_beginning(&Default::default(), window, cx);
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
context_editor.update_in(cx, |context_editor, window, cx| {
|
||||||
|
context_editor.editor.update(cx, |editor, cx| {
|
||||||
|
editor.copy(&Default::default(), window, cx);
|
||||||
|
editor.paste(&Default::default(), window, cx);
|
||||||
|
|
||||||
|
assert_eq!(editor.text(cx), "abc\nabc\ndef\nghi");
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
context_editor.update_in(cx, |context_editor, window, cx| {
|
||||||
|
context_editor.editor.update(cx, |editor, cx| {
|
||||||
|
editor.cut(&Default::default(), window, cx);
|
||||||
|
assert_eq!(editor.text(cx), "abc\ndef\nghi");
|
||||||
|
|
||||||
|
editor.paste(&Default::default(), window, cx);
|
||||||
|
assert_eq!(editor.text(cx), "abc\nabc\ndef\nghi");
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test]
|
||||||
fn test_find_code_blocks(cx: &mut App) {
|
fn test_find_code_blocks(cx: &mut App) {
|
||||||
|
@ -3279,4 +3358,17 @@ mod tests {
|
||||||
assert_eq!(range, expected, "unexpected result on row {:?}", row);
|
assert_eq!(range, expected, "unexpected result on row {:?}", row);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn init_test(cx: &mut App) {
|
||||||
|
let settings_store = SettingsStore::test(cx);
|
||||||
|
prompt_store::init(cx);
|
||||||
|
LanguageModelRegistry::test(cx);
|
||||||
|
cx.set_global(settings_store);
|
||||||
|
language::init(cx);
|
||||||
|
assistant_settings::init(cx);
|
||||||
|
Project::init_settings(cx);
|
||||||
|
theme::init(theme::LoadThemes::JustBase, cx);
|
||||||
|
workspace::init_settings(cx);
|
||||||
|
editor::init_settings(cx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue