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

9.0

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 183 forms:

augment augment-final augride begin begin-for-syntax begin0 case
case-lambda class class* cond define define-check
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
delay delay/idle delay/name delay/strict delay/sync delay/thread
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 lazy let let*
let*-values let-syntax let-syntaxes let-values let/cc let/ec
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 send 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.