Skip to main content
5 of 7
Document potential solution, since posting an answer isn't available any more
dtk
  • 203
  • 1
  • 9

Elegant way to prevent command substitution from removing trailing newline

I'm customizing my zsh PROMPT and calling a function that may or may not echo a string based on the state of an environment variable:

function my_info {
    [[ -n "$ENV_VAR"]] && echo "Some useful information\n"
}

local my_info='$(my_info)'

PROMPT="${my_info}My awesome prompt $>"

I would like the info to end on a trailing newline, so that if it is set, it appears on its own line:

Some useful information
My awesome prompt $>

However, if it's not set, I want the prompt to be on a single line, avoiding an empty line caused by an unconditional newline in my prompt:

PROMPT="${my_info}  # <= Don't want that :)
My awesome prompt $>"

Currently I work around the $(command substitution) removing my newline by suffixing it with a non-printing character, so the newline isn't trailing anymore:

[[ -n "$ENV_VAR"]] && echo "Some useful information\n\r"

This is obviously a hack. Is there a clean way to return a string that ends on a newline?

Edit: I understand what causes the loss of the trailing newline and why that happens, but in this question I would specifically like to know how to prevent that behaviour (and I don't think this workaround applies in my case, since I'm looking for a "conditional" newline).

Edit: I stand corrected: the referenced workaround might actually be a rather nice solution (since prefixing strings in comparisons is a common and somewhat similar pattern), except I can't get it to work properly:

echo "Some useful information\n"x
  [...]
PROMPT="${my_info%x}My awesome prompt $>"

does not strip the trailing x for me.

Edit: Adjusting the proposed workaround for the weirdness that is prompt expansion, this worked for me:

function my_info {
    [[ -n "$ENV_VAR"]] && echo "Some useful information\n"x
}

local my_info='${$(my_info)%x}'

PROMPT="$my_info My awesome prompt $>"

You be the judge if this is a better solution than the original one. It's a tad more explicit, I think, but it also feels a bit less readable.

dtk
  • 203
  • 1
  • 9