hylang / hy-mode

Hy mode for Emacs
GNU General Public License v3.0
189 stars 48 forks source link

Indent dict keys wrongly if the keys are strings #32

Closed larme closed 6 years ago

larme commented 9 years ago

I'm not sure if it's just my setup or a universal problem. But my emacs always indent a dict with the second string keys aligned to the first value part. For example:

(def a {"key1" value1
               "key2" value2
               "key3" value3})

From the example above you can see that the third (and later) keys are not affected.

clemux commented 8 years ago

I have the same problem here. Latest master, no changes to the .el file.

gilch commented 6 years ago

This one is a real pain. I have to switch to clojure-mode whenever there's a file containing such a form. I'd call fixing this one a top priority.

ekaschalk commented 6 years ago

I've found where the bug occurs: parse-partial-sexp.

In particular lines 789-790 in calculate-lisp-indent in lisp-mode.el.

      (while (< (point) indent-point)
        (setq state (parse-partial-sexp (point) indent-point 0)))

Unfortunately this is a C function in src/syntax.c so a non-hackish solution is beyond me.

gilch commented 6 years ago

I wonder how clojure-mode does it. Maybe we can detect a { or [ and define an indent of 1 in hy-indent-function, the same way we have custom indents for special forms.

ekaschalk commented 6 years ago

I've got a solution.

Update calculate-lisp-indent at line 789 to now be:

      (while (< (point) indent-point)
        (setq state (parse-partial-sexp (point) indent-point 0))
        (save-excursion
          (goto-char (elt state 1))
          (if (looking-at "\{\"")
              (setcar (nthcdr 2 state) (+ 1 (elt state 1)))))
        )

Indenting is working at various sexp depths.

Now editing lisp-mode's source is clearly not the best approach. I'll see if I can due some advice-add magic to setup a PR for hy-mode.el.

ekaschalk commented 6 years ago

In the meantime you can find the fix at: https://github.com/ekaschalk/.spacemacs.d/blob/master/layers/langs/local/hy-indent-fix/hy-indent-fix.el

Just load the file in your emacs config.

ekaschalk commented 6 years ago

https://emacs.stackexchange.com/questions/10230/how-to-indent-keywords-aligned

This is apparantly a known problem, the stackexchange links a robust solution for aligning with colons.

We can see that common lisp's mode defines their own version of calculate-lisp-indent with, among other things, modifications in that same loop I linked earlier including:

              (when (and (null tem)
                         (string-match ":[^:]+" function))

Where it explicitly deals with the colon keyword indentation.

So the solution is to write a modified calculate-lisp-indent mirroring common-lisp-indent-function-1 as a new hy-indent-function.

ekaschalk commented 6 years ago

Finally fixed, for lists as well. As compared to previous fix, doesn't fail on newlines, nor cause issues with the #@ with-decorator tag macro.