Use stable rustfmt instead of nightly (#967)
This commit is contained in:
parent
ca2b596c90
commit
629c75ff04
12
.github/workflows/build.yaml
vendored
12
.github/workflows/build.yaml
vendored
@ -80,7 +80,7 @@ jobs:
|
||||
|
||||
- name: Install Rust Toolchain
|
||||
run: |
|
||||
rustup component add clippy
|
||||
rustup component add clippy rustfmt
|
||||
rustup target add ${{ matrix.target }}
|
||||
rustup default "`cat rust-toolchain`-${{ matrix.target }}"
|
||||
|
||||
@ -108,16 +108,8 @@ jobs:
|
||||
- name: Clippy
|
||||
run: cargo clippy --all --all-targets --all-features
|
||||
|
||||
- name: Install Rustfmt Toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: nightly
|
||||
target: ${{ matrix.target }}
|
||||
profile: minimal
|
||||
components: rustfmt
|
||||
|
||||
- name: Format
|
||||
run: cargo +nightly fmt --all -- --check
|
||||
run: cargo fmt --all -- --check
|
||||
|
||||
- name: Completion Scripts
|
||||
if: ${{ matrix.os != 'windows-2016' }}
|
||||
|
3
justfile
3
justfile
@ -31,7 +31,7 @@ build:
|
||||
cargo lbuild
|
||||
|
||||
fmt:
|
||||
cargo +nightly fmt --all
|
||||
cargo fmt --all
|
||||
|
||||
watch +COMMAND='ltest':
|
||||
cargo watch --clear --exec "{{COMMAND}}"
|
||||
@ -94,7 +94,6 @@ install:
|
||||
install-dev-deps:
|
||||
rustup install nightly
|
||||
rustup update nightly
|
||||
rustup run nightly cargo install clippy
|
||||
cargo +nightly install cargo-fuzz
|
||||
cargo install cargo-check
|
||||
cargo install cargo-limit
|
||||
|
15
rustfmt.toml
15
rustfmt.toml
@ -1,21 +1,6 @@
|
||||
comment_width = 80
|
||||
edition = "2018"
|
||||
error_on_line_overflow = true
|
||||
error_on_unformatted = true
|
||||
format_code_in_doc_comments = true
|
||||
format_macro_bodies = true
|
||||
format_strings = true
|
||||
imports_granularity = "Crate"
|
||||
match_arm_blocks = false
|
||||
match_block_trailing_comma = true
|
||||
max_width = 100
|
||||
newline_style = "Unix"
|
||||
normalize_comments = true
|
||||
overflow_delimited_expr = true
|
||||
reorder_impl_items = true
|
||||
struct_field_align_threshold = 20
|
||||
tab_spaces = 2
|
||||
unstable_features = true
|
||||
use_field_init_shorthand = true
|
||||
use_try_shorthand = true
|
||||
wrap_comments = true
|
||||
|
@ -21,20 +21,20 @@ impl<'src> Analyzer<'src> {
|
||||
Item::Alias(alias) => {
|
||||
self.analyze_alias(&alias)?;
|
||||
self.aliases.insert(alias);
|
||||
},
|
||||
}
|
||||
Item::Assignment(assignment) => {
|
||||
self.analyze_assignment(&assignment)?;
|
||||
self.assignments.insert(assignment);
|
||||
},
|
||||
}
|
||||
Item::Comment(_) => (),
|
||||
Item::Recipe(recipe) => {
|
||||
self.analyze_recipe(&recipe)?;
|
||||
self.recipes.insert(recipe);
|
||||
},
|
||||
}
|
||||
Item::Set(set) => {
|
||||
self.analyze_set(&set)?;
|
||||
self.sets.insert(set);
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,17 +65,17 @@ impl<'src> Analyzer<'src> {
|
||||
match set.value {
|
||||
Setting::DotenvLoad(dotenv_load) => {
|
||||
settings.dotenv_load = Some(dotenv_load);
|
||||
},
|
||||
}
|
||||
Setting::Export(export) => {
|
||||
settings.export = export;
|
||||
},
|
||||
}
|
||||
Setting::PositionalArguments(positional_arguments) => {
|
||||
settings.positional_arguments = positional_arguments;
|
||||
},
|
||||
}
|
||||
Setting::Shell(shell) => {
|
||||
assert!(settings.shell.is_none());
|
||||
settings.shell = Some(shell);
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,26 +74,26 @@ impl<'src: 'run, 'run> AssignmentResolver<'src, 'run> {
|
||||
} else {
|
||||
Err(name.token().error(UndefinedVariable { variable }))
|
||||
}
|
||||
},
|
||||
}
|
||||
Expression::Call { thunk } => match thunk {
|
||||
Thunk::Nullary { .. } => Ok(()),
|
||||
Thunk::Unary { arg, .. } => self.resolve_expression(arg),
|
||||
Thunk::Binary { args: [a, b], .. } => {
|
||||
self.resolve_expression(a)?;
|
||||
self.resolve_expression(b)
|
||||
},
|
||||
}
|
||||
Thunk::Ternary {
|
||||
args: [a, b, c], ..
|
||||
} => {
|
||||
self.resolve_expression(a)?;
|
||||
self.resolve_expression(b)?;
|
||||
self.resolve_expression(c)
|
||||
},
|
||||
}
|
||||
},
|
||||
Expression::Concatination { lhs, rhs } => {
|
||||
self.resolve_expression(lhs)?;
|
||||
self.resolve_expression(rhs)
|
||||
},
|
||||
}
|
||||
Expression::Conditional {
|
||||
lhs,
|
||||
rhs,
|
||||
@ -105,7 +105,7 @@ impl<'src: 'run, 'run> AssignmentResolver<'src, 'run> {
|
||||
self.resolve_expression(rhs)?;
|
||||
self.resolve_expression(then)?;
|
||||
self.resolve_expression(otherwise)
|
||||
},
|
||||
}
|
||||
Expression::StringLiteral { .. } | Expression::Backtick { .. } => Ok(()),
|
||||
Expression::Group { contents } => self.resolve_expression(contents),
|
||||
}
|
||||
|
@ -26,11 +26,11 @@ impl Display for CompileError<'_> {
|
||||
alias,
|
||||
recipe_line.ordinal(),
|
||||
)?;
|
||||
},
|
||||
}
|
||||
BacktickShebang => {
|
||||
write!(f, "Backticks may not start with `#!`")?;
|
||||
},
|
||||
CircularRecipeDependency { recipe, ref circle } =>
|
||||
}
|
||||
CircularRecipeDependency { recipe, ref circle } => {
|
||||
if circle.len() == 2 {
|
||||
write!(f, "Recipe `{}` depends on itself", recipe)?;
|
||||
} else {
|
||||
@ -40,11 +40,12 @@ impl Display for CompileError<'_> {
|
||||
recipe,
|
||||
circle.join(" -> ")
|
||||
)?;
|
||||
},
|
||||
}
|
||||
}
|
||||
CircularVariableDependency {
|
||||
variable,
|
||||
ref circle,
|
||||
} =>
|
||||
} => {
|
||||
if circle.len() == 2 {
|
||||
write!(f, "Variable `{}` is defined in terms of itself", variable)?;
|
||||
} else {
|
||||
@ -54,7 +55,8 @@ impl Display for CompileError<'_> {
|
||||
variable,
|
||||
circle.join(" -> ")
|
||||
)?;
|
||||
},
|
||||
}
|
||||
}
|
||||
DependencyArgumentCountMismatch {
|
||||
dependency,
|
||||
found,
|
||||
@ -77,7 +79,7 @@ impl Display for CompileError<'_> {
|
||||
} else {
|
||||
write!(f, "at most {} {}", max, Count("argument", *max))?;
|
||||
}
|
||||
},
|
||||
}
|
||||
DeprecatedEquals => {
|
||||
writeln!(
|
||||
f,
|
||||
@ -87,7 +89,7 @@ impl Display for CompileError<'_> {
|
||||
f,
|
||||
"Please see this issue for more details: https://github.com/casey/just/issues/379"
|
||||
)?;
|
||||
},
|
||||
}
|
||||
DuplicateAlias { alias, first } => {
|
||||
write!(
|
||||
f,
|
||||
@ -96,14 +98,14 @@ impl Display for CompileError<'_> {
|
||||
first.ordinal(),
|
||||
self.token.line.ordinal(),
|
||||
)?;
|
||||
},
|
||||
}
|
||||
DuplicateParameter { recipe, parameter } => {
|
||||
write!(
|
||||
f,
|
||||
"Recipe `{}` has duplicate parameter `{}`",
|
||||
recipe, parameter
|
||||
)?;
|
||||
},
|
||||
}
|
||||
DuplicateRecipe { recipe, first } => {
|
||||
write!(
|
||||
f,
|
||||
@ -112,7 +114,7 @@ impl Display for CompileError<'_> {
|
||||
first.ordinal(),
|
||||
self.token.line.ordinal()
|
||||
)?;
|
||||
},
|
||||
}
|
||||
DuplicateSet { setting, first } => {
|
||||
write!(
|
||||
f,
|
||||
@ -121,10 +123,10 @@ impl Display for CompileError<'_> {
|
||||
first.ordinal(),
|
||||
self.token.line.ordinal(),
|
||||
)?;
|
||||
},
|
||||
}
|
||||
DuplicateVariable { variable } => {
|
||||
write!(f, "Variable `{}` has multiple definitions", variable)?;
|
||||
},
|
||||
}
|
||||
ExpectedKeyword { expected, found } => write!(
|
||||
f,
|
||||
"Expected keyword {} but found identifier `{}`",
|
||||
@ -133,7 +135,7 @@ impl Display for CompileError<'_> {
|
||||
)?,
|
||||
ExtraLeadingWhitespace => {
|
||||
write!(f, "Recipe line has extra leading whitespace")?;
|
||||
},
|
||||
}
|
||||
FunctionArgumentCountMismatch {
|
||||
function,
|
||||
found,
|
||||
@ -147,7 +149,7 @@ impl Display for CompileError<'_> {
|
||||
Count("argument", *found),
|
||||
expected
|
||||
)?;
|
||||
},
|
||||
}
|
||||
InconsistentLeadingWhitespace { expected, found } => {
|
||||
write!(
|
||||
f,
|
||||
@ -156,7 +158,7 @@ impl Display for CompileError<'_> {
|
||||
ShowWhitespace(expected),
|
||||
ShowWhitespace(found)
|
||||
)?;
|
||||
},
|
||||
}
|
||||
Internal { ref message } => {
|
||||
write!(
|
||||
f,
|
||||
@ -164,7 +166,7 @@ impl Display for CompileError<'_> {
|
||||
consider filing an issue: https://github.com/casey/just/issues/new",
|
||||
message
|
||||
)?;
|
||||
},
|
||||
}
|
||||
InvalidEscapeSequence { character } => {
|
||||
let representation = match character {
|
||||
'`' => r"\`".to_owned(),
|
||||
@ -174,7 +176,7 @@ impl Display for CompileError<'_> {
|
||||
_ => character.escape_default().collect(),
|
||||
};
|
||||
write!(f, "`\\{}` is not a valid escape sequence", representation)?;
|
||||
},
|
||||
}
|
||||
MismatchedClosingDelimiter {
|
||||
open,
|
||||
open_line,
|
||||
@ -187,7 +189,7 @@ impl Display for CompileError<'_> {
|
||||
open.open(),
|
||||
open_line.ordinal(),
|
||||
)?;
|
||||
},
|
||||
}
|
||||
MixedLeadingWhitespace { whitespace } => {
|
||||
write!(
|
||||
f,
|
||||
@ -195,73 +197,73 @@ impl Display for CompileError<'_> {
|
||||
consist of tabs or spaces, but not both",
|
||||
ShowWhitespace(whitespace)
|
||||
)?;
|
||||
},
|
||||
}
|
||||
ParameterFollowsVariadicParameter { parameter } => {
|
||||
write!(f, "Parameter `{}` follows variadic parameter", parameter)?;
|
||||
},
|
||||
}
|
||||
ParameterShadowsVariable { parameter } => {
|
||||
write!(
|
||||
f,
|
||||
"Parameter `{}` shadows variable of the same name",
|
||||
parameter
|
||||
)?;
|
||||
},
|
||||
}
|
||||
RequiredParameterFollowsDefaultParameter { parameter } => {
|
||||
write!(
|
||||
f,
|
||||
"Non-default parameter `{}` follows default parameter",
|
||||
parameter
|
||||
)?;
|
||||
},
|
||||
}
|
||||
UndefinedVariable { variable } => {
|
||||
write!(f, "Variable `{}` not defined", variable)?;
|
||||
},
|
||||
}
|
||||
UnexpectedCharacter { expected } => {
|
||||
write!(f, "Expected character `{}`", expected)?;
|
||||
},
|
||||
}
|
||||
UnexpectedClosingDelimiter { close } => {
|
||||
write!(f, "Unexpected closing delimiter `{}`", close.close())?;
|
||||
},
|
||||
}
|
||||
UnexpectedEndOfToken { expected } => {
|
||||
write!(f, "Expected character `{}` but found end-of-file", expected)?;
|
||||
},
|
||||
}
|
||||
UnexpectedToken {
|
||||
ref expected,
|
||||
found,
|
||||
} => {
|
||||
write!(f, "Expected {}, but found {}", List::or(expected), found)?;
|
||||
},
|
||||
}
|
||||
UnknownAliasTarget { alias, target } => {
|
||||
write!(f, "Alias `{}` has an unknown target `{}`", alias, target)?;
|
||||
},
|
||||
}
|
||||
UnknownDependency { recipe, unknown } => {
|
||||
write!(
|
||||
f,
|
||||
"Recipe `{}` has unknown dependency `{}`",
|
||||
recipe, unknown
|
||||
)?;
|
||||
},
|
||||
}
|
||||
UnknownFunction { function } => {
|
||||
write!(f, "Call to unknown function `{}`", function)?;
|
||||
},
|
||||
}
|
||||
UnknownSetting { setting } => {
|
||||
write!(f, "Unknown setting `{}`", setting)?;
|
||||
},
|
||||
}
|
||||
UnknownStartOfToken => {
|
||||
write!(f, "Unknown start of token:")?;
|
||||
},
|
||||
}
|
||||
UnpairedCarriageReturn => {
|
||||
write!(f, "Unpaired carriage return")?;
|
||||
},
|
||||
}
|
||||
UnterminatedBacktick => {
|
||||
write!(f, "Unterminated backtick")?;
|
||||
},
|
||||
}
|
||||
UnterminatedInterpolation => {
|
||||
write!(f, "Unterminated interpolation")?;
|
||||
},
|
||||
}
|
||||
UnterminatedString => {
|
||||
write!(f, "Unterminated string")?;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -416,15 +416,17 @@ impl Config {
|
||||
match (justfile, working_directory) {
|
||||
(None, None) => SearchConfig::FromInvocationDirectory,
|
||||
(Some(justfile), None) => SearchConfig::WithJustfile { justfile },
|
||||
(Some(justfile), Some(working_directory)) =>
|
||||
(Some(justfile), Some(working_directory)) => {
|
||||
SearchConfig::WithJustfileAndWorkingDirectory {
|
||||
justfile,
|
||||
working_directory,
|
||||
},
|
||||
(None, Some(_)) =>
|
||||
}
|
||||
}
|
||||
(None, Some(_)) => {
|
||||
return Err(ConfigError::internal(
|
||||
"--working-directory set without --justfile",
|
||||
)),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -432,26 +434,26 @@ impl Config {
|
||||
for subcommand in cmd::ARGLESS {
|
||||
if matches.is_present(subcommand) {
|
||||
match (!overrides.is_empty(), !positional.arguments.is_empty()) {
|
||||
(false, false) => {},
|
||||
(false, false) => {}
|
||||
(true, false) => {
|
||||
return Err(ConfigError::SubcommandOverrides {
|
||||
subcommand,
|
||||
overrides,
|
||||
});
|
||||
},
|
||||
}
|
||||
(false, true) => {
|
||||
return Err(ConfigError::SubcommandArguments {
|
||||
arguments: positional.arguments,
|
||||
subcommand,
|
||||
});
|
||||
},
|
||||
}
|
||||
(true, true) => {
|
||||
return Err(ConfigError::SubcommandOverridesAndArguments {
|
||||
arguments: positional.arguments,
|
||||
subcommand,
|
||||
overrides,
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
89
src/error.rs
89
src/error.rs
@ -204,7 +204,7 @@ impl<'src> ColorDisplay for Error<'src> {
|
||||
min,
|
||||
max,
|
||||
..
|
||||
} =>
|
||||
} => {
|
||||
if min == max {
|
||||
let expected = min;
|
||||
write!(
|
||||
@ -234,17 +234,18 @@ impl<'src> ColorDisplay for Error<'src> {
|
||||
Count("argument", *found),
|
||||
max
|
||||
)?;
|
||||
},
|
||||
}
|
||||
}
|
||||
Backtick { output_error, .. } => match output_error {
|
||||
OutputError::Code(code) => {
|
||||
write!(f, "Backtick failed with exit code {}", code)?;
|
||||
},
|
||||
}
|
||||
OutputError::Signal(signal) => {
|
||||
write!(f, "Backtick was terminated by signal {}", signal)?;
|
||||
},
|
||||
}
|
||||
OutputError::Unknown => {
|
||||
write!(f, "Backtick failed for an unknown reason")?;
|
||||
},
|
||||
}
|
||||
OutputError::Io(io_error) => {
|
||||
match io_error.kind() {
|
||||
io::ErrorKind::NotFound => write!(
|
||||
@ -263,14 +264,14 @@ impl<'src> ColorDisplay for Error<'src> {
|
||||
io_error
|
||||
),
|
||||
}?;
|
||||
},
|
||||
}
|
||||
OutputError::Utf8(utf8_error) => {
|
||||
write!(
|
||||
f,
|
||||
"Backtick succeeded but stdout was not utf8: {}",
|
||||
utf8_error
|
||||
)?;
|
||||
},
|
||||
}
|
||||
},
|
||||
ChooserInvoke {
|
||||
shell_binary,
|
||||
@ -286,7 +287,7 @@ impl<'src> ColorDisplay for Error<'src> {
|
||||
chooser.to_string_lossy(),
|
||||
io_error,
|
||||
)?;
|
||||
},
|
||||
}
|
||||
ChooserRead { chooser, io_error } => {
|
||||
write!(
|
||||
f,
|
||||
@ -294,7 +295,7 @@ impl<'src> ColorDisplay for Error<'src> {
|
||||
chooser.to_string_lossy(),
|
||||
io_error
|
||||
)?;
|
||||
},
|
||||
}
|
||||
ChooserStatus { chooser, status } => {
|
||||
write!(
|
||||
f,
|
||||
@ -302,7 +303,7 @@ impl<'src> ColorDisplay for Error<'src> {
|
||||
chooser.to_string_lossy(),
|
||||
status
|
||||
)?;
|
||||
},
|
||||
}
|
||||
ChooserWrite { chooser, io_error } => {
|
||||
write!(
|
||||
f,
|
||||
@ -310,12 +311,12 @@ impl<'src> ColorDisplay for Error<'src> {
|
||||
chooser.to_string_lossy(),
|
||||
io_error
|
||||
)?;
|
||||
},
|
||||
}
|
||||
Code {
|
||||
recipe,
|
||||
line_number,
|
||||
code,
|
||||
} =>
|
||||
} => {
|
||||
if let Some(n) = line_number {
|
||||
write!(
|
||||
f,
|
||||
@ -324,7 +325,8 @@ impl<'src> ColorDisplay for Error<'src> {
|
||||
)?;
|
||||
} else {
|
||||
write!(f, "Recipe `{}` failed with exit code {}", recipe, code)?;
|
||||
},
|
||||
}
|
||||
}
|
||||
CommandInvoke {
|
||||
binary,
|
||||
arguments,
|
||||
@ -340,7 +342,7 @@ impl<'src> ColorDisplay for Error<'src> {
|
||||
.join(" "),
|
||||
io_error,
|
||||
)?;
|
||||
},
|
||||
}
|
||||
CommandStatus {
|
||||
binary,
|
||||
arguments,
|
||||
@ -356,7 +358,7 @@ impl<'src> ColorDisplay for Error<'src> {
|
||||
.join(" "),
|
||||
status,
|
||||
)?;
|
||||
},
|
||||
}
|
||||
Compile { compile_error } => Display::fmt(compile_error, f)?,
|
||||
Config { config_error } => Display::fmt(config_error, f)?,
|
||||
Cygpath {
|
||||
@ -370,7 +372,7 @@ impl<'src> ColorDisplay for Error<'src> {
|
||||
path",
|
||||
code, recipe
|
||||
)?;
|
||||
},
|
||||
}
|
||||
OutputError::Signal(signal) => {
|
||||
write!(
|
||||
f,
|
||||
@ -378,7 +380,7 @@ impl<'src> ColorDisplay for Error<'src> {
|
||||
path",
|
||||
signal, recipe
|
||||
)?;
|
||||
},
|
||||
}
|
||||
OutputError::Unknown => {
|
||||
write!(
|
||||
f,
|
||||
@ -386,7 +388,7 @@ impl<'src> ColorDisplay for Error<'src> {
|
||||
interpreter path",
|
||||
recipe
|
||||
)?;
|
||||
},
|
||||
}
|
||||
OutputError::Io(io_error) => {
|
||||
match io_error.kind() {
|
||||
io::ErrorKind::NotFound => write!(
|
||||
@ -403,7 +405,7 @@ impl<'src> ColorDisplay for Error<'src> {
|
||||
),
|
||||
_ => write!(f, "Could not run `cygpath` executable:\n{}", io_error),
|
||||
}?;
|
||||
},
|
||||
}
|
||||
OutputError::Utf8(utf8_error) => {
|
||||
write!(
|
||||
f,
|
||||
@ -411,7 +413,7 @@ impl<'src> ColorDisplay for Error<'src> {
|
||||
not utf8: {}",
|
||||
recipe, utf8_error
|
||||
)?;
|
||||
},
|
||||
}
|
||||
},
|
||||
DefaultRecipeRequiresArguments {
|
||||
recipe,
|
||||
@ -424,10 +426,10 @@ impl<'src> ColorDisplay for Error<'src> {
|
||||
min_arguments,
|
||||
Count("argument", *min_arguments),
|
||||
)?;
|
||||
},
|
||||
}
|
||||
Dotenv { dotenv_error } => {
|
||||
write!(f, "Failed to load environment file: {}", dotenv_error)?;
|
||||
},
|
||||
}
|
||||
EditorInvoke { editor, io_error } => {
|
||||
write!(
|
||||
f,
|
||||
@ -435,7 +437,7 @@ impl<'src> ColorDisplay for Error<'src> {
|
||||
editor.to_string_lossy(),
|
||||
io_error
|
||||
)?;
|
||||
},
|
||||
}
|
||||
EditorStatus { editor, status } => {
|
||||
write!(
|
||||
f,
|
||||
@ -443,7 +445,7 @@ impl<'src> ColorDisplay for Error<'src> {
|
||||
editor.to_string_lossy(),
|
||||
status
|
||||
)?;
|
||||
},
|
||||
}
|
||||
EvalUnknownVariable {
|
||||
variable,
|
||||
suggestion,
|
||||
@ -452,7 +454,7 @@ impl<'src> ColorDisplay for Error<'src> {
|
||||
if let Some(suggestion) = *suggestion {
|
||||
write!(f, "\n{}", suggestion)?;
|
||||
}
|
||||
},
|
||||
}
|
||||
FunctionCall { function, message } => {
|
||||
write!(
|
||||
f,
|
||||
@ -460,10 +462,10 @@ impl<'src> ColorDisplay for Error<'src> {
|
||||
function.lexeme(),
|
||||
message
|
||||
)?;
|
||||
},
|
||||
}
|
||||
InitExists { justfile } => {
|
||||
write!(f, "Justfile `{}` already exists", justfile.display())?;
|
||||
},
|
||||
}
|
||||
Internal { message } => {
|
||||
write!(
|
||||
f,
|
||||
@ -471,7 +473,7 @@ impl<'src> ColorDisplay for Error<'src> {
|
||||
consider filing an issue: https://github.com/casey/just/issues/new",
|
||||
message
|
||||
)?;
|
||||
},
|
||||
}
|
||||
Io { recipe, io_error } => {
|
||||
match io_error.kind() {
|
||||
io::ErrorKind::NotFound => write!(
|
||||
@ -490,7 +492,7 @@ impl<'src> ColorDisplay for Error<'src> {
|
||||
recipe, io_error
|
||||
),
|
||||
}?;
|
||||
},
|
||||
}
|
||||
Load { io_error, path } => {
|
||||
write!(
|
||||
f,
|
||||
@ -498,20 +500,20 @@ impl<'src> ColorDisplay for Error<'src> {
|
||||
path.display(),
|
||||
io_error
|
||||
)?;
|
||||
},
|
||||
}
|
||||
NoChoosableRecipes => {
|
||||
write!(f, "Justfile contains no choosable recipes.")?;
|
||||
},
|
||||
}
|
||||
NoRecipes => {
|
||||
write!(f, "Justfile contains no recipes.")?;
|
||||
},
|
||||
}
|
||||
Search { search_error } => Display::fmt(search_error, f)?,
|
||||
Shebang {
|
||||
recipe,
|
||||
command,
|
||||
argument,
|
||||
io_error,
|
||||
} =>
|
||||
} => {
|
||||
if let Some(argument) = argument {
|
||||
write!(
|
||||
f,
|
||||
@ -524,12 +526,13 @@ impl<'src> ColorDisplay for Error<'src> {
|
||||
"Recipe `{}` with shebang `#!{}` execution error: {}",
|
||||
recipe, command, io_error
|
||||
)?;
|
||||
},
|
||||
}
|
||||
}
|
||||
Signal {
|
||||
recipe,
|
||||
line_number,
|
||||
signal,
|
||||
} =>
|
||||
} => {
|
||||
if let Some(n) = line_number {
|
||||
write!(
|
||||
f,
|
||||
@ -538,7 +541,8 @@ impl<'src> ColorDisplay for Error<'src> {
|
||||
)?;
|
||||
} else {
|
||||
write!(f, "Recipe `{}` was terminated by signal {}", recipe, signal)?;
|
||||
},
|
||||
}
|
||||
}
|
||||
TmpdirIo { recipe, io_error } => write!(
|
||||
f,
|
||||
"Recipe `{}` could not be run because of an IO error while trying to create a temporary \
|
||||
@ -548,7 +552,7 @@ impl<'src> ColorDisplay for Error<'src> {
|
||||
Unknown {
|
||||
recipe,
|
||||
line_number,
|
||||
} =>
|
||||
} => {
|
||||
if let Some(n) = line_number {
|
||||
write!(
|
||||
f,
|
||||
@ -557,7 +561,8 @@ impl<'src> ColorDisplay for Error<'src> {
|
||||
)?;
|
||||
} else {
|
||||
write!(f, "Recipe `{}` failed for an unknown reason", recipe)?;
|
||||
},
|
||||
}
|
||||
}
|
||||
UnknownOverrides { overrides } => {
|
||||
write!(
|
||||
f,
|
||||
@ -565,7 +570,7 @@ impl<'src> ColorDisplay for Error<'src> {
|
||||
Count("Variable", overrides.len()),
|
||||
List::and_ticked(overrides),
|
||||
)?;
|
||||
},
|
||||
}
|
||||
UnknownRecipes {
|
||||
recipes,
|
||||
suggestion,
|
||||
@ -579,14 +584,14 @@ impl<'src> ColorDisplay for Error<'src> {
|
||||
if let Some(suggestion) = *suggestion {
|
||||
write!(f, "\n{}", suggestion)?;
|
||||
}
|
||||
},
|
||||
}
|
||||
Unstable { message } => {
|
||||
write!(
|
||||
f,
|
||||
"{} Invoke `just` with the `--unstable` flag to enable unstable features.",
|
||||
message
|
||||
)?;
|
||||
},
|
||||
}
|
||||
WriteJustfile { justfile, io_error } => {
|
||||
write!(
|
||||
f,
|
||||
@ -594,7 +599,7 @@ impl<'src> ColorDisplay for Error<'src> {
|
||||
justfile.display(),
|
||||
io_error
|
||||
)?;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
write!(f, "{}", color.message().suffix())?;
|
||||
|
@ -64,7 +64,7 @@ impl<'src, 'run> Evaluator<'src, 'run> {
|
||||
message: format!("attempted to evaluate undefined variable `{}`", variable),
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
Expression::Call { thunk } => {
|
||||
use Thunk::*;
|
||||
|
||||
@ -75,11 +75,12 @@ impl<'src, 'run> Evaluator<'src, 'run> {
|
||||
};
|
||||
|
||||
match thunk {
|
||||
Nullary { name, function, .. } =>
|
||||
Nullary { name, function, .. } => {
|
||||
function(&context).map_err(|message| Error::FunctionCall {
|
||||
function: *name,
|
||||
message,
|
||||
}),
|
||||
})
|
||||
}
|
||||
Unary {
|
||||
name,
|
||||
function,
|
||||
@ -121,16 +122,18 @@ impl<'src, 'run> Evaluator<'src, 'run> {
|
||||
message,
|
||||
}),
|
||||
}
|
||||
},
|
||||
}
|
||||
Expression::StringLiteral { string_literal } => Ok(string_literal.cooked.clone()),
|
||||
Expression::Backtick { contents, token } =>
|
||||
Expression::Backtick { contents, token } => {
|
||||
if self.config.dry_run {
|
||||
Ok(format!("`{}`", contents))
|
||||
} else {
|
||||
Ok(self.run_backtick(contents, token)?)
|
||||
},
|
||||
Expression::Concatination { lhs, rhs } =>
|
||||
Ok(self.evaluate_expression(lhs)? + &self.evaluate_expression(rhs)?),
|
||||
}
|
||||
}
|
||||
Expression::Concatination { lhs, rhs } => {
|
||||
Ok(self.evaluate_expression(lhs)? + &self.evaluate_expression(rhs)?)
|
||||
}
|
||||
Expression::Conditional {
|
||||
lhs,
|
||||
rhs,
|
||||
@ -146,7 +149,7 @@ impl<'src, 'run> Evaluator<'src, 'run> {
|
||||
} else {
|
||||
self.evaluate_expression(otherwise)
|
||||
}
|
||||
},
|
||||
}
|
||||
Expression::Group { contents } => self.evaluate_expression(contents),
|
||||
}
|
||||
}
|
||||
@ -192,10 +195,10 @@ impl<'src, 'run> Evaluator<'src, 'run> {
|
||||
} else {
|
||||
evaluated += &lexeme;
|
||||
}
|
||||
},
|
||||
}
|
||||
Fragment::Interpolation { expression } => {
|
||||
evaluated += &self.evaluate_expression(expression)?;
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(evaluated)
|
||||
|
@ -29,7 +29,7 @@ impl InterruptHandler {
|
||||
.color_display(Color::auto().stderr())
|
||||
);
|
||||
std::process::exit(EXIT_FAILURE);
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,16 +33,19 @@ impl<'src> Justfile<'src> {
|
||||
.recipes
|
||||
.keys()
|
||||
.map(|name| {
|
||||
(edit_distance(name, input), Suggestion {
|
||||
name,
|
||||
target: None,
|
||||
})
|
||||
(
|
||||
edit_distance(name, input),
|
||||
Suggestion { name, target: None },
|
||||
)
|
||||
})
|
||||
.chain(self.aliases.iter().map(|(name, alias)| {
|
||||
(edit_distance(name, input), Suggestion {
|
||||
(
|
||||
edit_distance(name, input),
|
||||
Suggestion {
|
||||
name,
|
||||
target: Some(alias.target.name.lexeme()),
|
||||
})
|
||||
},
|
||||
)
|
||||
}))
|
||||
.filter(|(distance, _suggestion)| distance < &3)
|
||||
.collect::<Vec<(usize, Suggestion)>>();
|
||||
@ -59,10 +62,10 @@ impl<'src> Justfile<'src> {
|
||||
.assignments
|
||||
.keys()
|
||||
.map(|name| {
|
||||
(edit_distance(name, input), Suggestion {
|
||||
name,
|
||||
target: None,
|
||||
})
|
||||
(
|
||||
edit_distance(name, input),
|
||||
Suggestion { name, target: None },
|
||||
)
|
||||
})
|
||||
.filter(|(distance, _suggestion)| distance < &3)
|
||||
.collect::<Vec<(usize, Suggestion)>>();
|
||||
@ -168,7 +171,7 @@ impl<'src> Justfile<'src> {
|
||||
};
|
||||
|
||||
return Ok(());
|
||||
},
|
||||
}
|
||||
Subcommand::Evaluate { variable, .. } => {
|
||||
if let Some(variable) = variable {
|
||||
if let Some(value) = scope.value(variable) {
|
||||
@ -197,8 +200,8 @@ impl<'src> Justfile<'src> {
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let argvec: Vec<&str> = if !arguments.is_empty() {
|
||||
|
39
src/lexer.rs
39
src/lexer.rs
@ -86,7 +86,7 @@ impl<'src> Lexer<'src> {
|
||||
self.next = self.chars.next();
|
||||
|
||||
Ok(())
|
||||
},
|
||||
}
|
||||
None => Err(self.internal_error("Lexer advanced past end of text")),
|
||||
}
|
||||
}
|
||||
@ -226,11 +226,12 @@ impl<'src> Lexer<'src> {
|
||||
UnterminatedString | UnterminatedBacktick => {
|
||||
let kind = match StringKind::from_token_start(self.lexeme()) {
|
||||
Some(kind) => kind,
|
||||
None =>
|
||||
return self.internal_error("Lexer::error: expected string or backtick token start"),
|
||||
None => {
|
||||
return self.internal_error("Lexer::error: expected string or backtick token start")
|
||||
}
|
||||
};
|
||||
kind.delimiter().len()
|
||||
},
|
||||
}
|
||||
// highlight the full token
|
||||
_ => self.lexeme().len(),
|
||||
};
|
||||
@ -304,7 +305,7 @@ impl<'src> Lexer<'src> {
|
||||
} else {
|
||||
self.lex_normal(first)?;
|
||||
};
|
||||
},
|
||||
}
|
||||
None => break,
|
||||
}
|
||||
}
|
||||
@ -411,7 +412,7 @@ impl<'src> Lexer<'src> {
|
||||
};
|
||||
|
||||
Ok(())
|
||||
},
|
||||
}
|
||||
Continue => {
|
||||
if !self.indentation().is_empty() {
|
||||
for _ in self.indentation().chars() {
|
||||
@ -422,7 +423,7 @@ impl<'src> Lexer<'src> {
|
||||
}
|
||||
|
||||
Ok(())
|
||||
},
|
||||
}
|
||||
Decrease => {
|
||||
while self.indentation() != whitespace {
|
||||
self.lex_dedent();
|
||||
@ -437,14 +438,14 @@ impl<'src> Lexer<'src> {
|
||||
}
|
||||
|
||||
Ok(())
|
||||
},
|
||||
}
|
||||
Mixed { whitespace } => {
|
||||
for _ in whitespace.chars() {
|
||||
self.advance()?;
|
||||
}
|
||||
|
||||
Err(self.error(MixedLeadingWhitespace { whitespace }))
|
||||
},
|
||||
}
|
||||
Inconsistent => {
|
||||
for _ in whitespace.chars() {
|
||||
self.advance()?;
|
||||
@ -454,7 +455,7 @@ impl<'src> Lexer<'src> {
|
||||
expected: self.indentation(),
|
||||
found: whitespace,
|
||||
}))
|
||||
},
|
||||
}
|
||||
Increase => {
|
||||
while self.next_is_whitespace() {
|
||||
self.advance()?;
|
||||
@ -472,7 +473,7 @@ impl<'src> Lexer<'src> {
|
||||
}
|
||||
|
||||
Ok(())
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -504,7 +505,7 @@ impl<'src> Lexer<'src> {
|
||||
_ => {
|
||||
self.advance()?;
|
||||
Err(self.error(UnknownStartOfToken))
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -585,7 +586,7 @@ impl<'src> Lexer<'src> {
|
||||
.interpolation_stack
|
||||
.push(self.tokens[self.tokens.len() - 1]);
|
||||
Ok(())
|
||||
},
|
||||
}
|
||||
EndOfFile => Ok(()),
|
||||
}
|
||||
}
|
||||
@ -644,11 +645,12 @@ impl<'src> Lexer<'src> {
|
||||
BracketR => self.close_delimiter(Bracket)?,
|
||||
ParenL => self.open_delimiter(Paren),
|
||||
ParenR => self.close_delimiter(Paren)?,
|
||||
_ =>
|
||||
_ => {
|
||||
return Err(self.internal_error(format!(
|
||||
"Lexer::lex_delimiter called with non-delimiter token: `{}`",
|
||||
kind,
|
||||
))),
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
// Emit the delimiter token
|
||||
@ -947,8 +949,9 @@ mod tests {
|
||||
Dedent | Eof => "",
|
||||
|
||||
// Variable lexemes
|
||||
Text | StringToken | Backtick | Identifier | Comment | Unspecified =>
|
||||
panic!("Token {:?} has no default lexeme", kind),
|
||||
Text | StringToken | Backtick | Identifier | Comment | Unspecified => {
|
||||
panic!("Token {:?} has no default lexeme", kind)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -992,7 +995,7 @@ mod tests {
|
||||
kind,
|
||||
};
|
||||
assert_eq!(have, want);
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -68,11 +68,11 @@ impl<T: Display, I: Iterator<Item = T> + Clone> Display for List<T, I> {
|
||||
write!(f, ", {}", c)?;
|
||||
current = Some(n);
|
||||
next = values.next();
|
||||
},
|
||||
}
|
||||
(Some(c), None) => {
|
||||
write!(f, ", {} {}", self.conjunction, c)?;
|
||||
return Ok(());
|
||||
},
|
||||
}
|
||||
_ => unreachable!("Iterator was fused, but returned Some after None"),
|
||||
}
|
||||
}
|
||||
|
17
src/node.rs
17
src/node.rs
@ -71,7 +71,7 @@ impl<'src> Node<'src> for Expression<'src> {
|
||||
tree.push_mut(then.tree());
|
||||
tree.push_mut(otherwise.tree());
|
||||
tree
|
||||
},
|
||||
}
|
||||
Expression::Call { thunk } => {
|
||||
use Thunk::*;
|
||||
|
||||
@ -82,14 +82,14 @@ impl<'src> Node<'src> for Expression<'src> {
|
||||
Unary { name, arg, .. } => {
|
||||
tree.push_mut(name.lexeme());
|
||||
tree.push_mut(arg.tree());
|
||||
},
|
||||
}
|
||||
Binary {
|
||||
name, args: [a, b], ..
|
||||
} => {
|
||||
tree.push_mut(name.lexeme());
|
||||
tree.push_mut(a.tree());
|
||||
tree.push_mut(b.tree());
|
||||
},
|
||||
}
|
||||
Ternary {
|
||||
name,
|
||||
args: [a, b, c],
|
||||
@ -99,11 +99,11 @@ impl<'src> Node<'src> for Expression<'src> {
|
||||
tree.push_mut(a.tree());
|
||||
tree.push_mut(b.tree());
|
||||
tree.push_mut(c.tree());
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
tree
|
||||
},
|
||||
}
|
||||
Expression::Variable { name } => Tree::atom(name.lexeme()),
|
||||
Expression::StringLiteral {
|
||||
string_literal: StringLiteral { cooked, .. },
|
||||
@ -213,14 +213,15 @@ impl<'src> Node<'src> for Set<'src> {
|
||||
set.push_mut(self.name.lexeme().replace('-', "_"));
|
||||
|
||||
match &self.value {
|
||||
DotenvLoad(value) | Export(value) | PositionalArguments(value) =>
|
||||
set.push_mut(value.to_string()),
|
||||
DotenvLoad(value) | Export(value) | PositionalArguments(value) => {
|
||||
set.push_mut(value.to_string());
|
||||
}
|
||||
Shell(setting::Shell { command, arguments }) => {
|
||||
set.push_mut(Tree::string(&command.cooked));
|
||||
for argument in arguments {
|
||||
set.push_mut(Tree::string(&argument.cooked));
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
set
|
||||
|
@ -28,7 +28,7 @@ pub(crate) fn output(mut command: Command) -> Result<String, OutputError> {
|
||||
.to_owned(),
|
||||
),
|
||||
}
|
||||
},
|
||||
}
|
||||
Err(io_error) => Err(OutputError::Io(io_error)),
|
||||
}
|
||||
}
|
||||
|
@ -101,10 +101,11 @@ impl<'tokens, 'src> Parser<'tokens, 'src> {
|
||||
let mut rest = self.rest();
|
||||
for kind in kinds {
|
||||
match rest.next() {
|
||||
Some(token) =>
|
||||
Some(token) => {
|
||||
if token.kind != *kind {
|
||||
return false;
|
||||
},
|
||||
}
|
||||
}
|
||||
None => return false,
|
||||
}
|
||||
}
|
||||
@ -322,22 +323,27 @@ impl<'tokens, 'src> Parser<'tokens, 'src> {
|
||||
break;
|
||||
} else if self.next_is(Identifier) {
|
||||
match Keyword::from_lexeme(next.lexeme()) {
|
||||
Some(Keyword::Alias) if self.next_are(&[Identifier, Identifier, Equals]) =>
|
||||
return Err(self.get(2)?.error(CompileErrorKind::DeprecatedEquals)),
|
||||
Some(Keyword::Alias) if self.next_are(&[Identifier, Identifier, ColonEquals]) =>
|
||||
items.push(Item::Alias(self.parse_alias()?)),
|
||||
Some(Keyword::Export) if self.next_are(&[Identifier, Identifier, Equals]) =>
|
||||
return Err(self.get(2)?.error(CompileErrorKind::DeprecatedEquals)),
|
||||
Some(Keyword::Alias) if self.next_are(&[Identifier, Identifier, Equals]) => {
|
||||
return Err(self.get(2)?.error(CompileErrorKind::DeprecatedEquals))
|
||||
}
|
||||
Some(Keyword::Alias) if self.next_are(&[Identifier, Identifier, ColonEquals]) => {
|
||||
items.push(Item::Alias(self.parse_alias()?));
|
||||
}
|
||||
Some(Keyword::Export) if self.next_are(&[Identifier, Identifier, Equals]) => {
|
||||
return Err(self.get(2)?.error(CompileErrorKind::DeprecatedEquals))
|
||||
}
|
||||
Some(Keyword::Export) if self.next_are(&[Identifier, Identifier, ColonEquals]) => {
|
||||
self.presume_keyword(Keyword::Export)?;
|
||||
items.push(Item::Assignment(self.parse_assignment(true)?));
|
||||
},
|
||||
}
|
||||
Some(Keyword::Set)
|
||||
if self.next_are(&[Identifier, Identifier, ColonEquals])
|
||||
|| self.next_are(&[Identifier, Identifier, Eol])
|
||||
|| self.next_are(&[Identifier, Identifier, Eof]) =>
|
||||
items.push(Item::Set(self.parse_set()?)),
|
||||
_ =>
|
||||
{
|
||||
items.push(Item::Set(self.parse_set()?));
|
||||
}
|
||||
_ => {
|
||||
if self.next_are(&[Identifier, Equals]) {
|
||||
return Err(self.get(1)?.error(CompileErrorKind::DeprecatedEquals));
|
||||
} else if self.next_are(&[Identifier, ColonEquals]) {
|
||||
@ -345,7 +351,8 @@ impl<'tokens, 'src> Parser<'tokens, 'src> {
|
||||
} else {
|
||||
let doc = pop_doc_comment(&mut items, eol_since_last_comment);
|
||||
items.push(Item::Recipe(self.parse_recipe(doc, false)?));
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if self.accepted(At)? {
|
||||
let doc = pop_doc_comment(&mut items, eol_since_last_comment);
|
||||
@ -516,13 +523,13 @@ impl<'tokens, 'src> Parser<'tokens, 'src> {
|
||||
'r' => cooked.push('\r'),
|
||||
't' => cooked.push('\t'),
|
||||
'\\' => cooked.push('\\'),
|
||||
'\n' => {},
|
||||
'\n' => {}
|
||||
'"' => cooked.push('"'),
|
||||
other => {
|
||||
return Err(
|
||||
token.error(CompileErrorKind::InvalidEscapeSequence { character: other }),
|
||||
);
|
||||
},
|
||||
}
|
||||
}
|
||||
escape = false;
|
||||
} else if c == '\\' {
|
||||
@ -859,7 +866,7 @@ mod tests {
|
||||
kind,
|
||||
};
|
||||
assert_eq!(have, want);
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -181,7 +181,7 @@ impl<'src, D> Recipe<'src, D> {
|
||||
|
||||
// run it!
|
||||
match InterruptHandler::guard(|| command.status()) {
|
||||
Ok(exit_status) =>
|
||||
Ok(exit_status) => {
|
||||
if let Some(code) = exit_status.code() {
|
||||
if code != 0 {
|
||||
return Err(Error::Code {
|
||||
@ -192,7 +192,8 @@ impl<'src, D> Recipe<'src, D> {
|
||||
}
|
||||
} else {
|
||||
return Err(error_from_signal(self.name(), None, exit_status));
|
||||
},
|
||||
}
|
||||
}
|
||||
Err(io_error) => {
|
||||
return Err(Error::Shebang {
|
||||
recipe: self.name(),
|
||||
@ -200,7 +201,7 @@ impl<'src, D> Recipe<'src, D> {
|
||||
argument: shebang.argument.map(String::from),
|
||||
io_error,
|
||||
});
|
||||
},
|
||||
}
|
||||
};
|
||||
} else {
|
||||
let mut lines = self.body.iter().peekable();
|
||||
@ -274,7 +275,7 @@ impl<'src, D> Recipe<'src, D> {
|
||||
cmd.export(context.settings, dotenv, &scope);
|
||||
|
||||
match InterruptHandler::guard(|| cmd.status()) {
|
||||
Ok(exit_status) =>
|
||||
Ok(exit_status) => {
|
||||
if let Some(code) = exit_status.code() {
|
||||
if code != 0 && !infallable_command {
|
||||
return Err(Error::Code {
|
||||
@ -289,13 +290,14 @@ impl<'src, D> Recipe<'src, D> {
|
||||
Some(line_number),
|
||||
exit_status,
|
||||
));
|
||||
},
|
||||
}
|
||||
}
|
||||
Err(io_error) => {
|
||||
return Err(Error::Io {
|
||||
recipe: self.name(),
|
||||
io_error,
|
||||
});
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ impl Search {
|
||||
justfile,
|
||||
working_directory,
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
SearchConfig::FromSearchDirectory { search_directory } => {
|
||||
let search_directory = Self::clean(invocation_directory, search_directory);
|
||||
@ -39,7 +39,7 @@ impl Search {
|
||||
justfile,
|
||||
working_directory,
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
SearchConfig::WithJustfile { justfile } => {
|
||||
let justfile = Self::clean(invocation_directory, justfile);
|
||||
@ -50,7 +50,7 @@ impl Search {
|
||||
justfile,
|
||||
working_directory,
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
SearchConfig::WithJustfileAndWorkingDirectory {
|
||||
justfile,
|
||||
@ -76,7 +76,7 @@ impl Search {
|
||||
justfile,
|
||||
working_directory,
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
SearchConfig::FromSearchDirectory { search_directory } => {
|
||||
let search_directory = Self::clean(invocation_directory, search_directory);
|
||||
@ -89,7 +89,7 @@ impl Search {
|
||||
justfile,
|
||||
working_directory,
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
SearchConfig::WithJustfile { justfile } => {
|
||||
let justfile = Self::clean(invocation_directory, justfile);
|
||||
@ -100,7 +100,7 @@ impl Search {
|
||||
justfile,
|
||||
working_directory,
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
SearchConfig::WithJustfileAndWorkingDirectory {
|
||||
justfile,
|
||||
@ -206,7 +206,7 @@ mod tests {
|
||||
fn not_found() {
|
||||
let tmp = testing::tempdir();
|
||||
match Search::justfile(tmp.path()) {
|
||||
Err(SearchError::NotFound) => {},
|
||||
Err(SearchError::NotFound) => {}
|
||||
_ => panic!("No justfile found error was expected"),
|
||||
}
|
||||
}
|
||||
@ -226,7 +226,7 @@ mod tests {
|
||||
fs::write(&path, "default:\n\techo ok").unwrap();
|
||||
path.pop();
|
||||
match Search::justfile(path.as_path()) {
|
||||
Err(SearchError::MultipleCandidates { .. }) => {},
|
||||
Err(SearchError::MultipleCandidates { .. }) => {}
|
||||
_ => panic!("Multiple candidates error was expected"),
|
||||
}
|
||||
}
|
||||
@ -301,7 +301,7 @@ mod tests {
|
||||
path.pop();
|
||||
path.push(DEFAULT_JUSTFILE_NAME);
|
||||
assert_eq!(found_path, path);
|
||||
},
|
||||
}
|
||||
Err(err) => panic!("No errors were expected: {}", err),
|
||||
}
|
||||
}
|
||||
|
@ -57,8 +57,9 @@ impl StringKind {
|
||||
|
||||
pub(crate) fn unterminated_error_kind(self) -> CompileErrorKind<'static> {
|
||||
match self.delimiter {
|
||||
StringDelimiter::QuoteDouble | StringDelimiter::QuoteSingle =>
|
||||
CompileErrorKind::UnterminatedString,
|
||||
StringDelimiter::QuoteDouble | StringDelimiter::QuoteSingle => {
|
||||
CompileErrorKind::UnterminatedString
|
||||
}
|
||||
StringDelimiter::Backtick => CompileErrorKind::UnterminatedBacktick,
|
||||
}
|
||||
}
|
||||
|
@ -45,10 +45,10 @@ impl Subcommand {
|
||||
Changelog => {
|
||||
Self::changelog();
|
||||
return Ok(());
|
||||
},
|
||||
}
|
||||
Completions { shell } => return Self::completions(&shell),
|
||||
Init => return Self::init(config),
|
||||
_ => {},
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let search = Search::find(&config.search_config, &config.invocation_directory)?;
|
||||
@ -70,8 +70,9 @@ impl Subcommand {
|
||||
}
|
||||
|
||||
match self {
|
||||
Choose { overrides, chooser } =>
|
||||
Self::choose(config, justfile, &search, overrides, chooser.as_deref())?,
|
||||
Choose { overrides, chooser } => {
|
||||
Self::choose(config, justfile, &search, overrides, chooser.as_deref())?;
|
||||
}
|
||||
Command { overrides, .. } => justfile.run(config, &search, overrides, &[])?,
|
||||
Dump => Self::dump(ast),
|
||||
Evaluate { overrides, .. } => justfile.run(config, &search, overrides, &[])?,
|
||||
@ -135,7 +136,7 @@ impl Subcommand {
|
||||
chooser,
|
||||
io_error,
|
||||
});
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
for recipe in recipes {
|
||||
@ -153,7 +154,7 @@ impl Subcommand {
|
||||
Ok(output) => output,
|
||||
Err(io_error) => {
|
||||
return Err(Error::ChooserRead { io_error, chooser });
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
if !output.status.success() {
|
||||
@ -200,23 +201,26 @@ impl Subcommand {
|
||||
let mut script = String::from_utf8(buffer).expect("Clap completion not UTF-8");
|
||||
|
||||
match shell {
|
||||
Shell::Bash =>
|
||||
Shell::Bash => {
|
||||
for (needle, replacement) in completions::BASH_COMPLETION_REPLACEMENTS {
|
||||
replace(&mut script, needle, replacement)?;
|
||||
},
|
||||
}
|
||||
}
|
||||
Shell::Fish => {
|
||||
script.insert_str(0, completions::FISH_RECIPE_COMPLETIONS);
|
||||
},
|
||||
Shell::PowerShell =>
|
||||
}
|
||||
Shell::PowerShell => {
|
||||
for (needle, replacement) in completions::POWERSHELL_COMPLETION_REPLACEMENTS {
|
||||
replace(&mut script, needle, replacement)?;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
Shell::Zsh =>
|
||||
Shell::Zsh => {
|
||||
for (needle, replacement) in completions::ZSH_COMPLETION_REPLACEMENTS {
|
||||
replace(&mut script, needle, replacement)?;
|
||||
},
|
||||
Shell::Elvish => {},
|
||||
}
|
||||
}
|
||||
Shell::Elvish => {}
|
||||
}
|
||||
|
||||
println!("{}", script.trim());
|
||||
@ -363,7 +367,7 @@ impl Subcommand {
|
||||
_ => {
|
||||
let alias_doc = format!("alias for `{}`", recipe.name);
|
||||
print_doc(&alias_doc);
|
||||
},
|
||||
}
|
||||
}
|
||||
println!();
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ pub(crate) fn analysis_error(
|
||||
kind,
|
||||
};
|
||||
assert_eq!(have, want);
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,7 +52,7 @@ impl<'src> Thunk<'src> {
|
||||
args: [a, b],
|
||||
name,
|
||||
})
|
||||
},
|
||||
}
|
||||
(Function::Ternary(function), 3) => {
|
||||
let c = Box::new(arguments.pop().unwrap());
|
||||
let b = Box::new(arguments.pop().unwrap());
|
||||
@ -62,7 +62,7 @@ impl<'src> Thunk<'src> {
|
||||
args: [a, b, c],
|
||||
name,
|
||||
})
|
||||
},
|
||||
}
|
||||
_ => Err(name.error(CompileErrorKind::FunctionArgumentCountMismatch {
|
||||
function: name.lexeme(),
|
||||
found: arguments.len(),
|
||||
|
@ -65,15 +65,16 @@ impl<'src> ColorDisplay for Token<'src> {
|
||||
space_width.max(1),
|
||||
color.suffix()
|
||||
)?;
|
||||
},
|
||||
None =>
|
||||
}
|
||||
None => {
|
||||
if self.offset != self.src.len() {
|
||||
write!(
|
||||
f,
|
||||
"internal error: Error has invalid line number: {}",
|
||||
line_number
|
||||
)?;
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -37,7 +37,10 @@ pub(crate) enum TokenKind {
|
||||
impl Display for TokenKind {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
|
||||
use TokenKind::*;
|
||||
write!(f, "{}", match *self {
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
match *self {
|
||||
AmpersandAmpersand => "'&&'",
|
||||
Asterisk => "'*'",
|
||||
At => "'@'",
|
||||
@ -68,6 +71,7 @@ impl Display for TokenKind {
|
||||
Text => "command text",
|
||||
Unspecified => "unspecified",
|
||||
Whitespace => "whitespace",
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ impl<'text> Tree<'text> {
|
||||
Tree::List(mut children) => {
|
||||
children.push(tree.into());
|
||||
Tree::List(children)
|
||||
},
|
||||
}
|
||||
Tree::Atom(text) => Tree::List(vec![Tree::Atom(text), tree.into()]),
|
||||
}
|
||||
}
|
||||
@ -137,7 +137,7 @@ impl Display for Tree<'_> {
|
||||
}
|
||||
|
||||
write!(f, ")")
|
||||
},
|
||||
}
|
||||
Tree::Atom(text) => write!(f, "{}", text),
|
||||
}
|
||||
}
|
||||
|
@ -31,17 +31,17 @@ impl<'expression, 'src> Iterator for Variables<'expression, 'src> {
|
||||
self.stack.push(then);
|
||||
self.stack.push(otherwise);
|
||||
self.next()
|
||||
},
|
||||
}
|
||||
Some(Expression::Variable { name, .. }) => Some(name.token()),
|
||||
Some(Expression::Concatination { lhs, rhs }) => {
|
||||
self.stack.push(lhs);
|
||||
self.stack.push(rhs);
|
||||
self.next()
|
||||
},
|
||||
}
|
||||
Some(Expression::Group { contents }) => {
|
||||
self.stack.push(contents);
|
||||
self.next()
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ adding the following line to your shell rc file:
|
||||
export JUST_SUPPRESS_DOTENV_LOAD_WARNING=1
|
||||
|
||||
See https://github.com/casey/just/issues/469 for more details.")?;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
write!(f, "{}", message.suffix())?;
|
||||
|
Loading…
Reference in New Issue
Block a user