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

use a shell parser to format commands #2

Open
mvdan opened this issue Feb 15, 2018 · 6 comments
Open

use a shell parser to format commands #2

mvdan opened this issue Feb 15, 2018 · 6 comments

Comments

@mvdan
Copy link

mvdan commented Feb 15, 2018

At the moment, the code simply treats shell code as a string, splitting by && and doing string replaces.

This will work most of the time, but will break fairly easily, with cases like:

  • bash -c 'foo && bar' - we don't want this to be split
  • apk update && apk add x - won't be replaced with apk add --no-cache due to the double space (markdown gets rid of the double space before &&, though)

I use this tool and suffer from these from time to time, so I'd be happy to work on a small patch to use mvdan.cc/sh/syntax. Using its printer you'd also format the shell code, such as replacing `foo` with $(foo).

I see no tests, though - so I'm a bit wary to touch the code. Chances are I'm going to introduce a couple of regressions :)

@jessfraz
Copy link
Owner

jessfraz commented Jun 6, 2018

please do :)

@jeffxf
Copy link
Contributor

jeffxf commented Aug 6, 2018

Instead of just ignoring &&'s that are inside quotes, I started implementing mvdan/sh/syntax last night for the full shell parser. I got it working but then had some concerns:

  • Just because something is quoted doesn't mean it's going to be shelled out (could try to address this by looking for 'bash', 'sh', etc. before the quotes but that could be a mess)
  • Should we provide a flag to enable the shell parser?
  • Should we provide flag(s) for shell parser options or just insist on formatting a certain way?

I'm leaning towards a shell parser being out of scope of what dockfmt is for, but I may be wrong and don't have a problem solving those ^ issues if you disagree and would like to have it.

Just let me know if you'd like to have the shell parser and if I should include anything to address those ^ . On the other hand, if you just want to stick with ignoring quoted &&'s, let me know if you have an issue with the regex solution; I can handle criticism :)

@mvdan
Copy link
Author

mvdan commented Aug 7, 2018

I personally think that using regular expressions is not a great solution for this - it's just a slightly smarter version of the old code :) Reminds me of https://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags

To name a few possible edge cases that aren't handled by the regex:

  • echo $'&&'
  • echo ${x//&&/||} # replace all '&&' with '||'
  • [[ x && y ]] # this is a bash test AND, not a command AND

You also don't need to enforce the formatting that the sh/syntax package produces - you could simply use its parser to find the location of the command && operators, and then manually split the lines like the existing code does.

Just because something is quoted doesn't mean it's going to be shelled out

I'm not sure I understand - my point is that anything that is quoted should never be split in multiple lines. For example, this can result in the string having extra whitespace due to the indentation. And as you say, one can never know if the string is really a shell program.

Ultimately this won't matter for most people as this issue is about edge cases, but I tend to prefer correctness when it is possible :)

@jeffxf
Copy link
Contributor

jeffxf commented Aug 8, 2018

@mvdan I agree that regex is rarely the perfect answer and needs to be used cautiously. The first example you gave parses correctly for me with the regex though, but you're right about the last two since quotes aren't involved. Using the parser by itself might be a good idea then. I got carried away implementing full command parsing which is what I started to question being in scope. I'll try to take another look at your syntax parser sometime this week.

@tianon
Copy link
Collaborator

tianon commented Oct 19, 2018

I've just played with @mvdan's shell parser / shfmt in the context of moby/moby#38055, and I can say it's definitely got me impressed. I was stylistically happier with the output after turning on several of the optional configuration knobs (-bn -ci -sr), but the basics were definitely all correct (including weird features like <<-EOF getting indented properly, which isn't relevant for Dockerfile syntax but is still useful to gauge how well @mvdan understands the space of "shell code parsing" 👍 ❤️).

@jeffxf
Copy link
Contributor

jeffxf commented Oct 24, 2018

@tianon Oh without a doubt. My hacked up PR a few months ago wasn't meant to discredit @mvdan's work. I agree that his syntax parser needs to be used here. I dropped the ball on "taking a look this week" since its well... been much longer than that. I started a new job the week after that and got way too busy. I won't specify a time frame this time but it's definitely something I hope to look into again soon.

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

No branches or pull requests

4 participants