Restructure workflow step resolution and fix inserting newlines (#15720)
Release Notes: - N/A --------- Co-authored-by: Nathan <nathan@zed.dev>
This commit is contained in:
parent
49e736d8ef
commit
0ec29d6866
18 changed files with 1316 additions and 815 deletions
|
@ -53,6 +53,7 @@ settings.workspace = true
|
|||
similar.workspace = true
|
||||
smallvec.workspace = true
|
||||
smol.workspace = true
|
||||
strsim.workspace = true
|
||||
sum_tree.workspace = true
|
||||
task.workspace = true
|
||||
text.workspace = true
|
||||
|
|
|
@ -1876,6 +1876,63 @@ impl Buffer {
|
|||
cx.notify();
|
||||
}
|
||||
|
||||
// Inserts newlines at the given position to create an empty line, returning the start of the new line.
|
||||
// You can also request the insertion of empty lines above and below the line starting at the returned point.
|
||||
pub fn insert_empty_line(
|
||||
&mut self,
|
||||
position: impl ToPoint,
|
||||
space_above: bool,
|
||||
space_below: bool,
|
||||
cx: &mut ModelContext<Self>,
|
||||
) -> Point {
|
||||
let mut position = position.to_point(self);
|
||||
|
||||
self.start_transaction();
|
||||
|
||||
self.edit(
|
||||
[(position..position, "\n")],
|
||||
Some(AutoindentMode::EachLine),
|
||||
cx,
|
||||
);
|
||||
|
||||
if position.column > 0 {
|
||||
position += Point::new(1, 0);
|
||||
}
|
||||
|
||||
if !self.is_line_blank(position.row) {
|
||||
self.edit(
|
||||
[(position..position, "\n")],
|
||||
Some(AutoindentMode::EachLine),
|
||||
cx,
|
||||
);
|
||||
}
|
||||
|
||||
if space_above {
|
||||
if position.row > 0 && !self.is_line_blank(position.row - 1) {
|
||||
self.edit(
|
||||
[(position..position, "\n")],
|
||||
Some(AutoindentMode::EachLine),
|
||||
cx,
|
||||
);
|
||||
position.row += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if space_below {
|
||||
if position.row == self.max_point().row || !self.is_line_blank(position.row + 1) {
|
||||
self.edit(
|
||||
[(position..position, "\n")],
|
||||
Some(AutoindentMode::EachLine),
|
||||
cx,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
self.end_transaction(cx);
|
||||
|
||||
position
|
||||
}
|
||||
|
||||
/// Applies the given remote operations to the buffer.
|
||||
pub fn apply_ops<I: IntoIterator<Item = Operation>>(
|
||||
&mut self,
|
||||
|
|
|
@ -1822,6 +1822,92 @@ fn test_autoindent_query_with_outdent_captures(cx: &mut AppContext) {
|
|||
});
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
fn test_insert_empty_line(cx: &mut AppContext) {
|
||||
init_settings(cx, |_| {});
|
||||
|
||||
// Insert empty line at the beginning, requesting an empty line above
|
||||
cx.new_model(|cx| {
|
||||
let mut buffer = Buffer::local("abc\ndef\nghi", cx);
|
||||
let point = buffer.insert_empty_line(Point::new(0, 0), true, false, cx);
|
||||
assert_eq!(buffer.text(), "\nabc\ndef\nghi");
|
||||
assert_eq!(point, Point::new(0, 0));
|
||||
buffer
|
||||
});
|
||||
|
||||
// Insert empty line at the beginning, requesting an empty line above and below
|
||||
cx.new_model(|cx| {
|
||||
let mut buffer = Buffer::local("abc\ndef\nghi", cx);
|
||||
let point = buffer.insert_empty_line(Point::new(0, 0), true, true, cx);
|
||||
assert_eq!(buffer.text(), "\n\nabc\ndef\nghi");
|
||||
assert_eq!(point, Point::new(0, 0));
|
||||
buffer
|
||||
});
|
||||
|
||||
// Insert empty line at the start of a line, requesting empty lines above and below
|
||||
cx.new_model(|cx| {
|
||||
let mut buffer = Buffer::local("abc\ndef\nghi", cx);
|
||||
let point = buffer.insert_empty_line(Point::new(2, 0), true, true, cx);
|
||||
assert_eq!(buffer.text(), "abc\ndef\n\n\n\nghi");
|
||||
assert_eq!(point, Point::new(3, 0));
|
||||
buffer
|
||||
});
|
||||
|
||||
// Insert empty line in the middle of a line, requesting empty lines above and below
|
||||
cx.new_model(|cx| {
|
||||
let mut buffer = Buffer::local("abc\ndefghi\njkl", cx);
|
||||
let point = buffer.insert_empty_line(Point::new(1, 3), true, true, cx);
|
||||
assert_eq!(buffer.text(), "abc\ndef\n\n\n\nghi\njkl");
|
||||
assert_eq!(point, Point::new(3, 0));
|
||||
buffer
|
||||
});
|
||||
|
||||
// Insert empty line in the middle of a line, requesting empty line above only
|
||||
cx.new_model(|cx| {
|
||||
let mut buffer = Buffer::local("abc\ndefghi\njkl", cx);
|
||||
let point = buffer.insert_empty_line(Point::new(1, 3), true, false, cx);
|
||||
assert_eq!(buffer.text(), "abc\ndef\n\n\nghi\njkl");
|
||||
assert_eq!(point, Point::new(3, 0));
|
||||
buffer
|
||||
});
|
||||
|
||||
// Insert empty line in the middle of a line, requesting empty line below only
|
||||
cx.new_model(|cx| {
|
||||
let mut buffer = Buffer::local("abc\ndefghi\njkl", cx);
|
||||
let point = buffer.insert_empty_line(Point::new(1, 3), false, true, cx);
|
||||
assert_eq!(buffer.text(), "abc\ndef\n\n\nghi\njkl");
|
||||
assert_eq!(point, Point::new(2, 0));
|
||||
buffer
|
||||
});
|
||||
|
||||
// Insert empty line at the end, requesting empty lines above and below
|
||||
cx.new_model(|cx| {
|
||||
let mut buffer = Buffer::local("abc\ndef\nghi", cx);
|
||||
let point = buffer.insert_empty_line(Point::new(2, 3), true, true, cx);
|
||||
assert_eq!(buffer.text(), "abc\ndef\nghi\n\n\n");
|
||||
assert_eq!(point, Point::new(4, 0));
|
||||
buffer
|
||||
});
|
||||
|
||||
// Insert empty line at the end, requesting empty line above only
|
||||
cx.new_model(|cx| {
|
||||
let mut buffer = Buffer::local("abc\ndef\nghi", cx);
|
||||
let point = buffer.insert_empty_line(Point::new(2, 3), true, false, cx);
|
||||
assert_eq!(buffer.text(), "abc\ndef\nghi\n\n");
|
||||
assert_eq!(point, Point::new(4, 0));
|
||||
buffer
|
||||
});
|
||||
|
||||
// Insert empty line at the end, requesting empty line below only
|
||||
cx.new_model(|cx| {
|
||||
let mut buffer = Buffer::local("abc\ndef\nghi", cx);
|
||||
let point = buffer.insert_empty_line(Point::new(2, 3), false, true, cx);
|
||||
assert_eq!(buffer.text(), "abc\ndef\nghi\n\n");
|
||||
assert_eq!(point, Point::new(3, 0));
|
||||
buffer
|
||||
});
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
fn test_language_scope_at_with_javascript(cx: &mut AppContext) {
|
||||
init_settings(cx, |_| {});
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use crate::{BufferSnapshot, Point, ToPoint};
|
||||
use fuzzy::{StringMatch, StringMatchCandidate};
|
||||
use gpui::{relative, AppContext, BackgroundExecutor, HighlightStyle, StyledText, TextStyle};
|
||||
use settings::Settings;
|
||||
|
@ -24,6 +25,27 @@ pub struct OutlineItem<T> {
|
|||
pub annotation_range: Option<Range<T>>,
|
||||
}
|
||||
|
||||
impl<T: ToPoint> OutlineItem<T> {
|
||||
/// Converts to an equivalent outline item, but with parameterized over Points.
|
||||
pub fn to_point(&self, buffer: &BufferSnapshot) -> OutlineItem<Point> {
|
||||
OutlineItem {
|
||||
depth: self.depth,
|
||||
range: self.range.start.to_point(buffer)..self.range.end.to_point(buffer),
|
||||
text: self.text.clone(),
|
||||
highlight_ranges: self.highlight_ranges.clone(),
|
||||
name_ranges: self.name_ranges.clone(),
|
||||
body_range: self
|
||||
.body_range
|
||||
.as_ref()
|
||||
.map(|r| r.start.to_point(buffer)..r.end.to_point(buffer)),
|
||||
annotation_range: self
|
||||
.annotation_range
|
||||
.as_ref()
|
||||
.map(|r| r.start.to_point(buffer)..r.end.to_point(buffer)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Outline<T> {
|
||||
pub fn new(items: Vec<OutlineItem<T>>) -> Self {
|
||||
let mut candidates = Vec::new();
|
||||
|
@ -62,6 +84,16 @@ impl<T> Outline<T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Find the most similar symbol to the provided query according to the Jaro-Winkler distance measure.
|
||||
pub fn find_most_similar(&self, query: &str) -> Option<&OutlineItem<T>> {
|
||||
let candidate = self.path_candidates.iter().max_by(|a, b| {
|
||||
strsim::jaro_winkler(&a.string, query)
|
||||
.total_cmp(&strsim::jaro_winkler(&b.string, query))
|
||||
})?;
|
||||
Some(&self.items[candidate.id])
|
||||
}
|
||||
|
||||
/// Find all outline symbols according to a longest subsequence match with the query, ordered descending by match score.
|
||||
pub async fn search(&self, query: &str, executor: BackgroundExecutor) -> Vec<StringMatch> {
|
||||
let query = query.trim_start();
|
||||
let is_path_query = query.contains(' ');
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue