expez / evil-smartparens

Evil integration for Smartparens
GNU General Public License v3.0
133 stars 17 forks source link

Emacs hangs on haskell-mode when evil-smartparens is enabled #50

Open zzantares opened 6 years ago

zzantares commented 6 years ago

Hello, first let me thank you for this package, I've been using it for years without any issue at all, but now I'm experiencing an Emacs freeze and the only clue I have led me here. Let me explain:

When I'm in haskell-mode and want to yank to the end of line with Y emacs freezes, pressing C-g unfreezes it, it happens the same when using D or C. At first I didn't know what was the cause but I create this issue here because when I disable evil-smartparens-mode the problem goes away.

I've used toggle-debug-on-quit and this is what happens when emacs freezes:

Debugger entered--Lisp error: (quit)
  syntax-ppss(5925)
  sp--syntax-ppss(5925)
  sp-point-in-comment()
  sp-get-comment-bounds()
  sp-get-enclosing-sexp(1)
  sp-up-sexp(-1 nil)
  sp-backward-up-sexp()
  evil-sp--depth-at(3964)
  evil-sp--get-endpoint-for-killing()
  evil-sp-yank-line(3953 4014 line)
  funcall-interactively(evil-sp-yank-line 3953 4014 line)
  call-interactively(evil-sp-yank-line nil nil)
  command-execute(evil-sp-yank-line)

Why does this happen? I appreciate any help, Thanks!

expez commented 6 years ago

Hi,

thanks for the bug report and sorry to hear this isn't working as it should in Haskell mode.

If you want to get your hands dirty, instrument the function called evil-sp--depth-at. This function is used to check if the depth at start and end is the same. If so we can safely delete the desired region.

That function has two code paths, one for lisp modes, and one for all others. The slow code path, which runs in haskell-mode doesn't look completely bulletproof to me. I'm guessing the loop in there never terminates.

zzantares commented 6 years ago

Thank you! I'll try it this weekend, for now I've disabled the package in haskell-mode.

zzantares commented 6 years ago

Hello again! I've followed the recommendation and indeed as you guessed it this while loop never ends:

(while (and (not (sp-point-in-comment))
                 (ignore-errors (sp-backward-up-sexp)))
            (cl-incf depth))

I'm testing it inside a lambda: map f = foldr (\e a -> |f e : a) []:

So it is necessary for (sp-backward-up-sexp) to throw an error to terminate the loop? couldn't be another way to do the "slow path"?

expez commented 6 years ago

So it is necessary for (sp-backward-up-sexp) to throw an error to terminate the loop?

Or it just has to return nil to indicate that it's done moving. Since it moves 69 lines below to another function it appears it might be doing the wrong thing entirely in Haskell mode. You might have uncovered a bug in smartparens-mode.

couldn't be another way to do the "slow path"?

Probably. I'm not married to the current implementation. In fact, I expect it to change slightly every now and again as smartparens evolves.

Thanks for rolling up your sleeves!

imobachgs commented 5 years ago

I think I have the same (or a similar) problem using ruby-mode. Here is the debugging output:

Debugger entered--Lisp error: (quit)
  re-search-backward("\\(?:if\\)\\=" nil t)
  looking-back("if" nil)
  sp-ruby-in-string-word-or-inline-p("if" navigate code)
  sp--do-action-p("if" navigate)
  sp--get-allowed-pair-list()
  sp--get-allowed-regexp()
  sp-get-expression(nil)
  sp-get-sexp()
  sp-get-enclosing-sexp(1)
  sp-up-sexp(-1 nil)
  sp-backward-up-sexp()
  evil-sp--depth-at(41391)
  evil-sp--get-endpoint-for-killing()
  evil-sp-delete-line(nil nil nil nil)
  funcall-interactively(evil-sp-delete-line nil nil nil nil)
  call-interactively(evil-sp-delete-line nil nil)
  command-execute(evil-sp-delete-line)

In my case, it eventually continues working after waiting for a few seconds. Disabling evil-smartparens fixes the issue.

Thanks!