Giter VIP home page Giter VIP logo

beautysh's Introduction

Beautysh CI

This program takes upon itself the hard task of beautifying Bash scripts (yeesh). Processing Bash scripts is not trivial, they aren't like C or Java programs — they have a lot of ambiguous syntax, and (shudder) you can use keywords as variables. Years ago, while testing the first version of this program, I encountered this example:

done=0;while (( $done <= 10 ));do echo done=$done;done=$((done+1));done

Same name, but three distinct meanings (sigh). The Bash interpreter can sort out this perversity, but I decided not to try to recreate the Bash interpreter to beautify a script. This means there will be some border cases this Python program won't be able to process. But in tests with large Linux system Bash scripts, its error-free score was ~99%.

Installation

If you have pip set up you can do

pip install beautysh

or clone the repo and install:

git clone https://github.com/lovesegfault/beautysh
cd beautysh
poetry install

Usage

You can call Beautysh from the command line such as

beautysh file1.sh file2.sh file3.sh

in which case it will beautify each one of the files.

Available flags are:

  --indent-size INDENT_SIZE, -i INDENT_SIZE
                        Sets the number of spaces to be used in indentation.
  --backup, -b          Beautysh will create a backup file in the same path as
                        the original.
  --check, -c           Beautysh will just check the files without doing any
                        in-place beautify.
  --tab, -t             Sets indentation to tabs instead of spaces.
  --force-function-style FORCE_FUNCTION_STYLE, -s FORCE_FUNCTION_STYLE
                        Force a specific Bash function formatting. See below
                        for more info.
  --version, -v         Prints the version and exits.
  --help, -h            Print this help message.

Bash function styles that can be specified via --force-function-style are:
  fnpar: function keyword, open/closed parentheses, e.g.      function foo()
  fnonly: function keyword, no open/closed parentheses, e.g.  function foo
  paronly: no function keyword, open/closed parentheses, e.g. foo()

You can also call beautysh as a module:

from beautysh import Beautify

source = "my_string"

result, error = Beautify().beautify_string(source)

As written, beautysh can beautify large numbers of Bash scripts when called from a variety of means,including a Bash script:

#!/bin/sh

for path in `find /path -name '*.sh'`
do
   beautysh $path
done

As well as the more obvious example:

$ beautysh *.sh

CAUTION: Because Beautysh overwrites all the files submitted to it, this could have disastrous consequences if the files include some of the increasingly common Bash scripts that have appended binary content (a regime where Beautysh has undefined behaviour ). So please — back up your files, and don't treat Beautysh as a harmless utility. Even if that is true most of the time.

Beautysh handles Bash here-docs with care(and there are probably some border cases it doesn't handle). The basic idea is that the originator knew what format he wanted in the here-doc, and a beautifier shouldn't try to outguess him. So Beautysh does all it can to pass along the here-doc content unchanged:

if true
then

   echo "Before here-doc"

   # Insert 2 lines in file, then save.
   #--------Begin here document-----------#
vi $TARGETFILE <<x23LimitStringx23
i
This is line 1 of the example file.
This is line 2 of the example file.
^[
ZZ
x23LimitStringx23
   #----------End here document-----------#

   echo "After here-doc"

fi

Special comments @formatter:off and @formatter:on are available to disable formatting around a block of statements.

# @formatter:off
command \
    --option1 \
        --option2 \
            --option3 \
# @formatter:on

This takes inspiration from the Eclipse feature.

Contributing

Contributions are welcome and appreciated, however test cases must be added to prevent regression. Adding a test case is easy, and involves the following:

  1. Create a file tests/fixtures/my_test_name_raw.sh containing the unformatted version of your test case.
  2. Create a file tests/fixtures/my_test_name_formatted.sh containing the formatted version of your test case.
  3. Register your test case in tests/test_integration.py, It should look something like this:
def test_my_test_name(self):
    self.assert_formatting("my_test_name")

Originally written by Paul Lutus

beautysh's People

Contributors

ankitshubham97 avatar bollwyvl avatar dependabot-preview[bot] avatar dependabot[bot] avatar ewiger avatar f18m avatar gtrunsec avatar hatesegfault avatar hukkinj1 avatar jesselang avatar jwhonce avatar lovesegfault avatar streambinder avatar trystero11 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

beautysh's Issues

3.7 tag missing

I see you created a 3.7 release. Could you also tag it since folks using pre-commit would generally be checking out the repo using a tag? Thanks!

Bad indent of multi-line subcommand

before:

cd $(python -c "print('/');
                print('tmp');
                print('/');
                print('foo');")

after

cd $(python -c "print('/');
                print('tmp');
                print('/');
print('foo');")

I am pretty sure there are multiple ways to format this 'beauty', but imho the provided one is the least correct 😉

mangles indentation after "do case"

Looks like having the do and case statements adjacent on the same line confounds beautysh.

Fails

$ scripts/beautysh.py - <<EOF
> #!/bin/bash
> while getopts "h" OPT; do case $OPT in
> *) true ;;
> esac
> done
> 
> fn() {
>   echo not indented
> }
> EOF
File (stdin): error: indent/outdent mismatch: -1.
#!/bin/bash
while getopts "h" OPT; do case  in
    *) true ;;
esac
done

fn() {
echo not indented
}

Succeeds

$ scripts/beautysh.py - <<EOF
> #!/bin/bash
> while getopts "h" OPT; do
>   case $OPT in
>     *) true ;;
>   esac
> done
> 
> fn() {
>   echo indented
> }
> EOF
#!/bin/bash
while getopts "h" OPT; do
    case  in
        *) true ;;
    esac
done

fn() {
    echo indented ok
}

beautysh change line endings character during formatting

Hi,

I'd like to run beautysh in a Windows 10 (Python 3.8) environment to format a bunch of shell scripts.
These scripts all have a new line character \n but after the beautysh run the new line character was changed to \r\n.

Now the scripts couldn't execute on a Linux or Unix system and they are useless.

Is there a way to preserve the original line separator character?
By the the way, using beautysh in Linux/Unix environment is not an option at the moment.

Regression in indentation of multiline conditions

I noticed that with latest master the following code block

    # do basic argument checks
    if [ "$A" == "true" ] || [ "$A" == "false" ] || [ "$A" == "noconflicts" ] || \
        [ "$B" == "true" ] || [ "$B" == "false" ] || [ "$B" == "noconflicts" ] || \
        [ "$C" == "true" ] || [ "$C" == "false" ]; then
        printerr "Internal error: invalid function call argument"
        exit 2
    fi

is now indented as:

    # do basic argument checks
    if [ "$A" == "true" ] || [ "$A" == "false" ] || [ "$A" == "noconflicts" ] || \
        [ "$B" == "true" ] || [ "$B" == "false" ] || [ "$B" == "noconflicts" ] || \
    [ "$C" == "true" ] || [ "$C" == "false" ]; then
        printerr "Internal error: invalid function call argument"
        exit 2
    fi

3rd line has wrong indentation. I think this is perhaps a regression introduced with one of my latest patches, so I'm opening this to avoid forgetting.

Error: when install with pip, it shows UnicodeDecodeError: 'cp950' codec can't decode...

When I update beautysh, I got the following output...

c:\>pip` install -U beautysh
Collecting beautysh
  Using cached https://files.pythonhosted.org/packages/a9/2c/91a68193e758db22a92e08cb9f49898d545036aa20fee8db63a062c1449e/beautysh-3.12.tar.gz
    Complete output from command python setup.py egg_info:
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "C:\Users\fish\AppData\Local\Temp\pip-install-87geoahp\beautysh\setup.py", line 13, in <module>
        DESCRIPTION = fh.read()
    UnicodeDecodeError: 'cp950' codec can't decode byte 0xe2 in position 288: illegal multibyte sequence

    ----------------------------------------
Command "python setup.py egg_info" failed with error code 1 in C:\Users\fish\AppData\Local\Temp\pip-install-87geoahp\beautysh\

How to fix it?

In setup.py, please modify it as following...

--- with open("README.md", "r") as fh:
+++ with open("README.md", "r", encoding='utf8') as fh:

version 4.0 is available only from pip3

Hi @bemeurer ,
I noticed that I can install the new release (4.0) only by doing:
pip3 install beautysh
if I do:
pip install beautysh==4.0
I get:

Collecting beautysh==4.0
  Could not find a version that satisfies the requirement beautysh==4.0 (from versions: 4.0.macosx-10.14-x86_64, 2.2.2, 3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 3.10, 3.11, 3.12)
No matching distribution found for beautysh==4.0

I think this is due to the fact that on pypi there is no .tar.gz...

Error message for correct code

I got the following error message 'indent/outdent mismatch: 1', when adding this line of code to my script:

max=$((1<<63))

Possible regex parse error 'echo multiline MD link with code in name' [indent/outdent mismatch]

I had a bash script that generates a markdown file which has the following problem when trying to format it (I simplified the code that failed):

./test.sh

if true; then
    echo "
[\`something\`](Markdown link)
"
fi

It also fails with:

if true; then
    echo "
[\`something\`
"
fi

Command: beautysh --check ./test.sh

Error: File ./test.sh: error: indent/outdent mismatch: 1.

beautysh --version: 5.0.2

It's not really a problem for me (I just changed the line so that this error is not thrown), but I wanted to notify anyone that this parse error exists in case someone wants to fix it.

Feature: Add check mode

Would be useful if it could just verify if something would change, without actually changing the files. So that it can be used as part of a test suite.

See the --check flag in black for comparison.

It could print something like "x number of changes would be made to file zzz", and exit with 0 if there are no changes, and exit with 1 if there are changes.

Feature request: Convert test ([) to new form ([[)

It would be nice if beautysh had an option to replace old test format with new eg:

if [ "$foo" == "$bar" ]; then

becomes

if [[ "$foo" == "$bar" ]]; then

Personally I would prefer the variables to remain quoted in this case even thought it is optional with the [[ form.

Examples:

find . -name '*.sh' -exec grep -H 'if \[ ' {} \;

The reverse would also be good for people who want to write portable code. Could be implemented in a similar way to --force-function-style ie:

--force-test-style bash|compatible

Shell test styles that can be specified via --force-test-style are:
compatible: single bracket test compatible with sh, e.g.     if [ "$foo"
bash: double bracket test used by bash and zsh, e.g.   if [[ "$foo"

indent/outdent mismatch when using multi-line array assignment inside case...esac

My go-to way of quickly parsing arguments is as follows:

#!/bin/bash                                                                  
                                                                             
quiet="true"                                                                 
files=()                                                                     
                                                                             
for arg in "${@}"; do                                                        
    case "${arg}" in                                                         
        "-v" | "--verbose")                                                  
            quiet="false"                                                    
            ;;                                                               
        *)
            files+=(                                                         
                "${arg}"                                                     
            )                                                                   
            ;;                                                               
    esac                                                                     
done                                                                         

Beautysh (v6.1.0) incorrectly reports this as indent/outdent mismatch and instead indents it like so:

#!/bin/bash                                                                  
                                                                             
quiet="true"                                                                 
files=()                                                                     
                                                                             
for arg in "${@}"; do                                                        
    case "${arg}" in                                                         
        "-v" | "--verbose")                                                  
            quiet="false"                                                    
            ;;                                                               
        *)                                                                   
            files+=(                                                         
                "${arg}"                                                     
            )                                                                
                ;;                                                           
        esac                                                                 
    done

The deciding factor seems to be the multi-line parenthesis in assigning files. If I assign it all on one line, like this:

            files+=("${arg}")                                                

then beautysh is satisfied with the indentation (i.e. doesn't change it or report a mismatch).

Installation via pip fails

Installing beautysh via pip fails, see failure output below.

$ pip install beautysh
Collecting beautysh
  Using cached beautysh-3.7.tar.gz
Installing collected packages: beautysh
  Running setup.py install for beautysh ... error
    Complete output from command /usr/bin/python -u -c "import setuptools, tokenize;__file__='/private/var/folders/sv/5gh4tk990539nzhdt311pg0h000_fp/T/pip-build-9uWIcs/beautysh/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record /var/folders/sv/5gh4tk990539nzhdt311pg0h000_fp/T/pip-knmUwV-record/install-record.txt --single-version-externally-managed --compile:
    running install
    running build
    running build_py
    file beautysh.py (for module beautysh) not found
    creating build
    creating build/lib
    creating build/lib/beautysh
    copying beautysh/__init__.py -> build/lib/beautysh
    copying beautysh/__main__.py -> build/lib/beautysh
    copying beautysh/beautysh.py -> build/lib/beautysh
    file beautysh.py (for module beautysh) not found
    running install_lib
    creating /Library/Python/2.7/site-packages/beautysh
    error: could not create '/Library/Python/2.7/site-packages/beautysh': Permission denied
    
    ----------------------------------------
Command "/usr/bin/python -u -c "import setuptools, tokenize;__file__='/private/var/folders/sv/5gh4tk990539nzhdt311pg0h000_fp/T/pip-build-9uWIcs/beautysh/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record /var/folders/sv/5gh4tk990539nzhdt311pg0h000_fp/T/pip-knmUwV-record/install-record.txt --single-version-externally-managed --compile" failed with error code 1 in /private/var/folders/sv/5gh4tk990539nzhdt311pg0h000_fp/T/pip-build-9uWIcs/beautysh/

Machine specs:
MacOS Sierra 10.12.6

$ pip --version
pip 9.0.1 from /Library/Python/2.7/site-packages/pip-9.0.1-py2.7.egg (python 2.7)

elif has wrong indentation

If you have something like:

#!/bin/bash

if [ -f testfile1 ]; then
    echo "1"
elif [ -f testfile2 ]; then
    echo "2"
else
    echo "3"
fi

The result is:

#!/bin/bash

if [ -f testfile1 ]; then
  echo "1"
  elif [ -f testfile2 ]; then
  echo "2"
else
  echo "3"
fi

So it seems elif is not handled correctly.

Beautysh does nothing

I installed beautysh as pip install beautysh, and then tried to run it but it did nothing.

~ ❱❱❱ python --version
Python 3.9.6
~ ❱❱❱ cat temp.sh
echo "meep"|grep "e";echo "no u"~ ❱❱❱ 
~ ❱❱❱ beautysh temp.sh 
~ ❱❱❱ cat temp.sh
echo "meep"|grep "e";echo "no u"~ ❱❱❱ 

Indentation stripped from elif statements

Hello, I seem to have encountered an issue which seems to be the inverse of #2

With the given block of code (tabs or spaces):

#!/usr/bin/env bash

foo(){
    thing=${1}
    if [[ ${thing} == "bob" ]]
    then
        echo "Yar!"
    elif [[ ${thing} == "jack" ]]
    then
        echo "Yip!"
    else
        echo "Nar"
    fi
}

for thing in "bob" "jim" "jack"
do
    foo "${thing}"
    if (( $? == 0 ))
    then
        echo "Returned success"
    elif (( $? > 0 ))
    then
        echo "No bueno"
    else
        echo "Bad magic"
    fi
done

When run through beautysh ( 4.1 or 5.0.2 ), indentation is stripped at elif:

$ beautysh -v
5.0.2
$ beautysh foo.sh
$ cat foo.sh 
#!/usr/bin/env bash

foo(){
    thing=${1}
    if [[ ${thing} == "bob" ]]
    then
        echo "Yar!"
elif [[ ${thing} == "jack" ]]
    then
        echo "Yip!"
    else
        echo "Nar"
    fi
}

for thing in "bob" "jim" "jack"
do
    foo "${thing}"
    if (( $? == 0 ))
    then
        echo "Returned success"
elif (( $? > 0 ))
    then
        echo "No bueno"
    else
        echo "Bad magic"
    fi
done

missing dependency: ImportError: No module named 'setuptools'

The following:
$python setup.py

throughs this error:

Traceback (most recent call last):
File "setup.py", line 2, in
from setuptools import setup
ImportError: No module named setuptools

Please add to docs the dependency for:

[SOLUTION]

To install setuptools on Debian, Ubuntu or Mint:
$ sudo apt-get install python-setuptools

For Python 3.X applications, install python3-setuptools instead.
$ sudo apt-get install python3-setuptools

On Red Hat based systems, setuptools comes pre-installed. For whatever reason if you want to install it, use the yum command.
$ sudo yum python-setuptools

Thanks!

Instalation error via git

I'm trying to install beautysh via git. I used those commands:

git clone https://github.com/lovesegfault/beautysh
cd beautysh
python setup.py install

I get this error code:

Traceback (most recent call last):
  File "setup.py", line 2, in <module>
    from setuptools import setup
ImportError: No module named setuptools

I cannot beautify my code

It throw this error out, but i'm not sure what it mean??

File src/core/download_resource_management: error: indent/outdent mismatch: 2.

Error indent/outdent mismatch: 2 with multi-line

First of all, thanks for providing such a great tool that manages to parse shell syntax correctly 99% of the time. That's no small feat!

I have a case where beautysh appears to do the wrong thing, so I wanted to document it here in case it helps improve the project.

I have a script here that beautysh appears to parse incorrectly. If I remove the @formatter directives here then I get an indent/outdent mismatch: 2 error and beautysh over-indents the rest of the script.

Intent to package: Snaps are universal Linux packages

Dear maintainer(s),

Snaps are universal Linux packages that can be installed and run on many GNU+Linux distributions with ease. I've been following the Snapcrafters instructions and have built a working snap on the Snap Store, you may try it by running the following commands after installing snapd:

sudo snap install beautysh

I'm also looking forward to working with you to make the packaging work upstream (if you're interested). You may want to check out the current packaging recipe, the documentation, registering a developer account on the Snap Store, and get in touch with us to transfer the work under your control.

Thanks for your time and attention.

Failed to install on Arch with pip

Hi, am I missing something?

angristan@xps ~> pip install beautysh
Collecting beautysh
  Using cached beautysh-3.3.tar.gz
Installing collected packages: beautysh
  Running setup.py install for beautysh ... error
    Complete output from command /usr/bin/python -u -c "import setuptools, tokenize;__file__='/tmp/pip-build-i4efxqie/beautysh/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record /tmp/pip-g3mimjnp-record/install-record.txt --single-version-externally-managed --compile:
    running install
    running build
    running build_py
    file beautysh.py (for module beautysh) not found                                                                                                                        
    creating build                                                                                                                                                          
    creating build/lib
    creating build/lib/beautysh
    copying beautysh/__main__.py -> build/lib/beautysh
    copying beautysh/__init__.py -> build/lib/beautysh
    copying beautysh/beautysh.py -> build/lib/beautysh
    file beautysh.py (for module beautysh) not found
    running install_lib
    creating /usr/lib/python3.6/site-packages/beautysh
    error: could not create '/usr/lib/python3.6/site-packages/beautysh': Permission denied
    
    ----------------------------------------
Command "/usr/bin/python -u -c "import setuptools, tokenize;__file__='/tmp/pip-build-i4efxqie/beautysh/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record /tmp/pip-g3mimjnp-record/install-record.txt --single-version-externally-managed --compile" failed with error code 1 in /tmp/pip-build-i4efxqie/beautysh/

CLI --help and --version exit !=0 in 5.0.0

Over on conda-forge we had to temporarily break our "sanity check" testing for 5.0.0, as the behavior of --help (and --version) has changed:

jovyan@jupyter-jupyterlab-2djupyterlab-2ddemo-2dvsakdy2y:~$ beautysh --help
usage: beautysh [--indent-size INDENT_SIZE] [--backup] [--check] [--tab] [--force-function-style FORCE_FUNCTION_STYLE] [--version] [--help] FILE [FILE ...]
beautysh: error: the following arguments are required: FILE
jovyan@jupyter-jupyterlab-2djupyterlab-2ddemo-2dvsakdy2y:~$ beautysh --version
usage: beautysh [--indent-size INDENT_SIZE] [--backup] [--check] [--tab] [--force-function-style FORCE_FUNCTION_STYLE] [--version] [--help] FILE [FILE ...]
beautysh: error: the following arguments are required: FILE

I haven't dug into the source too much, but it seems like this is probably a regression... nargs="*", or special-casing --help and --version would be great.

Different bash function syntaxes are tolerated

Hi,
I noticed that beautysh is not enforcing any specific style for the function declarations:

A)

function myfunc()
{
    ...
}

is accepted as well as
B)

function myfunc
{
    ...
}

and as well as
C)

myfunc()
{
    ...
}

I think beautysh should stick with one and enforce it.
What do you think?

Unable to handle specific while format

It seems this executable is unable to handle while loops formatted as below:

while read -r thing; do
	echo "thing done"
done <<< $filename # or command

As soon as I remove those <<<, beautysh is behaving perfectly, as expected.

Example in readme has not a valid syntax

Just a minor comment regarding your example of bash's ambiguous syntax. It's not a valid code:

bash-4.3$ bash -n <<< "echo done;done"
bash: line 1: syntax error near unexpected token `done'
bash: line 1: `echo done;done'

And even other parser, Bashlex, returns "unexpected token 'done'".

I'd love to see some example where is Beautysh failing on a valid code if there is any.

Thanks!

Variant of case selector does not get indented

Hi.

Here is a script that uses both variants of the case selector: a single close parenthesis, as well as open AND close parentheses. The output from the driver script runs the 4 usual shells, bash, dash, ksh, zsh to show that the syntax is acceptable to all. The final output is the result of beautysh, which does not indent correctly.

$ ./helper 

Environment: LC_ALL = C, LANG = C
(Versions displayed with local utility "version")
OS, ker|rel, machine: Linux, 3.16.0-4-amd64, x86_64
Distribution        : Debian 8.7 (jessie) 
bash GNU bash 4.3.30
beautysh - ( local: RepRev 1.4, ~/bin/beautysh, 2016-03-31 )

-----
 Code:
#!/usr/bin/env bash

# @(#) s1       Demonstrate paren-case alternative, dash, bash, ksh.

LC_ALL=C ; LANG=C ; export LC_ALL LANG
pe() { for _i;do printf "%s" "$_i";done; printf "\n"; }
pl() { pe;pe "-----" ;pe "$*"; }
em() { pe "$*" >&2 ; }
db() { ( printf " db, ";for _i;do printf "%s" "$_i";done;printf "\n" ) >&2 ; }
db() { : ; }
# C=$HOME/bin/context && [ -f $C ] && $C

printf "\n Shell = %s\n\n" "$(ps | grep $$ | awk '{print $4}')"

w=0 x=0 y=0 z=0
case $1 in
  w)    w=1 ;;
  (x)   x=1 ;;
  (y)   y=1 ;;
  (z)   z=1 ;;
esac

pe " w = $w, x = $x, y = $y, z = $z"

exit

-----
 Execution with bash:

 Shell = bash

 w = 1, x = 0, y = 0, z = 0

-----
 Execution with dash:

 Shell = dash

 w = 0, x = 1, y = 0, z = 0

-----
 Execution with ksh:

 Shell = ksh

 w = 0, x = 0, y = 1, z = 0

-----
 Execution with zsh:

 Shell = zsh

 w = 0, x = 0, y = 0, z = 1

-----
 Result of beautysh:
#!/usr/bin/env bash

# @(#) s1       Demonstrate paren-case alternative, dash, bash, ksh.

LC_ALL=C ; LANG=C ; export LC_ALL LANG
pe() { for _i;do printf "%s" "$_i";done; printf "\n"; }
pl() { pe;pe "-----" ;pe "$*"; }
em() { pe "$*" >&2 ; }
db() { ( printf " db, ";for _i;do printf "%s" "$_i";done;printf "\n" ) >&2 ; }
db() { : ; }
# C=$HOME/bin/context && [ -f $C ] && $C

printf "\n Shell = %s\n\n" "$(ps | grep $$ | awk '{print $4}')"

w=0 x=0 y=0 z=0
case $1 in
  w)    w=1 ;;
(x)     x=1 ;;
(y)     y=1 ;;
(z)     z=1 ;;
esac

pe " w = $w, x = $x, y = $y, z = $z"

exit

Sublime Text plugin

Hi @bemeurer Can you create a sublime text plugin for this. It would be really helpful for a lot of sublime text users like me.

Check outputting why files are wrong

I don't know if this is inside the scope of the project, but it would be awesome if the --check option could output, maybe combining with another option, why a file is not beautified.

The use case is that I want to use beautysh for parse a lot of files, but I can risk beautysh making a mistake and the effort of checking file by file seems excessive to me.

Anyway, thanks for this tool, is very useful!

Strings defined by multiple successive lines may be erroneously filled with spaces

Sometimes I define in bash scripts a variable using multiple successive lines to get one or more newlines in the according string. For e.g. the script

#!/bin/sh
T=""
if [ "$T" = "" ]; then
T="Line1
Line2"
fi
echo "$T"

would output

Line1
Line2

But after running beautysh about that script one get the code

#!/bin/sh
T=""
if [ "$T" = "" ]; then
    T="Line1
    Line2"
fi
echo "$T"

and the according output is now erroneously

Line1
    Line2

So such continuation lines should probably not be indented.

Configuration by file

Hello,

I would like to ask if it would be possible to provide the configuration with a file rather than cli flags. Potential fiels could be setup.cfg, an own file or the pyproject.toml.
If you see an option to add this, I'm happy to open a PR (if I manage it :-) )

Thanks,
Kai

Unable to use in Atom: unrecognized arguments: -f

usage: beautysh [--indent-size INDENT_SIZE] [--backup] [--check] [--tab]
                [--force-function-style FORCE_FUNCTION_STYLE] [--version]
                [--help]
                [FILE [FILE ...]]
beautysh: error: unrecognized arguments: -f
Hide Stack Trace
Error: usage: beautysh [--indent-size INDENT_SIZE] [--backup] [--check] [--tab]
                [--force-function-style FORCE_FUNCTION_STYLE] [--version]
                [--help]
                [FILE [FILE ...]]
beautysh: error: unrecognized arguments: -f
    at /Users/treverchambersewing/.atom/packages/atom-beautify/src/beautifiers/executable.coffee:183:23
    at tryCatcher (/Users/treverchambersewing/.atom/packages/atom-beautify/node_modules/bluebird/js/release/util.js:16:23)
    at Promise._settlePromiseFromHandler (/Users/treverchambersewing/.atom/packages/atom-beautify/node_modules/bluebird/js/release/promise.js:512:31)
    at Promise._settlePromise (/Users/treverchambersewing/.atom/packages/atom-beautify/node_modules/bluebird/js/release/promise.js:569:18)
    at Promise._settlePromise0 (/Users/treverchambersewing/.atom/packages/atom-beautify/node_modules/bluebird/js/release/promise.js:614:10)
    at Promise._settlePromises (/Users/treverchambersewing/.atom/packages/atom-beautify/node_modules/bluebird/js/release/promise.js:694:18)
    at _drainQueueStep (/Users/treverchambersewing/.atom/packages/atom-beautify/node_modules/bluebird/js/release/async.js:138:12)
    at _drainQueue (/Users/treverchambersewing/.atom/packages/atom-beautify/node_modules/bluebird/js/release/async.js:131:9)
    at Async._drainQueues (/Users/treverchambersewing/.atom/packages/atom-beautify/node_modules/bluebird/js/release/async.js:147:5)
    at Async.drainQueues (/Users/treverchambersewing/.atom/packages/atom-beautify/node_modules/bluebird/js/release/async.js:17:14)
    at processTicksAndRejections (internal/process/task_queues.js:86:5)

Removed -f flag broke atom-beautify integration

Hello,
your PR #49 unnecessarily broke the integration with atom-beautify which is rather sad. After reading the comments I am sad about this little respect to other peoples work and time.

In the end, "bumping the major version" as you described, didn't really help me much in getting my scripts nicer!

beautysh error in atom-beautify

Please either put the parameter back in, at least for a while, or inform the maintainers of atom-beautify about this change.

Indent on continuation is eaten by formatter

I would prefer indentation on continued lines

git fetch --prune upstream \
      && git merge upstream/$branch \
      && git push origin $branch 

currently becomes:

git fetch --prune upstream \
&& git merge upstream/$branch \
&& git push origin $branch

Even a markers for copy block to output would be better.

Feature request: Support indentation with tabs

It would be great if i had an option to use tabs instead of spaces, or if the formatter would respect the setting that my file is set to rather than replace all my tabs with spaces every time I format it.

wrongly indents contents of multiline strings

This changes the value of the string. Perhaps multiline strings should be treated like herefiles?

$ scripts/beautysh.py - <<EOF
> #!/bin/bash
> if true; then
> VAR="
> value"
> fi
> EOF
#!/bin/bash
if true; then
    VAR="
    value"
fi

Error: sre_constants.error: nothing to repeat at position 25

Hello @bemeurer

I encounter this error

Traceback (most recent call last):
  File "/usr/local/bin/beautysh", line 11, in <module>
    sys.exit(main())
  File "/usr/local/lib/python3.6/site-packages/beautysh/beautysh.py", line 11, in main
    Beautify().main()
  File "/usr/local/lib/python3.6/site-packages/beautysh/beautysh.py", line 215, in main
    error |= self.beautify_file(path)
  File "/usr/local/lib/python3.6/site-packages/beautysh/beautysh.py", line 181, in beautify_file
    result, error = self.beautify_string(data, path)
  File "/usr/local/lib/python3.6/site-packages/beautysh/beautysh.py", line 76, in beautify_string
    if(re.search(here_string, test_record) and not
  File "/usr/local/Cellar/python/3.6.5/Frameworks/Python.framework/Versions/3.6/lib/python3.6/re.py", line 182, in search
    return _compile(pattern, flags).search(string)
  File "/usr/local/Cellar/python/3.6.5/Frameworks/Python.framework/Versions/3.6/lib/python3.6/re.py", line 301, in _compile
    p = sre_compile.compile(pattern, flags)
  File "/usr/local/Cellar/python/3.6.5/Frameworks/Python.framework/Versions/3.6/lib/python3.6/sre_compile.py", line 562, in compile
    p = sre_parse.parse(p, flags)
  File "/usr/local/Cellar/python/3.6.5/Frameworks/Python.framework/Versions/3.6/lib/python3.6/sre_parse.py", line 855, in parse
    p = _parse_sub(source, pattern, flags & SRE_FLAG_VERBOSE, 0)
  File "/usr/local/Cellar/python/3.6.5/Frameworks/Python.framework/Versions/3.6/lib/python3.6/sre_parse.py", line 416, in _parse_sub
    not nested and not items))
  File "/usr/local/Cellar/python/3.6.5/Frameworks/Python.framework/Versions/3.6/lib/python3.6/sre_parse.py", line 616, in _parse
    source.tell() - here + len(this))
sre_constants.error: nothing to repeat at position 25

when trying to beautify this bash script

# Syntax-highlight JSON strings or files
# Usage: `json '{"foo":42}'` or `echo '{"foo":42}' | json`
function json() {
	if [ -t 0 ]; then # argument
		python -mjson.tool <<< "$*"
	else # pipe
		python -mjson.tool
	fi;
}

To test that the script actually works:

json '{"foo":42}'
echo '{"foo":42}' | json

I'm using beautysh 3.8

A few bash examples where it failed

Hi,

First, thanks for making this cause for my server stuff i write a lot of bash scripts so it's very useful for me.

But i have some examples for you where it failed :) I'm not very familiar with phyton but, i'm a developer long time, so if i'm finding some time i maybe debug it too, but i think maybe will be much faster than me solving this issues :)

It doesn't fail at any bash script, but 3 from 7 files i've tested

I've attached them, if you don't want open the zip you can get them here too:
https://github.com/ShrimpDev/BashUpdateChecker/blob/master/checker.sh
https://github.com/ShrimpDev/BashUpdateChecker/blob/master/checker/joomla3.sh
https://github.com/ShrimpDev/BashUpdateChecker/blob/master/checker/roundcube.sh

And here are the error messages:

From joomla3.sh and roundcube.sh: File ./checker/roundcube.sh: error: indent/outdent mismatch: 1.

From checker.sh:

Traceback (most recent call last):
File "/usr/local/bin/beautysh", line 9, in <module>
 load_entry_point('beautysh==2.2.2', 'console_scripts', 'beautysh')()
  File "build/bdist.linux-armv7l/egg/beautysh/beautysh.py", line 10, in main
  File "build/bdist.linux-armv7l/egg/beautysh/beautysh.py", line 162, in main
  File "build/bdist.linux-armv7l/egg/beautysh/beautysh.py", line 146, in beautify_file
  File "build/bdist.linux-armv7l/egg/beautysh/beautysh.py", line 67, in beautify_string
  File "/usr/lib/python2.7/re.py", line 146, in search
    return _compile(pattern, flags).search(string)
  File "/usr/lib/python2.7/re.py", line 251, in _compile
    raise error, v # invalid expression
sre_constants.error: nothing to repeat

PartsOfMyBashUpdateChecker.zip

Beautified BASH scripts are defunct.

Beautysh is currently not usable for BASH scripts.
List of modifications that change the meaning of statements:
``

  • [[ ... ]] statements are changed into [[...]] , which breaks conditionals.
  • $() is changed into $ () , which breaks command substitution
  • VARIABLE=VALUE statements get changed into VARIABLE = VALUE , which breaks variable assignments.
  • Spaces are added to file paths, e.g. /path/file changes into /path / file ,which breaks file paths
  • "[]" statements, which shouldn't even be interpreted because they're encased in double quotes get linebroken.
    ``

Error: indent/outdent mismatch

First: I'm very happy to find a bash beautifier. But for one of my scripts it fails with

error: indent/outdent mismatch: 1.

although I (and also "shellcheck") didn't find an error.

After some trail and error attempts I could reduce the problem to the following command using command substitution

T=$(echo "\"a\"")

But for e.g. putting a space before the right parenthesis let beautish work without an error!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.