Add basic support for ruby

Co-authored-by: Kay Simmons <kay@zed.dev>
This commit is contained in:
Max Brunsfeld 2022-11-01 15:36:47 -07:00
parent 9f3ea0c87f
commit d222904471
13 changed files with 349 additions and 7 deletions

View file

@ -1764,6 +1764,7 @@ impl BufferSnapshot {
.collect::<Vec<_>>();
let mut indent_ranges = Vec::<Range<Point>>::new();
let mut outdent_positions = Vec::<Point>::new();
while let Some(mat) = matches.peek() {
let mut start: Option<Point> = None;
let mut end: Option<Point> = None;
@ -1777,6 +1778,8 @@ impl BufferSnapshot {
start = Some(Point::from_ts_point(capture.node.end_position()));
} else if Some(capture.index) == config.end_capture_ix {
end = Some(Point::from_ts_point(capture.node.start_position()));
} else if Some(capture.index) == config.outdent_capture_ix {
outdent_positions.push(Point::from_ts_point(capture.node.start_position()));
}
}
@ -1797,6 +1800,19 @@ impl BufferSnapshot {
}
}
outdent_positions.sort();
for outdent_position in outdent_positions {
// find the innermost indent range containing this outdent_position
// set its end to the outdent position
if let Some(range_to_truncate) = indent_ranges
.iter_mut()
.filter(|indent_range| indent_range.contains(&outdent_position))
.last()
{
range_to_truncate.end = outdent_position;
}
}
// Find the suggested indentation increases and decreased based on regexes.
let mut indent_change_rows = Vec::<(u32, Ordering)>::new();
self.for_each_line(

View file

@ -1150,6 +1150,49 @@ fn test_autoindent_with_injected_languages(cx: &mut MutableAppContext) {
});
}
#[gpui::test]
fn test_autoindent_query_with_outdent_captures(cx: &mut MutableAppContext) {
let mut settings = Settings::test(cx);
settings.editor_defaults.tab_size = Some(2.try_into().unwrap());
cx.set_global(settings);
cx.add_model(|cx| {
let mut buffer = Buffer::new(0, "", cx).with_language(Arc::new(ruby_lang()), cx);
let text = r#"
class C
def a(b, c)
puts b
puts c
rescue
puts "errored"
exit 1
end
end
"#
.unindent();
buffer.edit([(0..0, text)], Some(AutoindentMode::EachLine), cx);
assert_eq!(
buffer.text(),
r#"
class C
def a(b, c)
puts b
puts c
rescue
puts "errored"
exit 1
end
end
"#
.unindent()
);
buffer
});
}
#[gpui::test]
fn test_serialization(cx: &mut gpui::MutableAppContext) {
let mut now = Instant::now();
@ -1497,6 +1540,26 @@ impl Buffer {
}
}
fn ruby_lang() -> Language {
Language::new(
LanguageConfig {
name: "Ruby".into(),
path_suffixes: vec!["rb".to_string()],
..Default::default()
},
Some(tree_sitter_ruby::language()),
)
.with_indents_query(
r#"
(class "end" @end) @indent
(method "end" @end) @indent
(rescue) @outdent
(then) @indent
"#,
)
.unwrap()
}
fn rust_lang() -> Language {
Language::new(
LanguageConfig {

View file

@ -312,6 +312,7 @@ struct IndentConfig {
indent_capture_ix: u32,
start_capture_ix: Option<u32>,
end_capture_ix: Option<u32>,
outdent_capture_ix: Option<u32>,
}
struct OutlineConfig {
@ -670,12 +671,14 @@ impl Language {
let mut indent_capture_ix = None;
let mut start_capture_ix = None;
let mut end_capture_ix = None;
let mut outdent_capture_ix = None;
get_capture_indices(
&query,
&mut [
("indent", &mut indent_capture_ix),
("start", &mut start_capture_ix),
("end", &mut end_capture_ix),
("outdent", &mut outdent_capture_ix),
],
);
if let Some(indent_capture_ix) = indent_capture_ix {
@ -684,6 +687,7 @@ impl Language {
indent_capture_ix,
start_capture_ix,
end_capture_ix,
outdent_capture_ix,
});
}
Ok(self)