Modify the lexer to keep track of opening `({[` and closing `]})` delimiters.
When the lexer would emit an eol or indent outside of a recipe when there
is at least one open delimiter, emit a whitespace token instead.
This allows expressions to be split on multiple lines, like so:
x := if 'a' == 'b' {
'x'
} else {
'y'
}
This does not work inside of recipe body interpolations, although this
restriction might relaxed in the future.
Add conditional expressions of the form:
foo := if lhs == rhs { then } else { otherwise }
`lhs`, `rhs`, `then`, and `otherwise` are all arbitrary expressions, and
can recursively include other conditionals. Conditionals short-circuit,
so the branch not taken isn't evaluated.
It is also possible to test for inequality with `==`.
Remove all manual tracking of which tokens would have been accepted by
the parser in favor of having the parser add tokens that it checks for
to a set of expected tokens, clearing them when it accepts a token, and
using the current contents of the set in error messages.
This is a massive improvement, and will make the parser easier to
modify going forward.
And, this actually solves my sole issue with hand-written parsers.
Thanks to matklad on reddit for suggesting this!
Modifies the bash completion script to complete both recipes and flags.
`just <TAB>` will complete recipes, and `just -<TAB>` will complete
flags and options.
Moves the separate quiet variable in the `Config` struct into the existing
verbosity field; the `Verbosity` enum now has a `Quiet` variant. When running, the
presence of the quiet flag will set the verbosity to `Quiet`, overriding any
number of verbosity flags in the CLI args.
The `--choose` subcommand runs a chooser to select a recipe to run. The
chooser should read lines containing recipe names from standard input,
and write one of those names to standard output.
The chooser defaults to `fzf`, a popular fuzzy finder, but can be
overridden by setting $JUST_CHOOSER or passing `--chooser <CHOOSER>`.
Combine all integration test binaries into a single binary with the root
in `tests/lib.rs`. This also turns of automatic test discovery, so
when adding another set of integration tests, a mod statement will need
to be added to `tests/lib.rs`.
If an environment variable exists with the same key as a variable from a
`.env` file, skip the variable from the `.env` file in favor fo the key
from the environment.
On Windows, skip conversion if a shebang path does not include `/`. In
this case it is not a Unix path, and does not need to be converted to a
Windows path before running.
Make line continuations strip leading spaces on the next line.
This changes what is passed to the shell, so this is a breaking change.
However, I don't think that this will break any recipes.
- Complete variable names after `--set`
- Complete recipe names
- Display recipe signature and body below command line
- Modify completions subcommand to produce enhanced zsh completion script
Trim whitespace at beginning and end of generated completions.
Additionally, since some editors will automatically insert a final
newline into text files, make sure a final newline is present.
Add a subcommand that prints out a space-separated list of the names of
top-level variables in the justfile.
The syntax is:
$ just --variables
a b c
This can be used for any purpose, but is mostly intended for completion
scripts, so that they can get the names of variables without using
`--evaluate`.
Additionally:
- Add `bin/generate-completions` script to regenerate checked-in
completions
- Update dependencies
- Regenerate checked-in completions
Make just print clap-generated shell completion scripts with `--completions`
command. Currently, Bash, Zsh, Fish, PowerShell, and Elvish are supported.
Additionally, the generated completion scripts are checked in to the
`completions` folder.
Improve indentation handling in preparation for implementing inline
submodules. This changes the lexer to only parse freeform text inside
the first indent after a ':', so that just can be extended with new
indented constructs which are not recipe bodies. In addition, the lexer
should now handle multiple levels of indentation correctly.
Add the `--shell-arg` and `--clear-shell-args` flags, which allow
setting and clearing arguments to the shell from the command line.
This allows full control over the shell from the command line. Additionally,
any shell-related arguments on the command line override
`set shell := [...]` in the Justfile, which I think will be the behavior that most
people expect.
Modifies parsing to return strongly-typed `Thunk`s, which contain both
the function implementation, as well as the correct number of arguments.
This moves unknown function and function argument count mismatch errors
to parse time.
During analysis, resolve alias targets from `Name`s to `Rc<Recipe>`,
giving us type-level assurance that alias resolution was performed, and
avoiding the need to look up alias targets in a separate table when
running.
Make analysis resolve recipe dependencies from names (`Name`) to recipes
(`Rc<Recipe>`), to give type-level certainty that resolution was performed
correctly and remove the need to look up dependencies on run.
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.