Просмотр исходного кода

refactor: separated json in another file

MartinFillon 1 год назад
Родитель
Сommit
e9a29fa662
4 измененных файлов с 104 добавлено и 111 удалено
  1. 7 98
      src/output/details.rs
  2. 3 13
      src/output/grid_details.rs
  3. 93 0
      src/output/json.rs
  4. 1 0
      src/output/mod.rs

+ 7 - 98
src/output/details.rs

@@ -81,6 +81,8 @@ use crate::output::table::{Options as TableOptions, Row as TableRow, Table};
 use crate::output::tree::{TreeDepth, TreeParams, TreeTrunk};
 use crate::theme::Theme;
 
+use super::json::JsonRenderer;
+
 /// With the **Details** view, the output gets formatted into columns, with
 /// each `Column` object showing some piece of information about the file,
 /// such as its size, or its permissions.
@@ -222,80 +224,6 @@ impl<'a> Render<'a> {
         Ok(())
     }
 
-    fn print_row_contents(
-        &self,
-        w: &mut impl Write,
-        row: &TextCell,
-        header: &Option<TextCell>,
-    ) -> io::Result<()> {
-        let mut header_idx: usize = 0;
-        for (i, cell) in row.contents.iter().enumerate() {
-            if cell.is_empty() || cell.trim().is_empty() {
-                continue;
-            };
-            if let Some(ref header) = header {
-                write!(w, "\"{}\": ", header.contents[header_idx])?;
-                header_idx += 1;
-            }
-            write!(w, "\"{cell}\"")?;
-            if (i + 1) < row.contents.len() {
-                writeln!(w, ", ")?;
-            }
-        }
-        Ok(())
-    }
-
-    fn print_row<W: Write>(
-        &self,
-        w: &mut W,
-        header: &Option<TextCell>,
-        iter: &mut JsonTableIter<'_>,
-        current_depth: usize,
-        idx: &mut usize,
-        len: usize,
-        max: usize,
-    ) -> io::Result<Option<TreeParams>> {
-        let (row, depth) = match iter.next() {
-            Some((row, depth)) => (row, depth),
-            None => return Ok(None),
-        };
-        if self.opts.header {
-            writeln!(w, "{{")?;
-        } else {
-            writeln!(w, "[")?;
-        }
-        self.print_row_contents(w, &row, header)?;
-        writeln!(w, ", \"depth\": {}", depth.depth.0)?;
-        *idx += 1;
-        if depth.depth.0 == current_depth && depth.depth.0 < max {
-            writeln!(w, ", \"children\": [")?;
-            let mut d = self.print_row(w, header, iter, depth.depth.0 + 1, idx, len, max)?;
-            while d.is_some() && !d.unwrap().last && d.unwrap().depth.0 > depth.depth.0 {
-                d = self.print_row(w, header, iter, depth.depth.0 + 1, idx, len, max)?;
-            }
-            writeln!(w, "]")?;
-        }
-        if self.opts.header {
-            writeln!(w, "}}")?;
-        } else {
-            writeln!(w, "]")?;
-        }
-        if !depth.last {
-            writeln!(w, ",")?;
-        }
-        Ok(Some(depth))
-    }
-
-    pub fn get_max_depth(&self, iter: &mut JsonTableIter<'_>) -> usize {
-        let mut max_depth = 0;
-        for (_, depth) in iter {
-            if depth.depth.0 > max_depth {
-                max_depth = depth.depth.0;
-            }
-        }
-        max_depth
-    }
-
     pub fn render_json<W: Write>(self, w: &mut W) -> io::Result<()> {
         let mut rows = Vec::new();
 
@@ -320,33 +248,15 @@ impl<'a> Render<'a> {
                 None,
             );
 
-            writeln!(w, "{{")?;
-            let mut row_iter = self.iterate_with_table_json(table.unwrap(), rows);
+            let mut row_iter = self.iterate_with_table(table.unwrap(), rows);
             let header = if self.opts.header {
-                let (header, _) = row_iter.next().unwrap();
+                let header = row_iter.next().unwrap();
                 Some(header.clean_content())
             } else {
                 None
             };
-            let mut i = 0;
-            let len = row_iter.len();
-            writeln!(w, "\"files\":[")?;
-
-            let current_depth = 0;
-            let max_depth = self.get_max_depth(&mut row_iter.clone());
-
-            while row_iter.len() > 0 {
-                self.print_row(
-                    w,
-                    &(header.clone()),
-                    &mut row_iter,
-                    current_depth,
-                    &mut i,
-                    len,
-                    max_depth,
-                )?;
-            }
-            writeln!(w, "]\n}}")?;
+
+            JsonRenderer::new(header, row_iter).render(w)
         } else {
             #[rustfmt::skip]
             self.add_files_to_table(
@@ -364,9 +274,8 @@ impl<'a> Render<'a> {
                     write!(w, ", ")?;
                 }
             }
-            writeln!(w, "]}}")?;
+            writeln!(w, "]}}")
         }
-        Ok(())
     }
 
     /// Whether to show the extended attribute hint

+ 3 - 13
src/output/grid_details.rs

@@ -108,21 +108,11 @@ impl<'a> Render<'a> {
     // This doesn’t take an IgnoreCache even though the details one does
     // because grid-details has no tree view.
 
-    pub fn render<W: Write>(mut self, w: &mut W) -> io::Result<()> {
-        if let Some((grid, width)) = self.find_fitting_grid() {
-            write!(w, "{}", grid.fit_into_columns(width))
-        } else {
-            self.give_up().render(w)
-        }
-    }
-
-    pub fn render_json<W: Write>(self, w: &mut W) -> io::Result<()> {
-        // As json is made to be piped we use the Details render method
-
-        self.give_up().render_json(w)
+    pub fn render_json<W: Write>(self, _w: &mut W) -> io::Result<()> {
+        todo!("Implement json rendering");
     }
 
-    pub fn find_fitting_grid(&mut self) -> Option<(grid::Grid, grid::Width)> {
+    pub fn render<W: Write>(mut self, w: &mut W) -> io::Result<()> {
         let options = self
             .details
             .table

+ 93 - 0
src/output/json.rs

@@ -0,0 +1,93 @@
+/*
+This file is a special renderer for json
+*/
+
+use std::{
+    fmt::Display,
+    io::{self, Write},
+};
+
+use super::{details::TableIter, TextCell};
+
+#[derive(Debug, Clone)]
+struct JsonFile {
+    cell: TextCell,
+    childrens: Option<Vec<JsonFile>>,
+}
+
+#[derive(Debug, Clone)]
+pub struct JsonRenderer {
+    header: Option<TextCell>,
+    files: Vec<JsonFile>,
+}
+
+impl JsonFile {
+    pub fn new(cell: TextCell) -> Self {
+        Self {
+            cell,
+            childrens: None,
+        }
+    }
+
+    pub fn display<W: Write>(&self, w: &mut W, header: &Option<TextCell>) -> io::Result<()> {
+        let mut header_idx = 0;
+
+        if header.is_some() {
+            writeln!(w, "{{")?;
+        } else {
+            writeln!(w, "[")?;
+        }
+        for (i, cell) in self.cell.contents.iter().enumerate() {
+            if cell.is_empty() || cell.trim().is_empty() {
+                continue;
+            };
+            if let Some(ref header) = header {
+                write!(w, "\"{}\": ", header.contents[header_idx])?;
+                header_idx += 1;
+            }
+            write!(w, "\"{cell}\"")?;
+            if (i + 1) < self.cell.contents.len() {
+                writeln!(w, ", ")?;
+            }
+        }
+        if self.childrens.is_some() {
+            if header.is_some() {
+                writeln!(w, ", \"childends\": [")
+            } else {
+                writeln!(w, ", [")
+            }?;
+            for (i, f) in self.childrens.as_ref().unwrap().iter().enumerate() {
+                if i != 0 {
+                    writeln!(w, ",")?;
+                }
+                f.display(w, header)?;
+            }
+            writeln!(w, "]")?;
+        }
+        if header.is_some() {
+            writeln!(w, "}}")
+        } else {
+            writeln!(w, "]")
+        }
+    }
+}
+
+impl JsonRenderer {
+    pub fn new(header: Option<TextCell>, files: TableIter<'_>) -> Self {
+        Self {
+            header,
+            files: files.map(|row| JsonFile::new(row)).collect(),
+        }
+    }
+
+    pub fn render<W: Write>(&self, w: &mut W) -> io::Result<()> {
+        writeln!(w, "{{\n\"files\":[")?;
+        for (i, f) in self.files.iter().enumerate() {
+            if i != 0 {
+                writeln!(w, ",")?;
+            }
+            f.display(w, &self.header)?;
+        }
+        writeln!(w, "]\n}}")
+    }
+}

+ 1 - 0
src/output/mod.rs

@@ -15,6 +15,7 @@ pub mod time;
 
 mod cell;
 mod escape;
+mod json;
 mod tree;
 
 /// The **view** contains all information about how to format output.