From bef5d095a4c59577d1400d980b7da62519bbe473 Mon Sep 17 00:00:00 2001 From: Kamal Marhubi Date: Sun, 10 Apr 2016 13:03:54 -0400 Subject: [PATCH] rustfmt: Add option to specify line ranges for formatting This commit adds the `--experimental-file-lines` option to rustfmt. This allows specifying line ranges to format from the command line. Refs #434 --- README.md | 19 +++++++++++++++++++ src/bin/rustfmt.rs | 26 +++++++++++++++++++++----- 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 60b29956218..4f0714a9997 100644 --- a/README.md +++ b/README.md @@ -73,6 +73,25 @@ the command line. For example `rustfmt --write-mode=display src/filename.rs` `cargo fmt` uses `--write-mode=replace` by default. +If you want to restrict reformatting to specific sets of lines, you can +use the `--file-lines` option. Its argument is a JSON array of objects +with `file` and `range` properties, where `file` is a file name, and +`range` is an array representing a range of lines like `[7,13]`. Ranges +are inclusive of both end points. Specifying an empty array will result in +no files being formatted. For example, + +``` +rustfmt --file-lines '[ + {"file":"src/lib.rs","range":[7,13]}, + {"file":"src/lib.rs","range":[21,29]}, + {"file":"src/foo.rs","range":[10,11]}, + {"file":"src/foo.rs","range":[15,15]}]' +``` + +would format lines `7-13` and `21-29` of `src/lib.rs`, and lines `10-11`, +and `15` of `src/foo.rs`. No other files would be formatted, even if they +are included as out of line modules from `src/lib.rs`. + If `rustfmt` successfully reformatted the code it will exit with `0` exit status. Exit status `1` signals some unexpected error, like an unknown option or a failure to read a file. Exit status `2` is returned if there are syntax errors diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 2105a962997..5aa7cc4e080 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -18,6 +18,7 @@ extern crate env_logger; extern crate getopts; use rustfmt::{run, Input, Summary}; +use rustfmt::file_lines::FileLines; use rustfmt::config::{Config, WriteMode}; use std::{env, error}; @@ -57,6 +58,7 @@ struct CliOptions { skip_children: bool, verbose: bool, write_mode: Option, + file_lines: FileLines, // Default is all lines in all files. } impl CliOptions { @@ -73,12 +75,17 @@ impl CliOptions { } } + if let Some(ref file_lines) = matches.opt_str("file-lines") { + options.file_lines = try!(file_lines.parse()); + } + Ok(options) } - fn apply_to(&self, config: &mut Config) { + fn apply_to(self, config: &mut Config) { config.skip_children = self.skip_children; config.verbose = self.verbose; + config.file_lines = self.file_lines; if let Some(write_mode) = self.write_mode { config.write_mode = write_mode; } @@ -168,6 +175,10 @@ fn make_opts() -> Options { "Recursively searches the given path for the rustfmt.toml config file. If not \ found reverts to the input file path", "[Path for the configuration file]"); + opts.optopt("", + "file-lines", + "Format specified line ranges. See README for more detail on the JSON format.", + "JSON"); opts } @@ -198,8 +209,12 @@ fn execute(opts: &Options) -> FmtResult { Ok(run(Input::Text(input), &config)) } - Operation::Format { files, config_path } => { + Operation::Format { mut files, config_path } => { let options = try!(CliOptions::from_matches(&matches)); + + // Add any additional files that were specified via `--file-lines`. + files.extend(options.file_lines.files().cloned().map(PathBuf::from)); + let mut config = Config::default(); let mut path = None; // Load the config path file if provided @@ -227,7 +242,7 @@ fn execute(opts: &Options) -> FmtResult { config = config_tmp; } - options.apply_to(&mut config); + options.clone().apply_to(&mut config); error_summary.add(run(Input::File(file), &config)); } Ok(error_summary) @@ -306,8 +321,8 @@ fn determine_operation(matches: &Matches) -> FmtResult { Some(dir) }); - // if no file argument is supplied, read from stdin - if matches.free.is_empty() { + // if no file argument is supplied and `--file-lines` is not specified, read from stdin + if matches.free.is_empty() && !matches.opt_present("file-lines") { let mut buffer = String::new(); try!(io::stdin().read_to_string(&mut buffer)); @@ -318,6 +333,7 @@ fn determine_operation(matches: &Matches) -> FmtResult { }); } + // We append files from `--file-lines` later in `execute()`. let files: Vec<_> = matches.free.iter().map(PathBuf::from).collect(); Ok(Operation::Format {