This is the first stable release as a proper module, now under
mvdan.cc/sh/v3/...
. Go 1.12 or later is supported.
A large number of changes have been done since the last feature release a year ago. All users are encouraged to update. Below are the major highlights.
- cmd/shfmt
- Support for EditorConfig files
- Drop the dependency on
diff
for the-d
flag, now using pure Go
- syntax
- Overhaul escaped newlines, now represented as
WordPart
positions - Improve some operator type names, to consistently convey meaning
- Completely remove
StmtList
- Redesign
IfClause
, making its "else" anotherIfClause
node - Redesign
DeclClause
to remove its brokenOpts
field - Brace expression parsing is now done with a
BraceExp
word part - Improve comment alignment in
Printer
via a post-process step - Add support for the
~
bitwise negation operator - Record the use of deprecated tokens in the syntax tree
- Overhaul escaped newlines, now represented as
- interp
- Improve the module API as "handlers", to reduce confusion with Go modules
- Split
LookPath
out ofExecHandler
to allow custom behavior Run
now returnsnil
instead ofShellExitStatus(0)
- expand
- Redesign
Variable
to reduce allocations - Add support for more escape sequences
- Make
Config
a bit more powerful viafunc
fields - Rework brace expansion via the new
BraceExp
word part
- Redesign
- pattern
- New package for shell pattern matching, extracted from
syntax
- Add support for multiple modes, including filenames and braces
- New package for shell pattern matching, extracted from
Special thanks to Konstantin Kulikov for his contribution to this release.
2.6.4 - 2019-03-10
- syntax
- Support array elements without values, like
declare -A x=([index]=)
- Parse
for i; do ...
uniquely, as it's short forfor i in "$@"
- Add missing error on unclosed nested backquotes
- Support array elements without values, like
- expand
- Don't expand tildes twice, fixing
echo ~
on Windows
- Don't expand tildes twice, fixing
- interp
- Fix the use of
Params
as an option toNew
- Support lowercase Windows volume names in
$PATH
- Fix the use of
2.6.3 - 2019-01-19
- expand
- Support globs with path prefixes and suffixes, like
./foo/*/
- Don't error when skipping non-directories in glob walks
- Support globs with path prefixes and suffixes, like
2.6.2 - 2018-12-08
- syntax
- Avoid premature reads in
Parser.Interactive
when parsing Unicode bytes - Fix parsing of certain Bash test expression involving newlines
Redirect.End
now takes theHdoc
field into accountValidName
now returnsfalse
for an empty string
- Avoid premature reads in
- expand
- Environment variables on Windows are case insensitive again
- interp
- Don't crash on
declare $unset=foo
- Fix a regression where executed programs would receive a broken environment
- Don't crash on
Note that the published Docker image was changed to set shfmt
as the
entrypoint, so previous uses with arguments like docker run mvdan/shfmt:v2.6.1 shfmt --version
should now be docker run mvdan/shfmt:v2.6.2 --version
.
2.6.1 - 2018-11-17
- syntax
- Fix
Parser.Incomplete
with some incomplete literals - Fix parsing of Bash regex tests in some edge cases
- Fix
- interp
- Add support for
$(<file)
special command substitutions
- Add support for
2.6.0 - 2018-11-10
This is the biggest v2 release to date. It's now possible to write an interactive shell, and it's easier and safer to perform shell expansions.
This will be the last major v2 version, to allow converting the project to a Go module in v3.
- Go 1.10 or later required to build
- syntax
- Add
Parser.Interactive
to implement an interactive shell - Add
Parser.Document
to parse a single here-document body - Add
Parser.Words
to incrementally parse separate words - Add the
Word.Lit
helper method - Support custom indentation in
<<-
heredoc bodies
- Add
- interp
- Stabilize API and add some examples
- Introduce a constructor, and redesign
Runner.Reset
- Move the context from a field to function parameters
- Remove
Runner.Stmt
in favor ofRun
withShellExitStatus
- shell
- Stabilize API and add some examples
- Add
Expand
, as a more powerfulos.Expand
- Add
Fields
, similar to the oldRunner.Fields
Source*
functions now take a contextSource*
functions no longer try to sandbox
- expand
- New package, split from
interp
- Allows performing shell expansions in a controlled way
- Redesigned
Environ
andVariable
moved frominterp
- New package, split from
2.5.1 - 2018-08-03
- syntax
- Fix a regression where semicolons would disappear within switch cases
2.5.0 - 2018-07-13
- syntax
- Add support for Bash's
{varname}<
redirects - Add
SpaceRedirects
to format redirects like> word
- Parse
$\"
correctly within double quotes - A few fixes where minification would break programs
- Printing of heredocs within
<()
no longer breaks them - Printing of single statements no longer adds empty lines
- Error on invalid parameter names like
${1a}
- Add support for Bash's
- interp
Runner.Dir
is now always an absolute path
- shell
Expand
now supports expanding a lone~
Expand
andSourceNode
now have default timeouts
- cmd/shfmt
- Add
-sr
to print spaces after redirect operators - Don't skip empty string values in
-tojson
- Include comment positions in
-tojson
- Add
2.4.0 - 2018-05-16
- Publish as a JS package, mvdan-sh
- syntax
- Add
DebugPrint
to pretty-print a syntax tree - Fix comment parsing and printing in some edge cases
- Indent
<<-
heredoc bodies if indenting with tabs - Add support for nested backquotes
- Relax parser to allow quotes in arithmetic expressions
- Don't rewrite
declare foo=
intodeclare foo
- Add
- interp
- Add support for
shopt -s globstar
- Replace
Runner.Env
with an interface
- Add support for
- shell
- Add
Expand
as a fully featured version ofos.Expand
- Add
- cmd/shfmt
- Set appropriate exit status when
-d
is used
- Set appropriate exit status when
2.3.0 - 2018-03-07
- syntax
- Case clause patterns are no longer forced on a single line
- Add
ExpandBraces
, to perform Bash brace expansion on words - Improve the handling of backslashes within backquotes
- Improve the parsing of Bash test regexes
- interp
- Support
$DIRSTACK
,${param[@]#word}
, and${param,word}
- Support
- cmd/shfmt
- Add
-d
, to display diffs when formatting differs - Promote
-exp.tojson
to-tojson
- Add
Pos
andEnd
fields to nodes in-tojson
- Inline
StmtList
fields to simplify the-tojson
output - Support
-l
on standard input
- Add
2.2.1 - 2018-01-25
- syntax
- Don't error on
${1:-default}
- Allow single quotes in
${x['str key']}
as well as double quotes - Add support for
${!foo[@]}
- Don't simplify
foo[$x]
tofoo[x]
, to not break string indexes - Fix
Stmt.End
when the end token is the background operator&
- Never apply the negation operator
!
to&&
and||
lists - Apply the background operator
&
to entire&&
and||
lists - Fix
StopAt
when the stop string is at the beginning of the source - In
N>word
, check thatN
is a valid numeric literal - Fix a couple of crashers found via fuzzing
- Don't error on
- cmd/shfmt
- Don't error if non-bash files can't be written to
2.2.0 - 2018-01-18
- Tests on Mac and Windows are now ran as part of CI
- syntax
- Add
StopAt
to stop lexing at a custom arbitrary token - Add
TranslatePattern
andQuotePattern
for pattern matching - Minification support added to the printer - see
Minify
- Add ParamExp.Names to represent
${!prefix*}
- Add TimeClause.PosixFormat for its
-p
flag - Fix parsing of assignment values containing
=
- Fix parsing of parameter expansions followed by a backslash
- Fix quotes in parameter expansion operators like
${v:-'def'}
- Fix parsing of negated declare attributes like
declare +x name
- Fix parsing of
${#@}
- Reject bad parameter expansion operators like
${v@WRONG}
- Reject inline array variables like
a=(b c) prog
- Reject indexing of special vars like
${1[3]}
- Reject
${!name}
when in POSIX mode - Reject multiple parameter expansion actions like
${#v:-def}
- Add
- interp
- Add Bash brace expansion support, including
{a,b}
and{x..y}
- Pattern matching actions are more correct and precise
- Exported some Runner internals, including
Vars
andFuncs
- Use the interpreter's
$PATH
to find binaries - Roll our own globbing to use our own pattern matching code
- Support the
getopts
sh builtin - Support the
read
bash builtin - Numerous changes to improve Windows support
- Add Bash brace expansion support, including
- shell
- New experimental package with high-level utility functions
- Add
SourceFile
to get the variables declared in a script - Add
SourceNode
as a lower-level version of the above
- cmd/shfmt
- Add
-mn
, which minifies programs viasyntax.Minify
- Add
2.1.0 - 2017-11-25
- syntax
- Add
Stmts
, to parse one statement at a time - Walk no longer ignores comments
- Parameter expansion end fixes, such as
$foo.bar
- Whitespace alignment can now be kept - see
KeepPadding
- Introduce an internal newline token to simplify the parser
- Fix
Block.Pos
to actually return the start position - Fix mishandling of inline comments in two edge cases
- Add
- interp
- Expose
Fields
to expand words into strings - First configurable modules - cmds and files
- Add support for the new
TimeClause
- Add support for namerefs and readonly vars
- Add support for associative arrays (maps)
- More sh builtins:
exec return
- More bash builtins:
command pushd popd dirs
- More
test
operators:-b -c -t -o
- Configurable kill handling - see
KillTimeout
- Expose
- cmd/shfmt
- Add
-f
to just list all the shell files found - Add
-kp
to keep the column offsets in place
- Add
- cmd/gosh
- Now supports a basic interactive mode
2.0.0 - 2017-08-30
- The package import paths were moved to
mvdan.cc/sh/...
- syntax
- Parser and Printer structs introduced with functional options
- Node positions are now independent -
Position
merged intoPos
- All comments are now attached to nodes
- Support
mksh
- MirBSD's Korn Shell, used in Android - Various changes to the AST:
EvalClause
removed;eval
is no longer parsed as a keyword- Add support for Bash's
time
andselect
- Merge
UntilClause
intoWhileClause
- Moved
Stmt.Assigns
toCallExpr.Assigns
- Remove
Elif
- chainIfClause
nodes instead
- Support for indexed assignments like
a[i]=b
- Allow expansions in arithmetic expressions again
- Unclosed heredocs now produce an error
- Binary ops are kept in the same line - see
BinaryNextLine
- Switch cases are not indented by default - see
SwitchCaseIndent
- cmd/shfmt
- Add
-s
, which simplifies programs viasyntax.Simplify
- Add
-ln <lang>
, like-ln mksh
- Add
-bn
to put binary ops in the next line, like in v1 - Add
-ci
to indent switch cases, like in v1
- Add
- interp
- Some progress made, though still experimental
- Most of POSIX done - some builtins remain to be done
1.3.1 - 2017-05-26
- syntax
- Fix parsing of
${foo[$bar]}
- Fix printer regression where
> >(foo)
would be turned into>>(foo)
- Break comment alignment on any line without a comment, fixing formatting issues
- Error on keywords like
fi
anddone
used as commands
- Fix parsing of
1.3.0 - 2017-04-24
- syntax
- Fix backslashes in backquote command substitutions
- Disallow some test expressions like
[[ a == ! b ]]
- Disallow some parameter expansions like
${$foo}
- Disallow some arithmetic expressions like
((1=3))
and(($(echo 1 + 2)))
- Binary commands like
&&
,||
and pipes are now left-associative
- fileutil
CouldBeScript
may now return true on non-regular files such as symlinks
- interp
- New experimental package to interpret a
syntax.File
in pure Go
- New experimental package to interpret a
1.2.0 - 2017-02-22
- syntax
- Add support for escaped characters in bash regular expressions
- fileutil
- New package with some code moved from
cmd/shfmt
, now importable - New funcs
HasShebang
andCouldBeScript
- Require shebangs to end with whitespace to reject
#!/bin/shfoo
- New package with some code moved from
1.1.0 - 2017-01-05
- syntax
- Parse
[[ a = b ]]
like[[ a == b ]]
, deprecatingTsAssgn
in favour ofTsEqual
- Add support for the
-k
,-G
,-O
and-N
unary operators inside[[ ]]
- Add proper support for
!
in parameter expansions, like${!foo}
- Fix a couple of crashes found via fuzzing
- Parse
- cmd/shfmt
- Rewrite
[[ a = b ]]
into the saner[[ a == b ]]
(see above)
- Rewrite
1.0.0 - 2016-12-13
- syntax
- Stable release, API now frozen
Parse
now reads input in chunks of 1KiB
- cmd/shfmt
- Add
-version
flag
- Add
0.6.0 - 2016-12-05
- syntax
Parse
now takes anio.Reader
instead of[]byte
- Invalid UTF-8 is now reported as an error
- Remove backtracking for
$((
and((
Walk
now takes a func literal to simplify its use
0.5.0 - 2016-11-24
- cmd/shfmt
- Remove
-cpuprofile
- Don't read entire files into memory to check for a shebang
- Remove
- syntax
- Use
uint32
for tokens and positions in nodes - Use
Word
andLit
pointers consistently instead of values - Ensure
Word.Parts
is never empty - Add support for expressions in array indexing and parameter expansion slicing
- Use
0.4.0 - 2016-11-08
- Merge
parser
,ast
,token
andprinter
into a single packagesyntax
- Use separate operator types in nodes rather than
Token
- Use operator value names that express their function
- Keep
;
if on a separate line when formatting - cmd/shfmt
- Allow whitespace after
#!
in a shebang
- Allow whitespace after
- syntax
- Implement operator precedence for
[[ ]]
- Parse
$(foo)
andfoo
as the same (shfmt
then converts the latter to the former) - Rename
Quoted
toDblQuoted
for clarity - Split
((foo))
nodes as their own type,ArithmCmd
- Add support for bash parameter expansion slicing
- Implement operator precedence for
0.3.0 - 2016-10-26
- Add support for bash's
coproc
and extended globbing like@(foo)
- Improve test coverage, adding tests to
cmd/shfmt
and bringingparser
andprinter
close to 100% - Support empty C-style for loops like
for ((;;)) ...
- Support for the
>|
redirect operand - cmd/shfmt
- Fix issue where
.sh
and.bash
files might not be walked if running on a directory - Fix issue where
-p
was not obeyed when formatting stdin
- Fix issue where
- parser
$''
now generates anast.SglQuoted
, not anast.Quoted
- Support for ambiguous
((
like with$((
- Improve special parameter expansions like
$@
or$!
- Improve bash's
export
typeset
,nameref
andreadonly
<>
,>&
and<&
are valid POSIX- Support for bash's
^
,^^
,,
and,,
operands inside${}
0.2.0 - 2016-10-13
- Optimizations all around, making
shfmt
~15% faster - cmd/shfmt
- Add
-p
flag to only accept POSIX Shell programs (parser.PosixConformant
)
- Add
- parser
- Add support for ambiguous
$((
as in$((foo) | bar)
- Limit more bash features to
PosixConformant
being false - Don't parse heredoc bodies in nested expansions and contexts
- Run tests through
bash
to confirm the presence of a parse error
- Add support for ambiguous
- ast
- Add
Walk(Visitor, Node)
function
- Add
0.1.0 - 2016-09-20
Initial release.