When `--init` is passed on the command line, search upward for the
project root, identified by the presence of a VCS directory like `.git`,
falling back to the current directory, and create a default justfile in
that directory.
Previously, we used `fs::canonicalize` to ensure paths used in search
were absolute. This lead to bad behavior when the justfile was symbolic
link to a file in another directory. Additionally, on Windows, this
produced paths in extended length syntax, which, I believe, has
compatibility issues.
This diff replaces uses of `fs::canonicalize` with a simpler algorithm
that roots path in the invocation directory (which will be a no-op if
said path is already absolute), uses `Path::components` to remove extra
`/` and `.`, and resolves instances of `..` without following symlinks, by
removing the `..` and the component that proceeds it.
Add a `set SETTING := VALUE` construct.
This construct is intended to be extended as needed with new settings,
but for now we're starting with `set shell := [COMMAND, ARG1, ...]`,
which allows setting the shell to use for recipe and backtick execution
in a justfile.
One of the primary reasons for adding this feature is to have a better
story on windows, where users are forced to scrounge up an `sh` binary
if they want to use `just`. This should allow them to use cmd.exe or
powershell in their justfiles, making just optionally dependency-free.
This diff makes positional argument parsing much cleaner, along with
adding a bunch of tests. Just's positional argument parsing is rather,
complex, so hopefully this reform allows it to both be correct and stay
correct.
User-visible changes:
- `just ..` is now accepted, with the same effect as `just ../`
- `just .` is also accepted, with the same effect as `just`
- It is now an error to pass arguments or overrides to subcommands
that do not accept them, namely `--dump`, `--edit`, `--list`,
`--show`, and `--summary`. It is also an error to pass arguments to
`--evaluate`, although `--evaluate` does of course still accept
overrides.
(This is a breaking change, but hopefully worth it, as it will allow us
to add arguments to subcommands which did not previously take
them, if we so desire.)
- Subcommands which do not accept arguments may now accept a
single search-directory argument, so `just --list ../` and
`just --dump foo/` are now accepted, with the former starting the
search for the justfile to list in the parent directory, and the latter
starting the search for the justfile to dump in `foo`.
- Instead of changing the current directory with `env::set_current_dir`
to be implicitly inherited by subprocesses, we now use
`Command::current_dir` to set it explicitly. This feels much better,
since we aren't dependent on the implicit state of the process's
current directory.
- Subcommand execution is much improved.
- Added a ton of tests for config parsing, config execution, working
dir, and search dir.
- Error messages are improved. Many more will be colored.
- The Config is now onwed, instead of borrowing from the arguments and
the `clap::ArgMatches` object. This is a huge ergonomic improvement,
especially in tests, and I don't think anyone will notice.
- `--edit` now uses `$VISUAL`, `$EDITOR`, or `vim`, in that order,
matching git, which I think is what most people will expect.
- Added a cute `tmptree!{}` macro, for creating temporary directories
populated with directories and files for tests.
- Admitted that grammer is LL(k) and I don't know what `k` is.
Moves the code which executes subcommands into Subcommand:run,
delegating to separate functions for each subcommand. This reduces the
disgustingness of `run::run` a bit, and paves the way for future
refactoring and cleanup.
Move `env::set_current_dir` outside of `Config::from_matches()` and into
`run()`. It's a bit cleaner this way, and sets us up to make the just
process not change its own directory at all, instead explicitly changing
the working directory of its child processes.
Borrow errors produced by an older version of rust forced us to create
copies of errors in the recipe resolver. The borrow checker appears to
have evolved to the point where these copies are unnecessary, so this
diff removes them.
Just's first parser performed both parsing, i.e the transformation of a
token stream according to the language grammar, and a number of consistency
checks and analysis passes.
This made parsing and analysis quite complex, so this diff introduces a
new, much cleaner `Parser`, and moves existing analysis into a dedicated
`Analyzer`.
- Differentiate between `arg`s, which are flags and options, and `cmd`s,
which are mutually exclusive subcommands
- Replace string literals, like "EVALUATE", with constants, like
`cmd::EVALUATE`, since they're slightly less error prone.
- Remove `Config::evaluate`, and handle it like other subcommands
- Refactor the lexer tests to be more readable, abandoning the
previous string-based summary DSL in favor of a more obvious
sequence of `TokenKinds` with optional lexemes. The new tests
also test that token lexemes are correct.
- Move duplicated `unindent` function into a shared crate,
`test-utilities`. This new versionless dev-dependency will
prevent publishing to crates.io, at least until rust-lang/cargo/pull/7333
makes it into stable. If we publish a new version before then,
test-utilities will need to be published to crates.io, so we can depend
on it by version.
run::run() is pretty unwieldy. As a first step in improving it, this
commit pulls most of the argument parsing into the `config` module.
It also renames `Configuration` to `Config`, just to be easier to type.
Previously, warnings upon encountering a deprecated use `=` in
assignments, exports, and aliases would print a message without any
indication of where the offending `=` was. This diff adds a proper
`Warning` enum, and uses it to report context, as is done with
compilation and runtime errors.
Eventually, there will probably be a `crate` visibility specifier that
does the same thing as `pub(crate)`. This commit replaces `pub` with
`pub(crate)`, so when `crate` is available we can easily switch to it.
Given the following justfile:
alias b := build
build:
echo 'Building!'
Just will show the alias along with the recipe:
$ just --show b
alias b := build
build:
echo 'Building!'
The generated man page doesn't look great by default, so this also adds the
help4help2man feature, which makes Just print a help message that produces
a better man page.
Just's dependency on brev was the cause of a
fairly deep branch of the transitive dependency
tree. To decrease build time and make the life of
packagers easier, this diff moves the functionality
that Just was using in Brev into Just itself, and
removes the dependency on Brev.
Fortunately, the only functionality that Just was
using was the output function and OutputError
enum, so this was easily done.
The parser could be confused into calling `PutBack::put_back` twice in a row, and thus dropping tokens. This commit switches to `PutBackN`, which allows any number of put backs in a row.
The invalid escape sequence error message is delimited with backticks
and isn't used as input to other programs. This diff tweaks the escaping rules
slightly when printing invalid escape sequences. In particular, `, \, ',
and " are now not be escaped.
`env_var(key)` looks up the value of the environment variable with name `key`, aborting execution if it is not found.
`env_var_or_default(key, default)` looks up the value of the environment variable with name `key`, returning `default` if it is not found.
- Switch to asciidoc, since it supports an auto-generated table of contents
- Re-organize into sections
- Document private recipes
- Document windows dependencies
- Document doc comments
This allows things like the following to work as,
I hope, one would expect:
commit +flags:
git commit {{flags}}
$ just commit -a
It is however a breaking change, so also bump version number to 0.3.0.
Color logic is fairly complicated, so moved it into its own
module.
A `Color` object now encapsulates the --color setting, which
stream we are printing to, and what color we are painting.
This way, Color::paint can just do the right thing when asked to
paint text.
Also added tests to make sure that --list and --highlight colors
are using the correct color codes.
We use EXEPATH, which points to the root of the MinGW installation
and can be used as a base for translating the unix path to the
executable in the shebang line.
If we're not on MinGW, well, we just throw up our hands and hope
for the best.
I was reusing TmpdirIoError for a few cases, but one of them
usually has more to do with the contents of the shebang line than
an actual io error involving the tmpdir. Pull it out into its own
RunError variant and improve the message.
* Run integration tests on multiple shells
To make sure that I don't break tests for shells other than my
dev-box's `sh` and the `sh` on travis, each integration test case
now runs using `sh`, `dash`, and `bash.
Moves platform specific functionality into its own module.
Thanks to @Meralis40 for starting this!
This also gets just building on windows \^_^/
Although a lot of tests still fail (✖╭╮✖)
The `PlatformInterface` trait contains functions which abstract
over platform specific functionality, with implementations for
different platforms behind #[cfg(*)] attributes.
- `make_shebang_command()` constructs a command which will execute
the given script as if by a shebang. On linux this executes the
file, on windows it runs the interpreter directly.
- `set_execute_permission()` sets the execute permission on a
file. This is a nop on windows, since all files are executable.
- `signal_from_exit_status()` extracts the signal a process was
halted by from its exit status, if it was halted by a signal.
Mostly for debugging purposes, so I can make sure behavior is
consistent across different shells. Although I suppose this might
also be of use if you've got a mega weird `sh` that you'd like to
avoid.
Defaults to `sh` so current behavior is preserved.
- Unicode 9 defines emoji to be wide characters; before their
width was ambiguous. unicode-width has picked this up, so the
tests which expected emoji to be single-width have been updated.
- The ordering of the --quiet and --dry-run flags seems to be
have flipped in a clap error message, which broke a test, which
is unbroken by this commit
This is done for two reasons:
1. Such names cannot be given on the command line, since clap will
intercept them and wrongly interpret them as flags.
2. The name '---' can conflict with yaml document delimiters. Kind of
speculative, but I was thinking that it would be nice to make sure that
'---' and '...' are illegal in a justfile, so that that one can be
included in a yaml document stream. Is this silly? I am really not sure.
This is backwards incompatible, but I don't think anyone will notice,
since names that start with '-' are likely to be rare.
The recipe dependency resolver had a bug which caused it to not resolve
dependencies after the first.
This caused the parameter check later in the program to crash.
Added a test and fixed it.
Fixes#148.
If the first argument to just contains a `/`, then it will be handled
specially. Everything before the last `/` is treated as a directory, and
just will search for the justfile starting there, instead of in the
current directory.
Previously, only one recipe with parameters could be passed on the
command line. This was to avoid confusion in case the number of
parameters a recipe took changed, and wound up using as an argument was
was once a recipe.
However, I don't think this is actually particularly confusing in
practice, and could be a slightly annoying limitation.
Now, any number of recipes with parameters may be given on the command
line.
Fixes#70
Recipes may now have a final variadic parameter:
```make
foo bar+:
@echo {{bar}}
```
Variadic parameters accept one or more arguments, and expand to a string containing those arguments separated by spaces:
```sh
$ just foo a b c d e
a b c d e
```
I elected to accept one or more arguments instead of zero or more arguments since unexpectedly empty arguments can sometimes be dangerous.
```make
clean dir:
rm -rf {{dir}}/bin
```
If `dir` is empty in the above recipe, you'll delete `/bin`, which is probably not what was intended.
The grammar now permits blank lines in recipes.
Note that inside of recipes, the token `NEWLINE` is used instead of the
non-terminal `eol`. This is because an `eol` optionally includes a
comment, whereas inside recipes bodies comments get no special
treatment.
Blank lines were being ignored by the parser, so lines would be reported
incorrectly in error messages from shebang recipes. Blank lines are now
included by the parser, so shebang recipes expand to have the non-blank
lines in the expected place in the file.
Causes all recipe lines to be printed, regardless of --quiet or `@`.
Prints the name of each recipe before running it. Hopefully useful for
diagnosing problems.
An invocation like `just foo=bar` would lead to no recipe being run due
to the way that override arguments were being processed.
Fix that and add a test that covers that case.
If a `#...` comment appears on the line immediately before a recipe, it
is considered to be a doc comment for that recipe.
Doc comments will be printed when recipes are `--list`ed or `--dump`ed.
Also adds some color to the `--list`ing.
Fixes#84
Some ugly code, but not as bad as I thought.
Elected not to go with indentation based line continuations. Too many
weird edge cases and feels like a gratuitious incompatibility with make.
Fixes#9
Looks like this:
```make
recipe argument default-argument='default value':
echo argument is {{argument}}
echo default-argument is {{default-argument}}
```
Thanks @deckarep for the feature request!
Fixes#49
Already implemented Display for Justfile, so no reason not to expose it
to the user.
Also only allow one of --list, --dump, or --show, since they don't make
a lot of sense together.
Input may contain tabs and other characters whose byte widths do not
correspond to their display widths. This causes error context
underlining to be off when lines contain those characters
Fixed by properly accounting for the display width of characters, as
well as replacing tabs with spaces when printing error messages.
This is a pretty gross commit, since it also includes a lot of
unrelated refactoring, especially of how error messages are printed.
Also adds a lint recipe that prints lines over 100 characters
To test, I added a `--color=[auto|always|never]` option that defaults to
auto in normal use, but can be forced to `always` for testing. In `auto`
mode it defers to `atty` to figure out if the current stream is a
terminal and uses color if so.
Color printing is controlled by the `alternate` formatting flag.
When printing an error message, using `{:#}` will print it with colors
and `{}` will print it normally.
I was using the width of the index of the line, not the displayed line
number, which is the index + 1, which could cause the error message to
be misaligned.
Fixed it, and added a test that checks for this.
I had previously not included the line for some error messages, but I
don't think that I had a good reason why, and they look pretty good,
so adding them back for consistency.
Surround variables with backticks, capitalize first letter of error
message, inflect properly depending on number of unknown overrides, and
improve wording.
Also added build dependency to `filter` recipe.
Saves the value in each expression fragment when that fragment is
evaluated so that we can print the value in Display. This allows
us to check fragment values in tests.