xref: /spdk/doc/shfmt.md (revision 1d269b072e50cd4828e1366d738170593deb3d16)
13c9a0d09SMichal Berger# shfmt {#shfmt}
23c9a0d09SMichal Berger
31e1fd9acSwawryk## In this document {#shfmt_toc}
43c9a0d09SMichal Berger
53c9a0d09SMichal Berger* @ref shfmt_overview
63c9a0d09SMichal Berger* @ref shfmt_usage
73c9a0d09SMichal Berger* @ref shfmt_installation
83c9a0d09SMichal Berger* @ref shfmt_examples
93c9a0d09SMichal Berger
101e1fd9acSwawryk## Overview {#shfmt_overview}
113c9a0d09SMichal Berger
123c9a0d09SMichal BergerThe majority of tests (and scripts overall) in the SPDK repo are written
133c9a0d09SMichal Bergerin Bash (with a quite significant emphasis on "Bashism"), thus a style
143c9a0d09SMichal Bergerformatter, shfmt, was introduced to help keep the .sh code consistent
153c9a0d09SMichal Bergeracross the entire repo. For more details on the tool itself, please see
163c9a0d09SMichal Berger[shfmt](https://github.com/mvdan/sh).
173c9a0d09SMichal Berger
18*1d269b07SMichal BergerWe also advise to use 4.4 Bash as a minimum version to make sure scripts
19*1d269b07SMichal Bergeracross the whole repo work as intended.
20*1d269b07SMichal Berger
211e1fd9acSwawryk## Usage {#shfmt_usage}
223c9a0d09SMichal Berger
233c9a0d09SMichal BergerOn the CI pool, the shfmt is run against all the updated .sh files that
243c9a0d09SMichal Bergerhave been committed but not merged yet. Additionally, shfmt will pick
253c9a0d09SMichal Bergerall .sh present in the staging area when run locally from our pre-commit
263c9a0d09SMichal Bergerhook (via check_format.sh). In case any style errors are detected, a
273c9a0d09SMichal Bergerpatch with needed changes is going to be generated and either build (CI)
283c9a0d09SMichal Bergeror the commit will be aborted. Said patch can be then easily applied:
293c9a0d09SMichal Berger
303c9a0d09SMichal Berger~~~{.sh}
313c9a0d09SMichal Berger# Run from the root of the SPDK repo
323c9a0d09SMichal Bergerpatch --merge -p0 <shfmt-3.1.0.patch
333c9a0d09SMichal Berger~~~
343c9a0d09SMichal Berger
353c9a0d09SMichal BergerThe name of the patch is derived from the version of shfmt that is
363c9a0d09SMichal Bergercurrently in use (3.1.0 is currently supported).
373c9a0d09SMichal Berger
383c9a0d09SMichal BergerPlease, see ./scripts/check_format.sh for all the arguments the shfmt
393c9a0d09SMichal Bergeris run with. Additionally, @ref shfmt_examples has more details on how
403c9a0d09SMichal Bergereach of the arguments behave.
413c9a0d09SMichal Berger
421e1fd9acSwawryk## Installation {#shfmt_installation}
433c9a0d09SMichal Berger
443c9a0d09SMichal BergerThe shfmt can be easily installed via pkgdep.sh:
453c9a0d09SMichal Berger
463c9a0d09SMichal Berger~~~{.sh}
473c9a0d09SMichal Berger./scripts/pkgdep.sh -d
483c9a0d09SMichal Berger~~~
493c9a0d09SMichal Berger
503c9a0d09SMichal BergerThis will install all the developers tools, including shfmt, on the
513c9a0d09SMichal Bergerlocal system. The precompiled binary will be saved, by default, to
523c9a0d09SMichal Berger/opt/shfmt and then linked under /usr/bin. Both paths can be changed
533c9a0d09SMichal Bergerby setting SHFMT_DIR and SHFMT_DIR_OUT in the environment. Example:
543c9a0d09SMichal Berger
553c9a0d09SMichal Berger~~~{.sh}
563c9a0d09SMichal BergerSHFMT_DIR=/keep_the_binary_here \
573c9a0d09SMichal BergerSHFMT_DIR_OUT=/and_link_it_here \
583c9a0d09SMichal Berger  ./scripts/pkgdep.sh -d
593c9a0d09SMichal Berger~~~
603c9a0d09SMichal Berger
611e1fd9acSwawryk## Examples {#shfmt_examples}
623c9a0d09SMichal Berger
633c9a0d09SMichal Berger~~~{.sh}
643c9a0d09SMichal Berger#######################################
653c9a0d09SMichal Bergerif foo=$(bar); then
663c9a0d09SMichal Berger  echo "$foo"
673c9a0d09SMichal Bergerfi
683c9a0d09SMichal Berger
693c9a0d09SMichal Bergerexec "$foo" \
703c9a0d09SMichal Berger  --bar \
713c9a0d09SMichal Berger  --foo
723c9a0d09SMichal Berger
733c9a0d09SMichal Berger# indent_style = tab
743c9a0d09SMichal Berger
753c9a0d09SMichal Bergerif foo=$(bar); then
763c9a0d09SMichal Berger        echo "$foo"
773c9a0d09SMichal Bergerfi
783c9a0d09SMichal Berger
793c9a0d09SMichal Bergerexec foobar \
803c9a0d09SMichal Berger        --bar \
813c9a0d09SMichal Berger        --foo
823c9a0d09SMichal Berger######################################
833c9a0d09SMichal Bergerif foo=$(bar); then
843c9a0d09SMichal Berger        echo "$foo" && \
853c9a0d09SMichal Berger        echo "$(bar)"
863c9a0d09SMichal Bergerfi
873c9a0d09SMichal Berger# binary_next_line = true
883c9a0d09SMichal Bergerif foo=$(bar); then
893c9a0d09SMichal Berger        echo "$foo" \
903c9a0d09SMichal Berger                && echo "$(bar)"
913c9a0d09SMichal Bergerfi
923c9a0d09SMichal Berger
933c9a0d09SMichal Berger# Note that each break line is also being indented:
943c9a0d09SMichal Berger
953c9a0d09SMichal Bergerif [[ -v foo ]] \
963c9a0d09SMichal Berger&& [[ -v bar ]] \
973c9a0d09SMichal Berger&& [[ -v foobar ]]; then
983c9a0d09SMichal Berger	echo "This is foo"
993c9a0d09SMichal Bergerfi
1003c9a0d09SMichal Berger# ->
1013c9a0d09SMichal Bergerif [[ -v foo ]] \
1023c9a0d09SMichal Berger        && [[ -v bar ]] \
1033c9a0d09SMichal Berger        && [[ -v foobar ]]; then
1043c9a0d09SMichal Berger        echo "This is foo"
1053c9a0d09SMichal Bergerfi
1063c9a0d09SMichal Berger
1073c9a0d09SMichal Berger# Currently, newlines are being escaped even if syntax-wise
1083c9a0d09SMichal Berger# they are not needed, thus watch for the following:
1093c9a0d09SMichal Bergerif [[ -v foo
1103c9a0d09SMichal Berger        && -v bar
1113c9a0d09SMichal Berger        && -v foobar ]]; then
1123c9a0d09SMichal Berger        echo "This is foo"
1133c9a0d09SMichal Bergerfi
1143c9a0d09SMichal Berger#->
1153c9a0d09SMichal Bergerif [[ -v foo && -v \
1163c9a0d09SMichal Berger        bar && -v \
1173c9a0d09SMichal Berger        foobar ]]; then
1183c9a0d09SMichal Berger        echo "This is foo"
1193c9a0d09SMichal Bergerfi
1203c9a0d09SMichal Berger# This, unfortunately, also breaks the -bn behavior.
1213c9a0d09SMichal Berger# (see https://github.com/mvdan/sh/issues/565) for details.
1223c9a0d09SMichal Berger######################################
1233c9a0d09SMichal Bergercase "$FOO" in
1243c9a0d09SMichal Berger        BAR)
1253c9a0d09SMichal Berger        echo "$FOO" ;;
1263c9a0d09SMichal Bergeresac
1273c9a0d09SMichal Berger# switch_case_indent = true
1283c9a0d09SMichal Bergercase "$FOO" in
1293c9a0d09SMichal Berger        BAR)
1303c9a0d09SMichal Berger                echo "$FOO"
1313c9a0d09SMichal Berger                ;;
1323c9a0d09SMichal Bergeresac
1333c9a0d09SMichal Berger######################################
1343c9a0d09SMichal Bergerexec {foo}>bar
1353c9a0d09SMichal Berger:>foo
1363c9a0d09SMichal Bergerexec {bar}<foo
1373c9a0d09SMichal Berger# -sr
1383c9a0d09SMichal Bergerexec {foo}> bar
1393c9a0d09SMichal Berger: > foo
1403c9a0d09SMichal Bergerexec {bar}< foo
1413c9a0d09SMichal Berger######################################
1423c9a0d09SMichal Berger# miscellaneous, enforced by shfmt
1433c9a0d09SMichal Berger(( no_spacing_at_the_beginning & ~and_no_spacing_at_the_end ))
1443c9a0d09SMichal Berger: $(( no_spacing_at_the_beginning & ~and_no_spacing_at_the_end ))
1453c9a0d09SMichal Berger
1463c9a0d09SMichal Berger# ->
1473c9a0d09SMichal Berger((no_spacing_at_the_beginning & ~and_no_spacing_at_the_end))
1483c9a0d09SMichal Berger: $((no_spacing_at_the_beginning & ~and_no_spacing_at_the_end))
1493c9a0d09SMichal Berger~~~
150