skeeto / skewer-mode

Live web development in Emacs
The Unlicense
1.1k stars 57 forks source link

Considered using in Web Mode? #67

Closed computersarecool closed 7 years ago

computersarecool commented 8 years ago

It seems that this package is geared towards use in html and css and js2 modes, is there any thought given as to how this could be used in Web Mode (which kind of combines those three)?

skeeto commented 8 years ago

Skewer could probably be updated to work with web-mode, but it's not something I currently plan to do. It's not that I object to it: I just haven't needed it.

computersarecool commented 8 years ago

👍 I will also look into it when I get a chance and feel that I have mastered skewer more.

lix90 commented 8 years ago

I know why I received "skewer-html-eval-tag: Error: cannot eval body and head tags." :( Because I used skewer-html-mode in web-mode.

UwUnyaa commented 7 years ago

I've been digging in skewer-html to figure out why evaluating HTML tags doesn't work in web-mode.

It seems that the function skewer-html-compute-tag-ancestry returns a mention of an additional <head> tag when pointed at a tag in <body>. It also returns a mention of an empty tag, but it seems that this isn't causing much problems.

I have no idea if html-mode sets some variables that make sgml functions work differently, and I didn't want to spend time checking for it. That might be the case.

I've written hacky advice that (seemingly) fixes the problem. It's in the commit to my personal configuration that I added below: https://github.com/DoMiNeLa10/.emacs.d/commit/1dc4d031d618781915664baf34f52e1e46b2c521 Note that I'm clearing out the empty tags here as well, but that's just me being paranoid.

skeeto commented 7 years ago

I'm aware of the incompatibility with web-mode, but since I don't use it I've never spent time investigating. It looks like the extra "head" tag you noticed comes about due to a bug in web-mode that subtly breaks some of sgml-mode. To demonstrate, put this in an html-mode buffer as well as in a web-mode buffer, then place the point on the opening angle bracket for the "c" tag:

Then M-: (sgml-get-context) in each. In html-mode you get the correct context of being inside just the "a" element. In web-mode, it reports that you're inside the "b" element. This is what leads to the invalid ancestry when Skewer tries to figure it out.

UwUnyaa commented 7 years ago

I've tried this example with multiple modes, and it seems like the result of sgml-show-context depends on font locking. (For example — trying to use it in a mode without font locking like fundamental-mode returns completely wrong tag names.) Maybe sgml functions aren't designed to work outside of sgml and html modes.

Some functions in sgml mode are defined by some macro that I can't find in sgml-mode's source code. It makes it a little bit harder to figure out what's the cause of this. This might be a problem on my part that might go away when I compile emacs from sources.

Maybe skewer should use some functions that work regardles of the major mode used (at least for html parsing.) I'll try to look for something that comes with emacs and is robust enough.

UwUnyaa commented 7 years ago

I came up with a better (and simpler) solution that should work with other modes as well. Running offending functions in a temporary buffer with the right major mode seems to avoid the problem completely, at the cost of losing the highlight effect. I think getting skewer-flash-region without modifying the code would be impossible. https://github.com/DoMiNeLa10/.emacs.d/commit/bfc1313ed92b5c078c413bdda5c30fc863c5a8db

I'll release it in a separate repo (or a gist) if anyone is interested.

skeeto commented 7 years ago

Cleaned up, this would be a perfectly reasonable workaround. Though I'd only want this copying to happen for buffers not already in html-mode, so that well-behaving buffer don't pay a performance penalty.

I also gave this a shot with indirect buffers, which saves on copying the entire buffer for a single evaluation. The indirect buffer shares the same memory contents but can be in a different major mode. However, it destroys all the font lock information, and the original buffer needs to have font-lock-fontify-buffer run in it after. That's probably more expensive than just copying the buffer.

UwUnyaa commented 7 years ago

I'll try to write a proper patch with a major mode check and make a pull request once I'm done.

skeeto commented 7 years ago

Thanks! I suggest doing it as a macro, which can then wrap the function bodies where it's needed:

(skewer-html--with-html-mode
  ...)

You can't use with-temp-buffer since its use is conditional in this macro. You'll essentially be re-implementing the macro, but in a richer way.