Compare commits

...

1 Commits

Author SHA1 Message Date
Ben Kunkle
0e6f44d87c wip - vim syntax node objects 2025-09-24 11:01:44 -04:00

View File

@@ -37,6 +37,7 @@ pub enum Object {
SquareBrackets, SquareBrackets,
CurlyBrackets, CurlyBrackets,
AngleBrackets, AngleBrackets,
SyntaxNode,
Argument, Argument,
IndentObj { include_below: bool }, IndentObj { include_below: bool },
Tag, Tag,
@@ -276,7 +277,10 @@ actions!(
Method, Method,
Class, Class,
Comment, Comment,
EntireFile /// Selects the entire file.
EntireFile,
/// Selects a syntax node.
SyntaxNode,
] ]
); );
@@ -368,6 +372,9 @@ pub fn register(editor: &mut Editor, cx: &mut Context<Vim>) {
vim.object(Object::IndentObj { include_below }, window, cx) vim.object(Object::IndentObj { include_below }, window, cx)
}, },
); );
Vim::action(editor, cx, |vim, _: &SyntaxNode, window, cx| {
vim.object(Object::SyntaxNode, window, cx);
});
} }
impl Vim { impl Vim {
@@ -409,7 +416,8 @@ impl Object {
| Object::Class | Object::Class
| Object::EntireFile | Object::EntireFile
| Object::Comment | Object::Comment
| Object::IndentObj { .. } => true, | Object::IndentObj { .. }
| Object::SyntaxNode => true,
} }
} }
@@ -437,7 +445,8 @@ impl Object {
| Object::Comment | Object::Comment
| Object::EntireFile | Object::EntireFile
| Object::CurlyBrackets | Object::CurlyBrackets
| Object::AngleBrackets => true, | Object::AngleBrackets
| Object::SyntaxNode => true,
} }
} }
@@ -467,7 +476,8 @@ impl Object {
| Object::Tag | Object::Tag
| Object::Comment | Object::Comment
| Object::Argument | Object::Argument
| Object::IndentObj { .. } => Mode::Visual, | Object::IndentObj { .. }
| Object::SyntaxNode => Mode::Visual,
Object::Method | Object::Class => { Object::Method | Object::Class => {
if around { if around {
Mode::VisualLine Mode::VisualLine
@@ -683,6 +693,13 @@ impl Object {
Object::Argument => argument(map, relative_to, around), Object::Argument => argument(map, relative_to, around),
Object::IndentObj { include_below } => indent(map, relative_to, around, include_below), Object::IndentObj { include_below } => indent(map, relative_to, around, include_below),
Object::EntireFile => entire_file(map), Object::EntireFile => entire_file(map),
Object::SyntaxNode => {
if around {
larger_syntax_node(map, selection, times.unwrap_or(1))
} else {
smaller_syntax_node(map, selection, times.unwrap_or(1))
}
}
} }
} }
@@ -1654,6 +1671,61 @@ fn surrounding_markers(
) )
} }
fn smaller_syntax_node(
map: &DisplaySnapshot,
selection: Selection<DisplayPoint>,
unwrap_or: usize,
) -> Option<Range<DisplayPoint>> {
todo!("take in editor and use ")
}
fn larger_syntax_node(
map: &DisplaySnapshot,
selection: Selection<DisplayPoint>,
count: usize,
) -> Option<Range<DisplayPoint>> {
let selection = selection.map(|p| {
map.display_point_to_anchor(p, Bias::Left)
.to_offset(&map.buffer_snapshot)
});
let old_range = selection.start..selection.end;
let buffer = &map.buffer_snapshot;
if let Some((node, _)) = buffer.syntax_ancestor(old_range.clone()) {
// manually select word at selection
if ["string_content", "inline"].contains(&node.kind()) {
let (word_range, _) = buffer.surrounding_word(old_range.start, None);
// ignore if word is already selected
if !word_range.is_empty() && old_range != word_range {
let (last_word_range, _) = buffer.surrounding_word(old_range.end, None);
// only select word if start and end point belongs to same word
if word_range == last_word_range {
return Some(
word_range.start.to_display_point(map)
..word_range.end.to_display_point(map),
);
}
}
}
}
let mut new_range = old_range.clone();
while let Some((node, containing_range)) = buffer.syntax_ancestor(new_range.clone()) {
new_range = match containing_range {
multi_buffer::MultiOrSingleBufferOffsetRange::Single(_) => break,
multi_buffer::MultiOrSingleBufferOffsetRange::Multi(range) => range,
};
if !node.is_named() {
continue;
}
if !map.intersects_fold(new_range.start) && !map.intersects_fold(new_range.end) {
break;
}
}
return Some(new_range.start.to_display_point(map)..new_range.end.to_display_point(map));
}
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use gpui::KeyBinding; use gpui::KeyBinding;