1
1
use std:: io:: Read ;
2
2
3
+ use clap:: value_parser;
4
+ use clap:: ArgAction ;
3
5
use clap:: Parser ;
4
6
use futures:: future:: RemoteHandle ;
5
7
use futures:: stream:: FuturesUnordered ;
6
8
use futures:: task:: SpawnExt ;
7
9
8
10
use crate :: ads:: random_ad;
9
-
10
- #[ derive( Clone ) ]
11
- pub ( crate ) struct FormattedPath {
12
- pub path : String ,
13
- pub status : alejandra:: format:: Status ,
14
- }
15
-
16
- const AFTER_HELP : & str = concat ! (
17
- "Alejandra will exit with status code:\n " ,
18
- " 1, if any error occurs.\n " ,
19
- " 2, if --check was used and any file requires formatting.\n " ,
20
- " 0, otherwise." ,
21
- ) ;
11
+ use crate :: verbosity:: Verbosity ;
22
12
23
13
/// The Uncompromising Nix Code Formatter.
24
14
#[ derive( Debug , Parser ) ]
25
15
#[ clap(
26
16
name="Alejandra" ,
27
17
28
- after_help = AFTER_HELP ,
18
+ after_help = concat!(
19
+ "Alejandra will exit with status code:\n " ,
20
+ " 1, if any error occurs.\n " ,
21
+ " 2, if --check was used and any file requires formatting.\n " ,
22
+ " 0, otherwise." ,
23
+ ) ,
29
24
term_width = 80 ,
30
25
version,
31
26
) ]
32
- struct Args {
27
+ struct CLIArgs {
33
28
/// Files or directories, or a single "-" (or leave empty) to format stdin.
34
29
#[ clap( multiple_values = true ) ]
35
30
include : Vec < String > ,
@@ -45,25 +40,34 @@ struct Args {
45
40
46
41
/// Number of formatting threads to spawn. Defaults to the number of
47
42
/// physical CPUs.
48
- #[ clap( long, short, value_parser = clap :: value_parser!( u8 ) . range( 1 ..) ) ]
43
+ #[ clap( long, short, value_parser = value_parser!( u8 ) . range( 1 ..) ) ]
49
44
threads : Option < u8 > ,
50
45
51
- /// Hide the details, only show error messages.
52
- #[ clap( long, short) ]
53
- quiet : bool ,
46
+ /// Use once to hide informational messages,
47
+ /// twice to hide error messages.
48
+ #[ clap( long, short, action = ArgAction :: Count ) ]
49
+ quiet : u8 ,
50
+ }
51
+
52
+ #[ derive( Clone ) ]
53
+ struct FormattedPath {
54
+ pub path : String ,
55
+ pub status : alejandra:: format:: Status ,
54
56
}
55
57
56
- pub ( crate ) fn stdin ( quiet : bool ) -> FormattedPath {
58
+ fn format_stdin ( verbosity : Verbosity ) -> FormattedPath {
57
59
let mut before = String :: new ( ) ;
58
60
let path = "<anonymous file on stdin>" . to_string ( ) ;
59
61
60
- if !quiet {
62
+ if verbosity . allows_info ( ) {
61
63
eprintln ! ( "Formatting stdin." ) ;
62
64
eprintln ! ( "Use --help to see all command line options." ) ;
63
- eprintln ! ( "use --quiet to suppress this and all messages." ) ;
65
+ eprintln ! ( "use --quiet to suppress this and other messages." ) ;
64
66
}
65
67
66
- std:: io:: stdin ( ) . read_to_string ( & mut before) . unwrap ( ) ;
68
+ std:: io:: stdin ( )
69
+ . read_to_string ( & mut before)
70
+ . expect ( "Unable to read stdin." ) ;
67
71
68
72
let ( status, data) =
69
73
alejandra:: format:: in_memory ( path. clone ( ) , before. clone ( ) ) ;
@@ -73,15 +77,15 @@ pub(crate) fn stdin(quiet: bool) -> FormattedPath {
73
77
FormattedPath { path, status }
74
78
}
75
79
76
- pub ( crate ) fn simple (
80
+ fn format_paths (
77
81
paths : Vec < String > ,
78
82
in_place : bool ,
79
- quiet : bool ,
83
+ verbosity : Verbosity ,
80
84
threads : usize ,
81
85
) -> Vec < FormattedPath > {
82
86
let paths_len = paths. len ( ) ;
83
87
84
- if !quiet {
88
+ if verbosity . allows_info ( ) {
85
89
eprintln ! (
86
90
"{} {paths_len} file{} using {threads} thread{}." ,
87
91
"Checking style in" ,
@@ -94,7 +98,7 @@ pub(crate) fn simple(
94
98
let pool = futures:: executor:: ThreadPoolBuilder :: new ( )
95
99
. pool_size ( threads)
96
100
. create ( )
97
- . expect ( "Unable to instantiate a new thread pool" ) ;
101
+ . expect ( "Unable to instantiate a new thread pool. " ) ;
98
102
99
103
let futures: FuturesUnordered < RemoteHandle < FormattedPath > > = paths
100
104
. into_iter ( )
@@ -103,7 +107,7 @@ pub(crate) fn simple(
103
107
let status = alejandra:: format:: in_fs ( path. clone ( ) , in_place) ;
104
108
105
109
if let alejandra:: format:: Status :: Changed ( changed) = status {
106
- if changed && !quiet {
110
+ if changed && verbosity . allows_info ( ) {
107
111
println ! (
108
112
"{}: {path}" ,
109
113
if in_place {
@@ -117,33 +121,38 @@ pub(crate) fn simple(
117
121
118
122
FormattedPath { path : path. clone ( ) , status }
119
123
} )
120
- . expect ( "Unable to spawn formatting task" )
124
+ . expect ( "Unable to spawn formatting task. " )
121
125
} )
122
126
. collect ( ) ;
123
127
124
128
futures:: executor:: block_on_stream ( futures) . collect ( )
125
129
}
126
130
127
131
pub fn main ( ) -> std:: io:: Result < ( ) > {
128
- let args = Args :: parse ( ) ;
132
+ let args = CLIArgs :: parse ( ) ;
129
133
130
134
let in_place = !args. check ;
131
135
132
136
let include: Vec < & str > =
133
137
args. include . iter ( ) . map ( String :: as_str) . collect :: < Vec < & str > > ( ) ;
134
138
135
- let threads = args
136
- . threads
137
- . map_or_else ( num_cpus:: get_physical, |threads| threads as usize ) ;
139
+ let threads =
140
+ args. threads . map_or_else ( num_cpus:: get_physical, Into :: < usize > :: into) ;
141
+
142
+ let verbosity = match args. quiet {
143
+ 0 => Verbosity :: Everything ,
144
+ 1 => Verbosity :: NoInfo ,
145
+ _ => Verbosity :: NoErrors ,
146
+ } ;
138
147
139
148
let formatted_paths = match & include[ ..] {
140
149
& [ ] | & [ "-" ] => {
141
- vec ! [ crate :: cli:: stdin ( args . quiet ) ]
150
+ vec ! [ crate :: cli:: format_stdin ( verbosity ) ]
142
151
} ,
143
152
include => {
144
153
let paths = crate :: find:: nix_files ( include, & args. exclude ) ;
145
154
146
- crate :: cli:: simple ( paths, in_place, args . quiet , threads)
155
+ crate :: cli:: format_paths ( paths, in_place, verbosity , threads)
147
156
} ,
148
157
} ;
149
158
@@ -155,18 +164,21 @@ pub fn main() -> std::io::Result<()> {
155
164
. count ( ) ;
156
165
157
166
if errors > 0 {
158
- eprintln ! ( ) ;
159
- eprintln ! (
160
- "Failed! {errors} error{} found at:" ,
161
- if errors == 1 { "" } else { "s" }
162
- ) ;
163
- for formatted_path in formatted_paths {
164
- if let alejandra:: format:: Status :: Error ( error) =
165
- formatted_path. status
166
- {
167
- eprintln ! ( "- {}: {error}" , formatted_path. path) ;
167
+ if verbosity. allows_errors ( ) {
168
+ eprintln ! ( ) ;
169
+ eprintln ! (
170
+ "Failed! {errors} error{} found at:" ,
171
+ if errors == 1 { "" } else { "s" }
172
+ ) ;
173
+ for formatted_path in formatted_paths {
174
+ if let alejandra:: format:: Status :: Error ( error) =
175
+ formatted_path. status
176
+ {
177
+ eprintln ! ( "- {}: {error}" , formatted_path. path) ;
178
+ }
168
179
}
169
180
}
181
+
170
182
std:: process:: exit ( 1 ) ;
171
183
}
172
184
@@ -181,7 +193,7 @@ pub fn main() -> std::io::Result<()> {
181
193
. count ( ) ;
182
194
183
195
if changed > 0 {
184
- if !args . quiet {
196
+ if verbosity . allows_info ( ) {
185
197
eprintln ! ( ) ;
186
198
eprintln ! (
187
199
"{}! {changed} file{} {}." ,
@@ -204,7 +216,7 @@ pub fn main() -> std::io::Result<()> {
204
216
std:: process:: exit ( if in_place { 0 } else { 2 } ) ;
205
217
}
206
218
207
- if !args . quiet {
219
+ if verbosity . allows_info ( ) {
208
220
eprintln ! ( ) ;
209
221
eprintln ! ( "Congratulations! Your code complies with the Alejandra style." ) ;
210
222
eprintln ! ( ) ;
0 commit comments