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