Skip to content

Commit

Permalink
rustfmt: Add an ineffectual --file-lines flag behind a feature
Browse files Browse the repository at this point in the history
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
  • Loading branch information
kamalmarhubi committed Feb 27, 2016
1 parent cf6b335 commit 82da644
Show file tree
Hide file tree
Showing 3 changed files with 160 additions and 1 deletion.
12 changes: 12 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ include = ["src/*.rs", "Cargo.toml"]
[features]
default = ["cargo-fmt"]
cargo-fmt = []
# Feature for the in-development --file-lines argument, limiting formatting to
# specified line ranges.
experimental-file-lines = ["nom"]

[dependencies]
toml = "0.1.20"
Expand All @@ -25,3 +28,5 @@ syntex_syntax = "0.23.0"
log = "0.3.2"
env_logger = "0.3.1"
getopts = "0.2"
cfg-if = "0.1.0"
nom = { version = "1.2.1", optional = true }
144 changes: 143 additions & 1 deletion src/bin/rustfmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,23 @@

#![cfg(not(test))]

#[macro_use]
extern crate cfg_if;
#[macro_use]
extern crate log;
#[cfg(feature = "experimental-file-lines")]
#[macro_use]
extern crate nom;

extern crate rustfmt;
extern crate toml;
extern crate env_logger;
extern crate getopts;

use rustfmt::{run, run_from_stdin};
use rustfmt::config::{Config, WriteMode};
#[cfg(feature = "experimental-file-lines")]
use rustfmt::config::FileLinesMap;

use std::env;
use std::fs::{self, File};
Expand All @@ -42,6 +50,11 @@ enum Operation {
InvalidInput(String),
/// No file specified, read from stdin
Stdin(String, Option<PathBuf>),
/// Format a set of line ranges.
#[cfg(feature = "experimental-file-lines")]
FormatLineRanges {
file_lines_map: FileLinesMap,
},
}

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

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

let write_mode = matches.opt_str("write-mode");
match matches.opt_str("write-mode").map(|wm| WriteMode::from_str(&wm)) {
Expand Down Expand Up @@ -144,6 +159,13 @@ fn execute() -> i32 {
"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]");
if cfg!(feature = "experimental-file-lines") {
opts.optmulti("",
"file-lines",
"Format specified line RANGEs in FILENAME. RANGEs are inclusive of both \
endpoints. May be specified multiple times.",
"FILENAME:RANGE,RANGE,...");
}

let matches = match opts.parse(env::args().skip(1)) {
Ok(m) => m,
Expand Down Expand Up @@ -220,6 +242,28 @@ fn execute() -> i32 {
}
0
}
#[cfg(feature = "experimental-file-lines")]
// TODO: figure out what to do with config_path.
Operation::FormatLineRanges { file_lines_map } => {
for (file, line_ranges) in file_lines_map {
let (mut config, config_path) = resolve_config(file.parent().unwrap())
.expect(&format!("Error resolving config \
for {}",
file.display()));
if let Some(path) = config_path.as_ref() {
println!("Using rustfmt config file {} for {}",
path.display(),
file.display());
}
if let Err(e) = update_config(&mut config, &matches) {
print_usage(&opts, &e);
return 1;
}
config.line_ranges = line_ranges;
run(&file, &config);
}
0
}
}
}

Expand Down Expand Up @@ -275,6 +319,47 @@ fn determine_operation(matches: &Matches) -> Operation {
Some(dir)
});

if matches.opt_present("file-lines") {
cfg_if! {
if #[cfg(feature = "experimental-file-lines")] {
fn handle_file_lines(args: &[String]) -> Operation {
use rustfmt::config::{FileLinesMap, LineRanges};

use nom::IResult;

let mut file_lines_map = FileLinesMap::new();
for range_spec in args {
let res = parse::file_lines_arg(range_spec);

let invalid = || {
Operation::InvalidInput(format!("invalid file-lines argument: {}",
range_spec))
};

let (file, line_ranges) = match res {
IResult::Error(_) => return invalid(),
IResult::Incomplete(_) => return invalid(),
IResult::Done(remaining, _) if !remaining.is_empty() => {
return invalid()
}
IResult::Done(_, (file, line_ranges)) => (file, line_ranges),
};

let entry = file_lines_map.entry(file).or_insert(LineRanges(Vec::new()));
entry.0.extend(line_ranges.0);
}
return Operation::FormatLineRanges { file_lines_map: file_lines_map };
}
} else {
fn handle_file_lines(_: &[String]) -> ! {
unimplemented!();
}
}
}

return handle_file_lines(&matches.opt_strs("file-lines"));
}

// if no file argument is supplied, read from stdin
if matches.free.is_empty() {

Expand All @@ -291,3 +376,60 @@ fn determine_operation(matches: &Matches) -> Operation {

Operation::Format(files, config_path)
}


/// Parser for the `file-lines` argument.
#[cfg(feature = "experimental-file-lines")]
mod parse {
use std::path::PathBuf;
use std::str::FromStr;
use rustfmt::config::{LineRange, LineRanges};

use nom::digit;

named!(pub file_lines_arg<&str, (PathBuf, LineRanges)>,
chain!(
file: map!(
is_not_s!(":"),
PathBuf::from
) ~
tag_s!(":") ~
line_ranges: line_ranges,
|| (file, line_ranges)
)
);

named!(usize_digit<&str, usize>,
map_res!(
digit,
FromStr::from_str
)
);

named!(line_range<&str, LineRange>,
map_res!(
separated_pair!(
usize_digit,
tag_s!("-"),
usize_digit
),
|pair: (usize, usize)| {
let (start, end) = pair;
if end < start {
return Err(format!("empty line range: {}-{}", start, end));
}
Ok(pair)
}
)
);

named!(line_ranges<&str, LineRanges>,
map!(
separated_nonempty_list!(
tag_s!(","),
line_range
),
LineRanges
)
);
}

0 comments on commit 82da644

Please sign in to comment.