turbopack_cli_utils/
source_context.rs

1use std::fmt::{Display, Write};
2
3use owo_colors::OwoColorize;
4use turbo_tasks_fs::source_context::{SourceContextLine, SourceContextLines};
5
6struct MarkerRange {
7    start: char,
8    end: char,
9    pos: usize,
10    len: usize,
11}
12
13impl Display for MarkerRange {
14    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
15        for _ in 0..self.pos {
16            f.write_char(' ')?;
17        }
18        f.write_char(self.start)?;
19        if self.len > 1 {
20            for _ in 2..self.len {
21                f.write_char('-')?;
22            }
23            f.write_char(self.end)?;
24        }
25        Ok(())
26    }
27}
28
29pub fn format_source_context_lines(ctx: &SourceContextLines, f: &mut impl Write) {
30    const PADDING: usize = 6;
31    const SPACE: char = ' ';
32    for line in &ctx.0 {
33        match line {
34            SourceContextLine::Context { line, outside } => {
35                writeln!(
36                    f,
37                    "{}",
38                    format_args!("{line:>PADDING$} | {outside}").dimmed()
39                )
40                .unwrap();
41            }
42            SourceContextLine::Start {
43                line,
44                before,
45                inside,
46            } => {
47                writeln!(
48                    f,
49                    "{SPACE:PADDING$} | {}",
50                    MarkerRange {
51                        start: 'v',
52                        end: '-',
53                        pos: before.len(),
54                        len: inside.len(),
55                    }
56                    .bold(),
57                )
58                .unwrap();
59                writeln!(f, "{line:>PADDING$} + {}{}", before.dimmed(), inside.bold()).unwrap();
60            }
61            SourceContextLine::End {
62                line,
63                inside,
64                after,
65            } => {
66                writeln!(f, "{line:>PADDING$} + {}{}", inside.bold(), after.dimmed()).unwrap();
67                writeln!(
68                    f,
69                    "{SPACE:PADDING$} +{}",
70                    MarkerRange {
71                        start: '-',
72                        end: '^',
73                        pos: 0,
74                        len: inside.len() + 1,
75                    }
76                    .bold()
77                )
78                .unwrap();
79            }
80            SourceContextLine::StartAndEnd {
81                line,
82                before,
83                inside,
84                after,
85            } => {
86                writeln!(
87                    f,
88                    "{SPACE:PADDING$} + {}",
89                    MarkerRange {
90                        start: 'v',
91                        end: 'v',
92                        pos: before.len(),
93                        len: inside.len(),
94                    }
95                    .bold()
96                )
97                .unwrap();
98                if inside.len() >= 2 {
99                    writeln!(
100                        f,
101                        "{line:>PADDING$} + {}{}{}",
102                        before.dimmed(),
103                        inside.bold(),
104                        after.dimmed()
105                    )
106                    .unwrap();
107                } else {
108                    writeln!(
109                        f,
110                        "{line:>PADDING$} + {}{}{}",
111                        before.bold(),
112                        inside.bold(),
113                        after.bold()
114                    )
115                    .unwrap();
116                }
117                writeln!(
118                    f,
119                    "{SPACE:PADDING$} + {}",
120                    MarkerRange {
121                        start: '^',
122                        end: '^',
123                        pos: before.len(),
124                        len: inside.len(),
125                    }
126                    .bold()
127                )
128                .unwrap();
129            }
130            SourceContextLine::Inside { line, inside } => {
131                writeln!(f, "{:>PADDING$} + {}", line.bold(), inside.bold()).unwrap();
132            }
133        }
134    }
135}