I'm starting a new discussion topic, so as not to crowd
https://groups.google.com/forum/#!topic/racket-users/4SnwpX6gYqk .

2016-08-26 0:32 GMT+02:00 Alex Knauth <alexan...@knauth.org>:
> How would a library express indentation rules? Would indentation rules
meant for s-expression languages be useful in at-exp or sweet-exp notations?

Below are some ideas, but I'm definitely sure something better can be
achieved.
TL;DR: we could specify the indentation of each s-expression with respect
to another preceding s-expression (but not necessarily the one just
before), and indicating if it should be indented by 0, 2 or 4 spaces.



>From what I've seen, lisps and schemes have a few indentation styles for a
given line:

Indent a bit, with respect to the beginning of the enclosing s-expression:

    (define ;; indent = 0
      a     ;; indent += small
      1)

Indent a a lot (twice as much?), with respect to the beginning of the
enclosing s-expression.

    (λ         ;; indent = 0
        (args) ;; indent += big
      body)    ;; indent += small, with respect to line 1

Indent the as much as the first argument of the enclosing form.

    (displayln datum
               output-port)

Indent as much as the first s-expression on the previous line (this is
basically just `begin` specifying a +small indentation for all of
sub-expressions):

    (begin
      (define x 1) (define y 2) ;; indent = 2
      (displayln (+ x y)))      ;; indent += 0

Has anyone seen another kind of indentation? Reader extensions like #' and
dotted pairs may need some extra thought.

I think the cases above can be generalized to: “Indent this s-expression so
that it aligns with that other preceding s-expression (exactly | plus a
small indent of 2 spaces | plus a large indent of 4 spaces)“. It allows
some less common indentation styles:

The code
    (some-macro #:kw #:kw-one-arg arg1 #:kw-trhee-args argA argB argC)
may specify the following indentation styles:
    #:kw => +small, w.r.t some-macro
    #:kw-one-arg => exactly, w.r.t #:kw
    arg1 => +small, w.r.t #:kw-one-arg
    #:kw-three-args => exactly, w.r.t #:kw (or w.r.t #:kw-one-arg)
    argA => +small, w.r.t #:kw-three-args
    argB => exactly, w.r.t argA
    argC => exactly, w.r.t argA
which gives the following indentations, depending on where the newlines are:
    (some-macro #:kw #:kw-one-arg arg1 #:kw-three-args argA argB argC)
    (some-macro #:kw
                #:kw-one-arg arg1
                #:kw-three-args argA argB argC)
    (some-macro #:kw
                #:kw-one-arg
                  arg1
                #:kw-three-args
                  argA argB
                  argC)
    (some-macro
      #:kw
      #:kw-one-arg
        arg1
      #:kw-three-args argA argB
                      argC)

Given a caml-style let-in macro, the code
    (let (x . y) z = (values (cons 1 2) 3) t = 4 in body)
may specify the following indentation styles:
    (x . y) => +big, w.r.t let
    z => exactly, w.r.t (x . y)
    = => exactly w.r.t (x . y)
    t =>  exactly w.r.t (x . y)
    =  => exactly w.r.t (x . y)
    4 =>  exactly w.r.t (x . y)
    in => exactly w.r.t let
    body => +small w.r.t let
which gives the following indentations, depending on where the newlines are:
    (let (x . y) z = (values (cons 1 2) 3) t = 4 in body)
    (let
        (x . y) z = (values (cons 1 2) 3)
        t = 4
     in
       body)
    (let
        (x . y) z = (values (cons 1 2) 3)
        t = 4 in
       body)
    (let (x . y) z = (values (cons 1 2) 3)
         t = 4
     in body)
    (let (x . y) z = (values (cons 1 2) 3) t = 4 in
      body)

I'm not used to sweet-exp, so I cannot say much about it, but the rules
above seem to translate naturally to at-exp in most cases, but not all:
    @some-macro[#:kw #:kw-one-arg arg1 #:kw-three-args argA argB argC]
    @some-macro[#:kw
                #:kw-one-arg arg1
                #:kw-three-args argA argB argC]
    @some-macro[#:kw
                #:kw-one-arg
                  arg1
                #:kw-three-args
                  argA argB
                  argC]
    @some-macro[
      #:kw
      #:kw-one-arg
        arg1
      #:kw-three-args argA argB
                      argC]
bonus: if the [ appears first on its line, it uses the indentation of the
following token, and shifts everyting until ] by 1 space:
    @some-macro
      [#:kw
       #:kw-one-arg
         arg1
       #:kw-three-args argA argB]
things are do not look so good when using {} for the last argument:
    @some-macro
      [#:kw
       #:kw-one-arg
         arg1
       #:kw-three-args argA argB]{
                       argC}

    @let[(x . y) z = (values (cons 1 2) 3) t = 4 in body]
    @let[
        (x . y) z = (values (cons 1 2) 3)
        t = 4
     in
       body]
This one looks a bit weird too (because the "[" bracket is opened on the
second line):
    @let
        [(x . y) z = (values (cons 1 2) 3)
         t = 4 in
       body]
Where should the closing brace "}" be positioned ?
    @let[(x . y) z = (values (cons 1 2) 3)
         t = 4
     in]{
       body
     }
    @let[(x . y) z = (values (cons 1 2) 3) t = 4 in
      body]



An interesting feature that would require more thought would be to provide
"alignment tabs", so that getting the body of all clauses in a cond
statement is easy, if the IDE supports it:
    (cond
      [x                   body1]
      [very-long-condition body2]
      [much-too-much-too-long-condition-so-the-programmer-put-a-newline
                           body3]
      [yzt                 body4])

Regards,
Georges Dupéron

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to