Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

trailing line break dropped from function output #49

Closed
brainchild0 opened this issue Jan 23, 2022 · 5 comments
Closed

trailing line break dropped from function output #49

brainchild0 opened this issue Jan 23, 2022 · 5 comments

Comments

@brainchild0
Copy link
Contributor

brainchild0 commented Jan 23, 2022

After obtaining mo, I run a few commands, and capture their output, as follows:

  • $ bash --version | head -n1
    
    GNU bash, version 5.0.17(1)-release (x86_64-pc-linux-gnu)
    
  • $ source ./mo
    
  • $ mo --help | grep MO_VERSION
    
    MO_VERSION=2.2.0
    
  • $ myfunc() {
    echo Templates
    }
    
  • $ mo <<EOF
    Mustache
    {{#myfunc}}
    {{/myfunc}}
    in Bash
    EOF
    
    Mustache
    Templatesin Bash
    

Expected is the following final output:

Mustache
Templates
in Bash

The terminating line break of the function output appears to be lost. The result not only is undesirable formatting for text intended to be human readable, but breakage for certain configuration files interpreted by tools with strict rules regarding parsing white space.

@fidian
Copy link
Contributor

fidian commented Jan 27, 2022

This is by design. The command runs in a subshell and one trailing newline will be stripped automatically by Bash. I didn't employ any techniques to preserve the trailing newline, so it would remain similar to what others would experience if they used echo "$(command-goes-here)". If you need an extra newline at the end, you will need to output one. It's weird, especially in your example. However, one could easily imagine a function that gets the time of day ...

getTimeOfDay() {
    date -R
}

... and then use it in a template.

#!/usr/bin/env bash
# Yes, this is a template. I'm generating a shell script
echo "Shell script generated at {{getTimeOfDay}}"

With the trailing newline preserved, this function would not produce what you would expect.

Closing because this is an intentional design decision, even though it is certainly awkward for your scenario.

@fidian fidian closed this as completed Jan 27, 2022
@brainchild0
Copy link
Contributor Author

brainchild0 commented Jan 27, 2022

It is problematic that all functions are forced into the assumption that trailing new lines should be dropped. It might be helpful to support a static table providing rules over processing for individual functions, or to supply a decorator that adjusts the behavior of a function.

Presently, even additional line breaks are dropped entirely as a sequence. Changing the definition of the function appears to offer no means to work around the quirk.

Additionally, the example of the inline function is confusing when given as a counterexample. In this case, the invoking text has no line breaks, in contrast to the original example in which a line break immediately follows the closing of the template section. Even if the line break would be dropped from the function output, one may still be applied separating the template and literal sections of the input.

A decorator might work as follows:

moInlineFunc() {
  "$@" | if read l; then while read new_l; do echo "$l"; l="$new_l"; done; echo -n "$l"; fi
}

getTimeOfDay() {
    moInlineFunc date -R
}

@fidian fidian reopened this Jan 27, 2022
@fidian
Copy link
Contributor

fidian commented Feb 1, 2022

I've been pondering this one as well. What if you want newlines in some instances and no newlines in another? Do you need to make getTimeOfDayWithNewline and getTimeOfDayWithoutNewline?

The spec allows for {{{ ... }}} style delimiters and I have not decided if it is a good idea to use them in this instance or if that would create more confusion.

I currently have three options:

  • Keep it as-is and always trim as per subshells.
  • Change it so all functions preserve the output.
  • Have a way for the user to toggle this, probably via an environment variable, such as MO_PRESERVE_NEWLINES, but then you'd have to do that with each function where the newlines should be preserved.

My preference is to use option #2 because the functions are somewhat a niche market due to their complexity. I'm not completely sold on the idea yet, so I haven't taken action on it.

@brainchild0
Copy link
Contributor Author

brainchild0 commented Feb 1, 2022

I'm not understanding your question. The central issue I identify in my example is that the template footer and the following literal word are separated by a line break, but the output expresses no line break nor any space nor even any characters between the template substitution and the following word.

You had expressed concern over the case in which a function output ends with a line break but no line break is desired in the output, with the template element appearing inline. I suggested that you might provide library support for this distinction through a decorator that strips the trailing line break, so that users easily may construct a function not outputting a trailing line break based on a pre-existing function outputting a trailing line break.

The particular matter of function definition, however, I think is not central to the original issue. The central concern is understood by observing that the template may be divided into three sections, two literal and one template.

The three sections of the template are as follows:

  • "Moustache\n"
  • "{#myfunc}\n{/myfunc}"
  • "\nin Bash"

In the current implementation, template substitution of the middle section, for "Templates" has the unwanted side effect of destroying the line break in the following literal section. I have not found an example in which this behavior is desirable, and your example does not follow the same pattern.

If the output currently created were desired, then the following might the appropriate template:

Mustache
{{#myfunc}}
{{/myfunc}}in Bash

@fidian
Copy link
Contributor

fidian commented Apr 10, 2023

I have come around to your viewpoint and will always preserve whatever output the function provides. This has been fixed on the rewrite-parser branch and will make its way to the next release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants