expand: allow specifier only with last value

This commit is contained in:
Daniel Hofstetter 2022-06-05 15:16:48 +02:00
parent fc5aedfbb7
commit 804240164b
2 changed files with 39 additions and 0 deletions

View file

@ -41,6 +41,7 @@ static DEFAULT_TABSTOP: usize = 8;
/// The mode to use when replacing tabs beyond the last one specified in
/// the `--tabs` argument.
#[derive(PartialEq)]
enum RemainingMode {
None,
Slash,
@ -65,6 +66,7 @@ fn is_space_or_comma(c: char) -> bool {
enum ParseError {
InvalidCharacter(String),
SpecifierNotAtStartOfNumber(String, String),
SpecifierOnlyAllowedWithLastValue(String),
TabSizeCannotBeZero,
TabSizeTooLarge(String),
TabSizesMustBeAscending,
@ -85,6 +87,11 @@ impl fmt::Display for ParseError {
specifier.quote(),
s.quote(),
),
Self::SpecifierOnlyAllowedWithLastValue(specifier) => write!(
f,
"{} specifier only allowed with the last value",
specifier.quote()
),
Self::TabSizeCannotBeZero => write!(f, "tab size cannot be 0"),
Self::TabSizeTooLarge(s) => write!(f, "tab stop is too large {}", s.quote()),
Self::TabSizesMustBeAscending => write!(f, "tab sizes must be ascending"),
@ -112,6 +119,7 @@ fn tabstops_parse(s: &str) -> Result<(RemainingMode, Vec<usize>), ParseError> {
let mut nums = vec![];
let mut remaining_mode = RemainingMode::None;
let mut is_specifier_already_used = false;
for word in s.split(is_space_or_comma) {
let bytes = word.as_bytes();
for i in 0..bytes.len() {
@ -139,6 +147,19 @@ fn tabstops_parse(s: &str) -> Result<(RemainingMode, Vec<usize>), ParseError> {
}
}
if is_specifier_already_used {
let specifier = if remaining_mode == RemainingMode::Slash {
"/".to_string()
} else {
"+".to_string()
};
return Err(ParseError::SpecifierOnlyAllowedWithLastValue(
specifier,
));
} else if remaining_mode != RemainingMode::None {
is_specifier_already_used = true;
}
// Append this tab stop to the list of all tabstops.
nums.push(num);
break;

View file

@ -226,6 +226,24 @@ fn test_tabs_with_specifier_not_at_start() {
run_cmd("--tabs=1+2", "+", "+2");
}
#[test]
fn test_tabs_with_specifier_only_allowed_with_last_value() {
fn run_cmd(arg: &str, specifier: &str) {
let expected_msg = format!(
"{} specifier only allowed with the last value",
specifier.quote()
);
new_ucmd!().arg(arg).fails().stderr_contains(expected_msg);
}
run_cmd("--tabs=/1,2,3", "/");
run_cmd("--tabs=1,/2,3", "/");
new_ucmd!().arg("--tabs=1,2,/3").succeeds();
run_cmd("--tabs=+1,2,3", "+");
run_cmd("--tabs=1,+2,3", "+");
new_ucmd!().arg("--tabs=1,2,+3").succeeds();
}
#[test]
fn test_tabs_with_invalid_chars() {
new_ucmd!()