Add --fmt
subcommand (#837)
This commit is contained in:
parent
39e76488b5
commit
8677492d56
@ -20,7 +20,7 @@ _just() {
|
|||||||
|
|
||||||
case "${cmd}" in
|
case "${cmd}" in
|
||||||
just)
|
just)
|
||||||
opts=" -q -u -v -e -l -h -V -f -d -c -s --dry-run --highlight --no-dotenv --no-highlight --quiet --shell-command --clear-shell-args --unsorted --verbose --choose --dump --edit --evaluate --init --list --summary --variables --help --version --chooser --color --list-heading --list-prefix --justfile --set --shell --shell-arg --working-directory --command --completions --show <ARGUMENTS>... "
|
opts=" -q -u -v -e -l -h -V -f -d -c -s --dry-run --highlight --no-dotenv --no-highlight --quiet --shell-command --clear-shell-args --unsorted --verbose --choose --dump --edit --evaluate --fmt --init --list --summary --variables --help --version --chooser --color --list-heading --list-prefix --justfile --set --shell --shell-arg --working-directory --command --completions --show <ARGUMENTS>... "
|
||||||
if [[ ${cur} == -* ]] ; then
|
if [[ ${cur} == -* ]] ; then
|
||||||
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
|
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
|
||||||
return 0
|
return 0
|
||||||
|
@ -47,6 +47,7 @@ edit:completion:arg-completer[just] = [@words]{
|
|||||||
cand -e 'Edit justfile with editor given by $VISUAL or $EDITOR, falling back to `vim`'
|
cand -e 'Edit justfile with editor given by $VISUAL or $EDITOR, falling back to `vim`'
|
||||||
cand --edit 'Edit justfile with editor given by $VISUAL or $EDITOR, falling back to `vim`'
|
cand --edit 'Edit justfile with editor given by $VISUAL or $EDITOR, falling back to `vim`'
|
||||||
cand --evaluate 'Evaluate and print all variables. If a variable name is given as an argument, only print that variable''s value.'
|
cand --evaluate 'Evaluate and print all variables. If a variable name is given as an argument, only print that variable''s value.'
|
||||||
|
cand --fmt 'Format and overwrite justfile'
|
||||||
cand --init 'Initialize new justfile in project root'
|
cand --init 'Initialize new justfile in project root'
|
||||||
cand -l 'List available recipes and their arguments'
|
cand -l 'List available recipes and their arguments'
|
||||||
cand --list 'List available recipes and their arguments'
|
cand --list 'List available recipes and their arguments'
|
||||||
|
@ -34,6 +34,7 @@ complete -c just -n "__fish_use_subcommand" -l choose -d 'Select one or more rec
|
|||||||
complete -c just -n "__fish_use_subcommand" -l dump -d 'Print entire justfile'
|
complete -c just -n "__fish_use_subcommand" -l dump -d 'Print entire justfile'
|
||||||
complete -c just -n "__fish_use_subcommand" -s e -l edit -d 'Edit justfile with editor given by $VISUAL or $EDITOR, falling back to `vim`'
|
complete -c just -n "__fish_use_subcommand" -s e -l edit -d 'Edit justfile with editor given by $VISUAL or $EDITOR, falling back to `vim`'
|
||||||
complete -c just -n "__fish_use_subcommand" -l evaluate -d 'Evaluate and print all variables. If a variable name is given as an argument, only print that variable\'s value.'
|
complete -c just -n "__fish_use_subcommand" -l evaluate -d 'Evaluate and print all variables. If a variable name is given as an argument, only print that variable\'s value.'
|
||||||
|
complete -c just -n "__fish_use_subcommand" -l fmt -d 'Format and overwrite justfile'
|
||||||
complete -c just -n "__fish_use_subcommand" -l init -d 'Initialize new justfile in project root'
|
complete -c just -n "__fish_use_subcommand" -l init -d 'Initialize new justfile in project root'
|
||||||
complete -c just -n "__fish_use_subcommand" -s l -l list -d 'List available recipes and their arguments'
|
complete -c just -n "__fish_use_subcommand" -s l -l list -d 'List available recipes and their arguments'
|
||||||
complete -c just -n "__fish_use_subcommand" -l summary -d 'List names of available recipes'
|
complete -c just -n "__fish_use_subcommand" -l summary -d 'List names of available recipes'
|
||||||
|
@ -52,6 +52,7 @@ Register-ArgumentCompleter -Native -CommandName 'just' -ScriptBlock {
|
|||||||
[CompletionResult]::new('-e', 'e', [CompletionResultType]::ParameterName, 'Edit justfile with editor given by $VISUAL or $EDITOR, falling back to `vim`')
|
[CompletionResult]::new('-e', 'e', [CompletionResultType]::ParameterName, 'Edit justfile with editor given by $VISUAL or $EDITOR, falling back to `vim`')
|
||||||
[CompletionResult]::new('--edit', 'edit', [CompletionResultType]::ParameterName, 'Edit justfile with editor given by $VISUAL or $EDITOR, falling back to `vim`')
|
[CompletionResult]::new('--edit', 'edit', [CompletionResultType]::ParameterName, 'Edit justfile with editor given by $VISUAL or $EDITOR, falling back to `vim`')
|
||||||
[CompletionResult]::new('--evaluate', 'evaluate', [CompletionResultType]::ParameterName, 'Evaluate and print all variables. If a variable name is given as an argument, only print that variable''s value.')
|
[CompletionResult]::new('--evaluate', 'evaluate', [CompletionResultType]::ParameterName, 'Evaluate and print all variables. If a variable name is given as an argument, only print that variable''s value.')
|
||||||
|
[CompletionResult]::new('--fmt', 'fmt', [CompletionResultType]::ParameterName, 'Format and overwrite justfile')
|
||||||
[CompletionResult]::new('--init', 'init', [CompletionResultType]::ParameterName, 'Initialize new justfile in project root')
|
[CompletionResult]::new('--init', 'init', [CompletionResultType]::ParameterName, 'Initialize new justfile in project root')
|
||||||
[CompletionResult]::new('-l', 'l', [CompletionResultType]::ParameterName, 'List available recipes and their arguments')
|
[CompletionResult]::new('-l', 'l', [CompletionResultType]::ParameterName, 'List available recipes and their arguments')
|
||||||
[CompletionResult]::new('--list', 'list', [CompletionResultType]::ParameterName, 'List available recipes and their arguments')
|
[CompletionResult]::new('--list', 'list', [CompletionResultType]::ParameterName, 'List available recipes and their arguments')
|
||||||
|
@ -48,6 +48,7 @@ _just() {
|
|||||||
'-e[Edit justfile with editor given by $VISUAL or $EDITOR, falling back to `vim`]' \
|
'-e[Edit justfile with editor given by $VISUAL or $EDITOR, falling back to `vim`]' \
|
||||||
'--edit[Edit justfile with editor given by $VISUAL or $EDITOR, falling back to `vim`]' \
|
'--edit[Edit justfile with editor given by $VISUAL or $EDITOR, falling back to `vim`]' \
|
||||||
'--evaluate[Evaluate and print all variables. If a variable name is given as an argument, only print that variable'\''s value.]' \
|
'--evaluate[Evaluate and print all variables. If a variable name is given as an argument, only print that variable'\''s value.]' \
|
||||||
|
'--fmt[Format and overwrite justfile]' \
|
||||||
'--init[Initialize new justfile in project root]' \
|
'--init[Initialize new justfile in project root]' \
|
||||||
'-l[List available recipes and their arguments]' \
|
'-l[List available recipes and their arguments]' \
|
||||||
'--list[List available recipes and their arguments]' \
|
'--list[List available recipes and their arguments]' \
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::common::*;
|
use crate::common::*;
|
||||||
|
|
||||||
/// An alias, e.g. `name := target`
|
/// An alias, e.g. `name := target`
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub(crate) struct Alias<'src, T = Rc<Recipe<'src>>> {
|
pub(crate) struct Alias<'src, T = Rc<Recipe<'src>>> {
|
||||||
pub(crate) name: Name<'src>,
|
pub(crate) name: Name<'src>,
|
||||||
pub(crate) target: T,
|
pub(crate) target: T,
|
||||||
|
@ -29,6 +29,7 @@ impl<'src> Analyzer<'src> {
|
|||||||
self.analyze_assignment(&assignment)?;
|
self.analyze_assignment(&assignment)?;
|
||||||
self.assignments.insert(assignment);
|
self.assignments.insert(assignment);
|
||||||
},
|
},
|
||||||
|
Item::Comment(_) => (),
|
||||||
Item::Recipe(recipe) => {
|
Item::Recipe(recipe) => {
|
||||||
self.analyze_recipe(&recipe)?;
|
self.analyze_recipe(&recipe)?;
|
||||||
self.recipes.insert(recipe);
|
self.recipes.insert(recipe);
|
||||||
|
@ -2,3 +2,12 @@ use crate::common::*;
|
|||||||
|
|
||||||
/// An assignment, e.g `foo := bar`
|
/// An assignment, e.g `foo := bar`
|
||||||
pub(crate) type Assignment<'src> = Binding<'src, Expression<'src>>;
|
pub(crate) type Assignment<'src> = Binding<'src, Expression<'src>>;
|
||||||
|
|
||||||
|
impl<'src> Display for Assignment<'src> {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
|
||||||
|
if self.export {
|
||||||
|
write!(f, "export ")?;
|
||||||
|
}
|
||||||
|
write!(f, "{} := {}", self.name, self.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::common::*;
|
use crate::common::*;
|
||||||
|
|
||||||
/// A binding of `name` to `value`
|
/// A binding of `name` to `value`
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub(crate) struct Binding<'src, V = String> {
|
pub(crate) struct Binding<'src, V = String> {
|
||||||
/// Export binding as an environment variable to child processes
|
/// Export binding as an environment variable to child processes
|
||||||
pub(crate) export: bool,
|
pub(crate) export: bool,
|
||||||
|
@ -5,9 +5,10 @@ pub(crate) use std::{
|
|||||||
env,
|
env,
|
||||||
ffi::{OsStr, OsString},
|
ffi::{OsStr, OsString},
|
||||||
fmt::{self, Debug, Display, Formatter},
|
fmt::{self, Debug, Display, Formatter},
|
||||||
fs,
|
fs::{self, File},
|
||||||
io::{self, Cursor, Write},
|
io::{self, Cursor, Write},
|
||||||
iter::{self, FromIterator},
|
iter::{self, FromIterator},
|
||||||
|
mem,
|
||||||
ops::{Index, Range, RangeInclusive},
|
ops::{Index, Range, RangeInclusive},
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
process::{self, Command, Stdio},
|
process::{self, Command, Stdio},
|
||||||
@ -45,21 +46,21 @@ pub(crate) use crate::{
|
|||||||
alias::Alias, analyzer::Analyzer, assignment::Assignment,
|
alias::Alias, analyzer::Analyzer, assignment::Assignment,
|
||||||
assignment_resolver::AssignmentResolver, binding::Binding, color::Color,
|
assignment_resolver::AssignmentResolver, binding::Binding, color::Color,
|
||||||
compilation_error::CompilationError, compilation_error_kind::CompilationErrorKind,
|
compilation_error::CompilationError, compilation_error_kind::CompilationErrorKind,
|
||||||
compiler::Compiler, config::Config, config_error::ConfigError, count::Count,
|
config::Config, config_error::ConfigError, count::Count, delimiter::Delimiter,
|
||||||
delimiter::Delimiter, dependency::Dependency, enclosure::Enclosure, evaluator::Evaluator,
|
dependency::Dependency, enclosure::Enclosure, evaluator::Evaluator, expression::Expression,
|
||||||
expression::Expression, fragment::Fragment, function::Function,
|
fragment::Fragment, function::Function, function_context::FunctionContext,
|
||||||
function_context::FunctionContext, interrupt_guard::InterruptGuard,
|
interrupt_guard::InterruptGuard, interrupt_handler::InterruptHandler, item::Item,
|
||||||
interrupt_handler::InterruptHandler, item::Item, justfile::Justfile, keyword::Keyword,
|
justfile::Justfile, keyword::Keyword, lexer::Lexer, line::Line, list::List,
|
||||||
lexer::Lexer, line::Line, list::List, load_error::LoadError, module::Module, name::Name,
|
load_error::LoadError, module::Module, name::Name, output_error::OutputError,
|
||||||
output_error::OutputError, parameter::Parameter, parameter_kind::ParameterKind, parser::Parser,
|
parameter::Parameter, parameter_kind::ParameterKind, parser::Parser, platform::Platform,
|
||||||
platform::Platform, position::Position, positional::Positional, recipe::Recipe,
|
position::Position, positional::Positional, recipe::Recipe, recipe_context::RecipeContext,
|
||||||
recipe_context::RecipeContext, recipe_resolver::RecipeResolver, runtime_error::RuntimeError,
|
recipe_resolver::RecipeResolver, runtime_error::RuntimeError, scope::Scope, search::Search,
|
||||||
scope::Scope, search::Search, search_config::SearchConfig, search_error::SearchError, set::Set,
|
search_config::SearchConfig, search_error::SearchError, set::Set, setting::Setting,
|
||||||
setting::Setting, settings::Settings, shebang::Shebang, show_whitespace::ShowWhitespace,
|
settings::Settings, shebang::Shebang, show_whitespace::ShowWhitespace, string_kind::StringKind,
|
||||||
string_kind::StringKind, string_literal::StringLiteral, subcommand::Subcommand,
|
string_literal::StringLiteral, subcommand::Subcommand, suggestion::Suggestion, table::Table,
|
||||||
suggestion::Suggestion, table::Table, thunk::Thunk, token::Token, token_kind::TokenKind,
|
thunk::Thunk, token::Token, token_kind::TokenKind, unresolved_dependency::UnresolvedDependency,
|
||||||
unresolved_dependency::UnresolvedDependency, unresolved_recipe::UnresolvedRecipe,
|
unresolved_recipe::UnresolvedRecipe, use_color::UseColor, variables::Variables,
|
||||||
use_color::UseColor, variables::Variables, verbosity::Verbosity, warning::Warning,
|
verbosity::Verbosity, warning::Warning,
|
||||||
};
|
};
|
||||||
|
|
||||||
// type aliases
|
// type aliases
|
||||||
|
@ -38,6 +38,7 @@ mod cmd {
|
|||||||
pub(crate) const DUMP: &str = "DUMP";
|
pub(crate) const DUMP: &str = "DUMP";
|
||||||
pub(crate) const EDIT: &str = "EDIT";
|
pub(crate) const EDIT: &str = "EDIT";
|
||||||
pub(crate) const EVALUATE: &str = "EVALUATE";
|
pub(crate) const EVALUATE: &str = "EVALUATE";
|
||||||
|
pub(crate) const FORMAT: &str = "FORMAT";
|
||||||
pub(crate) const INIT: &str = "INIT";
|
pub(crate) const INIT: &str = "INIT";
|
||||||
pub(crate) const LIST: &str = "LIST";
|
pub(crate) const LIST: &str = "LIST";
|
||||||
pub(crate) const SHOW: &str = "SHOW";
|
pub(crate) const SHOW: &str = "SHOW";
|
||||||
@ -52,6 +53,7 @@ mod cmd {
|
|||||||
DUMP,
|
DUMP,
|
||||||
EDIT,
|
EDIT,
|
||||||
EVALUATE,
|
EVALUATE,
|
||||||
|
FORMAT,
|
||||||
INIT,
|
INIT,
|
||||||
LIST,
|
LIST,
|
||||||
SHOW,
|
SHOW,
|
||||||
@ -63,6 +65,7 @@ mod cmd {
|
|||||||
COMPLETIONS,
|
COMPLETIONS,
|
||||||
DUMP,
|
DUMP,
|
||||||
EDIT,
|
EDIT,
|
||||||
|
FORMAT,
|
||||||
INIT,
|
INIT,
|
||||||
LIST,
|
LIST,
|
||||||
SHOW,
|
SHOW,
|
||||||
@ -266,6 +269,11 @@ impl Config {
|
|||||||
"Evaluate and print all variables. If a variable name is given as an argument, only print \
|
"Evaluate and print all variables. If a variable name is given as an argument, only print \
|
||||||
that variable's value.",
|
that variable's value.",
|
||||||
))
|
))
|
||||||
|
.arg(
|
||||||
|
Arg::with_name(cmd::FORMAT)
|
||||||
|
.long("fmt")
|
||||||
|
.help("Format and overwrite justfile"),
|
||||||
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name(cmd::INIT)
|
Arg::with_name(cmd::INIT)
|
||||||
.long("init")
|
.long("init")
|
||||||
@ -442,6 +450,8 @@ impl Config {
|
|||||||
Subcommand::Summary
|
Subcommand::Summary
|
||||||
} else if matches.is_present(cmd::DUMP) {
|
} else if matches.is_present(cmd::DUMP) {
|
||||||
Subcommand::Dump
|
Subcommand::Dump
|
||||||
|
} else if matches.is_present(cmd::FORMAT) {
|
||||||
|
Subcommand::Format
|
||||||
} else if matches.is_present(cmd::INIT) {
|
} else if matches.is_present(cmd::INIT) {
|
||||||
Subcommand::Init
|
Subcommand::Init
|
||||||
} else if matches.is_present(cmd::LIST) {
|
} else if matches.is_present(cmd::LIST) {
|
||||||
@ -539,7 +549,9 @@ impl Config {
|
|||||||
})
|
})
|
||||||
.eprint(self.color)?;
|
.eprint(self.color)?;
|
||||||
|
|
||||||
let justfile = Compiler::compile(&src).eprint(self.color)?;
|
let tokens = Lexer::lex(&src).eprint(self.color)?;
|
||||||
|
let ast = Parser::parse(&tokens).eprint(self.color)?;
|
||||||
|
let justfile = Analyzer::analyze(ast.clone()).eprint(self.color)?;
|
||||||
|
|
||||||
if self.verbosity.loud() {
|
if self.verbosity.loud() {
|
||||||
for warning in &justfile.warnings {
|
for warning in &justfile.warnings {
|
||||||
@ -555,8 +567,9 @@ impl Config {
|
|||||||
Choose { overrides, chooser } =>
|
Choose { overrides, chooser } =>
|
||||||
self.choose(justfile, &search, overrides, chooser.as_deref())?,
|
self.choose(justfile, &search, overrides, chooser.as_deref())?,
|
||||||
Command { overrides, .. } => self.run(justfile, &search, overrides, &[])?,
|
Command { overrides, .. } => self.run(justfile, &search, overrides, &[])?,
|
||||||
Dump => Self::dump(justfile),
|
Dump => Self::dump(ast)?,
|
||||||
Evaluate { overrides, .. } => self.run(justfile, &search, overrides, &[])?,
|
Evaluate { overrides, .. } => self.run(justfile, &search, overrides, &[])?,
|
||||||
|
Format => self.format(ast, &search)?,
|
||||||
List => self.list(justfile),
|
List => self.list(justfile),
|
||||||
Run {
|
Run {
|
||||||
arguments,
|
arguments,
|
||||||
@ -676,8 +689,9 @@ impl Config {
|
|||||||
self.run(justfile, search, overrides, &recipes)
|
self.run(justfile, search, overrides, &recipes)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dump(justfile: Justfile) {
|
fn dump(ast: Module) -> Result<(), i32> {
|
||||||
println!("{}", justfile);
|
print!("{}", ast);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn edit(&self, search: &Search) -> Result<(), i32> {
|
pub(crate) fn edit(&self, search: &Search) -> Result<(), i32> {
|
||||||
@ -713,6 +727,24 @@ impl Config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn format(&self, ast: Module, search: &Search) -> Result<(), i32> {
|
||||||
|
if let Err(error) = File::open(&search.justfile).and_then(|mut file| write!(file, "{}", ast)) {
|
||||||
|
if self.verbosity.loud() {
|
||||||
|
eprintln!(
|
||||||
|
"Failed to write justfile to `{}`: {}",
|
||||||
|
search.justfile.display(),
|
||||||
|
error
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Err(EXIT_FAILURE)
|
||||||
|
} else {
|
||||||
|
if self.verbosity.loud() {
|
||||||
|
eprintln!("Wrote justfile to `{}`", search.justfile.display());
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn init(&self) -> Result<(), i32> {
|
pub(crate) fn init(&self) -> Result<(), i32> {
|
||||||
let search =
|
let search =
|
||||||
Search::init(&self.search_config, &self.invocation_directory).eprint(self.color)?;
|
Search::init(&self.search_config, &self.invocation_directory).eprint(self.color)?;
|
||||||
@ -920,6 +952,7 @@ FLAGS:
|
|||||||
--evaluate Evaluate and print all variables. If a variable name is given as an \
|
--evaluate Evaluate and print all variables. If a variable name is given as an \
|
||||||
argument, only print
|
argument, only print
|
||||||
that variable's value.
|
that variable's value.
|
||||||
|
--fmt Format and overwrite justfile
|
||||||
--highlight Highlight echoed recipe lines in bold
|
--highlight Highlight echoed recipe lines in bold
|
||||||
--init Initialize new justfile in project root
|
--init Initialize new justfile in project root
|
||||||
-l, --list List available recipes and their arguments
|
-l, --list List available recipes and their arguments
|
||||||
@ -1315,6 +1348,11 @@ ARGS:
|
|||||||
args: ["--list", "--dump"],
|
args: ["--list", "--dump"],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
error! {
|
||||||
|
name: subcommand_conflict_fmt,
|
||||||
|
args: ["--list", "--fmt"],
|
||||||
|
}
|
||||||
|
|
||||||
error! {
|
error! {
|
||||||
name: subcommand_conflict_init,
|
name: subcommand_conflict_init,
|
||||||
args: ["--list", "--init"],
|
args: ["--list", "--init"],
|
||||||
@ -1661,6 +1699,16 @@ ARGS:
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
error! {
|
||||||
|
name: fmt_arguments,
|
||||||
|
args: ["--fmt", "bar"],
|
||||||
|
error: ConfigError::SubcommandArguments { subcommand, arguments },
|
||||||
|
check: {
|
||||||
|
assert_eq!(subcommand, cmd::FORMAT);
|
||||||
|
assert_eq!(arguments, &["bar"]);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
error! {
|
error! {
|
||||||
name: init_arguments,
|
name: init_arguments,
|
||||||
args: ["--init", "bar"],
|
args: ["--init", "bar"],
|
||||||
|
@ -6,7 +6,7 @@ use crate::common::*;
|
|||||||
/// parenthetical groups).
|
/// parenthetical groups).
|
||||||
///
|
///
|
||||||
/// The parser parses both values and expressions into `Expression`s.
|
/// The parser parses both values and expressions into `Expression`s.
|
||||||
#[derive(PartialEq, Debug)]
|
#[derive(PartialEq, Debug, Clone)]
|
||||||
pub(crate) enum Expression<'src> {
|
pub(crate) enum Expression<'src> {
|
||||||
/// `contents`
|
/// `contents`
|
||||||
Backtick {
|
Backtick {
|
||||||
@ -45,7 +45,7 @@ impl<'src> Expression<'src> {
|
|||||||
impl<'src> Display for Expression<'src> {
|
impl<'src> Display for Expression<'src> {
|
||||||
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
|
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
|
||||||
match self {
|
match self {
|
||||||
Expression::Backtick { contents, .. } => write!(f, "`{}`", contents),
|
Expression::Backtick { token, .. } => write!(f, "{}", token.lexeme()),
|
||||||
Expression::Concatination { lhs, rhs } => write!(f, "{} + {}", lhs, rhs),
|
Expression::Concatination { lhs, rhs } => write!(f, "{} + {}", lhs, rhs),
|
||||||
Expression::Conditional {
|
Expression::Conditional {
|
||||||
lhs,
|
lhs,
|
||||||
@ -55,7 +55,7 @@ impl<'src> Display for Expression<'src> {
|
|||||||
inverted,
|
inverted,
|
||||||
} => write!(
|
} => write!(
|
||||||
f,
|
f,
|
||||||
"if {} {} {} {{ {} }} else {{ {} }} ",
|
"if {} {} {} {{ {} }} else {{ {} }}",
|
||||||
lhs,
|
lhs,
|
||||||
if *inverted { "!=" } else { "==" },
|
if *inverted { "!=" } else { "==" },
|
||||||
rhs,
|
rhs,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::common::*;
|
use crate::common::*;
|
||||||
|
|
||||||
/// A line fragment consisting either of…
|
/// A line fragment consisting either of…
|
||||||
#[derive(PartialEq, Debug)]
|
#[derive(PartialEq, Debug, Clone)]
|
||||||
pub(crate) enum Fragment<'src> {
|
pub(crate) enum Fragment<'src> {
|
||||||
/// …raw text…
|
/// …raw text…
|
||||||
Text { token: Token<'src> },
|
Text { token: Token<'src> },
|
||||||
|
15
src/item.rs
15
src/item.rs
@ -1,10 +1,23 @@
|
|||||||
use crate::common::*;
|
use crate::common::*;
|
||||||
|
|
||||||
/// A single top-level item
|
/// A single top-level item
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) enum Item<'src> {
|
pub(crate) enum Item<'src> {
|
||||||
Alias(Alias<'src, Name<'src>>),
|
Alias(Alias<'src, Name<'src>>),
|
||||||
Assignment(Assignment<'src>),
|
Assignment(Assignment<'src>),
|
||||||
|
Comment(&'src str),
|
||||||
Recipe(UnresolvedRecipe<'src>),
|
Recipe(UnresolvedRecipe<'src>),
|
||||||
Set(Set<'src>),
|
Set(Set<'src>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'src> Display for Item<'src> {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
Item::Alias(alias) => write!(f, "{}", alias),
|
||||||
|
Item::Assignment(assignment) => write!(f, "{}", assignment),
|
||||||
|
Item::Comment(comment) => write!(f, "{}", comment),
|
||||||
|
Item::Recipe(recipe) => write!(f, "{}", recipe),
|
||||||
|
Item::Set(set) => write!(f, "{}", set),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -802,7 +802,7 @@ goodbye := \"y\"
|
|||||||
hello a b c: x y z
|
hello a b c: x y z
|
||||||
#! blah
|
#! blah
|
||||||
#blarg
|
#blarg
|
||||||
{{foo + bar}}abc{{goodbye + \"x\"}}xyz
|
{{ foo + bar }}abc{{ goodbye + \"x\" }}xyz
|
||||||
1
|
1
|
||||||
2
|
2
|
||||||
3
|
3
|
||||||
@ -828,7 +828,7 @@ install:
|
|||||||
|
|
||||||
install:
|
install:
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
if [[ -f {{practicum}} ]]; then
|
if [[ -f {{ practicum }} ]]; then
|
||||||
\treturn
|
\treturn
|
||||||
fi",
|
fi",
|
||||||
}
|
}
|
||||||
@ -869,7 +869,7 @@ c := a + b + a + b",
|
|||||||
r#"a:
|
r#"a:
|
||||||
echo {{ `echo hello` + "blarg" }} {{ `echo bob` }}"#,
|
echo {{ `echo hello` + "blarg" }} {{ `echo bob` }}"#,
|
||||||
r#"a:
|
r#"a:
|
||||||
echo {{`echo hello` + "blarg"}} {{`echo bob`}}"#,
|
echo {{ `echo hello` + "blarg" }} {{ `echo bob` }}"#,
|
||||||
}
|
}
|
||||||
|
|
||||||
test! {
|
test! {
|
||||||
@ -895,7 +895,7 @@ c := a + b + a + b",
|
|||||||
"a b c:
|
"a b c:
|
||||||
{{b}} {{c}}",
|
{{b}} {{c}}",
|
||||||
"a b c:
|
"a b c:
|
||||||
{{b}} {{c}}",
|
{{ b }} {{ c }}",
|
||||||
}
|
}
|
||||||
|
|
||||||
test! {
|
test! {
|
||||||
@ -908,7 +908,7 @@ a:
|
|||||||
"x := arch()
|
"x := arch()
|
||||||
|
|
||||||
a:
|
a:
|
||||||
{{os()}} {{os_family()}}",
|
{{ os() }} {{ os_family() }}",
|
||||||
}
|
}
|
||||||
|
|
||||||
test! {
|
test! {
|
||||||
@ -921,7 +921,7 @@ a:
|
|||||||
r#"x := env_var('foo')
|
r#"x := env_var('foo')
|
||||||
|
|
||||||
a:
|
a:
|
||||||
{{env_var_or_default('foo' + 'bar', 'baz')}} {{env_var(env_var("baz"))}}"#,
|
{{ env_var_or_default('foo' + 'bar', 'baz') }} {{ env_var(env_var("baz")) }}"#,
|
||||||
}
|
}
|
||||||
|
|
||||||
test! {
|
test! {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::common::*;
|
use crate::common::*;
|
||||||
|
|
||||||
/// A single line in a recipe body, consisting of any number of `Fragment`s.
|
/// A single line in a recipe body, consisting of any number of `Fragment`s.
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub(crate) struct Line<'src> {
|
pub(crate) struct Line<'src> {
|
||||||
pub(crate) fragments: Vec<Fragment<'src>>,
|
pub(crate) fragments: Vec<Fragment<'src>>,
|
||||||
}
|
}
|
||||||
|
@ -7,10 +7,30 @@ use crate::common::*;
|
|||||||
/// Not all successful parses result in valid justfiles, so additional
|
/// Not all successful parses result in valid justfiles, so additional
|
||||||
/// consistency checks and name resolution are performed by the `Analyzer`,
|
/// consistency checks and name resolution are performed by the `Analyzer`,
|
||||||
/// which produces a `Justfile` from a `Module`.
|
/// which produces a `Justfile` from a `Module`.
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) struct Module<'src> {
|
pub(crate) struct Module<'src> {
|
||||||
/// Items in the justfile
|
/// Items in the justfile
|
||||||
pub(crate) items: Vec<Item<'src>>,
|
pub(crate) items: Vec<Item<'src>>,
|
||||||
/// Non-fatal warnings encountered during parsing
|
/// Non-fatal warnings encountered during parsing
|
||||||
pub(crate) warnings: Vec<Warning>,
|
pub(crate) warnings: Vec<Warning>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'src> Display for Module<'src> {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
|
||||||
|
let mut iter = self.items.iter().peekable();
|
||||||
|
|
||||||
|
while let Some(item) = iter.next() {
|
||||||
|
writeln!(f, "{}", item)?;
|
||||||
|
|
||||||
|
if let Some(next_item) = iter.peek() {
|
||||||
|
if matches!(item, Item::Recipe(_))
|
||||||
|
|| mem::discriminant(item) != mem::discriminant(next_item)
|
||||||
|
{
|
||||||
|
writeln!(f)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -20,6 +20,7 @@ impl<'src> Node<'src> for Item<'src> {
|
|||||||
match self {
|
match self {
|
||||||
Item::Alias(alias) => alias.tree(),
|
Item::Alias(alias) => alias.tree(),
|
||||||
Item::Assignment(assignment) => assignment.tree(),
|
Item::Assignment(assignment) => assignment.tree(),
|
||||||
|
Item::Comment(comment) => comment.tree(),
|
||||||
Item::Recipe(recipe) => recipe.tree(),
|
Item::Recipe(recipe) => recipe.tree(),
|
||||||
Item::Set(set) => set.tree(),
|
Item::Set(set) => set.tree(),
|
||||||
}
|
}
|
||||||
@ -210,3 +211,9 @@ impl<'src> Node<'src> for Warning {
|
|||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'src> Node<'src> for str {
|
||||||
|
fn tree(&self) -> Tree<'src> {
|
||||||
|
Tree::atom("comment").push(["\"", self, "\""].concat())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::common::*;
|
use crate::common::*;
|
||||||
|
|
||||||
/// A single function parameter
|
/// A single function parameter
|
||||||
#[derive(PartialEq, Debug)]
|
#[derive(PartialEq, Debug, Clone)]
|
||||||
pub(crate) struct Parameter<'src> {
|
pub(crate) struct Parameter<'src> {
|
||||||
/// The parameter name
|
/// The parameter name
|
||||||
pub(crate) name: Name<'src>,
|
pub(crate) name: Name<'src>,
|
||||||
@ -16,6 +16,9 @@ pub(crate) struct Parameter<'src> {
|
|||||||
impl<'src> Display for Parameter<'src> {
|
impl<'src> Display for Parameter<'src> {
|
||||||
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
|
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
|
||||||
let color = Color::fmt(f);
|
let color = Color::fmt(f);
|
||||||
|
if self.export {
|
||||||
|
write!(f, "$")?;
|
||||||
|
}
|
||||||
if let Some(prefix) = self.kind.prefix() {
|
if let Some(prefix) = self.kind.prefix() {
|
||||||
write!(f, "{}", color.annotation().paint(prefix))?;
|
write!(f, "{}", color.annotation().paint(prefix))?;
|
||||||
}
|
}
|
||||||
|
@ -296,17 +296,34 @@ impl<'tokens, 'src> Parser<'tokens, 'src> {
|
|||||||
|
|
||||||
/// Parse a justfile, consumes self
|
/// Parse a justfile, consumes self
|
||||||
fn parse_justfile(mut self) -> CompilationResult<'src, Module<'src>> {
|
fn parse_justfile(mut self) -> CompilationResult<'src, Module<'src>> {
|
||||||
|
fn pop_doc_comment<'src>(
|
||||||
|
items: &mut Vec<Item<'src>>,
|
||||||
|
eol_since_last_comment: bool,
|
||||||
|
) -> Option<&'src str> {
|
||||||
|
if !eol_since_last_comment {
|
||||||
|
if let Some(Item::Comment(contents)) = items.last() {
|
||||||
|
let doc = Some(contents[1..].trim_start());
|
||||||
|
items.pop();
|
||||||
|
return doc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
let mut items = Vec::new();
|
let mut items = Vec::new();
|
||||||
|
|
||||||
let mut doc = None;
|
let mut eol_since_last_comment = false;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let next = self.next()?;
|
let next = self.next()?;
|
||||||
|
|
||||||
if let Some(comment) = self.accept(Comment)? {
|
if let Some(comment) = self.accept(Comment)? {
|
||||||
doc = Some(comment.lexeme()[1..].trim());
|
items.push(Item::Comment(comment.lexeme().trim_end()));
|
||||||
self.expect_eol()?;
|
self.expect_eol()?;
|
||||||
|
eol_since_last_comment = false;
|
||||||
} else if self.accepted(Eol)? {
|
} else if self.accepted(Eol)? {
|
||||||
|
eol_since_last_comment = true;
|
||||||
} else if self.accepted(Eof)? {
|
} else if self.accepted(Eof)? {
|
||||||
break;
|
break;
|
||||||
} else if self.next_is(Identifier) {
|
} else if self.next_is(Identifier) {
|
||||||
@ -317,6 +334,7 @@ impl<'tokens, 'src> Parser<'tokens, 'src> {
|
|||||||
} else if self.next_are(&[Identifier, Identifier, ColonEquals]) {
|
} else if self.next_are(&[Identifier, Identifier, ColonEquals]) {
|
||||||
items.push(Item::Alias(self.parse_alias()?));
|
items.push(Item::Alias(self.parse_alias()?));
|
||||||
} else {
|
} else {
|
||||||
|
let doc = pop_doc_comment(&mut items, eol_since_last_comment);
|
||||||
items.push(Item::Recipe(self.parse_recipe(doc, false)?));
|
items.push(Item::Recipe(self.parse_recipe(doc, false)?));
|
||||||
},
|
},
|
||||||
Some(Keyword::Export) =>
|
Some(Keyword::Export) =>
|
||||||
@ -326,6 +344,7 @@ impl<'tokens, 'src> Parser<'tokens, 'src> {
|
|||||||
self.presume_keyword(Keyword::Export)?;
|
self.presume_keyword(Keyword::Export)?;
|
||||||
items.push(Item::Assignment(self.parse_assignment(true)?));
|
items.push(Item::Assignment(self.parse_assignment(true)?));
|
||||||
} else {
|
} else {
|
||||||
|
let doc = pop_doc_comment(&mut items, eol_since_last_comment);
|
||||||
items.push(Item::Recipe(self.parse_recipe(doc, false)?));
|
items.push(Item::Recipe(self.parse_recipe(doc, false)?));
|
||||||
},
|
},
|
||||||
Some(Keyword::Set) =>
|
Some(Keyword::Set) =>
|
||||||
@ -335,6 +354,7 @@ impl<'tokens, 'src> Parser<'tokens, 'src> {
|
|||||||
{
|
{
|
||||||
items.push(Item::Set(self.parse_set()?));
|
items.push(Item::Set(self.parse_set()?));
|
||||||
} else {
|
} else {
|
||||||
|
let doc = pop_doc_comment(&mut items, eol_since_last_comment);
|
||||||
items.push(Item::Recipe(self.parse_recipe(doc, false)?));
|
items.push(Item::Recipe(self.parse_recipe(doc, false)?));
|
||||||
},
|
},
|
||||||
_ =>
|
_ =>
|
||||||
@ -343,18 +363,16 @@ impl<'tokens, 'src> Parser<'tokens, 'src> {
|
|||||||
} else if self.next_are(&[Identifier, ColonEquals]) {
|
} else if self.next_are(&[Identifier, ColonEquals]) {
|
||||||
items.push(Item::Assignment(self.parse_assignment(false)?));
|
items.push(Item::Assignment(self.parse_assignment(false)?));
|
||||||
} else {
|
} else {
|
||||||
|
let doc = pop_doc_comment(&mut items, eol_since_last_comment);
|
||||||
items.push(Item::Recipe(self.parse_recipe(doc, false)?));
|
items.push(Item::Recipe(self.parse_recipe(doc, false)?));
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
} else if self.accepted(At)? {
|
} else if self.accepted(At)? {
|
||||||
|
let doc = pop_doc_comment(&mut items, eol_since_last_comment);
|
||||||
items.push(Item::Recipe(self.parse_recipe(doc, true)?));
|
items.push(Item::Recipe(self.parse_recipe(doc, true)?));
|
||||||
} else {
|
} else {
|
||||||
return Err(self.unexpected_token()?);
|
return Err(self.unexpected_token()?);
|
||||||
}
|
}
|
||||||
|
|
||||||
if next.kind != Comment {
|
|
||||||
doc = None;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.next != self.tokens.len() {
|
if self.next != self.tokens.len() {
|
||||||
@ -1097,11 +1115,17 @@ mod tests {
|
|||||||
test! {
|
test! {
|
||||||
name: comment,
|
name: comment,
|
||||||
text: "# foo",
|
text: "# foo",
|
||||||
tree: (justfile),
|
tree: (justfile (comment "# foo")),
|
||||||
}
|
}
|
||||||
|
|
||||||
test! {
|
test! {
|
||||||
name: comment_alias,
|
name: comment_before_alias,
|
||||||
|
text: "# foo\nalias x := y",
|
||||||
|
tree: (justfile (comment "# foo") (alias x y)),
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: comment_after_alias,
|
||||||
text: "alias x := y # foo",
|
text: "alias x := y # foo",
|
||||||
tree: (justfile (alias x y)),
|
tree: (justfile (alias x y)),
|
||||||
}
|
}
|
||||||
@ -1166,7 +1190,7 @@ mod tests {
|
|||||||
x := y
|
x := y
|
||||||
bar:
|
bar:
|
||||||
",
|
",
|
||||||
tree: (justfile (assignment x y) (recipe bar)),
|
tree: (justfile (comment "# foo") (assignment x y) (recipe bar)),
|
||||||
}
|
}
|
||||||
|
|
||||||
test! {
|
test! {
|
||||||
@ -1176,7 +1200,7 @@ mod tests {
|
|||||||
|
|
||||||
bar:
|
bar:
|
||||||
",
|
",
|
||||||
tree: (justfile (recipe bar)),
|
tree: (justfile (comment "# foo") (recipe bar)),
|
||||||
}
|
}
|
||||||
|
|
||||||
test! {
|
test! {
|
||||||
|
@ -23,7 +23,7 @@ fn error_from_signal(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A recipe, e.g. `foo: bar baz`
|
/// A recipe, e.g. `foo: bar baz`
|
||||||
#[derive(PartialEq, Debug)]
|
#[derive(PartialEq, Debug, Clone)]
|
||||||
pub(crate) struct Recipe<'src, D = Dependency<'src>> {
|
pub(crate) struct Recipe<'src, D = Dependency<'src>> {
|
||||||
pub(crate) dependencies: Vec<D>,
|
pub(crate) dependencies: Vec<D>,
|
||||||
pub(crate) doc: Option<&'src str>,
|
pub(crate) doc: Option<&'src str>,
|
||||||
@ -314,7 +314,7 @@ impl<'src, D> Keyed<'src> for Recipe<'src, D> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'src> Display for Recipe<'src> {
|
impl<'src, D: Display> Display for Recipe<'src, D> {
|
||||||
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
|
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
|
||||||
if let Some(doc) = self.doc {
|
if let Some(doc) = self.doc {
|
||||||
writeln!(f, "# {}", doc)?;
|
writeln!(f, "# {}", doc)?;
|
||||||
@ -344,7 +344,7 @@ impl<'src> Display for Recipe<'src> {
|
|||||||
}
|
}
|
||||||
match fragment {
|
match fragment {
|
||||||
Fragment::Text { token } => write!(f, "{}", token.lexeme())?,
|
Fragment::Text { token } => write!(f, "{}", token.lexeme())?,
|
||||||
Fragment::Interpolation { expression, .. } => write!(f, "{{{{{}}}}}", expression)?,
|
Fragment::Interpolation { expression, .. } => write!(f, "{{{{ {} }}}}", expression)?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if i + 1 < self.body.len() {
|
if i + 1 < self.body.len() {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::common::*;
|
use crate::common::*;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) struct Set<'src> {
|
pub(crate) struct Set<'src> {
|
||||||
pub(crate) name: Name<'src>,
|
pub(crate) name: Name<'src>,
|
||||||
pub(crate) value: Setting<'src>,
|
pub(crate) value: Setting<'src>,
|
||||||
@ -11,3 +11,9 @@ impl<'src> Keyed<'src> for Set<'src> {
|
|||||||
self.name.lexeme()
|
self.name.lexeme()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'src> Display for Set<'src> {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
|
||||||
|
write!(f, "set {} := {}", self.name, self.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::common::*;
|
use crate::common::*;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) enum Setting<'src> {
|
pub(crate) enum Setting<'src> {
|
||||||
DotenvLoad(bool),
|
DotenvLoad(bool),
|
||||||
Export(bool),
|
Export(bool),
|
||||||
@ -8,8 +8,31 @@ pub(crate) enum Setting<'src> {
|
|||||||
Shell(Shell<'src>),
|
Shell(Shell<'src>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub(crate) struct Shell<'src> {
|
pub(crate) struct Shell<'src> {
|
||||||
pub(crate) command: StringLiteral<'src>,
|
pub(crate) command: StringLiteral<'src>,
|
||||||
pub(crate) arguments: Vec<StringLiteral<'src>>,
|
pub(crate) arguments: Vec<StringLiteral<'src>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'src> Display for Setting<'src> {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
|
||||||
|
match self {
|
||||||
|
Setting::DotenvLoad(value) => write!(f, "{}", value),
|
||||||
|
Setting::Export(value) => write!(f, "{}", value),
|
||||||
|
Setting::PositionalArguments(value) => write!(f, "{}", value),
|
||||||
|
Setting::Shell(shell) => write!(f, "{}", shell),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'src> Display for Shell<'src> {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
|
||||||
|
write!(f, "[{}", self.command)?;
|
||||||
|
|
||||||
|
for argument in &self.arguments {
|
||||||
|
write!(f, ", {}", argument)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
write!(f, "]")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::common::*;
|
use crate::common::*;
|
||||||
|
|
||||||
#[derive(PartialEq, Debug)]
|
#[derive(PartialEq, Debug, Clone)]
|
||||||
pub(crate) struct StringLiteral<'src> {
|
pub(crate) struct StringLiteral<'src> {
|
||||||
pub(crate) kind: StringKind,
|
pub(crate) kind: StringKind,
|
||||||
pub(crate) raw: &'src str,
|
pub(crate) raw: &'src str,
|
||||||
|
@ -20,6 +20,7 @@ pub(crate) enum Subcommand {
|
|||||||
overrides: BTreeMap<String, String>,
|
overrides: BTreeMap<String, String>,
|
||||||
variable: Option<String>,
|
variable: Option<String>,
|
||||||
},
|
},
|
||||||
|
Format,
|
||||||
Init,
|
Init,
|
||||||
List,
|
List,
|
||||||
Run {
|
Run {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use crate::common::*;
|
use crate::common::*;
|
||||||
|
|
||||||
|
use crate::compiler::Compiler;
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
pub(crate) fn compile(text: &str) -> Justfile {
|
pub(crate) fn compile(text: &str) -> Justfile {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::common::*;
|
use crate::common::*;
|
||||||
|
|
||||||
#[derive(Derivative)]
|
#[derive(Derivative)]
|
||||||
#[derivative(Debug, PartialEq = "feature_allow_slow_enum")]
|
#[derivative(Debug, Clone, PartialEq = "feature_allow_slow_enum")]
|
||||||
pub(crate) enum Thunk<'src> {
|
pub(crate) enum Thunk<'src> {
|
||||||
Nullary {
|
Nullary {
|
||||||
name: Name<'src>,
|
name: Name<'src>,
|
||||||
|
@ -1,7 +1,23 @@
|
|||||||
use crate::common::*;
|
use crate::common::*;
|
||||||
|
|
||||||
#[derive(PartialEq, Debug)]
|
#[derive(PartialEq, Debug, Clone)]
|
||||||
pub(crate) struct UnresolvedDependency<'src> {
|
pub(crate) struct UnresolvedDependency<'src> {
|
||||||
pub(crate) recipe: Name<'src>,
|
pub(crate) recipe: Name<'src>,
|
||||||
pub(crate) arguments: Vec<Expression<'src>>,
|
pub(crate) arguments: Vec<Expression<'src>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'src> Display for UnresolvedDependency<'src> {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
|
||||||
|
if self.arguments.is_empty() {
|
||||||
|
write!(f, "{}", self.recipe)
|
||||||
|
} else {
|
||||||
|
write!(f, "({}", self.recipe)?;
|
||||||
|
|
||||||
|
for argument in &self.arguments {
|
||||||
|
write!(f, " {}", argument)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
write!(f, ")")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::common::*;
|
use crate::common::*;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub(crate) enum Warning {
|
pub(crate) enum Warning {
|
||||||
// Remove this on 2021-07-01.
|
// Remove this on 2021-07-01.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
@ -33,7 +33,7 @@ test! {
|
|||||||
USAGE:
|
USAGE:
|
||||||
just{} --color <COLOR> --shell <SHELL> --shell-arg <SHELL-ARG>... \
|
just{} --color <COLOR> --shell <SHELL> --shell-arg <SHELL-ARG>... \
|
||||||
<--choose|--command <COMMAND>|--completions <SHELL>|--dump|--edit|\
|
<--choose|--command <COMMAND>|--completions <SHELL>|--dump|--edit|\
|
||||||
--evaluate|--init|--list|--show <RECIPE>|--summary|--variables>
|
--evaluate|--fmt|--init|--list|--show <RECIPE>|--summary|--variables>
|
||||||
|
|
||||||
For more information try --help
|
For more information try --help
|
||||||
", EXE_SUFFIX),
|
", EXE_SUFFIX),
|
||||||
|
@ -149,10 +149,10 @@ test! {
|
|||||||
echo {{ a }}
|
echo {{ a }}
|
||||||
",
|
",
|
||||||
args: ("--dump"),
|
args: ("--dump"),
|
||||||
stdout: format!("
|
stdout: "
|
||||||
a := if '' == '' {{ '' }} else {{ '' }}{}
|
a := if '' == '' { '' } else { '' }
|
||||||
|
|
||||||
foo:
|
foo:
|
||||||
echo {{{{a}}}}
|
echo {{ a }}
|
||||||
", " ").as_str(),
|
",
|
||||||
}
|
}
|
||||||
|
891
tests/fmt.rs
Normal file
891
tests/fmt.rs
Normal file
@ -0,0 +1,891 @@
|
|||||||
|
test! {
|
||||||
|
name: alias_good,
|
||||||
|
justfile: "
|
||||||
|
alias f := foo
|
||||||
|
|
||||||
|
foo:
|
||||||
|
echo foo
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
alias f := foo
|
||||||
|
|
||||||
|
foo:
|
||||||
|
echo foo
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: alias_fix_indent,
|
||||||
|
justfile: "
|
||||||
|
alias f:= foo
|
||||||
|
|
||||||
|
foo:
|
||||||
|
echo foo
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
alias f := foo
|
||||||
|
|
||||||
|
foo:
|
||||||
|
echo foo
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: assignment_singlequote,
|
||||||
|
justfile: "
|
||||||
|
foo := 'foo'
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
foo := 'foo'
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: assignment_doublequote,
|
||||||
|
justfile: r#"
|
||||||
|
foo := "foo"
|
||||||
|
"#,
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: r#"
|
||||||
|
foo := "foo"
|
||||||
|
"#,
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: assignment_indented_singlequote,
|
||||||
|
justfile: "
|
||||||
|
foo := '''
|
||||||
|
foo
|
||||||
|
'''
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: r"
|
||||||
|
foo := '''
|
||||||
|
foo
|
||||||
|
'''
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: assignment_indented_doublequote,
|
||||||
|
justfile: r#"
|
||||||
|
foo := """
|
||||||
|
foo
|
||||||
|
"""
|
||||||
|
"#,
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: r#"
|
||||||
|
foo := """
|
||||||
|
foo
|
||||||
|
"""
|
||||||
|
"#,
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: assignment_backtick,
|
||||||
|
justfile: "
|
||||||
|
foo := `foo`
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
foo := `foo`
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: assignment_indented_backtick,
|
||||||
|
justfile: "
|
||||||
|
foo := ```
|
||||||
|
foo
|
||||||
|
```
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
foo := ```
|
||||||
|
foo
|
||||||
|
```
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: assignment_name,
|
||||||
|
justfile: "
|
||||||
|
bar := 'bar'
|
||||||
|
foo := bar
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
bar := 'bar'
|
||||||
|
foo := bar
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: assignment_parenthized_expression,
|
||||||
|
justfile: "
|
||||||
|
foo := ('foo')
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
foo := ('foo')
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: assignment_export,
|
||||||
|
justfile: "
|
||||||
|
export foo := 'foo'
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
export foo := 'foo'
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: assignment_concat_values,
|
||||||
|
justfile: "
|
||||||
|
foo := 'foo' + 'bar'
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
foo := 'foo' + 'bar'
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: assignment_if_oneline,
|
||||||
|
justfile: "
|
||||||
|
foo := if 'foo' == 'foo' { 'foo' } else { 'bar' }
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
foo := if 'foo' == 'foo' { 'foo' } else { 'bar' }
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: assignment_if_multiline,
|
||||||
|
justfile: "
|
||||||
|
foo := if 'foo' != 'foo' {
|
||||||
|
'foo'
|
||||||
|
} else {
|
||||||
|
'bar'
|
||||||
|
}
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
foo := if 'foo' != 'foo' { 'foo' } else { 'bar' }
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: assignment_nullary_function,
|
||||||
|
justfile: "
|
||||||
|
foo := arch()
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
foo := arch()
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: assignment_unary_function,
|
||||||
|
justfile: "
|
||||||
|
foo := env_var('foo')
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
foo := env_var('foo')
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: assignment_binary_function,
|
||||||
|
justfile: "
|
||||||
|
foo := env_var_or_default('foo', 'bar')
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
foo := env_var_or_default('foo', 'bar')
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: recipe_ordinary,
|
||||||
|
justfile: "
|
||||||
|
foo:
|
||||||
|
echo bar
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
foo:
|
||||||
|
echo bar
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: recipe_with_docstring,
|
||||||
|
justfile: "
|
||||||
|
# bar
|
||||||
|
foo:
|
||||||
|
echo bar
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
# bar
|
||||||
|
foo:
|
||||||
|
echo bar
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: recipe_with_comments_in_body,
|
||||||
|
justfile: "
|
||||||
|
foo:
|
||||||
|
# bar
|
||||||
|
echo bar
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
foo:
|
||||||
|
# bar
|
||||||
|
echo bar
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: recipe_body_is_comment,
|
||||||
|
justfile: "
|
||||||
|
foo:
|
||||||
|
# bar
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
foo:
|
||||||
|
# bar
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: recipe_several_commands,
|
||||||
|
justfile: "
|
||||||
|
foo:
|
||||||
|
echo bar
|
||||||
|
echo baz
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
foo:
|
||||||
|
echo bar
|
||||||
|
echo baz
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: recipe_quiet,
|
||||||
|
justfile: "
|
||||||
|
@foo:
|
||||||
|
echo bar
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
@foo:
|
||||||
|
echo bar
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: recipe_quiet_command,
|
||||||
|
justfile: "
|
||||||
|
foo:
|
||||||
|
@echo bar
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
foo:
|
||||||
|
@echo bar
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: recipe_quiet_comment,
|
||||||
|
justfile: "
|
||||||
|
foo:
|
||||||
|
@# bar
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
foo:
|
||||||
|
@# bar
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: recipe_ignore_errors,
|
||||||
|
justfile: "
|
||||||
|
foo:
|
||||||
|
-echo foo
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
foo:
|
||||||
|
-echo foo
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: recipe_parameter,
|
||||||
|
justfile: "
|
||||||
|
foo BAR:
|
||||||
|
echo foo
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
foo BAR:
|
||||||
|
echo foo
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: recipe_parameter_default,
|
||||||
|
justfile: "
|
||||||
|
foo BAR='bar':
|
||||||
|
echo foo
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
foo BAR='bar':
|
||||||
|
echo foo
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: recipe_parameter_envar,
|
||||||
|
justfile: "
|
||||||
|
foo $BAR:
|
||||||
|
echo foo
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
foo $BAR:
|
||||||
|
echo foo
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: recipe_parameter_default_envar,
|
||||||
|
justfile: "
|
||||||
|
foo $BAR='foo':
|
||||||
|
echo foo
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
foo $BAR='foo':
|
||||||
|
echo foo
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: recipe_parameter_concat,
|
||||||
|
justfile: "
|
||||||
|
foo BAR=('bar' + 'baz'):
|
||||||
|
echo foo
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
foo BAR=('bar' + 'baz'):
|
||||||
|
echo foo
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: recipe_parameters,
|
||||||
|
justfile: "
|
||||||
|
foo BAR BAZ:
|
||||||
|
echo foo
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
foo BAR BAZ:
|
||||||
|
echo foo
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: recipe_parameters_envar,
|
||||||
|
justfile: "
|
||||||
|
foo $BAR $BAZ:
|
||||||
|
echo foo
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
foo $BAR $BAZ:
|
||||||
|
echo foo
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: recipe_variadic_plus,
|
||||||
|
justfile: "
|
||||||
|
foo +BAR:
|
||||||
|
echo foo
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
foo +BAR:
|
||||||
|
echo foo
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: recipe_variadic_star,
|
||||||
|
justfile: "
|
||||||
|
foo *BAR:
|
||||||
|
echo foo
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
foo *BAR:
|
||||||
|
echo foo
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: recipe_positional_variadic,
|
||||||
|
justfile: "
|
||||||
|
foo BAR *BAZ:
|
||||||
|
echo foo
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
foo BAR *BAZ:
|
||||||
|
echo foo
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: recipe_variadic_default,
|
||||||
|
justfile: "
|
||||||
|
foo +BAR='bar':
|
||||||
|
echo foo
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
foo +BAR='bar':
|
||||||
|
echo foo
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: recipe_parameter_in_body,
|
||||||
|
justfile: "
|
||||||
|
foo BAR:
|
||||||
|
echo {{ BAR }}
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
foo BAR:
|
||||||
|
echo {{ BAR }}
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: recipe_parameter_conditional,
|
||||||
|
justfile: "
|
||||||
|
foo BAR:
|
||||||
|
echo {{ if 'foo' == 'foo' { 'foo' } else { 'bar' } }}
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
foo BAR:
|
||||||
|
echo {{ if 'foo' == 'foo' { 'foo' } else { 'bar' } }}
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: recipe_escaped_braces,
|
||||||
|
justfile: "
|
||||||
|
foo BAR:
|
||||||
|
echo '{{{{BAR}}}}'
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
foo BAR:
|
||||||
|
echo '{{{{BAR}}}}'
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: recipe_assignment_in_body,
|
||||||
|
justfile: "
|
||||||
|
bar := 'bar'
|
||||||
|
|
||||||
|
foo:
|
||||||
|
echo $bar
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
bar := 'bar'
|
||||||
|
|
||||||
|
foo:
|
||||||
|
echo $bar
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: recipe_dependency,
|
||||||
|
justfile: "
|
||||||
|
bar:
|
||||||
|
echo bar
|
||||||
|
|
||||||
|
foo: bar
|
||||||
|
echo foo
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
bar:
|
||||||
|
echo bar
|
||||||
|
|
||||||
|
foo: bar
|
||||||
|
echo foo
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: recipe_dependency_param,
|
||||||
|
justfile: "
|
||||||
|
bar BAR:
|
||||||
|
echo bar
|
||||||
|
|
||||||
|
foo: (bar 'bar')
|
||||||
|
echo foo
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
bar BAR:
|
||||||
|
echo bar
|
||||||
|
|
||||||
|
foo: (bar 'bar')
|
||||||
|
echo foo
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: recipe_dependency_params,
|
||||||
|
justfile: "
|
||||||
|
bar BAR BAZ:
|
||||||
|
echo bar
|
||||||
|
|
||||||
|
foo: (bar 'bar' 'baz')
|
||||||
|
echo foo
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
bar BAR BAZ:
|
||||||
|
echo bar
|
||||||
|
|
||||||
|
foo: (bar 'bar' 'baz')
|
||||||
|
echo foo
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: recipe_dependencies,
|
||||||
|
justfile: "
|
||||||
|
bar:
|
||||||
|
echo bar
|
||||||
|
|
||||||
|
baz:
|
||||||
|
echo baz
|
||||||
|
|
||||||
|
foo: baz bar
|
||||||
|
echo foo
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
bar:
|
||||||
|
echo bar
|
||||||
|
|
||||||
|
baz:
|
||||||
|
echo baz
|
||||||
|
|
||||||
|
foo: baz bar
|
||||||
|
echo foo
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: recipe_dependencies_params,
|
||||||
|
justfile: "
|
||||||
|
bar BAR:
|
||||||
|
echo bar
|
||||||
|
|
||||||
|
baz BAZ:
|
||||||
|
echo baz
|
||||||
|
|
||||||
|
foo: (baz 'baz') (bar 'bar')
|
||||||
|
echo foo
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
bar BAR:
|
||||||
|
echo bar
|
||||||
|
|
||||||
|
baz BAZ:
|
||||||
|
echo baz
|
||||||
|
|
||||||
|
foo: (baz 'baz') (bar 'bar')
|
||||||
|
echo foo
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: set_true_explicit,
|
||||||
|
justfile: "
|
||||||
|
set export := true
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
set export := true
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: set_true_implicit,
|
||||||
|
justfile: "
|
||||||
|
set export
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
set export := true
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: set_false,
|
||||||
|
justfile: "
|
||||||
|
set export := false
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
set export := false
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: set_shell,
|
||||||
|
justfile: r#"
|
||||||
|
set shell := ['sh', "-c"]
|
||||||
|
"#,
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: r#"
|
||||||
|
set shell := ['sh', "-c"]
|
||||||
|
"#,
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: comment,
|
||||||
|
justfile: "
|
||||||
|
# foo
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
# foo
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: comment_multiline,
|
||||||
|
justfile: "
|
||||||
|
# foo
|
||||||
|
# bar
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
# foo
|
||||||
|
# bar
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: comment_leading,
|
||||||
|
justfile: "
|
||||||
|
# foo
|
||||||
|
|
||||||
|
foo := 'bar'
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
# foo
|
||||||
|
|
||||||
|
foo := 'bar'
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: comment_trailing,
|
||||||
|
justfile: "
|
||||||
|
foo := 'bar'
|
||||||
|
|
||||||
|
# foo
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
foo := 'bar'
|
||||||
|
|
||||||
|
# foo
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: comment_before_recipe,
|
||||||
|
justfile: "
|
||||||
|
# foo
|
||||||
|
|
||||||
|
foo:
|
||||||
|
echo foo
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
# foo
|
||||||
|
|
||||||
|
foo:
|
||||||
|
echo foo
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: comment_before_docstring_recipe,
|
||||||
|
justfile: "
|
||||||
|
# bar
|
||||||
|
|
||||||
|
# foo
|
||||||
|
foo:
|
||||||
|
echo foo
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
# bar
|
||||||
|
|
||||||
|
# foo
|
||||||
|
foo:
|
||||||
|
echo foo
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: group_recipies,
|
||||||
|
justfile: "
|
||||||
|
foo:
|
||||||
|
echo foo
|
||||||
|
bar:
|
||||||
|
echo bar
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
foo:
|
||||||
|
echo foo
|
||||||
|
|
||||||
|
bar:
|
||||||
|
echo bar
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: group_aliases,
|
||||||
|
justfile: "
|
||||||
|
alias f := foo
|
||||||
|
|
||||||
|
alias b := bar
|
||||||
|
|
||||||
|
foo:
|
||||||
|
echo foo
|
||||||
|
|
||||||
|
bar:
|
||||||
|
echo bar
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
alias f := foo
|
||||||
|
alias b := bar
|
||||||
|
|
||||||
|
foo:
|
||||||
|
echo foo
|
||||||
|
|
||||||
|
bar:
|
||||||
|
echo bar
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: group_assignments,
|
||||||
|
justfile: "
|
||||||
|
foo := 'foo'
|
||||||
|
bar := 'bar'
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
foo := 'foo'
|
||||||
|
bar := 'bar'
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: group_sets,
|
||||||
|
justfile: "
|
||||||
|
set export := true
|
||||||
|
set positional-arguments := true
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
set export := true
|
||||||
|
set positional-arguments := true
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: group_comments,
|
||||||
|
justfile: "
|
||||||
|
# foo
|
||||||
|
|
||||||
|
# bar
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
# foo
|
||||||
|
# bar
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: separate_recipes_aliases,
|
||||||
|
justfile: "
|
||||||
|
alias f := foo
|
||||||
|
foo:
|
||||||
|
echo foo
|
||||||
|
",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
alias f := foo
|
||||||
|
|
||||||
|
foo:
|
||||||
|
echo foo
|
||||||
|
",
|
||||||
|
}
|
||||||
|
|
||||||
|
test! {
|
||||||
|
name: no_trailing_newline,
|
||||||
|
justfile: "
|
||||||
|
foo:
|
||||||
|
echo foo",
|
||||||
|
args: ("--dump"),
|
||||||
|
stdout: "
|
||||||
|
foo:
|
||||||
|
echo foo
|
||||||
|
",
|
||||||
|
}
|
@ -14,6 +14,7 @@ mod error_messages;
|
|||||||
mod evaluate;
|
mod evaluate;
|
||||||
mod examples;
|
mod examples;
|
||||||
mod export;
|
mod export;
|
||||||
|
mod fmt;
|
||||||
mod init;
|
mod init;
|
||||||
mod interrupts;
|
mod interrupts;
|
||||||
mod invocation_directory;
|
mod invocation_directory;
|
||||||
|
@ -265,7 +265,7 @@ recipe:
|
|||||||
args: ("--show", "recipe"),
|
args: ("--show", "recipe"),
|
||||||
stdout: r#"
|
stdout: r#"
|
||||||
recipe:
|
recipe:
|
||||||
echo {{hello + "bar" + bar}}
|
echo {{ hello + "bar" + bar }}
|
||||||
"#,
|
"#,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ impl<'a> Test<'a> {
|
|||||||
|
|
||||||
let mut justfile_path = tmp.path().to_path_buf();
|
let mut justfile_path = tmp.path().to_path_buf();
|
||||||
justfile_path.push("justfile");
|
justfile_path.push("justfile");
|
||||||
fs::write(justfile_path, justfile).unwrap();
|
fs::write(&justfile_path, justfile).unwrap();
|
||||||
|
|
||||||
let mut dotenv_path = tmp.path().to_path_buf();
|
let mut dotenv_path = tmp.path().to_path_buf();
|
||||||
dotenv_path.push(".env");
|
dotenv_path.push(".env");
|
||||||
|
Loading…
Reference in New Issue
Block a user