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

"}" can only be used to close a block #993

Closed
leetrout opened this issue Apr 20, 2023 · 5 comments
Closed

"}" can only be used to close a block #993

leetrout opened this issue Apr 20, 2023 · 5 comments

Comments

@leetrout
Copy link

Given this code:

function help_msg {
	echo "Wrong arguments" >&2
	echo "Usage:"
	echo "  $0 -s source -d destination"
	echo "Options:"
	echo "  -s  Source vault"
	echo "  -d  Destination vault"
}

I am getting this error:

file.sh:10:1: "}" can only be used to close a block

I am unsure how to fix this

@mvdan
Copy link
Owner

mvdan commented Apr 22, 2023

What did you run exactly?. It's likely that you're trying to parse in POSIX mode when this is bash syntax.

@leetrout
Copy link
Author

I just ran shfmt <file>

Will respond with additional details on Monday when I am back at work but I did figure out to change it to not use the function keyword yesterday and it worked.

I am inheriting some shell scripts I didn't write - thank you for the hint to look at the mode.

@rgowtham
Copy link

I am seeing a similar behavior with the below function as well,

function prettyTime {
    local _dt=$1
    local _dm
    local _dh
    local _ds
    _dh=$((_dt / 3600))
    _dm=$(((_dt / 60) % 60))
    _ds=$((_dt % 60))
    printf '%d:%02d:%02d' ${_dh} ${_dm} ${_ds}
}
~ shfmt run.sh
run.sh:41:1: "}" can only be used to close a block

I am using shfmt 3.7.0, not sure why shfmt considers this a bug

@mvdan
Copy link
Owner

mvdan commented Jun 23, 2023

@rgowtham as I tried to explain in my previous comment, this is not a bug in shfmt - the parser will work if you properly parse the script as Bash. You can do that explicitly via the -ln=bash flag, or by naming the script foo.bash, or by adding a shebang like #!/usr/bin/bash. Instead of any of those three options, your script probably just has a name like foo.sh, so the parser assumes POSIX shell, where function is not a valid way to declare functions.

@mvdan mvdan closed this as completed in a32111c Jul 13, 2023
@mvdan
Copy link
Owner

mvdan commented Jul 13, 2023

The parser should now give a better error message.

@mvdan mvdan removed the needs info label Jul 13, 2023
mvdan added a commit that referenced this issue Jul 13, 2023
When parsing in POSIX mode, we already gave a good error message
when a user used the "function foo()" Bash syntax:

    $ shfmt -p <<<'function foo() { bar; }'
    <standard input>:1:13: the "function" builtin exists in bash; tried parsing as posix

However, our heuristic depended on the opening parenthesis token,
so it didn't work without the parentheses, which is valid Bash:

    $ shfmt -p <<<'function foo { bar; }'
    <standard input>:1:21: "}" can only be used to close a block

This "can only be used to close a block" error was rather confusing,
and caused multiple users to file bugs thinking the parser was at fault.
We now catch this other common pitfall pattern as well:

    $ shfmt -p <<<'function foo { bar; }'
    <standard input>:1:14: the "function" builtin is a bash feature; tried parsing as posix

We add the logic to the bit of code that handles each call argument,
but there shouldn't be a noticeable impact to most users
since it only kicks in when we're parsing in POSIX mode
and the current argument is a simple "{" literal.

Fixes #993.
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

3 participants