Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

haskell-ident-pos-at-point does not work for operators #1213

Closed
geraldus opened this issue Mar 15, 2016 · 9 comments
Closed

haskell-ident-pos-at-point does not work for operators #1213

geraldus opened this issue Mar 15, 2016 · 9 comments
Assignees

Comments

@geraldus
Copy link
Contributor

haskell-ident-pos-at-point returns nil when point stands at operator. I believe it should work for them too. We have two cases: infix and normal form. I believe for normal form this function should take into account surrounding parentheses too.

One caveat: it's not clear what to do when point is at operator in unfinished expression preceded by opening parenthesis, e.g. (++. It may refer to (++ xs) or (++), the former is an infix form and latter is a normal form. I think in this case it's better not to include parenthesis.

Related #735

@gracjan
Copy link
Contributor

gracjan commented Mar 15, 2016

One more thing to observe is qualified operators: a Control.Monad.>>= b, (Control.Monad.>>=) a b

@geraldus
Copy link
Contributor Author

I'm confused a bit. haskell-ident-pos-at-point uses (skip-syntax-forward "w_") and (skip-syntax-backward "w_") to determine initial boundaries of expression. These functions return 0 when point stands at operator symbols, however (char-syntax (point)) returns me ?w. Also, skip-syntax functions stop at ., this is bad in case of operators. @gracjan can you suggest something? Can we use lexemes or something else in this function or have to rewrite boundaries capturing (conditionally skip syntax depending of last character of expression)?

Here is a code reference.

@geraldus
Copy link
Contributor Author

Hmm… I think this much involving that seems to be.

Actually, haskell-ident-pos-at-point is haskell-ident-pos-backward-near-point, because it skips preceding whitespace first and then tries to determine identifier bounds. I think this is what we have to do:

  • find all use cases of haskell-ident-pos-at-point
  • analyze that list and understand what this function should return, e.g. when point somewhere in the middle of module name, when point stands at qualified identifier or operator and etc.
  • rename current function and define truly ident-at-pos function which returns nil if point does not stand at identifier (e.g. whitespace, newline, parentheses and brackets)
  • new ident-at-point function should handle operators as well
  • find out where we need at-point function and where we need near-point function

what else?

@gracjan
Copy link
Contributor

gracjan commented Mar 15, 2016

haskell-lexeme knows how to do syntactic analysis from beginning to the end. Finding things around point requires a bit more cleverness.

@geraldus geraldus self-assigned this Mar 18, 2016
@geraldus
Copy link
Contributor Author

@gracjan do we have some predicate for operator symbols? If not should we support only ASCII symbols only or all unicode stuff too (there are very large variety of unicode symbols GHC treats as operator symbol)?

@gracjan
Copy link
Contributor

gracjan commented Mar 19, 2016

haskell-lexeme can recognize operators properly.

@geraldus
Copy link
Contributor Author

@gracjan great, I've tested haskell-lexeme-classify-by-first-char and likely it will help me with operators. But now I'm confused a little. haskell-ident-pos-at-point is indiscriminate: it works inside string and comments (I've already fixed this); in current implementation it returns spans for any word in buffer (or words sequence concatenated by . dots). This looks a bit odd for me because when I read "ident" is not associates with keywords in my head.
I'm on the way to fix this issue, but have a turtle speed.

@gracjan
Copy link
Contributor

gracjan commented Mar 20, 2016

So GHC parses stuff like this:

  • List.list.list => List.list . list
  • where.x => where . x
  • Module.where => Module.where

Note that in the last case where is not a keyword, it is an qualified identifier (although impossible to generate).

So to find real beginning of a qualified identifier we have to go back to a safe character and then move forward (possibly a couple of times). A safe character would be:

  • beginning of line
  • space
  • any of open of close parentheses
  • semicolon or comma

Or plainly anything that is not a character valid for qualified identifier or symbol, constructor or not.

Some of this logic is already present in haskell-forward-sexp in case when this function gets a negative argument. Maybe you can refactor it from there?

@geraldus
Copy link
Contributor Author

Fixed by #1224

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants