mathialo/bython

Formatting Bython code?

markus-wa opened this issue ยท 7 comments

I would like to enable auto-format-on-save for my IDE but can't find a way to format bython.

I thought by2py example.by && py2by example.py && rm example.py would achieve what I'm looking for, but it generates some additional newlines etc.

py2by also doesn't overwrite the existing example.by so it would have to be done with rm example.by between by2py & py2by. Deleting the file would probably mess up the IDE, 'in place' replacement would be preferable.

Input:

def print_message(num_of_times) {
 for i in range(num_of_times) {
print("Bython is awesome!");
          }
}

if __name__ == "__main__" {
    print_message(10);
}

After by2py:

def print_message(num_of_times):
    for i in range(num_of_times):
        print("Bython is awesome!")



if __name__ == "__main__":
    print_message(10)


After py2by:

def print_message(num_of_times){
    for i in range(num_of_times){
        print("Bython is awesome!")



    }
}
if __name__ == "__main__"{
    print_message(10)


}

Maybe cat example.by | by2py --stdin --stdout | py2by --stdin --stdout > example.by will be what you want, provided that CLI has been changed that way.

Thanks @b1f6c1c4 , I didn't know about the --stdin & --stdout flags.

I think those should be mentioned in the --help output?

So yeah if py2by were to generate nicely formatted output that could do it.

Actually, these flags seemingly haven't been implemented (nor planned) yet. ๐Ÿ˜‚ Probably you can turn this issue into a feature request.

Ohhh, right, I missunderstood ๐Ÿ˜…

Both py2by and bython -c (which by2py is an alias of) should overwrite files. Could it be your IDE messing things up? (by for example working on a local copy of the file).

For debugging, could you try this with no text editor open and diffing the results? I just did, and it is clear that by2py has overwritten the previous file:

$ cp test.by test2.by
$ by2py test.by && py2by test.py
$ diff test.by test2.by  # this produces a non-empty result

Doing this however, will create some newlines. It will also place the closing braces on somewhat clunky positions, imho (because of how the python parser tokenizes the source file). I haven't looked into autmatic formatting of Bython code, something like black could be used for autoformatting the resulting Python code, but that's another issue. From your example I guess that you would like to fix indentation?

Maybe some --format flag could be added to just fix indentation and such? ๐Ÿ™‚

@b1f6c1c4 I agree --stdin and --stdout options that should be added, feel free to open another issue on that ๐Ÿ™‚

I actually tried it outside of the IDE, I thought it didn't overwrite the files. I'll check again and post an update.

Actually, indentation seems correct. It's just the additional newlines (or missing ones between defs) that bother me.

+1 for --format, maybe this could even become the default behavior at some point in the future? (if it doesn't add too much to transpilation time)

I've looked a bit more into this, and making a good code formatter is a lot of work, and very difficult work, and I have more faith in other peoples ability to do it than my own. Thus, I propose the following hacky method of auto-formatting Bython:

  1. Run bython -c on your source code
  2. Run some Python formatter like yapf or black on the resulting Python code
  3. Run py2by to turn it back into Bython

Keep in mind that py2by is still regarded as experimental, so be careful. I have not had too many issues though.

In the recent version of Bython (version 0.7), one of the updates is reworking where the py2by translator places the closing brace. It is now much more logical, and more in-line with where a human would place it. It still produces some white spaces, but running a code formatter in-between solves this.

I've done some simple tests with yapf, and the results seem quite nice:

Input:

def print_message(num_of_times) {
 for i in range(num_of_times) {
print("Bython is awesome!");
          }
}

if __name__ =="__main__" {
    print_message(10);
}

After bython -c :

def print_message(num_of_times):
    for i in range(num_of_times):
        print("Bython is awesome!")
    


if __name__ =="__main__":
    print_message(10)

After yapf -i:

def print_message(num_of_times):
    for i in range(num_of_times):
        print("Bython is awesome!")


if __name__ == "__main__":
    print_message(10)

(notice how this also adds the space in if __name__ == "__main__", making the code prettier)

After py2by:

def print_message(num_of_times) {
    for i in range(num_of_times) {
        print("Bython is awesome!")
    }

}

if __name__ == "__main__" {
    print_message(10)
}