Skip to content

Commit

Permalink
rustfmt: Add option to specify line ranges for formatting
Browse files Browse the repository at this point in the history
This commit adds the `--experimental-file-lines` option to rustfmt. This
allows specifying line ranges to format from the command line.

Refs #434
  • Loading branch information
kamalmarhubi committed May 30, 2016
1 parent 9fa5a91 commit bef5d09
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 5 deletions.
19 changes: 19 additions & 0 deletions README.md
Expand Up @@ -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
Expand Down
26 changes: 21 additions & 5 deletions src/bin/rustfmt.rs
Expand Up @@ -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};
Expand Down Expand Up @@ -57,6 +58,7 @@ struct CliOptions {
skip_children: bool,
verbose: bool,
write_mode: Option<WriteMode>,
file_lines: FileLines, // Default is all lines in all files.
}

impl CliOptions {
Expand All @@ -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;
}
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -198,8 +209,12 @@ fn execute(opts: &Options) -> FmtResult<Summary> {

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
Expand Down Expand Up @@ -227,7 +242,7 @@ fn execute(opts: &Options) -> FmtResult<Summary> {
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)
Expand Down Expand Up @@ -306,8 +321,8 @@ fn determine_operation(matches: &Matches) -> FmtResult<Operation> {
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));
Expand All @@ -318,6 +333,7 @@ fn determine_operation(matches: &Matches) -> FmtResult<Operation> {
});
}

// We append files from `--file-lines` later in `execute()`.
let files: Vec<_> = matches.free.iter().map(PathBuf::from).collect();

Ok(Operation::Format {
Expand Down

0 comments on commit bef5d09

Please sign in to comment.