Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Permit multiple formats for the same form #20

Closed
default-kramer opened this issue Oct 11, 2021 · 2 comments
Closed

Permit multiple formats for the same form #20

default-kramer opened this issue Oct 11, 2021 · 2 comments
Labels
enhancement New feature or request

Comments

@default-kramer
Copy link

First of all, thanks for doing this project. For me, DrRacket's formatting is what I want 99% of the time, but every now and then I wish I could customize it. I think this project might be able to grow into my preferred solution.

=========

Consider the following example file

#lang racket

(define x (if #t 'foo 'bar))
(define y (if #f
              'foo
              'bar))

When I run DrRacket's indenter on this, nothing changes. This is the behavior I want. The rationale is that I added those newlines deliberately and unless I am breaking some rule I would like to keep them where they are. (Where "breaking some rule" means exceeding the width, incorrect indentation, or something like that.) But when I run fmt, the output is

#lang racket

(define x (if #t 'foo 'bar))
(define y (if #f 'foo 'bar))

I read the docs about formatters and I'm not sure if it is possible/easy to customize fmt to work like DrRacket for this example. Would this be implemented as a single formatter for the if form? Or maybe the formatter map should map if to a list of formatters. (But then how would it decide which one to use when the input doesn't match any of them?)

Is what I want to do even philosophically compatible with your project goals? Perhaps an "indenter" and a "formatter" are two different things, and I want an indenter.

PS - I'm sure I can find a non-contrived example from real code if you're wondering "why do you want to do this?"

@sorawee
Copy link
Owner

sorawee commented Oct 11, 2021

Yes, the indenter and formatter are different. An indenter will never insert or remove a newline. A formatter on the other hand aims to produce code with minimal height, subjected to the constraint that the code fit the page width limit. So it could insert a newline if your original code is too wide, or remove a newline if doing so will reduce the number of lines.

If you want a customizable indenter, both DrRacket and Racket Mode are customizable in different aspect. DrRacket allows you to use regexp to match forms to indent "begin-like keyword", "define-like keyword", "lambda-like keyword", and "for/fold-like keyword" (Preferences > Editing > Indenting). On the other hand, Racket Mode allows you to create a new keyword "category".

Currently it's not possible for fmt to do what you want, and you intuited correctly that it's somewhat not compatible with the project goal.

But theoretically, fmt is also flexible enough to do what you want (at least for this specific case). As you mentioned, you can create your own if-formatter. The code fragment that is the input to formatters ideally should contain the source locations (right now I haven't implemented this feature -- see #14). With the source locations, you can check if the "conditional" and the "branches" are on the same line. Depending on the answer, you would format differently.

Also note that while one newline is insignificant in fmt, two or more newlines are not (this is the what most code formatters for most languages do). fmt will try to preserve these significant newlines. For example, currently fmt formats

#lang racket

(
if test

hello

world
)

to:

#lang racket

(if test

    hello

    world)

@default-kramer
Copy link
Author

Thank you for the detailed explanation. It seems what I currently want is an indenter with maybe some very light formatting capabilities. Still, the idea of a standard formatter is intriguing (the Go community seems to universally love gofmt).

@sorawee sorawee added the enhancement New feature or request label Nov 11, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants