diff --git a/book/src/editor.md b/book/src/editor.md index b79792058..c2a7af764 100644 --- a/book/src/editor.md +++ b/book/src/editor.md @@ -138,7 +138,7 @@ The following statusline elements can be configured: | `file-type` | The type of the opened file | | `diagnostics` | The number of warnings and/or errors | | `workspace-diagnostics` | The number of warnings and/or errors on workspace | -| `selections` | The number of active selections | +| `selections` | The primary selection index out of the number of active selections | | `primary-selection-length` | The number of characters currently in primary selection | | `position` | The cursor position | | `position-percentage` | The cursor position as a percentage of the total number of lines | diff --git a/helix-core/src/syntax.rs b/helix-core/src/syntax.rs index 455774ec4..6332b437d 100644 --- a/helix-core/src/syntax.rs +++ b/helix-core/src/syntax.rs @@ -312,7 +312,22 @@ impl Loader { } pub fn language_for_shebang(&self, text: RopeSlice) -> Option { - let shebang: Cow = text.into(); + // NOTE: this is slightly different than the one for injection markers in tree-house. It + // is anchored at the beginning. + use helix_stdx::rope::Regex; + use once_cell::sync::Lazy; + const SHEBANG: &str = r"^#!\s*(?:\S*[/\\](?:env\s+(?:\-\S+\s+)*)?)?([^\s\.\d]+)"; + static SHEBANG_REGEX: Lazy = Lazy::new(|| Regex::new(SHEBANG).unwrap()); + + let marker = SHEBANG_REGEX + .captures_iter(regex_cursor::Input::new(text)) + .map(|cap| text.byte_slice(cap.get_group(1).unwrap().range())) + .next()?; + self.language_for_shebang_marker(marker) + } + + fn language_for_shebang_marker(&self, marker: RopeSlice) -> Option { + let shebang: Cow = marker.into(); self.languages_by_shebang.get(shebang.as_ref()).copied() } @@ -351,7 +366,7 @@ impl LanguageLoader for Loader { let path: Cow = text.into(); self.language_for_filename(Path::new(path.as_ref())) } - InjectionLanguageMarker::Shebang(text) => self.language_for_shebang(text), + InjectionLanguageMarker::Shebang(text) => self.language_for_shebang_marker(text), } } diff --git a/helix-term/src/ui/document.rs b/helix-term/src/ui/document.rs index d71c47a16..524d829c4 100644 --- a/helix-term/src/ui/document.rs +++ b/helix-term/src/ui/document.rs @@ -77,7 +77,8 @@ pub fn render_text( let mut formatter = DocumentFormatter::new_at_prev_checkpoint(text, text_fmt, text_annotations, anchor); - let mut syntax_highlighter = SyntaxHighlighter::new(syntax_highlighter, text, theme); + let mut syntax_highlighter = + SyntaxHighlighter::new(syntax_highlighter, text, theme, renderer.text_style); let mut overlay_highlighter = OverlayHighlighter::new(overlay_highlights, theme); let mut last_line_pos = LinePos { @@ -477,17 +478,24 @@ struct SyntaxHighlighter<'h, 'r, 't> { /// finished. pos: usize, theme: &'t Theme, + text_style: Style, style: Style, } impl<'h, 'r, 't> SyntaxHighlighter<'h, 'r, 't> { - fn new(inner: Option>, text: RopeSlice<'r>, theme: &'t Theme) -> Self { + fn new( + inner: Option>, + text: RopeSlice<'r>, + theme: &'t Theme, + text_style: Style, + ) -> Self { let mut highlighter = Self { inner, text, pos: 0, theme, - style: Style::default(), + style: text_style, + text_style, }; highlighter.update_pos(); highlighter @@ -516,7 +524,7 @@ impl<'h, 'r, 't> SyntaxHighlighter<'h, 'r, 't> { let (event, highlights) = highlighter.advance(); let base = match event { - HighlightEvent::Refresh => Style::default(), + HighlightEvent::Refresh => self.text_style, HighlightEvent::Push => self.style, }; diff --git a/helix-term/src/ui/statusline.rs b/helix-term/src/ui/statusline.rs index 8fb07ebe7..df23123c5 100644 --- a/helix-term/src/ui/statusline.rs +++ b/helix-term/src/ui/statusline.rs @@ -1,3 +1,5 @@ +use std::borrow::Cow; + use helix_core::{coords_at_pos, encoding, Position}; use helix_lsp::lsp::DiagnosticSeverity; use helix_view::document::DEFAULT_LANGUAGE_NAME; @@ -58,25 +60,16 @@ pub fn render(context: &mut RenderContext, viewport: Rect, surface: &mut Surface surface.set_style(viewport.with_height(1), base_style); - let write_left = |context: &mut RenderContext, text, style| { - append(&mut context.parts.left, text, &base_style, style) - }; - let write_center = |context: &mut RenderContext, text, style| { - append(&mut context.parts.center, text, &base_style, style) - }; - let write_right = |context: &mut RenderContext, text, style| { - append(&mut context.parts.right, text, &base_style, style) - }; - // Left side of the status line. let config = context.editor.config(); - let element_ids = &config.statusline.left; - element_ids - .iter() - .map(|element_id| get_render_function(*element_id)) - .for_each(|render| render(context, write_left)); + for element_id in &config.statusline.left { + let render = get_render_function(*element_id); + (render)(context, |context, span| { + append(&mut context.parts.left, span, base_style) + }); + } surface.set_spans( viewport.x, @@ -87,11 +80,12 @@ pub fn render(context: &mut RenderContext, viewport: Rect, surface: &mut Surface // Right side of the status line. - let element_ids = &config.statusline.right; - element_ids - .iter() - .map(|element_id| get_render_function(*element_id)) - .for_each(|render| render(context, write_right)); + for element_id in &config.statusline.right { + let render = get_render_function(*element_id); + (render)(context, |context, span| { + append(&mut context.parts.right, span, base_style) + }) + } surface.set_spans( viewport.x @@ -105,11 +99,12 @@ pub fn render(context: &mut RenderContext, viewport: Rect, surface: &mut Surface // Center of the status line. - let element_ids = &config.statusline.center; - element_ids - .iter() - .map(|element_id| get_render_function(*element_id)) - .for_each(|render| render(context, write_center)); + for element_id in &config.statusline.center { + let render = get_render_function(*element_id); + (render)(context, |context, span| { + append(&mut context.parts.center, span, base_style) + }) + } // Width of the empty space between the left and center area and between the center and right area. let spacing = 1u16; @@ -126,16 +121,14 @@ pub fn render(context: &mut RenderContext, viewport: Rect, surface: &mut Surface ); } -fn append(buffer: &mut Spans, text: String, base_style: &Style, style: Option