Skip to content

Commit ea6693e

Browse files
committed
Detect operators and binding operators at point for xref
This will be used for `xref-find-references` (`M-?`), although that command currently ignores the string and only uses the location. If an identifier both succeeds and precedes point, prefer the former. For instance, in `a+b` with the cursor on `+`, use `+` as the idenfier; with the cursor on `b`, use `b`.
1 parent 6271e31 commit ea6693e

File tree

1 file changed

+58
-1
lines changed

1 file changed

+58
-1
lines changed

emacs/merlin-xref.el

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,65 @@
9696
(cl-defmethod xref-backend-identifier-completion-table ((_backend (eql merlin-xref)))
9797
nil)
9898

99+
(defconst merlin-xref--operator-regexp
100+
(eval-when-compile
101+
(let* ((core-operator-char
102+
`(or "$" "&" "*" "+" "-" "/" "=" ">" "@" "^" "|"))
103+
(operator-char `(or "~" "!" "?" ,core-operator-char "%" "<" ":" "."))
104+
(prefix-symbol `(or (seq "!" (* ,operator-char))
105+
(seq (or "?" "~") (+ ,operator-char))))
106+
(infix-symbol `(or (seq (or ,core-operator-char "%" "<")
107+
(* ,operator-char))
108+
(seq "#" (+ ,operator-char))))
109+
(infix-op `(or ,infix-symbol
110+
":="
111+
;; Already handled as part of `infix-symbol':
112+
;; "*" "+" "-" "-." "=" "!=" "<" ">" "||" "&" "&&"
113+
;; Treated as normal symbols:
114+
;; "or" "mod" "land" "lor" "lxor" "lsl" "lsr" "asr"
115+
))
116+
(operator-name `(or ,prefix-symbol ,infix-op)))
117+
(rx-to-string operator-name t))))
118+
119+
(defconst merlin-xref--binding-operator-regexp
120+
(eval-when-compile
121+
(let* ((core-operator-char
122+
`(or "$" "&" "*" "+" "-" "/" "=" ">" "@" "^" "|"))
123+
(dot-operator-char
124+
`(or "!" "?" ,core-operator-char "%" ":"))
125+
(binding-suffix
126+
`(seq (or ,core-operator-char "<") (* ,dot-operator-char)))
127+
(binding-operator
128+
`(seq symbol-start (or "let" "and") ,binding-suffix)))
129+
(rx-to-string binding-operator t))))
130+
131+
(defconst merlin-xref--identifier-regexp
132+
(rx symbol-start (in "A-Za-z_") (* (in "A-Za-z0-9_'"))))
133+
99134
(cl-defmethod xref-backend-identifier-at-point ((_backend (eql merlin-xref)))
100-
(let ((symbol (thing-at-point 'symbol)))
135+
(let ((symbol
136+
(and
137+
(or
138+
;; binding operator starting at point
139+
(looking-at merlin-xref--binding-operator-regexp)
140+
;; ... before point
141+
(and (save-excursion
142+
(skip-chars-backward "letand$&*+/=<>@^|!?%:-")
143+
(looking-at merlin-xref--binding-operator-regexp))
144+
(<= (point) (match-end 0)))
145+
;; ordinary name starting at point
146+
(looking-at merlin-xref--identifier-regexp)
147+
;; operator starting at or before point
148+
(and (save-excursion
149+
(skip-chars-backward "$&*+/=<>@^|!?%:.~#-")
150+
(looking-at merlin-xref--operator-regexp))
151+
(<= (point) (match-end 0)))
152+
;; ordinary name starting before point
153+
(and (save-excursion
154+
(skip-chars-backward "A-Za-z0-9_'")
155+
(looking-at merlin-xref--identifier-regexp))
156+
(<= (point) (match-end 0))))
157+
(match-string 0))))
101158
;; Return a string with the buffer position in a property, in case
102159
;; point changes before the string is used by one of the methods above.
103160
(and symbol (propertize symbol 'merlin-xref-point (point)))))

0 commit comments

Comments
 (0)