@@ -401,6 +401,23 @@ impl EditorView {
401401 let text_style = theme.get("ui.text");
402402 let whitespace_style = theme.get("ui.virtual.whitespace");
403403
404+ let mut is_in_indent_area = true;
405+ let mut last_line_indent_level = 0;
406+ let indent_style = theme
407+ .try_get("ui.virtual.indent-guide")
408+ .unwrap_or_else(|| theme.get("comment"));
409+
410+ let draw_indent_guides = |indent_level, line, surface: &mut Surface| {
411+ for i in 0..(indent_level / tab_width as u16) {
412+ surface.set_string(
413+ viewport.x + (i * tab_width as u16) - offset.col as u16,
414+ viewport.y + line,
415+ "│",
416+ indent_style,
417+ );
418+ }
419+ };
420+
404421 'outer: for event in highlights {
405422 match event {
406423 HighlightEvent::HighlightStart(span) => {
@@ -453,8 +470,18 @@ impl EditorView {
453470 );
454471 }
455472
473+ // This is an empty line; draw indent guides at previous line's
474+ // indent level to avoid breaking the guides on blank lines.
475+ if visual_x == 0 {
476+ draw_indent_guides(last_line_indent_level, line, surface);
477+ } else if is_in_indent_area {
478+ // A line with whitespace only
479+ draw_indent_guides(visual_x, line, surface);
480+ }
481+
456482 visual_x = 0;
457483 line += 1;
484+ is_in_indent_area = true;
458485
459486 // TODO: with proper iter this shouldn't be necessary
460487 if line >= viewport.height {
@@ -499,6 +526,11 @@ impl EditorView {
499526 },
500527 );
501528 }
529+ if is_in_indent_area && !(grapheme == " " || grapheme == "\t") {
530+ draw_indent_guides(visual_x, line, surface);
531+ is_in_indent_area = false;
532+ last_line_indent_level = visual_x;
533+ }
502534
503535 visual_x = visual_x.saturating_add(width as u16);
504536 }