|
1 | 1 | use std::borrow::Cow; |
2 | 2 | use std::io::Write; |
3 | | -use std::path::{ |
4 | | - Path, |
5 | | - PathBuf, |
6 | | -}; |
7 | | -use std::sync::LazyLock; |
| 3 | +use std::path::PathBuf; |
8 | 4 |
|
9 | 5 | use crossterm::queue; |
10 | 6 | use crossterm::style::{ |
11 | 7 | self, |
12 | 8 | Color, |
13 | 9 | }; |
14 | 10 | use eyre::{ |
15 | | - ContextCompat, |
16 | 11 | Result, |
17 | 12 | bail, |
18 | 13 | eyre, |
19 | 14 | }; |
20 | 15 | use fig_os_shim::Context; |
21 | 16 | use serde::Deserialize; |
22 | | -use syntect::easy::HighlightLines; |
23 | | -use syntect::highlighting::ThemeSet; |
24 | | -use syntect::parsing::SyntaxSet; |
25 | | -use syntect::util::{ |
26 | | - LinesWithEndings, |
27 | | - as_24_bit_terminal_escaped, |
28 | | -}; |
29 | | -use tracing::error; |
30 | 17 |
|
31 | 18 | use super::{ |
32 | 19 | InvokeOutput, |
33 | 20 | format_path, |
| 21 | + stylize_output_if_able, |
34 | 22 | }; |
35 | 23 |
|
36 | | -static SYNTAX_SET: LazyLock<SyntaxSet> = LazyLock::new(SyntaxSet::load_defaults_newlines); |
37 | | -static THEME_SET: LazyLock<ThemeSet> = LazyLock::new(ThemeSet::load_defaults); |
38 | | - |
39 | 24 | #[derive(Debug, Deserialize)] |
40 | 25 | #[serde(tag = "command")] |
41 | 26 | pub enum FsWrite { |
@@ -254,103 +239,6 @@ fn truncate_str(text: &str, max_len: usize) -> Cow<'_, str> { |
254 | 239 | } |
255 | 240 | } |
256 | 241 |
|
257 | | -/// Returns the number of characters required for displaying line numbers for `file_text`. |
258 | | -fn terminal_width(line_count: usize) -> usize { |
259 | | - ((line_count as f32 + 0.1).log10().ceil()) as usize |
260 | | -} |
261 | | - |
262 | | -fn stylize_output_if_able<'a>( |
263 | | - path: impl AsRef<Path>, |
264 | | - file_text: &'a str, |
265 | | - starting_line: Option<usize>, |
266 | | - gutter_prefix: Option<&str>, |
267 | | -) -> Cow<'a, str> { |
268 | | - match stylized_file(path, file_text, starting_line, gutter_prefix) { |
269 | | - Ok(s) => s.into(), |
270 | | - Err(err) => { |
271 | | - error!(?err, "unable to syntax highlight the output"); |
272 | | - file_text.into() |
273 | | - }, |
274 | | - } |
275 | | -} |
276 | | - |
277 | | -/// Returns a 24bit terminal escaped syntax-highlighted [String] of the file pointed to by `path`, |
278 | | -/// if able. |
279 | | -/// |
280 | | -/// Params: |
281 | | -/// - `starting_line` - 1-indexed line to start the line number at. |
282 | | -/// - `gutter_prefix` - character to display in the first cell of the gutter, before the file |
283 | | -/// number. |
284 | | -fn stylized_file( |
285 | | - path: impl AsRef<Path>, |
286 | | - file_text: impl AsRef<str>, |
287 | | - starting_line: Option<usize>, |
288 | | - gutter_prefix: Option<&str>, |
289 | | -) -> Result<String> { |
290 | | - let starting_line = starting_line.unwrap_or(1); |
291 | | - let gutter_prefix = gutter_prefix.unwrap_or(" "); |
292 | | - |
293 | | - let ps = &*SYNTAX_SET; |
294 | | - let ts = &*THEME_SET; |
295 | | - |
296 | | - let extension = path |
297 | | - .as_ref() |
298 | | - .extension() |
299 | | - .wrap_err("missing extension")? |
300 | | - .to_str() |
301 | | - .wrap_err("not utf8")?; |
302 | | - |
303 | | - let syntax = ps |
304 | | - .find_syntax_by_extension(extension) |
305 | | - .wrap_err_with(|| format!("missing extension: {}", extension))?; |
306 | | - |
307 | | - let theme = &ts.themes["base16-ocean.dark"]; |
308 | | - let mut h = HighlightLines::new(syntax, theme); |
309 | | - let gutter_width = terminal_width(file_text.as_ref().lines().count()) + terminal_width(starting_line); |
310 | | - let file_text = LinesWithEndings::from(file_text.as_ref()); |
311 | | - let (gutter_fg, gutter_bg) = match ( |
312 | | - theme.settings.gutter_foreground, |
313 | | - theme.settings.gutter, |
314 | | - theme.settings.foreground, |
315 | | - theme.settings.background, |
316 | | - ) { |
317 | | - (Some(gutter_fg), Some(gutter_bg), _, _) => (gutter_fg, gutter_bg), |
318 | | - (_, _, Some(fg), Some(bg)) => (fg, bg), |
319 | | - _ => bail!("missing theme"), |
320 | | - }; |
321 | | - let gutter_prefix_style = syntect::highlighting::Style { |
322 | | - foreground: gutter_fg, |
323 | | - background: gutter_bg, |
324 | | - font_style: syntect::highlighting::FontStyle::BOLD, |
325 | | - }; |
326 | | - let gutter_linenum_style = syntect::highlighting::Style { |
327 | | - foreground: gutter_fg, |
328 | | - background: gutter_bg, |
329 | | - font_style: syntect::highlighting::FontStyle::default(), |
330 | | - }; |
331 | | - |
332 | | - let mut file = String::new(); |
333 | | - // We need to append newlines here for some reason, otherwise the highlighting ends at the end |
334 | | - // of the content for the first line. |
335 | | - file.push_str(&as_24_bit_terminal_escaped(&[(gutter_linenum_style, "\n\n")], true)); |
336 | | - for (i, line) in file_text.enumerate() { |
337 | | - let i = (i + starting_line).to_string(); |
338 | | - let gutter_content = format!("{:>width$} ", i, width = gutter_width); |
339 | | - let mut ranges = vec![ |
340 | | - (gutter_prefix_style, gutter_prefix), |
341 | | - (gutter_linenum_style, gutter_content.as_str()), |
342 | | - ]; |
343 | | - ranges.append(&mut h.highlight_line(line, ps)?); |
344 | | - let escaped_line = as_24_bit_terminal_escaped(&ranges[..], true); |
345 | | - file.push_str(&escaped_line); |
346 | | - } |
347 | | - if !file.ends_with("\n") { |
348 | | - file.push('\n'); |
349 | | - } |
350 | | - |
351 | | - Ok(file) |
352 | | -} |
353 | | - |
354 | 242 | /// Returns a 1-indexed line number range of the start and end of `needle` inside `file`. |
355 | 243 | fn line_number_at(file: impl AsRef<str>, needle: impl AsRef<str>) -> Option<(usize, usize)> { |
356 | 244 | let file = file.as_ref(); |
@@ -643,14 +531,4 @@ mod tests { |
643 | 531 | let s = "Hello, world!"; |
644 | 532 | assert_eq!(truncate_str(s, 0), "<...Truncated>"); |
645 | 533 | } |
646 | | - |
647 | | - #[test] |
648 | | - fn test_gutter_width() { |
649 | | - assert_eq!(terminal_width(1), 1); |
650 | | - assert_eq!(terminal_width(9), 1); |
651 | | - assert_eq!(terminal_width(10), 2); |
652 | | - assert_eq!(terminal_width(99), 2); |
653 | | - assert_eq!(terminal_width(100), 3); |
654 | | - assert_eq!(terminal_width(999), 3); |
655 | | - } |
656 | 534 | } |
0 commit comments