Custom code reformatting

The Xojo Code Editor can format your code for you as you type or when you select code and choose "Standardize Format" from the contextual menu. If you don't like the way the Code Editor formats the code, you can override the code formatter by providing an IDE Script that does code formatting the way you want.

There are two types of code formatting:

  • Single Line Reformatting: In the Code Editor Preference "Apply standardized format after ending line" is selected then this means that code formatting is applied:

    • As you enter each line of code.

    • When pasting a single line of code.

  • Block Reformatting: Applied when:

    • You select a block of code and choose "Standardize Format" from the contextual menu.

    • Paste multiple lines of code.

To substitute your own code formatting, create an IDE Script and name it "ReformatCode.xojo_script". You should place this script in the Scripts folder alongside the Xojo IDE or alongside your project.

In this IDE Script you'll need to implement the CleanBlock method in order to override code formatting:

This IDE Script runs with a special Context that gives you access to things to help identify what to format. Essentially you are getting access to the Lexer (the one the compiler users), along with all the tokenized identifiers.

Limitations

The ReformatCode.xojo_script has these limitations:

  • You can only use the core Xojo language with the Context methods and properties described below and the default language functions for Xojo Script. You cannot use other IDE Scripting commands.

  • ReformatCode.xojo_script is loaded and compiled once when the IDE starts. If you make changes you'll have to restart the IDE in order for them to take effect.

  • You cannot run ReformatCode.xojo_script from the IDE Scripts menu.

Script example

This simple code just turns every identifier to uppercase:

Sub CleanBlock()
  For i As Integer = 0 To LineCount - 1
      Var s As String

      StartTokenizer(Line(i))

      While NextToken = True
        If Not s.IsEmpty Then s = s + " "
        s = s + TokenText.Uppercase
      Wend
       ' If the line ends in a comment you will not get the token for a comment,
       ' but you will get the comment text in RemainingLine.
       If Not RemainingLine.IsEmpty Then
        s = s + RemainingLine
       End If

      Line(i) = s
  Next
End Sub

Context methods

The following methods are available for use within the ReformatCode script.

ConstantValue(propName As String) As String

Returns the value of a constant in a project item. The value is returned as a String regardless of its type.

DebugLog(message As String)

Outputs the message to the debug log.

XojoVersion As Double

Returns the current Xojo version as a Double. New in 2019r2.

Var version As String = XojoVersion.ToString

If you need your script to be compatible with pre-2019r2 IDEs, you can create your own XojoVersion constant like this:

Const XojoVersion = 0

When your script is run on 2019r2 or later, this constant will be removed so that the built-in one takes effect.

Notes

On Windows, this logs to the debugger, so programs like DebugView can be used to view the string. On macOS, this logs to the Console. On Linux, this prints the message to StdErr which can be viewed when Xojo is run from the Terminal.

LineCount As Integer

The number of lines of code to be reformatted.

Line(i As Integer, Assigns s As String)

Line(i As Integer) As String

Gets or sets a specific line of code.

NextToken As Boolean

Updates TokenText to contain the next token in the code's token stream. Returns False when there are no more tokens.

RemainingLine As String

This is the text remaining in the line after a token has been parsed. You can use this to get the comments on a line after parsing all the tokens in the line.

TokenText As String

The textual representation of the current token

TokenType As Integer

The symbolic representation of the current token (should be matched against one of the exposed TOKEN_TK_xxxx properties below.

StartTokenizer(code As String)

Initializes the tokenizer so that it can start fetching tokens for the provided code.

Context properties

The following properties are available for use within the ReformatCode script. These properties tell you the type of the token in TokenText (all are read-only).

  • TOKEN_TK_IF As Integer

  • TOKEN_TK_SUB As Integer

  • TOKEN_TK_FUNCTION As Integer

  • TOKEN_TK_UNTIL As Integer

  • TOKEN_TK_AS As Integer

  • TOKEN_TK_END As Integer

  • TOKEN_TK_MOD As Integer

  • TOKEN_TK_DIM As Integer

  • TOKEN_TK_THEN As Integer

  • TOKEN_TK_ELSE As Integer

  • TOKEN_TK_WHILE As Integer

  • TOKEN_TK_WEND As Integer

  • TOKEN_TK_RAISE As Integer

  • TOKEN_TK_FOR As Integer

  • TOKEN_TK_EXCEPTION As Integer

  • TOKEN_TK_ARRAY As Integer

  • TOKEN_TK_OF As Integer

  • TOKEN_TK_NOT As Integer

  • TOKEN_TK_GOTO As Integer

  • TOKEN_TK_AND As Integer

  • TOKEN_TK_OR As Integer

  • TOKEN_TK_NIL As Integer

  • TOKEN_TK_REM As Integer

  • TOKEN_TK_NEXT As Integer

  • TOKEN_TK_ELSEIF As Integer

  • TOKEN_TK_TO As Integer

  • TOKEN_TK_TRUE As Integer

  • TOKEN_TK_FALSE As Integer

  • TOKEN_TK_BYREF As Integer

  • TOKEN_TK_NEW As Integer

  • TOKEN_TK_SELECT As Integer

  • TOKEN_TK_CASE As Integer

  • TOKEN_TK_RETURN As Integer

  • TOKEN_TK_SELF As Integer

  • TOKEN_TK_DO As Integer

  • TOKEN_TK_LOOP As Integer

  • TOKEN_TK_EXIT As Integer

  • TOKEN_TK_REDIM As Integer

  • TOKEN_TK_DOWNTO As Integer

  • TOKEN_TK_STEP As Integer

  • TOKEN_TK_ISA As Integer

  • TOKEN_TK_ME As Integer

  • TOKEN_TK_PRAGMA As Integer

  • TOKEN_TK_BYVAL As Integer

  • TOKEN_TK_OPTIONAL As Integer

  • TOKEN_TK_EXTENDS As Integer

  • TOKEN_TK_ASSIGNS As Integer

  • TOKEN_TK_CONST As Integer

  • TOKEN_TK_COMPILEIF As Integer

  • TOKEN_TK_COMPILEELSE As Integer

  • TOKEN_TK_COMPILEENDIF As Integer

  • TOKEN_TK_DECLARE As Integer

  • TOKEN_TK_CLASS As Integer

  • TOKEN_TK_INTERFACE As Integer

  • TOKEN_TK_IMPLEMENTS As Integer

  • TOKEN_TK_INHERITS As Integer

  • TOKEN_TK_PROPERTY As Integer

  • TOKEN_TK_PUBLIC As Integer

  • TOKEN_TK_PRIVATE As Integer

  • TOKEN_TK_PROTECTED As Integer

  • TOKEN_TK_SHARED As Integer

  • TOKEN_TK_NAMESPACE As Integer

  • TOKEN_TK_MODULE As Integer

  • TOKEN_TK_STATIC As Integer

  • TOKEN_TK_EVENT As Integer

  • TOKEN_TK_HANDLES As Integer

  • TOKEN_TK_EACH As Integer

  • TOKEN_TK_IN As Integer

  • TOKEN_TK_CATCH As Integer

  • TOKEN_TK_TRY As Integer

  • TOKEN_TK_FINALLY As Integer

  • TOKEN_TK_SUPER As Integer

  • TOKEN_TK_LIB As Integer

  • TOKEN_TK_IS As Integer

  • TOKEN_TK_CALL As Integer

  • TOKEN_TK_ADDRESSOF As Integer

  • TOKEN_TK_DELEGATE As Integer

  • TOKEN_TK_PARAMARRAY As Integer

  • TOKEN_TK_COMPILEELSEIF As Integer

  • TOKEN_TK_SOFT As Integer

  • TOKEN_TK_CONTINUE As Integer

  • TOKEN_TK_WITH As Integer

  • TOKEN_TK_STRUCTURE As Integer

  • TOKEN_TK_ENUM As Integer

  • TOKEN_TK_RAISEEVENT As Integer

  • TOKEN_TK_XOR As Integer

  • TOKEN_TK_GLOBAL As Integer

  • TOKEN_TK_AGGREGATES As Integer

  • TOKEN_TK_BREAK As Integer

  • TOKEN_TK_GETTYPE As Integer

  • TOKEN_TK_ATTRIBUTE As Integer

  • TOKEN_TK_CTYPE As Integer

  • TOKEN_TK_ADDHANDLER As Integer

  • TOKEN_TK_REMOVEHANDLER As Integer

  • TOKEN_TK_WITHEVENTS As Integer

  • TOKEN_TK_WEAKADDRESSOF As Integer

  • TOKEN_TK_USING As Integer

  • TOKEN_TK_ASYNC As Integer

  • TOKEN_TK_AWAIT As Integer

  • TOKEN_IDENTIFIER As Integer

  • TOKEN_NUMBER As Integer

  • TOKEN_STRING As Integer

  • TOKEN_ASSIGN As Integer

  • TOKEN_GE_RELOP As Integer

  • TOKEN_LE_RELOP As Integer

  • TOKEN_NE_RELOP As Integer

  • TOKEN_REALNUMBER As Integer

  • TOKEN_ENDL As Integer

  • TOKEN_UNMATCHEDQUOTES As Integer

  • TOKEN_COLOR As Integer

  • TOKEN_LINE_CONTINUATION As Integer

  • TOKEN_TK_VAR As Integer

See also

IDE Scripting topic