Format Code - Xojo Script to nicely format your source

This started as a project to simply clean up code entered by me via voice dictation, but it has since turned into a full code formatter for Xojo. It installs as an IDE script and runs from the File > IDE Scripts menu. It takes badly formatted code and makes it beautiful doing case conversion on keywords as well as fixing whitespace. It has a few options to accommodate quite a few different code formatting styles. For example you can choose to pad parenthesis characters on the inside or outside, pad a comma, convert keyword case to TitleCase, lowercase or UPPERCASE, etc…

Here is an example using the default formatting (most common I believe), Your code before Format Code:

[code] dim apples AS INTEGER = 18

apples= 8+Abs(38 ) - 44

if apples> 8 then
MsgBox (“You have enough apples for the day”)
MsgBox( “You should really buy more apples”)
end if[/code]

After running Format Code, the result is:

[code] Dim apples As Integer = 18

apples = 8 + Abs(38) - 44

If apples > 8 Then
MsgBox(“You have enough apples for the day”)
MsgBox(“You should really buy more apples”)
End If[/code]

By changing various options at the top of the script, you can come up with:

[code] Dim apples As Integer = 18

apples = 8 + Abs ( 38 ) - 44

If apples > 8 Then
MsgBox ( “You have enough apples for the day” )
MsgBox ( “You should really buy more apples” )
End If[/code]

Or even:

[code] DIM apples AS INTEGER=18


IF apples>8 THEN
MsgBox(“You have enough apples for the day”)
MsgBox(“You should really buy more apples”)
END IF[/code]

if you wish.

Please see Format Code on GitHub page for more complete docs and Format Code Releases on GitHub for .zip and .tar.gz downloads.

Please be careful as this script does alter your code. You can always use Cmd/Ctrl+Z to undo its changes (in one fell swoop) but you must know where it fails and test early. It is working great for me, but with the 1.0.0b1 release, there has been many options added. So, please use it and test your code right after each format to find problems and not loose any code you may have changed after a bad format.

I am looking for feedback in the form of bug reports, feature requests and even simple it works great messages (hopefully only these kind :-D) The amount of feedback received will of course dictate how much effort I put into this for others. No feedback, I’ll just make things simple and use it internally, a lot of feedback, bug reports and new test cases? I’ll keep maintaining it for everyone.

If you do discover a bug, it would be great if you would install the optional Format Code - Test.xojo_script file and add a test case for the failing condition. Better yet, clone format-code on github, add the unit test (and bug fix if you see the error) and do a pull request!


Just to Bold this part.

Very nice, Jeremy.
Do you prefer feedback by email or commenting this topic (so others can comment)?

Doesn’t matter, if the information is pertinent to others, forum may be better, but don’t want to clutter it up with on going support as that’s not its purpose. Your call. If you have a github account, bug reports can be added there if that is the feedback, otherwise I’ll take them any way I can get them.

Ok, As I said this could be very welcomed to me, nice work. I will test more but for now a couple of feature requests and a missing thing.

  1. About capitalization I’d like to have also a semi-titleCase option. So then Myclass will become myClass

  2. Self, Me are always capitalized, while I’d like to have them following the capitalization preferences. I can change the code myself, but perhaps someone else could prefer this.

  3. You handle Self, Me, but not Super.

Keep up the good work! :smiley:

I wi take a look at this too, but I wonder if a companion module with constants would be a better place to keep the preferences for the script? That way, one wouldn’t have to change their prefs back with every bug fix.

I agree, it would be a nice change.

I wanted to do that but not sure how to make those variables in the companion module be available to my script? Or are you speaking of a module that you have to add to your project?

Right, you’d add the module to your project.

OK, 1.0.0b2 has been released… It includes: super. support, case conversion for Me., Self. and Super, and support for setting preferences in a module in your project named FormatCodePreferences.

The pro to setting configuration in the script is that you can format any project without setting up a particular module for it. The con is having to reset your configuration each new release of Format Code and that the setting is global, i.e. all projects will be formatted the same way.

The pro to setting configuration by the module is: No update hassles and each project can have its own preferences, for example contribute to an open source project w/a particular formatting scheme vs. your own private scheme.

Now, once Format Code settles down, you could use both… setup your default in the script and then when something varies from the default, create a module for it in the project itself.

Please see: Format Code - GitHub Releases and Format Code - for more info on this release.

This is a really nice job, especially adding the prefs module as optional. Brilliant.

I tend to mix case. For example, I prefer certain keywords to be title case and others lowercase. Why? Dunno, I just do. What about adding groups for KeywordsToUppercase, KeywordsToLowercase, and KeywordsToTitleCase? Not all groups would have to be filled in, so if a keyword doesn’t appear on any of the new lists, it will be treated to the default behavior. In other words, if you want all your keywords as title case except for if/then/else, you’d set CaseConversion to kTitleCase, but add those three exceptions to KeywordsToLowercase.

These three additional arrays could be maintained in the pref module as comma-delimited strings.

What do you think?

(I’ll clone the repo and make the change if you agree. I’m not looking to create work for you.)

Kem, that sounds great! Yeah, clone and I’ll happily pull!

BTW… I should add in my that you can turn off the module for Web, Console and Desktop applications so it’ll never be compiled in your code wasting space/time.

I can’t imagine that matters.

Anyway, I made the changes and sent a Pull Request.

I haven’t dived into it, but the tokens are always one word, yes? For example, end if would be considered two tokens?

Yeah, end if is turned into two tokens.

As I thought. I was wondering if it made sense to turn End If, End Select, and Select Case into one token each, but the more I think about the reasoning behind that, the less useful it seems. If you want If and Select capitalized, you probably want the End capitalized too.

I debated that also. When I wrote the tokenizer, I made it as generic as I could but still be able to understand Xojo code. In Xojo, however, “Select Case” and “End If” could be counted as a single token. As it is right now, if we ever want to do some more complex fixes, we may need to know if this “If” is part of an If statement or an “End If”. We can do it by checking the previous token, but… was something I debated. I think in the end I flipped a coin to decide.

Upon further consideration, I think it’s fine.

Does it make sense to add an “AdditionalTokens” property to the module? For example, I may always want Str and Format to title cased.

That’s a good idea, I wonder though if we should just make a MethodsToCapitalize array. One would then wonder, do we need a VariablesToCapitalize array. I actually think both is good and an AdditionalTokens array, which users can fill in items from their own libraries if they wish

With your idea of a comma list in the Module, it would be very nice. One could also use an External module to share settings amongst many projects.

I got a bit confused by that. Are you proposing adding three new arrays to the prefs?

I’ll have to look again, but I was thinking MethodsToCapitalize and VariablesToCapitalize could be populated with those from the Xojo library. AdditionalTokens could be for users to add support for their own projects and libraries.


So, MethodsToCapitalize could contain things like Str, Format, UBound, GetFolderItem, etc… I guess there really are not global variables. Maybe VariablesToCapitalize isn’t needed.