Add a way to copy with the selections trimmed (#27206)
No default binding currently, `cmd/ctr-shift-c` seem somewhat natural but those are occupied by the collab panel. https://github.com/user-attachments/assets/702cc52a-a4b7-4f2c-bb7f-12ca0c66faeb Release Notes: - Added a way to copy with the selections trimmed --------- Co-authored-by: Cole Miller <m@cole-miller.net>
This commit is contained in:
parent
a74f2bb18b
commit
9609e04bb2
4 changed files with 231 additions and 13 deletions
|
@ -4918,6 +4918,180 @@ async fn test_clipboard(cx: &mut TestAppContext) {
|
|||
tˇhe lazy dog"});
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_copy_trim(cx: &mut TestAppContext) {
|
||||
init_test(cx, |_| {});
|
||||
|
||||
let mut cx = EditorTestContext::new(cx).await;
|
||||
cx.set_state(
|
||||
r#" «for selection in selections.iter() {
|
||||
let mut start = selection.start;
|
||||
let mut end = selection.end;
|
||||
let is_entire_line = selection.is_empty() || self.selections.line_mode;
|
||||
if is_entire_line {
|
||||
start = Point::new(start.row, 0);ˇ»
|
||||
end = cmp::min(max_point, Point::new(end.row + 1, 0));
|
||||
}
|
||||
"#,
|
||||
);
|
||||
cx.update_editor(|e, window, cx| e.copy(&Copy, window, cx));
|
||||
assert_eq!(
|
||||
cx.read_from_clipboard()
|
||||
.and_then(|item| item.text().as_deref().map(str::to_string)),
|
||||
Some(
|
||||
"for selection in selections.iter() {
|
||||
let mut start = selection.start;
|
||||
let mut end = selection.end;
|
||||
let is_entire_line = selection.is_empty() || self.selections.line_mode;
|
||||
if is_entire_line {
|
||||
start = Point::new(start.row, 0);"
|
||||
.to_string()
|
||||
),
|
||||
"Regular copying preserves all indentation selected",
|
||||
);
|
||||
cx.update_editor(|e, window, cx| e.copy_and_trim(&CopyAndTrim, window, cx));
|
||||
assert_eq!(
|
||||
cx.read_from_clipboard()
|
||||
.and_then(|item| item.text().as_deref().map(str::to_string)),
|
||||
Some(
|
||||
"for selection in selections.iter() {
|
||||
let mut start = selection.start;
|
||||
let mut end = selection.end;
|
||||
let is_entire_line = selection.is_empty() || self.selections.line_mode;
|
||||
if is_entire_line {
|
||||
start = Point::new(start.row, 0);"
|
||||
.to_string()
|
||||
),
|
||||
"Copying with stripping should strip all leading whitespaces"
|
||||
);
|
||||
|
||||
cx.set_state(
|
||||
r#" « for selection in selections.iter() {
|
||||
let mut start = selection.start;
|
||||
let mut end = selection.end;
|
||||
let is_entire_line = selection.is_empty() || self.selections.line_mode;
|
||||
if is_entire_line {
|
||||
start = Point::new(start.row, 0);ˇ»
|
||||
end = cmp::min(max_point, Point::new(end.row + 1, 0));
|
||||
}
|
||||
"#,
|
||||
);
|
||||
cx.update_editor(|e, window, cx| e.copy(&Copy, window, cx));
|
||||
assert_eq!(
|
||||
cx.read_from_clipboard()
|
||||
.and_then(|item| item.text().as_deref().map(str::to_string)),
|
||||
Some(
|
||||
" for selection in selections.iter() {
|
||||
let mut start = selection.start;
|
||||
let mut end = selection.end;
|
||||
let is_entire_line = selection.is_empty() || self.selections.line_mode;
|
||||
if is_entire_line {
|
||||
start = Point::new(start.row, 0);"
|
||||
.to_string()
|
||||
),
|
||||
"Regular copying preserves all indentation selected",
|
||||
);
|
||||
cx.update_editor(|e, window, cx| e.copy_and_trim(&CopyAndTrim, window, cx));
|
||||
assert_eq!(
|
||||
cx.read_from_clipboard()
|
||||
.and_then(|item| item.text().as_deref().map(str::to_string)),
|
||||
Some(
|
||||
"for selection in selections.iter() {
|
||||
let mut start = selection.start;
|
||||
let mut end = selection.end;
|
||||
let is_entire_line = selection.is_empty() || self.selections.line_mode;
|
||||
if is_entire_line {
|
||||
start = Point::new(start.row, 0);"
|
||||
.to_string()
|
||||
),
|
||||
"Copying with stripping should strip all leading whitespaces, even if some of it was selected"
|
||||
);
|
||||
|
||||
cx.set_state(
|
||||
r#" «ˇ for selection in selections.iter() {
|
||||
let mut start = selection.start;
|
||||
let mut end = selection.end;
|
||||
let is_entire_line = selection.is_empty() || self.selections.line_mode;
|
||||
if is_entire_line {
|
||||
start = Point::new(start.row, 0);»
|
||||
end = cmp::min(max_point, Point::new(end.row + 1, 0));
|
||||
}
|
||||
"#,
|
||||
);
|
||||
cx.update_editor(|e, window, cx| e.copy(&Copy, window, cx));
|
||||
assert_eq!(
|
||||
cx.read_from_clipboard()
|
||||
.and_then(|item| item.text().as_deref().map(str::to_string)),
|
||||
Some(
|
||||
" for selection in selections.iter() {
|
||||
let mut start = selection.start;
|
||||
let mut end = selection.end;
|
||||
let is_entire_line = selection.is_empty() || self.selections.line_mode;
|
||||
if is_entire_line {
|
||||
start = Point::new(start.row, 0);"
|
||||
.to_string()
|
||||
),
|
||||
"Regular copying for reverse selection works the same",
|
||||
);
|
||||
cx.update_editor(|e, window, cx| e.copy_and_trim(&CopyAndTrim, window, cx));
|
||||
assert_eq!(
|
||||
cx.read_from_clipboard()
|
||||
.and_then(|item| item.text().as_deref().map(str::to_string)),
|
||||
Some(
|
||||
"for selection in selections.iter() {
|
||||
let mut start = selection.start;
|
||||
let mut end = selection.end;
|
||||
let is_entire_line = selection.is_empty() || self.selections.line_mode;
|
||||
if is_entire_line {
|
||||
start = Point::new(start.row, 0);"
|
||||
.to_string()
|
||||
),
|
||||
"Copying with stripping for reverse selection works the same"
|
||||
);
|
||||
|
||||
cx.set_state(
|
||||
r#" for selection «in selections.iter() {
|
||||
let mut start = selection.start;
|
||||
let mut end = selection.end;
|
||||
let is_entire_line = selection.is_empty() || self.selections.line_mode;
|
||||
if is_entire_line {
|
||||
start = Point::new(start.row, 0);ˇ»
|
||||
end = cmp::min(max_point, Point::new(end.row + 1, 0));
|
||||
}
|
||||
"#,
|
||||
);
|
||||
cx.update_editor(|e, window, cx| e.copy(&Copy, window, cx));
|
||||
assert_eq!(
|
||||
cx.read_from_clipboard()
|
||||
.and_then(|item| item.text().as_deref().map(str::to_string)),
|
||||
Some(
|
||||
"in selections.iter() {
|
||||
let mut start = selection.start;
|
||||
let mut end = selection.end;
|
||||
let is_entire_line = selection.is_empty() || self.selections.line_mode;
|
||||
if is_entire_line {
|
||||
start = Point::new(start.row, 0);"
|
||||
.to_string()
|
||||
),
|
||||
"When selecting past the indent, the copying works as usual",
|
||||
);
|
||||
cx.update_editor(|e, window, cx| e.copy_and_trim(&CopyAndTrim, window, cx));
|
||||
assert_eq!(
|
||||
cx.read_from_clipboard()
|
||||
.and_then(|item| item.text().as_deref().map(str::to_string)),
|
||||
Some(
|
||||
"in selections.iter() {
|
||||
let mut start = selection.start;
|
||||
let mut end = selection.end;
|
||||
let is_entire_line = selection.is_empty() || self.selections.line_mode;
|
||||
if is_entire_line {
|
||||
start = Point::new(start.row, 0);"
|
||||
.to_string()
|
||||
),
|
||||
"When selecting past the indent, nothing is trimmed"
|
||||
);
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_paste_multiline(cx: &mut TestAppContext) {
|
||||
init_test(cx, |_| {});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue