|
|
|
@ -56,6 +56,14 @@ impl IndentStyle {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
|
pub fn indent_width(&self, tab_width: usize) -> usize {
|
|
|
|
|
match *self {
|
|
|
|
|
IndentStyle::Tabs => tab_width,
|
|
|
|
|
IndentStyle::Spaces(width) => width as usize,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Attempts to detect the indentation style used in a document.
|
|
|
|
@ -177,7 +185,7 @@ pub fn auto_detect_indent_style(document_text: &Rope) -> Option<IndentStyle> {
|
|
|
|
|
|
|
|
|
|
/// To determine indentation of a newly inserted line, figure out the indentation at the last col
|
|
|
|
|
/// of the previous line.
|
|
|
|
|
pub fn indent_level_for_line(line: RopeSlice, tab_width: usize) -> usize {
|
|
|
|
|
pub fn indent_level_for_line(line: RopeSlice, tab_width: usize, indent_width: usize) -> usize {
|
|
|
|
|
let mut len = 0;
|
|
|
|
|
for ch in line.chars() {
|
|
|
|
|
match ch {
|
|
|
|
@ -187,7 +195,7 @@ pub fn indent_level_for_line(line: RopeSlice, tab_width: usize) -> usize {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
len / tab_width
|
|
|
|
|
len / indent_width
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Computes for node and all ancestors whether they are the first node on their line.
|
|
|
|
@ -466,6 +474,7 @@ fn extend_nodes<'a>(
|
|
|
|
|
text: RopeSlice,
|
|
|
|
|
line: usize,
|
|
|
|
|
tab_width: usize,
|
|
|
|
|
indent_width: usize,
|
|
|
|
|
) {
|
|
|
|
|
let mut stop_extend = false;
|
|
|
|
|
|
|
|
|
@ -490,10 +499,12 @@ fn extend_nodes<'a>(
|
|
|
|
|
if deepest_preceding.end_position().row == line {
|
|
|
|
|
extend_node = true;
|
|
|
|
|
} else {
|
|
|
|
|
let cursor_indent = indent_level_for_line(text.line(line), tab_width);
|
|
|
|
|
let cursor_indent =
|
|
|
|
|
indent_level_for_line(text.line(line), tab_width, indent_width);
|
|
|
|
|
let node_indent = indent_level_for_line(
|
|
|
|
|
text.line(deepest_preceding.start_position().row),
|
|
|
|
|
tab_width,
|
|
|
|
|
indent_width,
|
|
|
|
|
);
|
|
|
|
|
if cursor_indent > node_indent {
|
|
|
|
|
extend_node = true;
|
|
|
|
@ -562,6 +573,7 @@ pub fn treesitter_indent_for_pos(
|
|
|
|
|
syntax: &Syntax,
|
|
|
|
|
indent_style: &IndentStyle,
|
|
|
|
|
tab_width: usize,
|
|
|
|
|
indent_width: usize,
|
|
|
|
|
text: RopeSlice,
|
|
|
|
|
line: usize,
|
|
|
|
|
pos: usize,
|
|
|
|
@ -622,6 +634,7 @@ pub fn treesitter_indent_for_pos(
|
|
|
|
|
text,
|
|
|
|
|
line,
|
|
|
|
|
tab_width,
|
|
|
|
|
indent_width,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
let mut first_in_line = get_first_in_line(node, new_line.then_some(byte_pos));
|
|
|
|
@ -709,6 +722,7 @@ pub fn indent_for_newline(
|
|
|
|
|
line_before_end_pos: usize,
|
|
|
|
|
current_line: usize,
|
|
|
|
|
) -> String {
|
|
|
|
|
let indent_width = indent_style.indent_width(tab_width);
|
|
|
|
|
if let (Some(query), Some(syntax)) = (
|
|
|
|
|
language_config.and_then(|config| config.indent_query()),
|
|
|
|
|
syntax,
|
|
|
|
@ -718,6 +732,7 @@ pub fn indent_for_newline(
|
|
|
|
|
syntax,
|
|
|
|
|
indent_style,
|
|
|
|
|
tab_width,
|
|
|
|
|
indent_width,
|
|
|
|
|
text,
|
|
|
|
|
line_before,
|
|
|
|
|
line_before_end_pos,
|
|
|
|
@ -726,7 +741,7 @@ pub fn indent_for_newline(
|
|
|
|
|
return indent;
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
let indent_level = indent_level_for_line(text.line(current_line), tab_width);
|
|
|
|
|
let indent_level = indent_level_for_line(text.line(current_line), tab_width, indent_width);
|
|
|
|
|
indent_style.as_str().repeat(indent_level)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -763,12 +778,22 @@ mod test {
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_indent_level() {
|
|
|
|
|
let tab_width = 4;
|
|
|
|
|
let indent_width = 4;
|
|
|
|
|
let line = Rope::from(" fn new"); // 8 spaces
|
|
|
|
|
assert_eq!(indent_level_for_line(line.slice(..), tab_width), 2);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
indent_level_for_line(line.slice(..), tab_width, indent_width),
|
|
|
|
|
2
|
|
|
|
|
);
|
|
|
|
|
let line = Rope::from("\t\t\tfn new"); // 3 tabs
|
|
|
|
|
assert_eq!(indent_level_for_line(line.slice(..), tab_width), 3);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
indent_level_for_line(line.slice(..), tab_width, indent_width),
|
|
|
|
|
3
|
|
|
|
|
);
|
|
|
|
|
// mixed indentation
|
|
|
|
|
let line = Rope::from("\t \tfn new"); // 1 tab, 4 spaces, tab
|
|
|
|
|
assert_eq!(indent_level_for_line(line.slice(..), tab_width), 3);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
indent_level_for_line(line.slice(..), tab_width, indent_width),
|
|
|
|
|
3
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|