hylang / hy-mode

Hy mode for Emacs
GNU General Public License v3.0
191 stars 47 forks source link

support Symbol Highlight Transient State in Spacemacs #50

Closed gilch closed 7 years ago

gilch commented 7 years ago

I'm not sure if this issue is in hy-mode itself or the Spacemacs layer, or both somehow.

In an Elisp buffer, in Evil normal mode, you can activate Symbol Highlight Transient State with * or # to search backwards or forwards for the symbol under the cursor. Then you can change the effective range of the search with r, cycling between Display Function and Buffer.

In a Hy buffer, the Function range is unavailable. This is important when renaming a local in a function definition.

It also doesn't recognize all instances of a symbol. For example, if you put the point on the first x, and use * in this elisp, then it finds all three x symbols.

(defun (x)
    `(x ,x))

But in the equivalent Hy,

(defn [x]
  `(x ~x))

It doesn't find the third x. But it can using the exact same code in clojure mode.

ekaschalk commented 7 years ago

I have absolutely no idea how Clojure manages to do this, as I can find no modifications in either its layer or mode file that would enable it. The solution I added isn't what Clojure does.

Edit: Missed the Function range part of this issue, I'll look at that.

gilch commented 7 years ago

I checked clojure mode and it doesn't seem to support the Function range like elisp does. You won't find the answer there. But Function does work in a Common Lisp buffer.

Maybe we should report that for clojure, but to Spacemacs or clojure mode?

gilch commented 7 years ago

It looks like the Function range is a misnomer (but not without precedent). It searches the entire top-level form in elisp mode, even if it's not a defun, and it also searches the entire top-level form if started from within a nested defun. This is not as nice as full IDE refactoring support, but should be easier to implement. We just have to find the right hook, I guess.

ekaschalk commented 7 years ago

Are you familiar with the https://github.com/Foxboron/HyREPL project? I tried getting it to run a while back but it needs to be fixed. I'm not sure if attacking autocompletion through an nREPL protocol is the best course of action or not.

gilch commented 7 years ago

I've not used it, so I'm not sure either.

Extending IPython is another option.

Hy's bundled command line repl also has tab completions via readline, I think. That might be the easiest place to start. There's probably some way to integrate that.

HyREPL is written in a older version of Hy. I'm not sure how thorough the tests are, but if you want to try updating it in a fork, replacing let would be the first step.

You could start with a shim macro implementing something like the old, broken, let and require it at the top of every .hy file that uses let. (Or just paste it in--it's short.)

(defmacro let [pairs &rest body]
  `((fn [] (setv ~@pairs) ~@body)))

Then see if the tests pass, or if anything else needs updating. Some other things have been removed and HyREPL might have been using them, but they have near or total equivalents. Check Hy's news file, or ask me if you can't tell what something missing meant.

At that point, you could start testing it with emacs.

Before making a PR from your fork, update the let macro to a do/setv implementation.

(defmacro let [pairs &rest body]
  `(do (setv ~@pairs) ~@body))

This should work for any use of let that doesn't need a closure, which is probably all of them, but if not, replace those few with the manually expanded fn version. There also might be nested lets that shadow a variable, in which case you can simply change that variable name to avoid clobbering the outer one, without making a function.

Once that's working, you can remove all the lets, and replace them with do/setvs. Often, you can omit the do because the enclosing form implicitly has one.

ekaschalk commented 7 years ago

I'm likely to hold off on this in favor of an imenu implementation down the road. I'm not too familiar with AHS, I typically use iedit in these situations. I'm going to close this for now.

I've updated AHS to include dashes in symbols so eg. foo-bar can now properly be highlighted/searched. Let me know if any other non-intelligent changes for AHS.

gilch commented 7 years ago

AHS? What's that?

I do use iedit. The usual way to activate iedit in spacemacs is via the Symbol Highlight Transient State, then e, or at least that's how I do it.

I have noticed one more issue with #/* searching--it doesn't recognize dot access. For example, in a class you might have the point on a method definition name foo and want to find it accessed in another method as self.foo. Hy-mode should probably consider those separate symbols, self and foo, but it doesn't find it.

ekaschalk commented 7 years ago

Auto highlight symbol, the implementing emacs package. I typically use expand-region to access iedit.

I'll look to fix the dots.

ekaschalk commented 7 years ago

For the dots, no matter how I work with the syntax table we either have the entire foo.bar as one symbol or (func) foo.bar => (func foo.)bar will occur when slurping. Not sure if it is possible to have both proper slurping yet use . as a symbol delimiter.