1 use gleam_core::{
2     error::{Error, FileIoAction, FileKind, Result, StandardIoAction, Unformatted},
3     io::OutputFile,
4 };
5 use std::{io::Read, path::PathBuf, str::FromStr};
6 
run(stdin: bool, check: bool, files: Vec<String>) -> Result<()>7 pub fn run(stdin: bool, check: bool, files: Vec<String>) -> Result<()> {
8     if stdin {
9         process_stdin(check)
10     } else {
11         process_files(check, files)
12     }
13 }
14 
process_stdin(check: bool) -> Result<()>15 fn process_stdin(check: bool) -> Result<()> {
16     let src = read_stdin()?;
17     let mut out = String::new();
18     gleam_core::format::pretty(&mut out, &src)?;
19 
20     if !check {
21         print!("{}", out);
22         return Ok(());
23     }
24 
25     if src != out {
26         return Err(Error::Format {
27             problem_files: vec![Unformatted {
28                 source: PathBuf::from("<standard input>"),
29                 destination: PathBuf::from("<standard output>"),
30                 input: src,
31                 output: out,
32             }],
33         });
34     }
35 
36     Ok(())
37 }
38 
process_files(check: bool, files: Vec<String>) -> Result<()>39 fn process_files(check: bool, files: Vec<String>) -> Result<()> {
40     if check {
41         check_files(files)
42     } else {
43         format_files(files)
44     }
45 }
46 
check_files(files: Vec<String>) -> Result<()>47 fn check_files(files: Vec<String>) -> Result<()> {
48     let problem_files = unformatted_files(files)?;
49 
50     if problem_files.is_empty() {
51         Ok(())
52     } else {
53         Err(Error::Format { problem_files })
54     }
55 }
56 
format_files(files: Vec<String>) -> Result<()>57 fn format_files(files: Vec<String>) -> Result<()> {
58     for file in unformatted_files(files)? {
59         crate::fs::write_output(&OutputFile {
60             path: file.destination,
61             text: file.output,
62         })?;
63     }
64     Ok(())
65 }
66 
unformatted_files(files: Vec<String>) -> Result<Vec<Unformatted>>67 pub fn unformatted_files(files: Vec<String>) -> Result<Vec<Unformatted>> {
68     let mut problem_files = Vec::with_capacity(files.len());
69 
70     for file_path in files {
71         let path = PathBuf::from_str(&file_path).map_err(|e| Error::FileIo {
72             action: FileIoAction::Open,
73             kind: FileKind::File,
74             path: PathBuf::from(file_path),
75             err: Some(e.to_string()),
76         })?;
77 
78         if path.is_dir() {
79             for path in crate::fs::gleam_files_excluding_gitignore(&path) {
80                 format_file(&mut problem_files, path)?;
81             }
82         } else {
83             format_file(&mut problem_files, path)?;
84         }
85     }
86 
87     Ok(problem_files)
88 }
89 
format_file(problem_files: &mut Vec<Unformatted>, path: PathBuf) -> Result<()>90 fn format_file(problem_files: &mut Vec<Unformatted>, path: PathBuf) -> Result<()> {
91     let src = crate::fs::read(&path)?;
92     let mut output = String::new();
93     gleam_core::format::pretty(&mut output, &src)?;
94 
95     if src != output {
96         problem_files.push(Unformatted {
97             source: path.clone(),
98             destination: path,
99             input: src,
100             output,
101         });
102     }
103     Ok(())
104 }
105 
read_stdin() -> Result<String>106 pub fn read_stdin() -> Result<String> {
107     let mut src = String::new();
108     let _ = std::io::stdin()
109         .read_to_string(&mut src)
110         .map_err(|e| Error::StandardIo {
111             action: StandardIoAction::Read,
112             err: Some(e.kind()),
113         })?;
114     Ok(src)
115 }
116