proc_macro2_diagnostics/
line.rs
1use std::fmt;
2use std::borrow::Cow;
3
4use crate::Level;
5
6#[derive(Copy, Clone, PartialEq)]
7enum Kind {
8 New,
9 Joined,
10}
11
12impl Kind {
13 fn raw_split(self) -> (Cow<'static, str>, Cow<'static, str>) {
14 match self {
15 Kind::New => ("[".into(), "] ".into()),
16 Kind::Joined => ("= ".into(), ": ".into()),
17 }
18 }
19
20 #[cfg(not(all(feature = "colors", not(nightly_diagnostics))))]
21 fn split(self) -> (Cow<'static, str>, Cow<'static, str>) {
22 self.raw_split()
23 }
24
25 #[cfg(all(feature = "colors", not(nightly_diagnostics)))]
26 fn split(self) -> (Cow<'static, str>, Cow<'static, str>) {
27 use yansi::Paint;
28
29 let (prefix, suffix) = self.raw_split();
30 let (prefix, suffix) = match self {
31 Kind::New => (prefix.blue().bold(), suffix.blue().bold()),
32 Kind::Joined => (prefix.blue().bold(), suffix.primary()),
33 };
34
35 (prefix.to_string().into(), suffix.to_string().into())
36 }
37}
38
39pub struct Line<'a> {
40 pub level: Level,
41 pub msg: &'a str,
42 kind: Kind
43}
44
45impl<'a> Line<'a> {
46 pub fn new(level: Level, msg: &'a str) -> Line<'a> {
47 Line { kind: Kind::New, level, msg }
48 }
49
50 pub fn joined(level: Level, msg: &'a str) -> Line<'a> {
51 Line { kind: Kind::Joined, level, msg }
52 }
53
54 pub fn is_new(&self) -> bool {
55 self.kind == Kind::New
56 }
57
58 fn parse_kind(kind: Kind, string: &str) -> Option<Line<'_>> {
59 let string = string.trim_start();
60 let (prefix, suffix) = kind.split();
61 if !string.starts_with(&*prefix) {
62 return None;
63 }
64
65 let end = string.find(&*suffix)?;
66 let level: Level = string[prefix.len()..end].parse().ok()?;
67 let msg = &string[end + suffix.len()..];
68 Some(Line { level, msg, kind })
69 }
70
71 pub fn parse(string: &str) -> Option<Line<'_>> {
72 Line::parse_kind(Kind::Joined, string)
73 .or_else(|| Line::parse_kind(Kind::New, string))
74 }
75}
76
77impl fmt::Display for Line<'_> {
78 #[cfg(all(feature = "colors", not(nightly_diagnostics)))]
79 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
80 use yansi::{Paint, Color};
81 let style = match self.level {
82 Level::Error => Color::Red.bold(),
83 Level::Warning => Color::Yellow.bold(),
84 Level::Note => Color::Green.bold(),
85 Level::Help => Color::Cyan.bold(),
86 };
87
88 let ((prefix, suffix), msg) = (self.kind.split(), self.msg.primary());
89 write!(f, "{}{}{}{}", prefix, self.level.paint(style), suffix, msg.bold())
90 }
91
92 #[cfg(not(all(feature = "colors", not(nightly_diagnostics))))]
93 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
94 let (prefix, suffix) = self.kind.split();
95 write!(f, "{}{}{}{}", prefix, self.level, suffix, self.msg)
96 }
97}