mbutterick / pollen

book-publishing system [mirror of main repo at https://git.matthewbutterick.com/mbutterick/pollen]
https://git.matthewbutterick.com/mbutterick/pollen
MIT License
1.19k stars 64 forks source link

`pollen/mode' changes indentation in whole document #124

Closed leafac closed 8 years ago

leafac commented 8 years ago

CURRENT BEHAVIOR

The indentation for #lang racket is the following:

#lang racket

(define foo
  `{(a)
    (b)})

Adding pollen/mode makes available in Racket code, and is correctly indented according to -indentation rules:

#lang pollen/mode racket

◊bar{a
 b}

The addition of pollen/mode changes the indentation of existing code:

#lang pollen/mode racket

(define foo
  `{(a)
 (b)})

EXPECTED BEHAVIOR

Adding pollen/mode does not change the indentation of non- code.

#lang pollen/mode racket

◊bar{a
 b}

(define foo
  `{(a)
    (b)})

Do you think this makes sense? If so, how can I help turning this idea into code?

As always, thank you for Pollen!

mbutterick commented 8 years ago

I see your point. But I also think this notation is slightly mischievous:

#lang pollen/mode racket

(define foo
  `{(a)
 (b)})

Because in racket, {braces} count as parentheses. Whereas in pollen/mode, they mean something else, and thus indent differently. So your notation invites ambiguity. For instance, if I rewrite with parentheses, I get the right indentation:

#lang pollen/mode racket

(define foo
  `{(a)
 (b)})

(define foo-paren
  `((a)
    (b)))

Moreover, pollen/mode is based on Racket’s own at-exp metalanguage, and the behavior is the same there:

#lang at-exp racket

(define foo
  `{(a)
 (b)})

(define foo-paren
  `((a)
    (b)))

So, I grant your point that it would be nice for DrRacket to handle this better. But if the folks who wrote at-exp couldn’t figure it out, I doubt I will be able to do better 😱

leafac commented 8 years ago

Because in racket, {braces} count as parentheses. Whereas in pollen/mode, they mean something else, and thus indent differently.

As far as I understand, the meaning of {braces} only change on -expressions—e.g., ◊values{Braces with another meaning}. Elsewhere, pollen/mode preserves the meaning of {braces} counting as parentheses. The following program illustrates what I mean:

#lang pollen/mode racket

'{same-as-parentheses} ;; => '(same-as-parentheses)
◊values{Not the same as parentheses} ;; => "Not the same as parentheses"

So, DrRacket could indent the two differently as I proposed, it seems to me. But I agree that it is a bit awkward, so I'm closing the issue.


To give a bit of background of how I ended up opening this issue: I'm using pollen.rkt to store some data that should be available for the whole site (e.g., the website's name and description)—pollen/mode comes in handy for that. Also, I'm defining in pollen.rkt reusable HTML components which should be available for the whole site (e.g., a function to create links)—{braces} as parentheses make that portion of the code more readable. But then, indentation is awkward.

I guess my solution is going to be: extract one of these parts—or maybe both—to separate files, which I require and provide in pollen.rkt. These separate files are free to use pollen/mode where convenient, without messing anything else.

If you have a better idea, please let me know.

mbutterick commented 8 years ago

As far as I understand, the meaning of {braces} only change on ◊-expressions

Yes, that’s what I was getting at (though you have phrased it more precisely).

If I had to guess, I think you’ve found an edge case that the at-exp indenter (and therefore, the pollen/mode indenter) doesn’t handle. Whether that’s deliberate or accidental by the at-exp authors, I don’t know. I can say at least that using {braces} as list delimiters in racket is not idiomatic — for extra readability, typically [brackets] are used, so maybe the at-exp authors didn’t consider the possibility below. For instance, the bracketed version of your list indents as it should:

#lang pollen/mode racket

(define foo
  `{(a)
 (b)})

(define foo-paren
  `((a)
    (b)))

(define foo-bracket
  `[(a)
    (b)])

Fixing it would require deeper knowledge of the at-exp indenter than I have. Perhaps post an issue at scribble.

mbutterick commented 8 years ago

If you have a better idea, please let me know.

PS. I won’t call it “better”, but you can use one or more Pollen source files strictly as a store of values, and require those into a pollen.rkt. Any variable defined in a Pollen source is automatically provided, and of course there’s always doc and metas.

leafac commented 8 years ago

I can say at least that using {braces} as list delimiters in racket is not idiomatic (...)

Indeed, but I am creating an embedded DSL to define the HTML components and, in my language, {braces} are idiomatic in a few selected parts.

Perhaps post an issue at scribble.

I will. Thank you.

UPDATE: I opened the issue https://github.com/racket/scribble/issues/54.

(...) you can use one or more Pollen source files strictly as a store of values (...)

That is a good idea. Maybe I'll do that.


Thank you very much for your time.