fxbois / web-mode

web template editing mode for emacs
https://web-mode.org
GNU General Public License v3.0
1.64k stars 260 forks source link

Indentation in Elixir eex templates inconsistent #1188

Closed Matsa59 closed 1 year ago

Matsa59 commented 3 years ago

Multi line inside a <% ... %> block should be aligned as HTML does


Edit : Finally, I made a PR, I used it form weeks and everything works great so far.


Expected

<%= form_for @changeset, "#",
  id: "post-form",
  phx_target: @myself,
  phx_change: "validate",
  phx_submit: "save" do %>

  <%= textarea f, :body %>
  <%= error_tag f, :body %>

  <%= submit "Save", phx_disable_with: "Saving..." %>
<% end %>

OR

<%= form_for @changeset, "#",
    id: "post-form",
    phx_target: @myself,
    phx_change: "validate",
    phx_submit: "save" do %>

  <%= textarea f, :body %>
  <%= error_tag f, :body %>

  <%= submit "Save", phx_disable_with: "Saving..." %>
<% end %>

I personnaly prefer the 2nd way. Currently can't fint any "convention" on multi lines.

Obtains

<%= form_for @changeset, "#",
id: "post-form",
phx_target: @myself,
phx_change: "validate",
phx_submit: "save" do %>

  <%= textarea f, :body %>
  <%= error_tag f, :body %>

  <%= submit "Save", phx_disable_with: "Saving..." %>
<% end %>

(same as https://github.com/fxbois/web-mode/issues/1047 for ruby)

Matsa59 commented 3 years ago

Just try 2/3 things and following code could be a beginning

(defun web-mode-elixir-indentation (pos line initial-column language-offset limit)
  (unless limit (setq limit nil))
  (let (h offset prev-line prev-indentation open-ctx)
    (setq open-ctx (web-mode-bracket-up pos "elixir" limit))
    ;;(message "%S" open-ctx)
    (if (plist-get open-ctx :pos)
        (cond
         ((web-mode-looking-at-p ".[ \t\n]+" (plist-get open-ctx :pos))
          (setq offset (+ (plist-get open-ctx :indentation) language-offset)))
         (t
          (setq offset (1+ (plist-get open-ctx :column))))
         )
      (setq h (web-mode-previous-line pos limit))
      (setq offset initial-column)
      (when h
        (setq prev-line (car h))
        (setq prev-indentation (cdr h))
        (cond
         ((string-match-p ",$" prev-line)
          (save-excursion
            (goto-char limit)
            (looking-at "<%=? [a-z]+ ")
            ;; (setq offset (+ initial-column (length (match-string-no-properties 0))))
             (setq offset (+ initial-column 4))
            ) ;save-excursion
          )
         ((string-match-p "\\(do\\)" prev-line)
          (setq offset (+ prev-indentation language-offset))
          )
         (t
          (setq offset prev-indentation)
          )
         )
        ) ;when
      ) ;if
    offset))

Don't know why (setq offset (+ initial-column (length (match-string-no-properties 0)))) return me an error

fxbois commented 3 years ago

@Matsa59 thank you ... I'll look at this very soon

Matsa59 commented 3 years ago

Also please add the following piece of code:

       ((string= web-mode-engine "elixir")
        (cond
         ((web-mode-block-starts-with "</form>" reg-beg)
          (setq controls (append controls (list (cons 'close "form-ctrl")))))
         ((web-mode-block-starts-with "f =" reg-beg)
          (setq controls (append controls (list (cons 'open "ctrl")))))
         ...

It fix the "simple" eex pattern

<%= f = form_for ... %>
  <%= text_input f, :some_field %>
</form>

Currently it's transformed to

<%= f = form_for ... %>
<%= text_input f, :some_field %>
</form>

Edit : Finally, I made a PR, I used it form weeks and everything works great so far.