diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs index fd8e8fb2..09050ca8 100644 --- a/helix-term/src/ui/editor.rs +++ b/helix-term/src/ui/editor.rs @@ -531,8 +531,24 @@ impl EditorView { let mut x = viewport.x; let current_doc = view!(editor).doc; + let config = editor.config(); + let icons_enabled = config.icons.bufferline; for doc in editor.documents() { + let filetype_icon = doc + .language_config() + .and_then(|config| { + config + .file_types + .iter() + .map(|filetype| match filetype { + helix_core::syntax::FileType::Extension(s) => s, + helix_core::syntax::FileType::Suffix(s) => s, + }) + .find_map(|filetype| editor.icons.icon_from_filetype(filetype)) + }) + .or_else(|| editor.icons.icon_from_path(doc.path())); + let fname = doc .path() .unwrap_or(&scratch) @@ -551,6 +567,22 @@ impl EditorView { let used_width = viewport.x.saturating_sub(x); let rem_width = surface.area.width.saturating_sub(used_width); + if icons_enabled { + if let Some(icon) = filetype_icon { + x = surface + .set_stringn( + x, + viewport.y, + format!(" {}", icon.icon_char), + rem_width as usize, + match icon.style { + Some(s) => style.patch(s.into()), + None => style, + }, + ) + .0; + } + } x = surface .set_stringn(x, viewport.y, text, rem_width as usize, style) .0; diff --git a/helix-term/src/ui/statusline.rs b/helix-term/src/ui/statusline.rs index 88786351..72f716dc 100644 --- a/helix-term/src/ui/statusline.rs +++ b/helix-term/src/ui/statusline.rs @@ -4,6 +4,7 @@ use helix_view::document::DEFAULT_LANGUAGE_NAME; use helix_view::{ document::{Mode, SCRATCH_BUFFER_NAME}, graphics::Rect, + icons::Icon, theme::Style, Document, Editor, View, }; @@ -21,6 +22,7 @@ pub struct RenderContext<'a> { pub focused: bool, pub spinners: &'a ProgressSpinners, pub parts: RenderBuffer<'a>, + pub icons: RenderContextIcons<'a>, } impl<'a> RenderContext<'a> { @@ -31,6 +33,25 @@ impl<'a> RenderContext<'a> { focused: bool, spinners: &'a ProgressSpinners, ) -> Self { + // Determine icon based on language name if possible + let mut filetype_icon = None; + if let Some(language_config) = doc.language_config() { + for filetype in &language_config.file_types { + let filetype_str = match filetype { + helix_core::syntax::FileType::Extension(s) => s, + helix_core::syntax::FileType::Suffix(s) => s, + }; + filetype_icon = editor.icons.icon_from_filetype(filetype_str); + if filetype_icon.is_some() { + break; + } + } + } + // Otherwise based on filetype + if filetype_icon.is_none() { + filetype_icon = editor.icons.icon_from_path(doc.path()) + } + RenderContext { editor, doc, @@ -38,10 +59,21 @@ impl<'a> RenderContext<'a> { focused, spinners, parts: RenderBuffer::default(), + icons: RenderContextIcons { + enabled: editor.config().icons.statusline, + filetype_icon, + vcs_icon: editor.icons.ui.as_ref().and_then(|ui| ui.get("vcs_branch")), + }, } } } +pub struct RenderContextIcons<'a> { + pub enabled: bool, + pub filetype_icon: Option<&'a Icon>, + pub vcs_icon: Option<&'a Icon>, +} + #[derive(Default)] pub struct RenderBuffer<'a> { pub left: Spans<'a>, @@ -148,6 +180,7 @@ where helix_view::editor::StatusLineElement::FileEncoding => render_file_encoding, helix_view::editor::StatusLineElement::FileLineEnding => render_file_line_ending, helix_view::editor::StatusLineElement::FileType => render_file_type, + helix_view::editor::StatusLineElement::FileTypeIcon => render_file_type_icon, helix_view::editor::StatusLineElement::Diagnostics => render_diagnostics, helix_view::editor::StatusLineElement::WorkspaceDiagnostics => render_workspace_diagnostics, helix_view::editor::StatusLineElement::Selections => render_selections, @@ -240,7 +273,13 @@ where if warnings > 0 { write( context, - "●".to_string(), + context + .editor + .icons + .diagnostic + .warning + .icon_char + .to_string(), Some(context.editor.theme.get("warning")), ); write(context, format!(" {} ", warnings), None); @@ -249,7 +288,7 @@ where if errors > 0 { write( context, - "●".to_string(), + context.editor.icons.diagnostic.error.icon_char.to_string(), Some(context.editor.theme.get("error")), ); write(context, format!(" {} ", errors), None); @@ -282,7 +321,13 @@ where if warnings > 0 { write( context, - "●".to_string(), + context + .editor + .icons + .diagnostic + .warning + .icon_char + .to_string(), Some(context.editor.theme.get("warning")), ); write(context, format!(" {} ", warnings), None); @@ -291,7 +336,7 @@ where if errors > 0 { write( context, - "●".to_string(), + context.editor.icons.diagnostic.error.icon_char.to_string(), Some(context.editor.theme.get("error")), ); write(context, format!(" {} ", errors), None); @@ -412,6 +457,21 @@ where write(context, format!(" {} ", file_type), None); } +fn render_file_type_icon(context: &mut RenderContext, write: F) +where + F: Fn(&mut RenderContext, String, Option