emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Syntax tables for multiple modes [was: bug#22983: syntax-ppss return


From: Stefan Monnier
Subject: Re: Syntax tables for multiple modes [was: bug#22983: syntax-ppss returns wrong result.]
Date: Tue, 22 Mar 2016 10:51:33 -0400
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/25.1.50 (gnu/linux)

> Noweb is not essential here.  The story will hold for pretty much all
> multi-modes with non-full-line headers.  In noweb `<<foo,
> some_arg=4>>=` is a header of a chunk.  Polymode places heads and tail
> in their own modes because they are not conceptually part of nor host
> or sub-mode.  You can specify arbitrary parameters in the head which
> might even instruct how to indent the chunk.  The first code line
> `some_call(blabla)` is placed on the same line with the head.  This is
> uncommon but it's the simplest real case I can think of.

OK.

> There are two issues here.

Haha!

> First one is how do you indent the head itself?  Let's assume point is
> after `foo`.  If you follow the naive prog-indentation-context the
> indentation should be handled by the mode in the head chunk, right?

If it's got its own "chunk", then yes.

> Let's call it noweb-head-mode.  This mode is the same for many noweb
> host-mode/inner-mode combinations and defaults to poly-head-tail-mode.

OK.

> Host mode is commonly LaTeX but it can be anything.

OK.

> One reasonable way to indent it is to use the host mode
> indentation engine.

Right, since the beginning of line is still in latex-mode, the "<<foo,
some_arg=4>>= some_call(blabla)" line would be indented by latex-mode.
I.e. the generic code would go to BOL, and call latex-mode's indentation
while setting prog-indentation-context with an "end of chunk" that's
at point.

> Note that this is in contrast of the prog-indentation-context
> assumption for which PREVIOUS-CHUNK is assumed to be of the same mode
> type as the current type.

Not sure what PREVIOUS-CHUNK has to do with it.

> The second issue is with respect to the first line immediately after the
> header.

Since it's not on its own line, I don't see why it would be an issue
for indentation.

> If you naively call inner mode indentation engine on that line in a
> narrowed buffer starting after >>= you will get it indented to FIRST-COLUMN,

That's also one of the reasons why I didn't want to impose narrowing in
prog-indentation-context.

> mode for indentation. Consider this example of erb mode taken from
> https://github.com/fxbois/web-mode/blob/master/tests/demo.erb.
>
>     <div id='header'>
>       <% if signed_in? -%>
>         <%= link_to t('.sign_out'), sign_out_path, :method => :delete %>
>       <% else -%>
>         <%= link_to t('.sign_in'), sign_in_path %>
>       <% end -%>
>     </div>

IIUC, we have here a tight interleaving of lots of little chunks,
alternating between HTML and ..[according to duckduckgo].. Ruby.

> One meaningful approach here is to indent if-else-end block using inner mode
> rules, right?

Another approach would be to consider it as a sequence of chunks, rather
than as chunks of one mode nested in another.  So each chunk controls
the FIRST-COLUMN of the next chunk.

In any case, this seems messy.

> This is what web-mode seems to be currently doing. Assume you are
> just in front of `<%= link_to`. This is host hmtl mode. But you need to indent
> according to inner mode construct. So what do you do? You go to the end of
> previous code chunk and call prog-indentation-function of inner mode with
> STRING-BEFORE = "\n" and STRING-AFTER="link_to t('.sign_out'), sign_out_path,
> :method => :delete". Simple isn't it? That's precisely my proposal.

Ah, now I see a use of STRING-BEFORE and STRING-AFTER, thanks.

This case of STRING-BEFORE being "\n" is very special: in SMIE, the core
indentation function (smie-indent-calculate) basically behaves as if
it's always called with STRING-BEFORE="\n".

IOW, we could define prog-indent-function as always behaving "as if
STRING-BEFORE was \n".  In the normal case, the foo-calculate-indent
function is called at the beginning of line anyway, so adding
a STRING-BEFORE="\n" won't affect its behavior.

As for STRING-AFTER, the example is compelling, but I don't yet
understand really how it would all work out overall.
I'm thinking of cases like:

    <% 3.times do %>
      <li>
        some text
        <% if signed_in? -%>
          <%= link_to t('.sign_out'), sign_out_path, :method => :delete %>
        <% else -%>
          <%= link_to t('.sign_in'), sign_in_path %>
        <% end -%>
      </li>
    <% end %>

How should the "generic" code that links HTML and Ruby know when to
indent using the HTML indentation code and when to use the Ruby
indentation rules?

Maybe my suggestion of considering it as a sequence of chunks (where each
chunk controls the FIRST-COLUMN of the next chunk) could work, but it's
far from obvious.


        Stefan




reply via email to

[Prev in Thread] Current Thread [Next in Thread]