an extensible code formatter for Racket (original) (raw)

8.15

This package provides a tool raco fmt to reformat Racket code.

The package uses syntax-color/module-lexer to lex the input program, and uses pretty-expressive, an expressive pretty printer library, to compute an optimal layout of the output code.

The interface to allow users to extend formatting style is extremely unstable and is still a work in progress. For now, the only thing that is stable is the command raco fmt.

1 Requirements and Installation🔗

Make sure Racket 8.0 or later is installed. Run raco pkg install fmt to install the formatter.

2 Running raco fmt🔗

raco fmt ‹file.rkt› ... reads ‹file.rkt›s and displays the formatted programs to the standard output. If ‹file.rkt›s are not given, it accepts an input program from the standard input.

The raco fmt command accepts the following flags:

3 Examples🔗

Given the file "example.rkt" shown on the left, running raco fmt --width 40 example.rkt outputs the program on the right:

example.rkt#lang racket ; low :: number? -> listof number?(define low(λ (argument) (cond (; this is the base case (zero? argument) '()) (else (define content (* argument (+ argument 1) (+ argument 2) (+ argument 3))) (define next ( low ........................... ...)) ; recursive call (cons content next))))) ; high :: number? -> listof number?( define high ...) formatted example.rkt#lang racket ; low :: number? -> listof number?(define low (λ (argument) (cond ; this is the base case [(zero? argument) '()] [else (define content (* argument (+ argument 1) (+ argument 2) (+ argument 3))) (define next (low ........................... ...)) ; recursive call (cons content next)]))) ; high :: number? -> listof number?(define high ...)

4 Unstable concepts🔗

A formatter is a function that accepts a code fragment and returns a doc?. In principle, you can create your own formatter, but you need to understand many structures that are currently undocumented and unstable. (If you want to implement one, perhaps take a look atthis file.)

A formatter map is a function that accepts either a string or #f, and returns either a formatter or #f. Conceptually, when the input is a string s, a formatter map should return a formatter that will format a form named s, and When the input is #f, the formatter map should return a formatter that will format function application. An exception is that the formatter map can also return #f, which means the formatter map wants to let other fallbackformatter maps to handle formatting instead.

Recognizes a formatter map.

5 Unstable API🔗

Formats string s with formatter-map under various configurations (see Running raco fmt for details).

Examples:

> (define s "(define (foo) (bar baz) food) (define-like (foo) (bar baz) food)")
> (display (program-format s))
(define (foo) (bar baz) food)(define-like (foo) (bar baz) food)
> (display (program-format s #:formatter-map lib-define-formatter-map))
(define (foo) (bar baz) food)(define-like (foo) (bar baz) food)
> (display (program-format s #:formatter-map lib-bar-formatter-map))
(define (foo) (bar baz) food)(define-like (foo) (bar baz) food)
> (display (program-format s #:formatter-map (compose-formatter-map lib-define-formatter-map lib-bar-formatter-map)))
(define (foo) (bar baz) food)(define-like (foo) (bar baz) food)

A formatter map that does not handle any form.

The fallback formatter map. It defines format styles for the following 172 forms:

augment augment-final augride begin begin-for-syntax begin0 case
case-lambda class class* cond define define-for-syntax
define-match-expander define-simple-macro define-struct
define-syntax define-syntax-class define-syntax-parameter
define-syntax-parse-rule define-syntax-parser define-syntax-rule
define-syntaxes define-values define-values-for-syntax
define/augment define/augment-final define/augride
define/contract define/match define/overment define/override
define/override-final define/private define/public
define/public-final define/pubment export field for for*
for*/and for*/async for*/first for*/fold for*/hash for*/hasheq
for*/hasheqv for*/last for*/list for*/list/concurrent
for*/mutable-set for*/mutable-setalw for*/mutable-seteq
for*/mutable-seteqv for*/or for*/set for*/setalw for*/seteq
for*/seteqv for*/vector for*/weak-set for*/weak-setalw
for*/weak-seteq for*/weak-seteqv for-label for-syntax
for-template for/and for/async for/first for/fold for/hash
for/hasheq for/hasheqv for/last for/list for/list/concurrent
for/mutable-set for/mutable-setalw for/mutable-seteq
for/mutable-seteqv for/or for/set for/setalw for/seteq
for/seteqv for/vector for/weak-set for/weak-setalw
for/weak-seteq for/weak-seteqv if import inherit init
instantiate interface interface* lambda let let* let*-values
let-syntax let-syntaxes let-values letrec letrec-syntax
letrec-syntaxes letrec-syntaxes+values letrec-values link match
match* match-define match-define-values match-lambda
match-lambda* match-lambda** match-let match-let*
match-let*-values match-let-values match-letrec
match-letrec-values mixin module module* module+ overment
override override-final parameterize parameterize* pattern
private provide public public-final pubment quasisyntax/loc
rename require shared splicing-let splicing-let-syntax
splicing-let-syntaxes splicing-let-values splicing-letrec
splicing-letrec-syntax splicing-letrec-syntaxes
splicing-letrec-syntaxes+values splicing-letrec-values
splicing-parameterize splicing-syntax-parameterize struct
syntax-case syntax-parameterize syntax-parse syntax-parser
syntax-rules syntax/loc test-begin test-case test-suite unless
when with-handlers with-handlers* with-syntax with-syntax* λ

For other forms, it uses the function application style.

Constructs a formatter map that tries the input functions in order. The first function that returns a formatter will be used.

6 Parameters🔗

Parameter for the page width limit. See Running raco fmt for details.

Parameter for the maximum number of blank lines. See Running raco fmt for details.

Parameter for the initial indentation level. See Running raco fmt for details.