Skip to content

Commit 647af6b

Browse files
committed
rustfmt: Add an ineffectual --file-lines flag behind a feature
This adds a `--file-lines` flag that is behind the Cargo feature `experimental-file-lines`. The argument is parsed and propagated, but so far it is only an alternative and verbose way to specify files and set `skip_children`. Refs https://github.com/nrc/rustfmt/issues/434
1 parent e557450 commit 647af6b

File tree

3 files changed

+128
-1
lines changed

3 files changed

+128
-1
lines changed

Cargo.lock

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ include = ["src/*.rs", "Cargo.toml"]
1212
[features]
1313
default = ["cargo-fmt"]
1414
cargo-fmt = []
15+
# Feature for the in-development --file-lines argument, limiting formatting to
16+
# specified line ranges.
17+
experimental-file-lines = []
1518

1619
[dependencies]
1720
toml = "0.1.20"
@@ -25,3 +28,4 @@ syntex_syntax = "0.23.0"
2528
log = "0.3.2"
2629
env_logger = "0.3.1"
2730
getopts = "0.2"
31+
nom = "1.2.1"

src/bin/rustfmt.rs

Lines changed: 118 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,19 @@
1212

1313
#[macro_use]
1414
extern crate log;
15+
#[macro_use]
16+
extern crate nom;
17+
1518
extern crate rustfmt;
1619
extern crate toml;
1720
extern crate env_logger;
1821
extern crate getopts;
1922

23+
use nom::IResult;
24+
2025
use rustfmt::{run, run_from_stdin};
2126
use rustfmt::config::{Config, WriteMode};
27+
use rustfmt::config::{FileLinesMap, LineRanges};
2228

2329
use std::env;
2430
use std::fs::{self, File};
@@ -42,6 +48,10 @@ enum Operation {
4248
InvalidInput(String),
4349
/// No file specified, read from stdin
4450
Stdin(String, Option<PathBuf>),
51+
/// Format a set of line ranges.
52+
FormatLineRanges {
53+
file_lines_map: FileLinesMap,
54+
},
4555
}
4656

4757
/// Try to find a project file in the given directory and its parents. Returns the path of a the
@@ -112,7 +122,9 @@ fn match_cli_path_or_file(config_path: Option<PathBuf>,
112122

113123
fn update_config(config: &mut Config, matches: &Matches) -> Result<(), String> {
114124
config.verbose = matches.opt_present("verbose");
115-
config.skip_children = matches.opt_present("skip-children");
125+
// `file-lines` implies `skip-children`.
126+
config.skip_children = matches.opt_present("skip-children") ||
127+
matches.opt_present("file-lines");
116128

117129
let write_mode = matches.opt_str("write-mode");
118130
match matches.opt_str("write-mode").map(|wm| WriteMode::from_str(&wm)) {
@@ -144,6 +156,13 @@ fn execute() -> i32 {
144156
"Recursively searches the given path for the rustfmt.toml config file. If not \
145157
found reverts to the input file path",
146158
"[Path for the configuration file]");
159+
if cfg!(feature = "experimental-file-lines") {
160+
opts.optmulti("",
161+
"file-lines",
162+
"Format specified line RANGEs in FILENAME. RANGEs are inclusive of both \
163+
endpoints. May be specified multiple times.",
164+
"FILENAME:RANGE,RANGE,...");
165+
}
147166

148167
let matches = match opts.parse(env::args().skip(1)) {
149168
Ok(m) => m,
@@ -220,6 +239,27 @@ fn execute() -> i32 {
220239
}
221240
0
222241
}
242+
// TODO: figure out what to do with config_path.
243+
Operation::FormatLineRanges { file_lines_map } => {
244+
for (file, line_ranges) in file_lines_map {
245+
let (mut config, config_path) = resolve_config(file.parent().unwrap())
246+
.expect(&format!("Error resolving config \
247+
for {}",
248+
file.display()));
249+
if let Some(path) = config_path.as_ref() {
250+
println!("Using rustfmt config file {} for {}",
251+
path.display(),
252+
file.display());
253+
}
254+
if let Err(e) = update_config(&mut config, &matches) {
255+
print_usage(&opts, &e);
256+
return 1;
257+
}
258+
config.line_ranges = line_ranges;
259+
run(&file, &config);
260+
}
261+
0
262+
}
223263
}
224264
}
225265

@@ -275,6 +315,27 @@ fn determine_operation(matches: &Matches) -> Operation {
275315
Some(dir)
276316
});
277317

318+
if matches.opt_present("file-lines") {
319+
let file_lines = matches.opt_strs("file-lines");
320+
let mut file_lines_map = FileLinesMap::new();
321+
for range_spec in file_lines {
322+
let invalid = || {
323+
Operation::InvalidInput(format!("invalid file-lines argument: {}", range_spec))
324+
};
325+
326+
let (file, line_ranges) = match parse::file_lines_arg(&range_spec) {
327+
IResult::Error(_) |
328+
IResult::Incomplete(_) => return invalid(),
329+
IResult::Done(remaining, _) if !remaining.is_empty() => return invalid(),
330+
IResult::Done(_, (file, line_ranges)) => (file, line_ranges),
331+
};
332+
333+
let entry = file_lines_map.entry(file).or_insert(LineRanges(Vec::new()));
334+
entry.0.extend(line_ranges.0);
335+
}
336+
return Operation::FormatLineRanges { file_lines_map: file_lines_map };
337+
}
338+
278339
// if no file argument is supplied, read from stdin
279340
if matches.free.is_empty() {
280341

@@ -291,3 +352,59 @@ fn determine_operation(matches: &Matches) -> Operation {
291352

292353
Operation::Format(files, config_path)
293354
}
355+
356+
357+
/// Parser for the `file-lines` argument.
358+
mod parse {
359+
use std::path::PathBuf;
360+
use std::str::FromStr;
361+
use rustfmt::config::{LineRange, LineRanges};
362+
363+
use nom::digit;
364+
365+
named!(pub file_lines_arg<&str, (PathBuf, LineRanges)>,
366+
chain!(
367+
file: map!(
368+
is_not_s!(":"),
369+
PathBuf::from
370+
) ~
371+
tag_s!(":") ~
372+
line_ranges: line_ranges,
373+
|| (file, line_ranges)
374+
)
375+
);
376+
377+
named!(usize_digit<&str, usize>,
378+
map_res!(
379+
digit,
380+
FromStr::from_str
381+
)
382+
);
383+
384+
named!(line_range<&str, LineRange>,
385+
map_res!(
386+
separated_pair!(
387+
usize_digit,
388+
tag_s!("-"),
389+
usize_digit
390+
),
391+
|pair: (usize, usize)| {
392+
let (start, end) = pair;
393+
if end < start {
394+
return Err(format!("empty line range: {}-{}", start, end));
395+
}
396+
Ok(pair)
397+
}
398+
)
399+
);
400+
401+
named!(line_ranges<&str, LineRanges>,
402+
map!(
403+
separated_nonempty_list!(
404+
tag_s!(","),
405+
line_range
406+
),
407+
LineRanges
408+
)
409+
);
410+
}

0 commit comments

Comments
 (0)