on master help sign in
Improve statusline (#916)
2505802Omnikar
helix-term/src/ui/editor.rs+70−27
@@ -548,6 +548,8 @@ impl EditorView {
548 theme: &Theme,
548 theme: &Theme,
549 is_focused: bool,
549 is_focused: bool,
550 ) {
550 ) {
551+ use tui::text::{Span, Spans};
552+
551 //-------------------------------
553 //-------------------------------
552 // Left side of the status line.
554 // Left side of the status line.
553 //-------------------------------
555 //-------------------------------
@@ -566,17 +568,17 @@ impl EditorView {
566 })
568 })
567 .unwrap_or("");
569 .unwrap_or("");
568
570
569− let style = if is_focused {
571+ let base_style = if is_focused {
570 theme.get("ui.statusline")
572 theme.get("ui.statusline")
571 } else {
573 } else {
572 theme.get("ui.statusline.inactive")
574 theme.get("ui.statusline.inactive")
573 };
575 };
574 // statusline
576 // statusline
575− surface.set_style(viewport.with_height(1), style);
577+ surface.set_style(viewport.with_height(1), base_style);
576 if is_focused {
578 if is_focused {
577− surface.set_string(viewport.x + 1, viewport.y, mode, style);
579+ surface.set_string(viewport.x + 1, viewport.y, mode, base_style);
578 }
580 }
579− surface.set_string(viewport.x + 5, viewport.y, progress, style);
581+ surface.set_string(viewport.x + 5, viewport.y, progress, base_style);
580
582
581 if let Some(path) = doc.relative_path() {
583 if let Some(path) = doc.relative_path() {
582 let path = path.to_string_lossy();
584 let path = path.to_string_lossy();
@@ -587,7 +589,7 @@ impl EditorView {
587 viewport.y,
589 viewport.y,
588 title,
590 title,
589 viewport.width.saturating_sub(6) as usize,
591 viewport.width.saturating_sub(6) as usize,
590− style,
592+ base_style,
591 );
593 );
592 }
594 }
593
595
@@ -595,8 +597,50 @@ impl EditorView {
595 // Right side of the status line.
597 // Right side of the status line.
596 //-------------------------------
598 //-------------------------------
597
599
600+ let mut right_side_text = Spans::default();
601+
598− // Compute the individual info strings.
602+ // Compute the individual info strings and add them to `right_side_text`.
603+
604+ // Diagnostics
599− let diag_count = format!("{}", doc.diagnostics().len());
605+ let diags = doc.diagnostics().iter().fold((0, 0), |mut counts, diag| {
606+ use helix_core::diagnostic::Severity;
607+ match diag.severity {
608+ Some(Severity::Warning) => counts.0 += 1,
609+ Some(Severity::Error) | None => counts.1 += 1,
610+ _ => {}
611+ }
612+ counts
613+ });
614+ let (warnings, errors) = diags;
615+ let warning_style = theme.get("warning");
616+ let error_style = theme.get("error");
617+ for i in 0..2 {
618+ let (count, style) = match i {
619+ 0 => (warnings, warning_style),
620+ 1 => (errors, error_style),
621+ _ => unreachable!(),
622+ };
623+ if count == 0 {
624+ continue;
625+ }
626+ let style = base_style.patch(style);
627+ right_side_text.0.push(Span::styled("●", style));
628+ right_side_text
629+ .0
630+ .push(Span::styled(format!(" {} ", count), base_style));
631+ }
632+
633+ // Selections
634+ let sels_count = doc.selection(view.id).len();
635+ right_side_text.0.push(Span::styled(
636+ format!(
637+ " {} sel{} ",
638+ sels_count,
639+ if sels_count == 1 { "" } else { "s" }
640+ ),
641+ base_style,
642+ ));
643+
600 // let indent_info = match doc.indent_style {
644 // let indent_info = match doc.indent_style {
601 // IndentStyle::Tabs => "tabs",
645 // IndentStyle::Tabs => "tabs",
602 // IndentStyle::Spaces(1) => "spaces:1",
646 // IndentStyle::Spaces(1) => "spaces:1",
@@ -609,29 +653,28 @@ impl EditorView {
609 // IndentStyle::Spaces(8) => "spaces:8",
653 // IndentStyle::Spaces(8) => "spaces:8",
610 // _ => "indent:ERROR",
654 // _ => "indent:ERROR",
611 // };
655 // };
612− let position_info = {
613− let pos = coords_at_pos(
614− doc.text().slice(..),
615− doc.selection(view.id)
616− .primary()
617− .cursor(doc.text().slice(..)),
618− );
619− format!("{}:{}", pos.row + 1, pos.col + 1) // convert to 1-indexing
620− };
621
656
622− // Render them to the status line together.
657+ // Position
623− let right_side_text = format!(
658+ let pos = coords_at_pos(
624− "{} {} ",
659+ doc.text().slice(..),
625− &diag_count[..diag_count.len().min(4)],
660+ doc.selection(view.id)
626− // indent_info,
661+ .primary()
627− position_info
662+ .cursor(doc.text().slice(..)),
628 );
663 );
629− let text_len = right_side_text.len() as u16;
664+ right_side_text.0.push(Span::styled(
665+ format!(" {}:{} ", pos.row + 1, pos.col + 1), // Convert to 1-indexing.
666+ base_style,
667+ ));
668+
669+ // Render to the statusline.
630− surface.set_string(
670+ surface.set_spans(
631− viewport.x + viewport.width.saturating_sub(text_len),
671+ viewport.x
672+ + viewport
673+ .width
674+ .saturating_sub(right_side_text.width() as u16),
632 viewport.y,
675 viewport.y,
633− right_side_text,
676+ &right_side_text,
634− style,
677+ right_side_text.width() as u16,
635 );
678 );
636 }
679 }
637
680