diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index a3ad392547..eb3d6c2f8b 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -1382,6 +1382,7 @@ impl EditorElement { MAX_LINE_LEN, rows.len() as usize, line_number_layouts, + snapshot.mode, ) } } @@ -1728,6 +1729,7 @@ fn layout_highlighted_chunks<'a>( max_line_len: usize, max_line_count: usize, line_number_layouts: &[Option], + editor_mode: EditorMode, ) -> Vec { let mut layouts = Vec::with_capacity(max_line_count); let mut line = String::new(); @@ -1787,30 +1789,37 @@ fn layout_highlighted_chunks<'a>( }, )); - // Line wrap pads its contents with fake whitespaces, - // avoid printing them - let inside_wrapped_string = line_number_layouts[row].is_none(); - if highlighted_chunk.is_tab { - if non_whitespace_added || !inside_wrapped_string { - invisibles.push(Invisible::Tab { - line_start_offset: line.len(), - }); + if editor_mode == EditorMode::Full { + // Line wrap pads its contents with fake whitespaces, + // avoid printing them + let inside_wrapped_string = line_number_layouts + .get(row) + .and_then(|layout| layout.as_ref()) + .is_none(); + if highlighted_chunk.is_tab { + if non_whitespace_added || !inside_wrapped_string { + invisibles.push(Invisible::Tab { + line_start_offset: line.len(), + }); + } + } else { + invisibles.extend( + line_chunk + .chars() + .enumerate() + .filter(|(_, line_char)| { + let is_whitespace = line_char.is_whitespace(); + non_whitespace_added |= !is_whitespace; + is_whitespace + && (non_whitespace_added || !inside_wrapped_string) + }) + .map(|(whitespace_index, _)| Invisible::Whitespace { + line_offset: line.len() + whitespace_index, + }), + ) } - } else { - invisibles.extend( - line_chunk - .chars() - .enumerate() - .filter(|(_, line_char)| { - let is_whitespace = line_char.is_whitespace(); - non_whitespace_added |= !is_whitespace; - is_whitespace && (non_whitespace_added || !inside_wrapped_string) - }) - .map(|(whitespace_index, _)| Invisible::Whitespace { - line_offset: line.len() + whitespace_index, - }), - ) } + line.push_str(line_chunk); } } @@ -2925,4 +2934,56 @@ mod tests { assert_eq!(expected_invisibles, actual_invisibles); } + + #[gpui::test] + fn test_invisibles_dont_appear_in_certain_editors(cx: &mut TestAppContext) { + cx.update(|cx| { + let mut test_settings = Settings::test(cx); + test_settings.editor_defaults.show_whitespaces = Some(ShowWhitespaces::All); + test_settings.editor_defaults.tab_size = Some(NonZeroU32::new(4).unwrap()); + cx.set_global(test_settings); + }); + + for editor_mode_without_invisibles in [ + EditorMode::SingleLine, + EditorMode::AutoHeight { max_lines: 100 }, + ] { + let (_, editor) = cx.add_window(|cx| { + let buffer = MultiBuffer::build_simple("\t\t\t| | a b", cx); + Editor::new(editor_mode_without_invisibles, buffer, None, None, cx) + }); + + let mut element = + EditorElement::new(editor.read_with(cx, |editor, cx| editor.style(cx))); + let (_, layout_state) = editor.update(cx, |editor, cx| { + let mut new_parents = Default::default(); + let mut notify_views_if_parents_change = Default::default(); + let mut layout_cx = LayoutContext::new( + cx, + &mut new_parents, + &mut notify_views_if_parents_change, + false, + ); + element.layout( + SizeConstraint::new(vec2f(500., 500.), vec2f(500., 500.)), + editor, + &mut layout_cx, + ) + }); + + let line_layouts = &layout_state.position_map.line_layouts; + let invisibles = line_layouts + .iter() + .map(|line_with_invisibles| &line_with_invisibles.invisibles) + .flatten() + .sorted_by(|invisible_1, invisible_2| { + invisible_1.offset().cmp(&invisible_2.offset()) + }) + .cloned() + .collect::>(); + + assert!(invisibles.is_empty(), + "For editor mode {editor_mode_without_invisibles:?} no invisibles was expected but got {invisibles:?}"); + } + } }