On this page:
1.1 Syntax Coloring
1.2 Indentation
1.3 Keystrokes
1.4 Filename Extensions
1.5 REPL Submit Predicate
1.6 Show Big “Definitions” and “Interactions” Labels
1.7 Opting Out of Standard Toolbar Buttons
1.8 Opting In to Language-Specific Toolbar Buttons
1.9 Adding New Toolbar Buttons
1.10 Definitions Text Surrogate

1 DrRacket support for #lang-based Languages

The simplest and best way to extend DrRacket with support for a new language is to implement the language via #lang (see Defining new #lang Languages for more details). DrRacket will then use read-language to find code and values that it uses to customize itself to the language.

If the call to read-language raises an error, DrRacket logs the error at the debug level to a logger with the name 'drracket-language (see Logging for more about how to follow specific loggers).

With the exception of the 'definitions-text-surrogate, if there is an error during a use of one of these extensions, DrRacket notices the error and removes all of the extensions for the language. It also shows the error at the bottom of the DrRacket frame (prefixed by #lang). Note that this applies only to errors that occur during the dynamic extent of a use of one of these extensions. If an extension were to, for example, create a new thread that (eventually) caused an error, DrRacket would not notice that error and would not remove the extensions.

When experimenting with changes to these extensions, use the Racket|Reload #lang Extensions menu item to cause DrRacket to remove the extensions and reload the implementations from the files on disk.

DrRacket calls the language’s read-language’s get-info procedure with the following key arguments:

1.1 Syntax Coloring

When a language’s get-info procedure responds to 'color-lexer, it is expected to return a procedure suitable to pass as the get-token argument to start-colorer.

The recognized token styles (specified implicitly via start-colorer’s token-sym->style argument) are:
  • 'symbol

  • 'keyword

  • 'comment

  • 'string

  • 'constant

  • 'parenthesis

  • 'error

  • 'other

These precise colors for these identifiers are controlled by the preferences dialog in DrRacket.

1.2 Indentation

When a language’s get-info procedure responds to 'drracket:indentation, it is expected to return a function with this contract:
The function is used to indent lines in DrRacket. It is called with the position containing the line to be indented. It is expected to return the number of spaces that should appear at the beginning of the line or #f. If #f is returned, DrRacket uses the standard s-expression indentation rules.

Added in version 1.3 of package drracket.

1.3 Keystrokes

When a language’s get-info procedure responds to 'drracket:keystrokes, it is expected to return a list of keybindings and callbacks matching this contract:
(listof (list/c string?
                (-> (is-a?/c text%)
                    (is-a?/c event%)
                    any)))
Each element of the list is a different keybinding, where the string indicates the keystroke (see the documentation for map-function for the precise contents of the string and how it maps to particular keystrokes) and the procedure is called when the user types that keystroke in the definitions window.

The procedure’s first argument will be the definitions text, the second will be the event object supplied from the GUI system and the result of the procedure is ignored.

1.4 Filename Extensions

When a language’s get-info procedure responds to 'drracket:default-filters, it is expected to return (listof (list/c string? string?)).

These results are added as a prefix to finder:default-filters, extending the default that DrRacket normally uses, namely:
`(["Racket Sources" "*.rkt;*.scrbl;*.rktl;*.rktd;*.ss;*.scm"]
  ["Any" "*.*"])

Added in version 1.2 of package drracket.

When a language’s get-info procedure responds to 'drracket:default-extension, it is expected to return (and/c string? (not/c #rx"[.]")); the result is used as the default extension when saving files by setting finder:default-extension.

Added in version 1.2 of package drracket.

1.5 REPL Submit Predicate

When using the language declared in the source, DrRacket queries that language via read-language to determine if an expression in the interactions window is ready to be submitted to the evaluator (when the user types return). The info procedure is passed 'drracket:submit-predicate and should return a function matching this contract:
(-> input-port?
    boolean?
    boolean?)
This function’s first argument is a port that contains the interactions window’s data, starting just after the prompt and continuing to the end of the editor. The second argument is a boolean indicating if the insertion point is followed only by whitespace. The results should be a boolean indicating if the expression should be evaluated.

For backwards compatibility reasons, DrRacket also queries the result of module->language-info for 'drracket:submit-predicate. It does this during the evaluation of the definitions (so the Racket|Reload #lang extensions menu item does not trigger a re-load). If the submit predicate is specified both ways, then the predicate supplied via read-language takes precedence.

Changed in version 1.5 of package drracket: Look for drracket:submit-predicate via read-language.

1.6 Show Big “Definitions” and “Interactions” Labels

If the read-language predicate returns #t for 'drracket:show-big-defs/ints-labels, then DrRacket shows the words “Definitions” and “Interactions” in a large font in the corresponding windows. This is intended as a help for students who are reading instructions about where to type their programs but might not have internalized this particular bit of DrRacket terminology.

1.7 Opting Out of Standard Toolbar Buttons

Some of the built-in buttons in the DrRacket button bar at the top of the window can be disabled on a per-language basis. DrRacket will invoke the get-info proc returned by read-language with 'drracket:opt-out-toolbar-buttons (and 'drscheme:opt-out-toolbar-buttons for backwards compatibility).

If the result is a list of symbols, the listed symbols are opted out. If the result is #f, all buttons are opted out. The default is the empty list, meaning that all opt-out buttons appear.

The Check Syntax button uses the symbol 'drracket:syncheck; the debugger uses the symbol 'debug-tool and the macro stepper uses 'macro-stepper.

Plugins may add more opt-out buttons via drracket:module-language-tools:add-opt-out-toolbar-button.

1.8 Opting In to Language-Specific Toolbar Buttons

Like drracket:opt-out-toolbar-buttons, but for languages to opt in to buttons that are not enabled by default.

Plugins may add more opt-out buttons via drracket:module-language-tools:add-opt-in-toolbar-button.

Added in version 1.6 of package drracket.

1.9 Adding New Toolbar Buttons

DrRacket queries the result of read-language to determine if there are any new toolbar buttons to be used when editing files in this language.

Specifically, DrRacket will pass 'drracket:toolbar-buttons to the function and expect back a value matching this contract:
(or/c (listof (list/c string?
                      (is-a?/c bitmap%)
                      (-> (is-a?/c drracket:unit:frame<%>) any)
                      (or/c real? #f)))
      #f)
which is then used to create new toolbar buttons, one for each element in the result list. The string is the label on the button; the bitmap is the icon (it should be 16x16 pixels); the function is called when the button is clicked; and the number is passed as the #:number argument to register-toolbar-button.

If the result is #f, then no toolbar buttons are created.

To implement functionality similar to the Run button, call the execute-callback method. You may also want to use the drracket:rep:after-expression parameter.

If 'drracket:toolbar-buttons is not recognized, DrRacket will also pass 'drscheme:toolbar-buttons; this is for backwards compatibility and new code should not use it. Similarly, if the fourth element from the list (the argument to #:number) is not present, then it is treated as #f.

1.10 Definitions Text Surrogate

Using a #lang-specific definitions text surrogate is a very powerful way to flexibly control DrRacket’s behavior when a new language is installed. It is also easy to cause DrRacket to completely misbehave with this form of extension. It is here only when one of the other forms of extension listed above are not sufficient for the kind of extension your language requires. And even in that case, it is preferable to add something to this list that is more easily controlled in the case of errors, using the definitions text surrogate only until that more easily controlled extension has been added to DrRacket.

DrRacket calls read-language’s get-info procedure with 'definitions-text-surrogate and expects it to return a value matching the contract (or/c #f module-path?), which is then passed to dynamic-require together with 'surrogate%. The result is expected to be a class implementing the interface racket:text-mode<%> (presumably derived from racket:text-mode%. That mode is installed into the definitions text, where it can change its behavior by changing how is responds to any of the methods in the mode.

One consequence of this power is that errors that happen during the dynamic extent of calls into the mode are not trapped (much as errors that occur on newly created threads are not trapped, as described in the introduction to this section).