DogLooksGood / parinfer-mode

Parinfer for Emacs :)
GNU General Public License v3.0
407 stars 33 forks source link

Parinfer-mode insists on breaking this code in indent mode #57

Open Northcode opened 6 years ago

Northcode commented 6 years ago

I have this code in my emacs config:

(setq-default mode-line-format
          '("    "
        (:eval (case evil-state
             ('normal "N")
             ('insert "I")
             ('visual "V")
             ('emacs  "E")))
        " %04l %n "
        "    "
        (:propertize (:eval (if buffer-read-only " RO: "))
                 face font-lock-warning-face)
        (:propertize "%b"
                 face font-lock-keyword-face)
        " "
        (:eval (if (buffer-modified-p) "(!!)"))
        " "
        (:propertize
         (:eval (when (magit-get-current-branch)
              (concat " [" (magit-get-current-branch) "]")))
         face font-lock-string-face)
        " :: "
        (:propertize "%m"
                 face font-lock-constant-face)
        " %e "
        (:eval (format-time-string "%H:%M" (current-time)))
        " %-"))

Whenever I switch to parinfer-indent-mode it breaks the parens, and makes it impossible to get the correct parens back for the first case sexp, it forces 3 closing parens at the end of the line and no matter how I indent the 4 cases underneath the parens dont seem to be affected.

The entire block turns into this:

(setq-default mode-line-format
        '("    ")
    (:eval (case evil-state)
       ('normal "N")
       ('insert "I")
       ('visual "V")
       ('emacs  "E"))
    " %04l %n "
    "    "
    (:propertize (:eval (if buffer-read-only " RO: "))
           face font-lock-warning-face)
    (:propertize "%b"
           face font-lock-keyword-face)
    " "
    (:eval (if (buffer-modified-p) "(!!)"))
    " "
    (:propertize
     (:eval (when (magit-get-current-branch))
        (concat " [" (magit-get-current-branch) "]"))
     face font-lock-string-face)
    " :: "
    (:propertize "%m"
           face font-lock-constant-face)
    " %e "
    (:eval (format-time-string "%H:%M" (current-time)))
    " %-")
shaunlebron commented 6 years ago

Thanks for reporting this! This plugin should be protecting against breaking your code by running paren-mode before allowing you to go into indent-mode!

Also, I see tab characters here, and those are converted by Parinfer to two spaces. This should not break your code if Paren Mode is run first.

I wrote a quick thing to explain using your example: https://beta.observablehq.com/@shaunlebron/tab-characters-in-parinfer

This is the code that should've showed up in when turning on indent-mode if properly processed by paren-mode first:

(setq-default mode-line-format
        '("    "
          (:eval (case evil-state
                  ('normal "N")
                  ('insert "I")
                  ('visual "V")
                  ('emacs  "E")))
          " %04l %n "
          "    "
          (:propertize (:eval (if buffer-read-only " RO: "))
                   face font-lock-warning-face)
          (:propertize "%b"
                   face font-lock-keyword-face)
          " "
          (:eval (if (buffer-modified-p) "(!!)"))
          " "
          (:propertize
             (:eval (when (magit-get-current-branch)
                     (concat " [" (magit-get-current-branch) "]")))
             face font-lock-string-face)
          " :: "
          (:propertize "%m"
                   face font-lock-constant-face)
          " %e "
          (:eval (format-time-string "%H:%M" (current-time)))
          " %-"))
DogLooksGood commented 6 years ago

unfortunately, at this moment, parinfer-mode can't deal with tab correctly, every indentation must be whitespaces.

Northcode commented 6 years ago

I hit the wrong button, I guess this should still be open untl parinfer-mode deals with tab correctly, but thanks for the fix at least.

Northcode commented 6 years ago

@shaunlebron When you say paren-mode, you mean the paren mode in parinfer right, theres no separate package (I couldn't find one)? Because enabling parinfer in paren-mode first and then running (parinfer-toggle-mode) will still break the code, at least in emacs 25.3.1 with parinfer v0.4.0.

I can reproduce the problem with this:

If the problem is that its converting tabs to only 2 spaces, why not just have it respect emacs' tab-width mine is set to 8 in emacs-lisp-mode, but it differs between modes, I think its set to 4 or 2 in clojure-mode.

DogLooksGood commented 6 years ago

@Northcode Hi, this is not a problem of parinfer itself, this is a problem in parinfer-mode(this plugin). Parinfer itself can handle tab correctly, but parinfer-mode not.

Currently I'm working on the new version, which ships the smart-mode. There will be a rewrite for this. so I have no time for this enhancement, at least in two or three months.

shaunlebron commented 6 years ago

@Northcode right, I meant paren-mode in parinfer. thanks for confirming that this is still a problem even after running it.

Your only option at this point is to convert your tabs to spaces, until time is found for a fix.

For reference, this is the code that should've converted the tabs to spaces: https://github.com/DogLooksGood/parinfer-mode/blob/v0.4.10/parinferlib.el#L290-L292

Northcode commented 6 years ago

@DogLooksGood Ah, yeah I meant that this was a problem for parinfer-mode, I don't use it on anything other than emacs, I just thought it was implied because this is the issue tracker for parinfer-mode, I'll change the title.

DogLooksGood commented 6 years ago

@Northcode

There's a rewriting on branch smart. In this rewriting version, my solution is if there's a tab char in code, parinfer-mode won't enable. It also won't enable if parinfer will change you buffer.

IMO indent with tab char is bad, so handling tab indentation is low priority.

You can try the new version here: https://github.com/DogLooksGood/parinfer-mode-demo

It's still not have exactly same logic with official parinfer at this moment, these differences need more work to deal with.