This is a major release, containing architectural improvements and compatibility-focused features and fixes. A big thanks to all of the contributors over the last few months, including issue filers, question-askers, and code contributors 🙏.
Based on user-filed issues (thank you!), targeted work went into improving compatibility with popular tools like fzf and neofetch.
Additionally, a significant amount of work went into refactoring and improving usability of the public API surface within the crate-based libraries that make up brush's core. These come with breaking changes for programmatic clients, but we're confident they will come with significant benefit.
The following summary covers the most notable changes and the full change details are below.
✅ Features and Improvements
Builtins
The fc builtin received its initial implementation!
bind implementation received support for binding key sequences to readline functions (e.g., "\C-a":beginning-of-line).
trap now fully implements the EXIT trap.
Standard variables
Basic support for use of BASH_XTRACEFD was added. A new command-line parameter to brush (--inherit-fd) enables allow-listing inherited file descriptors for use within the shell.
Control flow
Support for an undocumented C-like syntax for arithmetic for loops has been implemented for improved compatibility.
🪳 Notable bug fixes
Fixes for quote handling of \' in double-quoted word contexts.
Targeted fixes to history importing make it more robust against non-UTF8 compatible text.
Fixes for parsing of here-documents in quoted command substitutions.
Fixes for nuanced quote removal in parameter expressions with replacements (e.g., "${var:+'x'}").
Fixes for command substitution expansions resulting in spawning processes with large volumes of output (e.g., $(emit-a-lot-of-text)).
Updates to the open file table made by commandless exec (e.g., exec 2>/dev/null) are now reflected immediately, even when in a loop context.
🚧 API Changes
Changes in this section pertain to programmatic clients of the brush-core, brush-parser, and brush-interactive crates. They do not apply to application-level shell users.
brush-builtins
All shell builtins have been moved into a new dedicated brush-builtins crate. With this move, significant refactoring was done to ensure that these builtins are all implementable using public APIs exposed by brush-core. In doing so, this also significantly advanced the richness of the latter APIs.
Important
Programmatic clients of the brush-core crate will find that a constructed Shell is not automatically populated with the usual set of builtins. New optional APIs exist in the brush-builtins crate to retrieve default builtins and in brush-core to register them with a Shell instance.
Parsing and AST
As an important step on our journey to evolve brush's parsers, @lu_zero has made contributions that start enriching our parsed Abstract Syntax Trees (ASTs) with links back to the source text. As part of this work, a new SourceLocation trait was introduced and implemented for many AST node types. Work will continue in the coming releases.
API Ergonomics
To improve ergonomics, we've introduce builder-based construction utilities to key structures like brush_core::Shell. We will continue to expand on this adoption over time to simplify the work of constructing these values.
Note that the signature of Shell::new() has changed and may require adjustment in callers.
Error handling
As preparatory work for future improvements, we've overhauled the core error types and execution result types in brush-core:
Error has been renamed to ErrorKind, with a new wrapping Error struct type that can carry additional context. This will be used in the future for improved diagnostics.
Clients of brush-core can now provide their own custom error formatter to render a displayable string from an Error value. This will be used by some of our frontends for fancier diagnostics in the future. It also decouples error formatting from writing.
Multiple overlapping result types across the core interpreter, command utilities, and builtins have been consolidated into a coherent set of ExecutionResult, ExecutionExitCode, and ExecutionControlFlow types. Along the way a handful of bugs for edge cases were identified and resolved as part of the streamlining.
Details
build(deps): bump the github-actions group with 6 updates by @dependabot[bot] in #669
build(deps): bump procfs from 0.17.0 to 0.18.0 in the cargo group across 1 directory by @dependabot[bot] in #671
build(deps): bump the github-actions group with 5 updates by @dependabot[bot] in #675