For personal development and projects I work on, we use four spaces instead of tabs. However, I need to use a heredoc, and I can't do so without breaking the indention flow.
The only working way to do this I can think of would be this:
usage() { cat << ' EOF' | sed -e 's/^ //'; Hello, this is a cool program. This should get unindented. This code should stay indented: something() { echo It works, yo!; } That's all. EOF }
Is there a better way to do this?
Let me know if this belongs on the Unix/Linux Stack Exchange instead.
press Ctrl - space at the top of the file. move the cursor to the bottom of the file. press Alt - X and type untabify then return. press Alt - X and type indent-region then return.
To use here-document in any bash script, you have to use the symbol << followed by any delimiting identifier after any bash command and close the HereDoc by using the same delimiting identifier at the end of the text.
(If you are using bash
4, scroll to the end for what I think is the best combination of pure shell and readability.)
For shell scripts, using tabs is not a matter of preference or style; it's how the language is defined.
usage () { ⟶# Lines between EOF are each indented with the same number of tabs ⟶# Spaces can follow the tabs for in-document indentation ⟶cat <<-EOF ⟶⟶Hello, this is a cool program. ⟶⟶This should get unindented. ⟶⟶This code should stay indented: ⟶⟶ something() { ⟶⟶ echo It works, yo!; ⟶⟶ } ⟶⟶That's all. ⟶EOF }
Another option is to avoid a here document altogether, at the cost of having to use more quotes and line continuations:
usage () { printf '%s\n' \ "Hello, this is a cool program." \ "This should get unindented." \ "This code should stay indented:" \ " something() {" \ " echo It works, yo!" \ " }" \ "That's all." }
If you are willing to forego POSIX compatibility, you can use an array to avoid the explicit line continuations:
usage () { message=( "Hello, this is a cool program." "This should get unindented." "This code should stay indented:" " something() {" " echo It works, yo!" " }" "That's all." ) printf '%s\n' "${message[@]}" }
The following uses a here document again, but this time with bash
4's readarray
command to populate an array. Parameter expansion takes care of removing a fixed number of spaces from the beginning of each lie.
usage () { # No tabs necessary! readarray message <<' EOF' Hello, this is a cool program. This should get unindented. This code should stay indented: something() { echo It works, yo!; } That's all. EOF # Each line is indented an extra 8 spaces, so strip them printf '%s' "${message[@]# }" }
One last variation: you can use an extended pattern to simplify the parameter expansion. Instead of having to count how many spaces are used for indentation, simply end the indentation with a chosen non-space character, then match the fixed prefix. I use :
. (The space following the colon is for readability; it can be dropped with a minor change to the prefix pattern.)
(Also, as an aside, one drawback to your very nice trick of using a here-doc delimiter that starts with whitespace is that it prevents you from performing expansions inside the here-doc. If you wanted to do so, you'd have to either leave the delimiter unindented, or make one minor exception to your no-tab rule and use <<-EOF
and a tab-indented closing delimiter.)
usage () { # No tabs necessary! closing="That's all" readarray message <<EOF : Hello, this is a cool program. : This should get unindented. : This code should stay indented: : something() { : echo It works, yo!; : } : $closing EOF shopt -s extglob printf '%s' "${message[@]#+( ): }" shopt -u extglob }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With