lingora_core/renderers/
analysis_renderer.rs1use std::{collections::BTreeMap, io};
2
3use crate::{
4 audit::{AuditIssue, AuditResult, Workspace},
5 domain::Locale,
6 error::LingoraError,
7};
8
9pub struct AnalysisRenderer {
21 workspace: Workspace,
22 issues: BTreeMap<Option<Locale>, Vec<AuditIssue>>,
23}
24
25impl AnalysisRenderer {
26 pub fn new(audit_result: &AuditResult) -> Self {
31 let workspace = audit_result.workspace().clone();
32
33 let issues = audit_result.issues().fold(BTreeMap::new(), |mut acc, i| {
34 let locale = i.locale();
35 acc.entry(locale).or_insert_with(Vec::new).push(i.clone());
36 acc
37 });
38
39 Self { workspace, issues }
40 }
41
42 pub fn render<W: io::Write>(&self, out: &mut W) -> Result<(), LingoraError> {
52 self.render_workspace(out)?;
53 self.render_language(out, "Canonical:", self.workspace.canonical_locale())?;
54 self.workspace
55 .primary_locales()
56 .try_for_each(|primary| self.render_language(out, "Primary:", primary))?;
57 self.workspace
58 .orphan_locales()
59 .try_for_each(|locale| self.render_locale(out, "Orphaned:", locale))
60 }
61
62 fn render_workspace<W: io::Write>(&self, out: &mut W) -> Result<(), LingoraError> {
63 if let Some(issues) = self.issues.get(&None) {
64 let issues = issues.iter().fold(BTreeMap::new(), |mut acc, issue| {
65 acc.entry(issue.subject())
66 .or_insert_with(Vec::new)
67 .push(issue);
68 acc
69 });
70
71 issues.iter().try_for_each(|(subject, issues)| {
72 writeln!(out, "Workspace: {subject}")?;
73
74 issues
75 .iter()
76 .try_for_each(|issue| writeln!(out, "{:10} {}", "", issue.message()))
77 })?;
78 }
79
80 Ok(())
81 }
82
83 fn render_language<W: io::Write>(
84 &self,
85 out: &mut W,
86 title: &str,
87 base: &Locale,
88 ) -> Result<(), LingoraError> {
89 writeln!(out, "Language: {}", base.language())?;
90
91 self.render_locale(out, title, base)?;
92
93 let mut variants_locales = Vec::from_iter(self.workspace.variant_locales(base));
94
95 if !variants_locales.is_empty() {
96 variants_locales.sort();
97 variants_locales
98 .iter()
99 .try_for_each(|v| self.render_locale(out, "Variant:", v))?
100 }
101
102 Ok(())
103 }
104
105 fn render_locale<W: io::Write>(
106 &self,
107 out: &mut W,
108 title: &str,
109 locale: &Locale,
110 ) -> Result<(), LingoraError> {
111 if let Some(issues) = self.issues.get(&Some(locale.clone())) {
112 writeln!(out, "{:10} {}", title, locale,)?;
113
114 let mut issues = issues.clone();
115 issues.sort_by(|a, b| match a.kind().cmp(b.kind()) {
116 std::cmp::Ordering::Less => std::cmp::Ordering::Less,
117 std::cmp::Ordering::Equal => a.message().cmp(b.message()),
118 std::cmp::Ordering::Greater => std::cmp::Ordering::Greater,
119 });
120
121 issues
122 .iter()
123 .try_for_each(|issue| writeln!(out, "{:11}{issue}", ""))?;
124 } else {
125 writeln!(out, "{:10} {} - Ok", title, locale)?;
126 }
127
128 Ok(())
129 }
130}