artifact_app/cmd/
display.rs

1
2/* Copyright (c) 2017 Garrett Berg, vitiral@gmail.com
3 *
4 * Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
5 * http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
6 * http://opensource.org/licenses/MIT>, at your option. This file may not be
7 * copied, modified, or distributed except according to those terms.
8 */
9//! methods to format the `FmtArtifact` object and write it to a stream
10
11use dev_prefix::*;
12use types::*;
13use cmd::types::*;
14use utils;
15
16impl FmtArtifact {
17    /// write the formatted version of the artifact to the
18    /// cmdline writter
19    ///
20    /// #SPC-cmd-ls-color
21    #[allow(cyclomatic_complexity)] // TODO: break this up
22    pub fn write<W: io::Write>(
23        &self,
24        w: &mut W,
25        cwd: &Path,
26        artifacts: &Artifacts,
27        color: bool,
28        indent: u8,
29    ) -> io::Result<()> {
30        let nfno = indent > 0 && self.name_only(); // not-first-name-only
31        if !self.name_only() {
32            for _ in 0..(indent * 2) {
33                try!(w.write_all(" ".as_ref()));
34            }
35        }
36        trace!("formatting artifact: {}", self.name);
37        let artifact = match artifacts.get(&self.name) {
38            Some(a) => a,
39            None => {
40                // invalid partof value
41                if color {
42                    write!(w, "{}", Red.bold().blink().paint(self.name.raw.as_str())).unwrap();
43                } else {
44                    write!(w, "{}", self.name.raw).unwrap();
45                }
46                return Ok(());
47            }
48        };
49
50        // format the completeness and name
51        let completed_str = if artifact.completed < 0. {
52            "-1".to_string()
53        } else {
54            ((artifact.completed * 100.) as u8).to_string()
55        };
56        let tested_str = if artifact.tested < 0. {
57            "-1".to_string()
58        } else {
59            ((artifact.tested * 100.) as u8).to_string()
60        };
61        let completed_len = completed_str.len();
62        let tested_len = tested_str.len();
63        if color {
64            let (d_sym, d_perc, t_sym, t_perc, name) =
65                if artifact.completed >= 1. && artifact.tested >= 1. {
66                    let name = if nfno {
67                        Green.paint(self.name.raw.as_str())
68                    } else {
69                        Green.bold().underline().paint(self.name.raw.as_str())
70                    };
71                    (
72                        Green.bold().paint("D"),
73                        Green.bold().paint(completed_str),
74                        Green.bold().paint("T"),
75                        Green.bold().paint(tested_str),
76                        name,
77                    )
78                } else {
79                    let mut score = 0;
80                    let (d_sym, d_perc) = if artifact.completed >= 1. {
81                        score += 3;
82                        (Blue.bold().paint("D"), Blue.bold().paint(completed_str))
83                    } else if artifact.completed >= 0.7 {
84                        score += 2;
85                        (Yellow.bold().paint("-"), Yellow.bold().paint(completed_str))
86                    } else if artifact.completed >= 0.4 {
87                        score += 1;
88                        (Yellow.bold().paint("-"), Yellow.bold().paint(completed_str))
89                    } else if artifact.completed < 0. {
90                        (
91                            Red.bold().blink().paint("!"),
92                            Red.bold().blink().paint(completed_str),
93                        )
94                    } else {
95                        (Red.bold().paint("-"), Red.bold().paint(completed_str))
96                    };
97                    let (t_sym, t_perc) = if artifact.tested >= 1. {
98                        score += 2;
99                        (Blue.bold().paint("T"), Blue.bold().paint(tested_str))
100                    } else if artifact.tested >= 0.5 {
101                        score += 1;
102                        (Yellow.bold().paint("-"), Yellow.bold().paint(tested_str))
103                    } else if artifact.tested < 0. {
104                        (
105                            Red.bold().blink().paint("!"),
106                            Red.bold().blink().paint(tested_str),
107                        )
108                    } else {
109                        (Red.bold().paint("-"), Red.bold().paint(tested_str))
110                    };
111                    let name = match score {
112                        3...4 => Blue,
113                        1...2 => Yellow,
114                        0 => Red,
115                        _ => unreachable!(),
116                    };
117                    let sname = self.name.raw.as_str();
118                    let name = if nfno {
119                        name.paint(sname)
120                    } else {
121                        name.bold().underline().paint(sname)
122                    };
123                    (d_sym, d_perc, t_sym, t_perc, name)
124                };
125            if nfno {
126                try!(write!(w, "{}", name));
127            } else {
128                try!(write!(w, "|{}{}| ", d_sym, t_sym));
129                // format completed %
130                for _ in 0..(3 - completed_len) {
131                    try!(w.write_all(" ".as_ref()));
132                }
133                try!(write!(w, "{}% ", d_perc));
134                // format tested %
135                for _ in 0..(3 - tested_len) {
136                    try!(w.write_all(" ".as_ref()));
137                }
138                try!(write!(w, "{}% ", t_perc));
139                try!(write!(w, "| {} ", name));
140            }
141        } else if nfno {
142            try!(write!(w, "{}", &self.name.raw));
143        } else {
144            let d_sym = if artifact.completed >= 1. { "D" } else { "-" };
145            let t_sym = if artifact.tested >= 1. { "T" } else { "-" };
146            try!(write!(
147                w,
148                "|{}{}| {:>3}% {:>3}% | {}",
149                d_sym,
150                t_sym,
151                completed_str,
152                tested_str,
153                &self.name.raw
154            ));
155        }
156
157        if nfno {
158            return Ok(());
159        }
160
161        // format the parts
162        if let Some(ref parts) = self.parts {
163            self.write_start(w, "\n * parts: ", color);
164            for (n, p) in parts.iter().enumerate() {
165                if self.long {
166                    w.write_all("\n    ".as_ref()).unwrap();
167                }
168                try!(p.write(w, cwd, artifacts, color, indent + 1));
169                if !self.long && n + 1 < parts.len() {
170                    w.write_all(", ".as_ref()).unwrap();
171                }
172            }
173        }
174
175        // format the artifacts that are a partof this artifact
176        if let Some(ref partof) = self.partof {
177            self.write_start(w, "\n * partof: ", color);
178            let mut first = true;
179            for p in partof {
180                if !first && p.name_only() {
181                    try!(w.write_all(", ".as_ref()));
182                }
183                first = false;
184                try!(p.write(w, cwd, artifacts, color, indent + 1));
185            }
186        }
187
188        // format the location that where the implementation of this artifact can be found
189        if let Some(ref done) = self.done {
190            self.write_start(w, "\n * done: ", color);
191            if color {
192                try!(write!(w, "{}", Green.paint(done.as_ref())));
193            } else {
194                try!(w.write_all(done.as_ref()));
195            }
196            try!(w.write_all(" ".as_ref()));
197        }
198
199        // format where the artifact is defined
200        if let Some(ref def) = self.def {
201            self.write_start(w, "\n * defined-at: ", color);
202            let def = utils::relative_path(def.as_path(), cwd);
203            try!(write!(w, "{}", def.display()));
204        }
205
206        // format the text
207        // TODO: use markdown to apply styles to the text
208        if let Some(ref text) = self.text {
209            self.write_start(w, "\n * text:\n", color);
210            w.write_all(text.trim_right().as_ref()).unwrap();
211            if self.long {
212                w.write_all("\n".as_ref()).unwrap();
213            }
214        }
215
216        try!(w.write_all("\n".as_ref()));
217        Ok(())
218    }
219
220    fn write_start<W: io::Write>(&self, w: &mut W, msg: &str, color: bool) {
221        if self.long {
222            if color {
223                write!(w, "{}", Green.paint(msg)).unwrap();
224            } else {
225                w.write_all(msg.as_ref()).unwrap();
226            }
227        } else {
228            w.write_all("\t| ".as_ref()).unwrap();
229        }
230    }
231
232    /// return whether this object is only the name
233    /// if it is, it is formatted differently
234    fn name_only(&self) -> bool {
235        match (&self.def, &self.parts, &self.partof, &self.done, &self.text) {
236            (&None, &None, &None, &None, &None) => true,
237            _ => false,
238        }
239    }
240}
241
242pub fn write_table_header<W: io::Write>(w: &mut W, fmt_set: &FmtSettings) {
243    let mut header = String::new();
244    header.write_str("|  | DONE TEST | NAME").unwrap();
245    if fmt_set.parts {
246        header.write_str("\t| PARTS   ").unwrap();
247    }
248    if fmt_set.partof {
249        header.write_str("\t| PARTOF   ").unwrap();
250    }
251    if fmt_set.loc_path {
252        header.write_str("\t| IMPLEMENTED   ").unwrap();
253    }
254    if fmt_set.def {
255        header.write_str("\t| DEFINED   ").unwrap();
256    }
257    if fmt_set.text {
258        header.write_str("\t| TEXT").unwrap();
259    }
260    header.push('\n');
261    if fmt_set.color {
262        write!(w, "{}", Style::new().bold().paint(header)).unwrap();
263    } else {
264        write!(w, "{}", header).unwrap();
265    }
266}