jlr / rainbow-delimiters

Emacs rainbow delimiters mode
http://www.emacswiki.org/emacs/RainbowDelimiters
112 stars 12 forks source link

Close parentheses aren't always properly recognized #3

Closed immerrr closed 12 years ago

immerrr commented 12 years ago

Hi!

I'm regularly running into this issue. This morning I've found the most compact example of this behavior. In the snippet below, closing parenthesis is considered unbalanced. I've double checked, (rainbow-delimiters-depth close-paren-pos) returns 0.

#!/usr/bin/perl
ff(
);

but if I remove ff, everything is fine

#!/usr/bin/perl
(
);

It's fine as well after removal of #!/usr/bin/perl line:

ff(
);

My wild guess would be that it's something wrong with inheriting syntax table from the one of emacs-lisp mode.

jlr commented 12 years ago

Hi, after some tinkering I see the behaviour you were describing. When I paste that snippet in and start rainbow delimiters it's colorized normally at first, but then if you delete the close paren and retype it, it turns red. I assume that's what you were reporting - that your matching close-parens are turning red when you type them, even though they're not unbalanced?

Your wild guess was precisely accurate - as soon as I changed the syntax-table in rainbow-delimiters.el from emacs-lisp-mode-syntax-table to perl-mode-syntax-table, the problem went away. One thing to note is you won't see this issue if you're not in perl-mode: in text-mode, I can insert that same snippet and it won't have any problems, despite my inheriting from emacs-lisp-mode-syntax-table. It's definitely something in the perl-mode syntax table confusing rainbow-delimiters which, as you noted, currently expects emacs-lisp syntax. In many modes there isn't a collision there, but there is in perl-mode.

I have felt for some time that inheriting from emacs-lisp-mode-syntax-table was the wrong way to go just on principle, so this pushes my desire to fix that up the priority list and I'll be sure to correct it for the next release.

For now, if you want it to work specifically in perl-mode, you can go modify the "defvar rainbow-delimiters-delim-syntax-table" inside rainbow-delimiters.el, and make it inherit from perl-mode-syntax-table instead of the current emacs-lisp-mode-syntax-table.

That would look like this (the only thing modified here is changing emacs-lisp-mode-syntax-table to perl-mode-syntax-table):

;; syntax-table: used with parse-partial-sexp for determining current depth.
(defvar rainbow-delimiters-delim-syntax-table
  (let ((table (copy-syntax-table perl-mode-syntax-table)))  ;; <---- HERE ----
    (modify-syntax-entry ?\( "()  " table)
    (modify-syntax-entry ?\) ")(  " table)
    (modify-syntax-entry ?\[ "(]" table)
    (modify-syntax-entry ?\] ")[" table)
    (modify-syntax-entry ?\{ "(}" table)
    (modify-syntax-entry ?\} "){" table)
    table)
  "Syntax table for recognizing all supported delimiter types.")

I will work on a fix for this problem by the next release, which is on its way, and which by the way will colorize nested tags (e.g. html/xml) as well - really excited about that. It's not quite as easy as it would seem to deal with this syntax-table issue since if I use an empty syntax table, I can no longer detect when something is inside a comment, so I have to look at potential solutions - the first that comes to mind is inheriting from whatever syntax-table is detected when rainbow-delimiters-minor-mode gets activated. If any suggestions come in on how to fix it I'll gladly look at them, but regardless I'll get this one sorted out by next release.

Appreciate your effort in sorting out a very concise example for me to work with. I'm very glad to see that rainbow-delimiters is being used in languages outside the lisp family such as perl. Thanks for your report.

immerrr commented 12 years ago

I run time to time into this when using other lang-modes too (c++, lua, etc). From what I've found on the internet, "the proper"(tm) way to have syntax-table defined during minor-mode initialization (somewhere inside (minor-mode) call). AFAIR, define-globalized-mode guarantees that its hooks are run only after corresponding major mode with its syntax table is already set up.

jlr commented 12 years ago

Thanks for the tip - I had been thinking along the same lines. I just got done making this work - the mode now inherits from the buffer's current syntax-table upon activation. I tested it on your example and perl-mode works correctly.

Figured I should get the bugfix out as soon as possible. I think I'll wait to update EmacsWiki until I finish the things I want in v1.4, but it's there for download in the github version. Please feel free to let me know if you run in to any other issues.

ryuslash commented 12 years ago

I still seem to have this issue with (not the default) python-mode using, for example, this:

    test = ('foo',
            'bar')

using emacs 24.0.94.1 (I build it daily from bzr trunk) and rainbow-delimiters 1.3.3 (from ELPA)

jlr commented 12 years ago

ryuslash, thanks for sending that info. I didn't see your message until now because the page I was checking didn't show comments on closed bugs.

I'm pretty sure that 1.3.4 fixes this. I added it to marmalade-repo/ELPA, so you can get it there. Please let me know if you still run into this problem.

ryuslash commented 12 years ago

Thanks for your response.

I don't know about 1.3.4, but the 20120428 version from (I assume) melpa seems to handle that case just fine indeed.